Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / utils / lustre_cfg.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *   Author: Peter J. Braam <braam@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *   Author: Andreas Dilger <adilger@clusterfs.com>
8  *   Author: Robert Read <rread@clusterfs.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26
27 #include <stdlib.h>
28 #include <sys/ioctl.h>
29 #include <stdio.h>
30 #include <stdarg.h>
31 #include <ctype.h>
32 #include <glob.h>
33
34 #ifndef __KERNEL__
35 #include <liblustre.h>
36 #endif
37 #include <lustre_lib.h>
38 #include <lustre_cfg.h>
39 #include <lustre/lustre_idl.h>
40 #include <lustre_dlm.h>
41 #include <obd.h>          /* for struct lov_stripe_md */
42 #include <obd_lov.h>
43 #include <lustre/lustre_build_version.h>
44
45 #include <unistd.h>
46 #include <sys/un.h>
47 #include <time.h>
48 #include <sys/time.h>
49 #include <errno.h>
50 #include <string.h>
51
52
53 #include "obdctl.h"
54 #include <lnet/lnetctl.h>
55 #include "parser.h"
56 #include <stdio.h>
57
58 static char * lcfg_devname;
59
60 int lcfg_set_devname(char *name)
61 {
62         if (name) {
63                 if (lcfg_devname)
64                         free(lcfg_devname);
65                 /* quietly strip the unnecessary '$' */
66                 if (*name == '$' || *name == '%')
67                         name++;
68                 if (isdigit(*name)) { 
69                         /* We can't translate from dev # to name */
70                         lcfg_devname = NULL;
71                 } else {
72                         lcfg_devname = strdup(name);
73                 }
74         } else {
75                 lcfg_devname = NULL;
76         } 
77         return 0;
78 }
79
80 char * lcfg_get_devname(void)
81 {
82         return lcfg_devname;
83 }
84
85 int jt_lcfg_device(int argc, char **argv)
86 {
87         return jt_obd_device(argc, argv);
88 }
89
90 int jt_lcfg_attach(int argc, char **argv)
91 {
92         struct lustre_cfg_bufs bufs;
93         struct lustre_cfg *lcfg;
94         int rc;
95
96         if (argc != 4)
97                 return CMD_HELP;
98
99         lustre_cfg_bufs_reset(&bufs, NULL);
100
101         lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
102         lustre_cfg_bufs_set_string(&bufs, 0, argv[2]);
103         lustre_cfg_bufs_set_string(&bufs, 2, argv[3]);
104
105         lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs);
106         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
107         lustre_cfg_free(lcfg);
108         if (rc < 0) {
109                 fprintf(stderr, "error: %s: LCFG_ATTACH %s\n",
110                         jt_cmdname(argv[0]), strerror(rc = errno));
111         } else if (argc == 3) {
112                 char name[1024];
113
114                 lcfg_set_devname(argv[2]);
115                 if (strlen(argv[2]) > 128) {
116                         printf("Name too long to set environment\n");
117                         return -EINVAL;
118                 }
119                 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
120                 rc = setenv(name, argv[1], 1);
121                 if (rc) {
122                         printf("error setting env variable %s\n", name);
123                 }
124         } else {
125                 lcfg_set_devname(argv[2]);
126         }
127
128         return rc;
129 }
130
131 int jt_lcfg_setup(int argc, char **argv)
132 {
133         struct lustre_cfg_bufs bufs;
134         struct lustre_cfg *lcfg;
135         int i;
136         int rc;
137
138         if (lcfg_devname == NULL) {
139                 fprintf(stderr, "%s: please use 'device name' to set the "
140                         "device name for config commands.\n", 
141                         jt_cmdname(argv[0])); 
142                 return -EINVAL;
143         }
144
145         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
146
147         if (argc > 6)
148                 return CMD_HELP;
149
150         for (i = 1; i < argc; i++) {
151                 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
152         }
153
154         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
155         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
156         lustre_cfg_free(lcfg);
157         if (rc < 0)
158                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
159                         strerror(rc = errno));
160
161         return rc;
162 }
163
164 int jt_obd_detach(int argc, char **argv)
165 {
166         struct lustre_cfg_bufs bufs;
167         struct lustre_cfg *lcfg;
168         int rc;
169
170         if (lcfg_devname == NULL) {
171                 fprintf(stderr, "%s: please use 'device name' to set the "
172                         "device name for config commands.\n", 
173                         jt_cmdname(argv[0])); 
174                 return -EINVAL;
175         }
176
177         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
178
179         if (argc != 1)
180                 return CMD_HELP;
181
182         lcfg = lustre_cfg_new(LCFG_DETACH, &bufs);
183         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
184         lustre_cfg_free(lcfg);
185         if (rc < 0)
186                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
187                         strerror(rc = errno));
188
189         return rc;
190 }
191
192 int jt_obd_cleanup(int argc, char **argv)
193 {
194         struct lustre_cfg_bufs bufs;
195         struct lustre_cfg *lcfg;
196         char force = 'F';
197         char failover = 'A';
198         char flags[3] = { 0 };
199         int flag_cnt = 0, n;
200         int rc;
201
202         if (lcfg_devname == NULL) {
203                 fprintf(stderr, "%s: please use 'device name' to set the "
204                         "device name for config commands.\n", 
205                         jt_cmdname(argv[0])); 
206                 return -EINVAL;
207         }
208
209         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
210
211         if (argc < 1 || argc > 3)
212                 return CMD_HELP;
213
214         /* we are protected from overflowing our buffer by the argc
215          * check above
216          */
217         for (n = 1; n < argc; n++) {
218                 if (strcmp(argv[n], "force") == 0) {
219                         flags[flag_cnt++] = force;
220                 } else if (strcmp(argv[n], "failover") == 0) {
221                         flags[flag_cnt++] = failover;
222                 } else {
223                         fprintf(stderr, "unknown option: %s", argv[n]);
224                         return CMD_HELP;
225                 }
226         }
227
228         if (flag_cnt) {
229                 lustre_cfg_bufs_set_string(&bufs, 1, flags);
230         }
231
232         lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
233         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
234         lustre_cfg_free(lcfg);
235         if (rc < 0)
236                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
237                         strerror(rc = errno));
238
239         return rc;
240 }
241
242 static 
243 int do_add_uuid(char * func, char *uuid, lnet_nid_t nid) 
244 {
245         int rc;
246         struct lustre_cfg_bufs bufs;
247         struct lustre_cfg *lcfg;
248
249         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
250         if (uuid)
251                 lustre_cfg_bufs_set_string(&bufs, 1, uuid);
252
253         lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs);
254         lcfg->lcfg_nid = nid;
255         /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it 
256            doesn't work without crashing (bz 10130) */
257         lcfg->lcfg_nal = 0x5a;
258
259 #if 0
260         fprintf(stderr, "adding\tnid: %d\tuuid: %s\n",
261                lcfg->lcfg_nid, uuid);
262 #endif
263         rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg);
264         lustre_cfg_free(lcfg);
265         if (rc) {
266                 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
267                         strerror(errno));
268                 return -1;
269         }
270
271         printf ("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid));
272         return 0;
273 }
274
275 int jt_lcfg_add_uuid(int argc, char **argv)
276 {
277         lnet_nid_t nid;
278         
279         if (argc != 3) {                
280                 return CMD_HELP;
281         }
282
283         nid = libcfs_str2nid(argv[2]);
284         if (nid == LNET_NID_ANY) {
285                 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
286                 return (-1);
287         }
288
289         return do_add_uuid(argv[0], argv[1], nid);
290 }
291
292 int obd_add_uuid(char *uuid, lnet_nid_t nid)
293 {
294         return do_add_uuid("obd_add_uuid", uuid, nid);
295 }
296
297 int jt_lcfg_del_uuid(int argc, char **argv)
298 {
299         int rc;
300         struct lustre_cfg_bufs bufs;
301         struct lustre_cfg *lcfg;
302
303         if (argc != 2) {
304                 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
305                 return 0;
306         }
307
308         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
309         if (strcmp (argv[1], "_all_"))
310                 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
311         
312         lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs);
313         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
314         lustre_cfg_free(lcfg);
315         if (rc) {
316                 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
317                         strerror(errno));
318                 return -1;
319         }
320         return 0;
321 }
322
323
324
325
326 int jt_lcfg_del_mount_option(int argc, char **argv)
327 {
328         int rc;
329         struct lustre_cfg_bufs bufs;
330         struct lustre_cfg *lcfg;
331
332         if (argc != 2)
333                 return CMD_HELP;
334
335         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
336
337         /* profile name */
338         lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
339
340         lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
341         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
342         lustre_cfg_free(lcfg);
343         if (rc < 0) {
344                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
345                         strerror(rc = errno));
346         }
347         return rc;
348 }
349
350 int jt_lcfg_set_timeout(int argc, char **argv)
351 {
352         int rc;
353         struct lustre_cfg_bufs bufs;
354         struct lustre_cfg *lcfg;
355
356         fprintf(stderr, "%s has been deprecated. Use conf_param instead.\n"
357                 "e.g. conf_param lustre-MDT0000 obd_timeout=50\n",
358                 jt_cmdname(argv[0]));
359         return CMD_HELP;
360
361
362         if (argc != 2)
363                 return CMD_HELP;
364
365         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
366         lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
367         lcfg->lcfg_num = atoi(argv[1]);
368         
369         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
370         //rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
371
372         lustre_cfg_free(lcfg);
373         if (rc < 0) {
374                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
375                         strerror(rc = errno));
376         }
377         return rc;
378 }
379
380
381
382 int jt_lcfg_add_conn(int argc, char **argv)
383 {
384         struct lustre_cfg_bufs bufs;
385         struct lustre_cfg *lcfg;
386         int priority;
387         int rc;
388
389         if (argc == 2)
390                 priority = 0;
391         else if (argc == 3)
392                 priority = 1;
393         else
394                 return CMD_HELP;
395
396         if (lcfg_devname == NULL) {
397                 fprintf(stderr, "%s: please use 'device name' to set the "
398                         "device name for config commands.\n", 
399                         jt_cmdname(argv[0])); 
400                 return -EINVAL;
401         }
402
403         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
404
405         lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
406
407         lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs);
408         lcfg->lcfg_num = priority;
409
410         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
411         lustre_cfg_free (lcfg);
412         if (rc < 0) {
413                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
414                         strerror(rc = errno));
415         }
416
417         return rc;
418 }
419
420 int jt_lcfg_del_conn(int argc, char **argv)
421 {
422         struct lustre_cfg_bufs bufs;
423         struct lustre_cfg *lcfg;
424         int rc;
425
426         if (argc != 2)
427                 return CMD_HELP;
428
429         if (lcfg_devname == NULL) {
430                 fprintf(stderr, "%s: please use 'device name' to set the "
431                         "device name for config commands.\n", 
432                         jt_cmdname(argv[0])); 
433                 return -EINVAL;
434         }
435
436         lustre_cfg_bufs_reset(&bufs, lcfg_devname);
437
438         /* connection uuid */
439         lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
440
441         lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
442
443         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
444         lustre_cfg_free(lcfg);
445         if (rc < 0) {
446                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
447                         strerror(rc = errno));
448         }
449
450         return rc;
451 }
452
453 /* Param set locally, directly on target */
454 int jt_lcfg_param(int argc, char **argv)
455 {
456         int i, rc;
457         struct lustre_cfg_bufs bufs;
458         struct lustre_cfg *lcfg;
459
460         if (argc >= LUSTRE_CFG_MAX_BUFCOUNT)
461                 return CMD_HELP;
462
463         lustre_cfg_bufs_reset(&bufs, NULL);
464
465         for (i = 1; i < argc; i++) {
466                 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
467         }
468
469         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
470         
471         rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
472         lustre_cfg_free(lcfg);
473         if (rc < 0) {
474                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
475                         strerror(rc = errno));
476         }
477         return rc;
478 }
479
480 /* Param set in config log on MGS */
481 /* conf_param key1=value1 [key2=value2...] */
482 int jt_lcfg_mgsparam(int argc, char **argv)
483 {
484         int i, rc;
485         struct lustre_cfg_bufs bufs;
486         struct lustre_cfg *lcfg;
487
488         if ((argc >= LUSTRE_CFG_MAX_BUFCOUNT) || (argc <= 1))
489                 return CMD_HELP;
490
491         lustre_cfg_bufs_reset(&bufs, NULL);
492         for (i = 1; i < argc; i++) {
493                 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
494         }
495
496         /* We could put other opcodes here. */
497         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
498
499         rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
500         lustre_cfg_free(lcfg);
501         if (rc < 0) {
502                 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
503                         strerror(rc = errno));
504         }
505         
506         return rc;
507 }
508
509 /* Display the path in the same format as sysctl
510  * For eg. obdfilter.lustre-OST0000.stats */
511 static char *display_name(char *filename)
512 {
513         char *tmp;
514
515         filename += strlen("/proc/");
516         if (strncmp(filename, "fs/", strlen("fs/")) == 0)
517                 filename += strlen("fs/");
518         else
519                 filename += strlen("sys/");
520
521         if (strncmp(filename, "lustre/", strlen("lustre/")) == 0)
522                 filename += strlen("lustre/");
523
524         /* replace '/' with '.' to match conf_param and sysctl */
525         tmp = filename;
526         while ((tmp = strchr(tmp, '/')) != NULL)
527                 *tmp = '.';
528
529         return filename;
530 }
531
532 /* Find a character in a length limited string */
533 static char *strnchr(const char *p, char c, size_t n)
534 {
535        if (!p)
536                return (0);
537
538        while (n-- > 0) {
539                if (*p == c)
540                        return ((char *)p);
541                p++;
542        }
543        return (0);
544 }
545
546 int jt_lcfg_getparam(int argc, char **argv)
547 {
548         int fp;
549         int rc = 0, i, show_path = 0, only_path = 0;
550         char pattern[PATH_MAX];
551         char *path, *tmp, *buf;
552         glob_t glob_info;
553
554         if (argc == 3 && (strcmp(argv[1], "-n") == 0 || strcmp(argv[1], "-N") == 0)) {
555                 path = argv[2];
556                 if (strcmp(argv[1], "-N") == 0) {
557                         only_path = 1;
558                         show_path = 1;
559                 }
560         } else if (argc == 2) {
561                 show_path = 1;
562                 path = argv[1];
563         } else {
564                 return CMD_HELP;
565         }
566
567         /* If the input is in form Eg. obdfilter.*.stats */
568         if (strchr(path, '.')) {
569                 tmp = path;
570                 while (*tmp != '\0') {
571                         if (*tmp == '.')
572                                 *tmp = '/';
573                         tmp ++;
574                 }
575         }
576
577         /* If the entire path is specified as input */
578         fp = open(path, O_RDONLY);
579         if (fp < 0)
580                 snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s",
581                          path);
582         else {
583                 strcpy(pattern, path);
584                 close(fp);
585         }
586
587         rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
588         if (rc) {
589                 fprintf(stderr, "error : glob %s: %s \n", pattern,strerror(rc));
590                 return rc;
591         }
592
593         buf = malloc(CFS_PAGE_SIZE);
594         for (i = 0; i  < glob_info.gl_pathc; i++) {
595                 char *valuename = NULL;
596
597                 memset(buf, 0, CFS_PAGE_SIZE);
598                 if (show_path) {
599                         char *filename;
600                         filename = strdup(glob_info.gl_pathv[i]);
601                         valuename = display_name(filename);
602                         if (valuename && only_path) {
603                                 printf("%s\n", valuename);
604                                 continue;
605                         }
606                 }
607
608                 /* Write the contents of file to stdout */
609                 fp = open(glob_info.gl_pathv[i], O_RDONLY);
610                 if (fp < 0) {
611                         fprintf(stderr, "error: %s: opening('%s') failed: %s\n",
612                                 jt_cmdname(argv[0]), glob_info.gl_pathv[i],
613                                 strerror(errno));
614                         continue;
615                 }
616
617                 do {
618                         rc = read(fp, buf, CFS_PAGE_SIZE);
619                         if (rc == 0)
620                                 break;
621                         if (rc < 0) {
622                                 fprintf(stderr, "error: %s: read('%s') "
623                                         "failed: %s\n", jt_cmdname(argv[0]),
624                                         glob_info.gl_pathv[i], strerror(errno));
625                                 break;
626                         }
627                         /* Print the output in the format path=value if the
628                          * value contains no new line character or cab be
629                          * occupied in a line, else print value on new line */
630                         if (valuename && show_path) {
631                                 int longbuf = strnchr(buf, rc - 1, '\n') != NULL
632                                               || rc > 60;
633                                 printf("%s=%s", valuename, longbuf ? "\n" : buf);
634                                 valuename = NULL;
635                                 if (!longbuf)
636                                         continue;
637                                 fflush(stdout);
638                         }
639                         rc = write(fileno(stdout), buf, rc);
640                         if (rc < 0) {
641                                 fprintf(stderr, "error: %s: write to stdout "
642                                         "failed: %s\n", jt_cmdname(argv[0]),
643                                         strerror(errno));
644                                 break;
645                         }
646                 } while (1);
647                 close(fp);
648         }
649
650         globfree(&glob_info);
651         free(buf);
652         return rc;
653 }
654
655
656 int jt_lcfg_setparam(int argc, char **argv)
657 {
658         int rc = 0, i;
659         int fp, show_path = 0;
660         char pattern[PATH_MAX];
661         char *path, *value, *tmp;
662         glob_t glob_info;
663
664         path = argv[1];
665         if (argc == 4 && (strcmp(argv[1], "-n") == 0)) {
666                 /* Format: lctl set_param -n param value */
667                 path = argv[2];
668                 value = argv[3];
669         } else if (argc == 3) {
670                 if (strcmp(argv[1], "-n") != 0) {
671                         /* Format: lctl set_param param value */
672                         show_path = 1;
673                         value = argv[2];
674                 } else if ((value = strchr(argv[2], '=')) != NULL) {
675                         /* Format: lctl set_param -n param=value */
676                         path = argv[2];
677                         *value = '\0';
678                         value ++;
679                 } else {
680                         fprintf(stderr, "error: %s Incorrect arguments."
681                                         "See Usage\n",
682                                 jt_cmdname(argv[0]));
683                         return CMD_HELP;
684                 }
685         } else if (argc == 2 && ((value = strchr(argv[1], '=')) != NULL)) {
686                 /* Format: lctl set_param param=value */
687                 show_path = 1;
688                 *value = '\0';
689                 value++;
690         } else {
691                 fprintf(stderr, "error: %s Incorrect arguments. See Usage\n",
692                         jt_cmdname(argv[0]));
693                 return CMD_HELP;
694         }
695
696         /* If the input is in form Eg. obdfilter.*.stats */
697         if (strchr(path, '.')) {
698                 tmp = path;
699                 while (*tmp != '\0') {
700                         if (*tmp == '.')
701                                 *tmp = '/';
702                         tmp ++;
703                 }
704         }
705
706         fp = open(path, O_RDONLY);
707         if (fp < 0)
708                 snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s",
709                          path);
710         else {
711                 strcpy(pattern, path);
712                 close(fp);
713         }
714
715         rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
716         if (rc) {
717                 fprintf(stderr, "error : glob %s: %s \n", pattern,strerror(rc));
718                 return rc;
719         }
720         for (i = 0; i  < glob_info.gl_pathc; i++) {
721                 if (show_path) {
722                         char *valuename, *filename;
723                         filename = strdup(glob_info.gl_pathv[i]);
724                         valuename = display_name(filename);
725                         printf("%s=%s\n", valuename, value);
726                 }
727                 /* Write the new value to the file */
728                 fp = open(glob_info.gl_pathv[i], O_WRONLY);
729                 if (fp > 0) {
730                         rc = write(fp, value, strlen(value));
731                         if (rc < 0)
732                                 fprintf(stderr,
733                                         "error writing to file %s\n",
734                                         glob_info.gl_pathv[i]);
735                         else
736                                 rc = 0;
737                         close(fp);
738                 } else {
739                         fprintf(stderr, "error: %s: %s opening %s\n",
740                                 jt_cmdname(argv[0]), strerror(rc = errno),
741                                 glob_info.gl_pathv[i]);
742                 }
743         }
744
745         globfree(&glob_info);
746         return rc;
747 }