1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 #include <stdio.h>
30 #include <errno.h>
31 #include <limits.h>
32 #include <fcntl.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/wait.h>
37 #include <sys/vfstab.h>
38 #include <sys/mntent.h>
39 #include <sys/sysmacros.h>
40 #include <locale.h>
41 #include <libintl.h>
42 #include <sys/dkio.h>
43
44 #define DEV_BSIZE 512
45 #define ARGV_MAX 16
46 #define FSTYPE_MAX 8
47 #define VFS_PATH "/usr/lib/fs"
48 #define VFS_PATH2 "/etc/fs"
49
50 #define CHECK(xx, yy)\
51 if (xx == (yy)-1) {\
52 fprintf(stderr, gettext("%s: too many arguments\n"), myname); \
53 usage(); \
54 }
55 #define OPTION(flag)\
56 options++; \
57 nargv[nargc++] = flag; \
58 CHECK(nargc, ARGV_MAX); \
59 break
60 #define OPTARG(flag)\
61 nargv[nargc++] = flag; \
62 CHECK(nargc, ARGV_MAX); \
63 if (optarg) {\
64 nargv[nargc++] = optarg; \
65 CHECK(nargc, ARGV_MAX); \
66 }\
67 break
68
69
70 int nrun, ndisks;
71 int maxrun = 8; /* should be based on the machine resources */
72
73 extern char *default_fstype();
74
75 int nargc = 2;
76 int options = 0;
77 int mnt_passno = 0;
78 int exitstat = 0;
79 int verbose = 0;
80 char *nargv[ARGV_MAX];
81 char *myname, *fstype;
82 char *malloc();
83 char vfstab[] = VFSTAB;
84 char pflg = 0, Vflg = 0;
85
86 /*
87 * Keep an idea of the last device arg type as a hint to the
88 * type of the next arg. In the case of mountall, it's very likely
89 * to be the same type and the next entry in the file. This should
90 * help speed vfstab lookups.
91 */
92 enum dev_arg_t { UNKNOWN, SPECIAL, FSCKDEV, MOUNTPT };
93 enum dev_arg_t arg_hint = UNKNOWN;
94
95 static struct devlist {
96 char *name;
97 char *fsname;
98 pid_t pid;
99 struct devlist *nxt;
100 } *newdev(), *getdev();
101
102 /*
103 * private copy vfstab functions
104 */
105 static struct vfstab vfsave = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
106
107 static void usage(void);
108 static void fsck_dopreen(struct devlist **devp, int ndevs);
109 static void waiter(struct devlist **blp, struct devlist **badlist);
110 static void print_badlist(struct devlist *lp);
111 static void startdisk(struct devlist *dp);
112 static void do_exec(char *fstype, char *nargv[]);
113 static void prnt_cmd(FILE *fd, char *fstype);
114 static void vfserror(int flag);
115
116 static int
vfdup(struct vfstab * vp)117 vfdup(struct vfstab *vp)
118 {
119 if (vfsave.vfs_special != NULL) {
120 free(vfsave.vfs_special);
121 vfsave.vfs_special = NULL;
122 }
123 if ((vp->vfs_special != NULL) &&
124 ((vfsave.vfs_special = strdup(vp->vfs_special)) == NULL)) {
125 perror(myname);
126 return (4); /* XXX */
127 }
128
129 if (vfsave.vfs_fsckdev != NULL) {
130 free(vfsave.vfs_fsckdev);
131 vfsave.vfs_fsckdev = NULL;
132 }
133 if ((vp->vfs_fsckdev != NULL) &&
134 ((vfsave.vfs_fsckdev = strdup(vp->vfs_fsckdev)) == NULL)) {
135 perror(myname);
136 return (4); /* XXX */
137 }
138
139 if (vfsave.vfs_mountp != NULL) {
140 free(vfsave.vfs_mountp);
141 vfsave.vfs_mountp = NULL;
142 }
143 if ((vp->vfs_mountp != NULL) &&
144 ((vfsave.vfs_mountp = strdup(vp->vfs_mountp)) == NULL)) {
145 perror(myname);
146 return (4); /* XXX */
147 }
148
149 if (vfsave.vfs_fstype != NULL) {
150 free(vfsave.vfs_fstype);
151 vfsave.vfs_fstype = NULL;
152 }
153 if ((vp->vfs_fstype != NULL) &&
154 ((vfsave.vfs_fstype = strdup(vp->vfs_fstype)) == NULL)) {
155 perror(myname);
156 return (4); /* XXX */
157 }
158
159 if (vfsave.vfs_fsckpass != NULL) {
160 free(vfsave.vfs_fsckpass);
161 vfsave.vfs_fsckpass = NULL;
162 }
163 if ((vp->vfs_fsckpass != NULL) &&
164 ((vfsave.vfs_fsckpass = strdup(vp->vfs_fsckpass)) == NULL)) {
165 perror(myname);
166 return (4); /* XXX */
167 }
168
169 if (vfsave.vfs_automnt != NULL) {
170 free(vfsave.vfs_automnt);
171 vfsave.vfs_automnt = NULL;
172 }
173 if ((vp->vfs_automnt != NULL) &&
174 ((vfsave.vfs_automnt = strdup(vp->vfs_automnt)) == NULL)) {
175 perror(myname);
176 return (4); /* XXX */
177 }
178
179 if (vfsave.vfs_mntopts != NULL) {
180 free(vfsave.vfs_mntopts);
181 vfsave.vfs_mntopts = NULL;
182 }
183 if ((vp->vfs_mntopts != NULL) &&
184 ((vfsave.vfs_mntopts = strdup(vp->vfs_mntopts)) == NULL)) {
185 perror(myname);
186 return (4); /* XXX */
187 }
188
189 *vp = vfsave;
190 return (0);
191 }
192
193 static int
mygetvfsent(FILE * fp,struct vfstab * vp)194 mygetvfsent(FILE *fp, struct vfstab *vp)
195 {
196 int error;
197
198 if ((error = getvfsent(fp, vp)) != 0)
199 return (error);
200 return (vfdup(vp));
201 }
202
203 static int
mygetvfsany(FILE * fp,struct vfstab * vp,struct vfstab * vrefp)204 mygetvfsany(FILE *fp, struct vfstab *vp, struct vfstab *vrefp)
205 {
206 int error;
207
208 if ((error = getvfsany(fp, vp, vrefp)) != 0)
209 return (error);
210 return (vfdup(vp));
211 }
212
213 int
main(int argc,char * argv[])214 main(int argc, char *argv[])
215 {
216 int cc, ret, other_than_ufs = 0;
217 int questflg = 0, Fflg = 0, Vflg = 0, sanity = 0;
218 char *subopt;
219 FILE *fd = NULL;
220 int devfd;
221 struct vfstab vget, vref;
222 struct dk_minfo dkminfo;
223 int preencnt = 0;
224 struct devlist *dp, *devs = NULL;
225 int status;
226 uint_t lbs;
227
228 (void) setlocale(LC_ALL, "");
229 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
230 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
231 #endif
232 (void) textdomain(TEXT_DOMAIN);
233
234 myname = strrchr(argv[0], '/');
235 if (myname)
236 myname++;
237 else
238 myname = argv[0];
239
240 while ((cc = getopt(argc, argv, "?F:mnNo:vVyY")) != -1) {
241 switch (cc) {
242 case '?':
243 questflg++;
244 if (questflg > 1)
245 usage();
246 nargv[nargc++] = "-?";
247 CHECK(nargc, ARGV_MAX);
248 break;
249 case 'F':
250 Fflg++;
251 /* check for more that one -F */
252 if (Fflg > 1) {
253 fprintf(stderr,
254 gettext("%s: more than one fstype specified\n"),
255 myname);
256 usage();
257 }
258 fstype = optarg;
259 if (strlen(fstype) > (size_t)FSTYPE_MAX) {
260 fprintf(stderr,
261 gettext("%s: Fstype %s exceeds %d characters\n"),
262 myname, fstype, FSTYPE_MAX);
263 exit(1);
264 }
265 break;
266 case 'm':
267 sanity++;
268 OPTION("-m");
269 case 'n':
270 OPTION("-n");
271 case 'N':
272 OPTION("-N");
273 case 'o':
274 subopt = optarg;
275 while (*subopt != '\0') {
276 if (*subopt == 'p') {
277 pflg++;
278 break;
279 }
280 subopt++;
281 }
282 OPTARG("-o");
283 case 'v':
284 OPTION("-v");
285 case 'V':
286 Vflg++;
287 if (Vflg > 1)
288 usage();
289 break;
290 case 'y':
291 OPTION("-y");
292 case 'Y':
293 OPTION("-Y");
294 }
295 optarg = NULL;
296 }
297
298 /* copy '--' to specific */
299 if (strcmp(argv[optind-1], "--") == 0) {
300 nargv[nargc++] = argv[optind-1];
301 CHECK(nargc, ARGV_MAX);
302 }
303
304 if (questflg) {
305 if (Fflg) {
306 nargc = 2;
307 nargv[nargc++] = "-?";
308 nargv[nargc] = NULL;
309 do_exec(fstype, nargv);
310 }
311 usage();
312 }
313
314 if ((sanity) && (options > 1)) {
315 usage();
316 }
317
318 if (optind == argc) { /* no device name is specified */
319 if (fstype == NULL) {
320 if ((argc > 2) && (sanity)) {
321 usage();
322 }
323 }
324 /*
325 * Try to check UFS filesystems first, then check other
326 * filesystems if they exist.
327 * Note: Parallel checking is only available in UFS for now.
328 */
329 if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
330 if ((fd = fopen(vfstab, "r")) == NULL) {
331 fprintf(stderr,
332 gettext("%s: cannot open vfstab\n"),
333 myname);
334 exit(1);
335 }
336 while ((ret = mygetvfsent(fd, &vget)) == 0) {
337 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) &&
338 numbers(vget.vfs_fsckpass)) {
339 other_than_ufs ++;
340 continue;
341 }
342 if (numbers(vget.vfs_fsckpass))
343 mnt_passno = atoi(vget.vfs_fsckpass);
344 else
345 continue;
346 if (mnt_passno < 1)
347 continue;
348 if (pflg == 0 || mnt_passno == 1) {
349 status = execute(vget.vfs_fsckdev,
350 MNTTYPE_UFS, Vflg, fd);
351 /* return the highest exit code */
352 if (status > exitstat)
353 exitstat = status;
354 } else if (preen_addev(vget.vfs_fsckdev) == 0) {
355 preencnt++;
356 dp = newdev(&vget);
357 dp->nxt = devs;
358 devs = dp;
359 } else {
360 /*
361 * preening setup failed, so
362 * execute serially here...
363 */
364 fprintf(stderr,
365 gettext("%s: preen_addev error\n"),
366 myname);
367 status = execute(vget.vfs_fsckdev,
368 MNTTYPE_UFS, Vflg, fd);
369 /* return the highest exit code */
370 if (status > exitstat)
371 exitstat = status;
372 }
373 }
374 fclose(fd);
375 if (ret > 0)
376 vfserror(ret);
377 if (pflg && exitstat == 0) {
378 fsck_dopreen(&devs, preencnt);
379 }
380 }
381 else
382 other_than_ufs = 1;
383
384 if (other_than_ufs) {
385 if ((fd = fopen(vfstab, "r")) == NULL) {
386 fprintf(stderr,
387 gettext("%s: cannot open vfstab\n"),
388 myname);
389 exit(1);
390 }
391 while ((ret = mygetvfsent(fd, &vget)) == 0)
392 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) &&
393 numbers(vget.vfs_fsckpass) &&
394 vget.vfs_fsckdev != NULL &&
395 (fstype == NULL ||
396 strcmp(fstype, vget.vfs_fstype) == 0)) {
397 status = execute(vget.vfs_fsckdev,
398 vget.vfs_fstype, Vflg, fd);
399 /* return the highest exit code */
400 if (status > exitstat)
401 exitstat = status;
402 }
403 fclose(fd);
404 if (ret > 0)
405 vfserror(ret);
406 }
407
408 } else { /* device name is specified */
409 if (fstype == NULL && (fd = fopen(vfstab, "r")) == NULL) {
410 fprintf(stderr, gettext("%s: cannot open vfstab\n"),
411 myname);
412 exit(1);
413 }
414
415 while (optind < argc) {
416 /*
417 * If "-F FStype" is specified, use that fs type.
418 * Otherwise, determine the fs type from /etc/vfstab
419 * if the entry exists. Otherwise, determine the
420 * local or remote fs type from /etc/default/df
421 * or /etc/dfs/fstypes respectively.
422 */
423 if (fstype == NULL) {
424 if ((argc > 3) && (sanity)) {
425 usage();
426 }
427 /* must check for both special && raw devices */
428 vfsnull(&vref);
429
430 /*
431 * Find the vfstab entry for this device.
432 * arg_hint tells us what to try to match,
433 * based on the type of the last arg. If
434 * arg_hint equals UNKNOWN, then we're not
435 * sure of the type and need to fallthrough
436 * all 3 possibilities for vfstab lookup.
437 * Try it as a mountpt first, since that's
438 * what mountall gives us.
439 */
440 try_again:
441 switch (arg_hint) {
442 case UNKNOWN:
443 /* FALLTHROUGH */
444
445 case MOUNTPT:
446 vref.vfs_mountp = argv[optind];
447 if ((ret = mygetvfsany(fd, &vget,
448 &vref)) == -1 ||
449 vget.vfs_fstype == NULL) {
450
451 vref.vfs_mountp = NULL;
452 rewind(fd);
453
454 if (arg_hint == MOUNTPT) {
455 arg_hint = UNKNOWN;
456 goto try_again;
457 }
458 /* FALLTHROUGH */
459 } else {
460 /* Found it */
461 if (vget.vfs_fsckdev != NULL) {
462 argv[optind] =
463 vget.vfs_fsckdev;
464 }
465 arg_hint = MOUNTPT;
466 break;
467 }
468
469 case FSCKDEV:
470 vref.vfs_fsckdev = argv[optind];
471
472 /*
473 * Check the media sector size
474 */
475 if (((devfd = open(vref.vfs_fsckdev,
476 O_RDWR)) >= 0) && (ioctl(devfd,
477 DKIOCGMEDIAINFO, &dkminfo) !=
478 -1)) {
479 lbs = dkminfo.dki_lbsize;
480 if (lbs != 0 && ISP2(lbs /
481 DEV_BSIZE) &&
482 lbs != DEV_BSIZE) {
483 fprintf(stderr,
484 gettext("The device"
485 " sector size is"
486 " not supported by"
487 " fsck\n"));
488 (void) close(devfd);
489 exit(1);
490 }
491 }
492
493 if (devfd >= 0) {
494 (void) close(devfd);
495 }
496
497 if ((ret = mygetvfsany(fd, &vget,
498 &vref)) == -1 ||
499 vget.vfs_fstype == NULL) {
500
501 vref.vfs_fsckdev = NULL;
502 rewind(fd);
503
504 if (arg_hint == FSCKDEV) {
505 arg_hint = UNKNOWN;
506 goto try_again;
507 }
508 /* FALLTHROUGH */
509 } else {
510 /* Found it */
511 arg_hint = FSCKDEV;
512 break;
513 }
514
515 case SPECIAL:
516 vref.vfs_special = argv[optind];
517 if ((ret = mygetvfsany(fd, &vget,
518 &vref)) == -1 ||
519 vget.vfs_fstype == NULL) {
520
521 vref.vfs_special = NULL;
522 rewind(fd);
523
524 if (arg_hint == SPECIAL) {
525 arg_hint = UNKNOWN;
526 goto try_again;
527 }
528 /* FALLTHROUGH */
529 } else {
530 /* Found it */
531 arg_hint = SPECIAL;
532 break;
533 }
534 }
535
536 if (ret == 0 && vget.vfs_fstype) {
537 if ((pflg) && (strcmp(vget.vfs_fstype,
538 MNTTYPE_UFS) == 0) && (preen_addev(
539 vget.vfs_fsckdev) == 0)) {
540 preencnt++;
541 dp = newdev(&vget);
542 dp->nxt = devs;
543 devs = dp;
544 } else {
545 status = execute(argv[optind],
546 vget.vfs_fstype, Vflg, fd);
547 if (status > exitstat)
548 exitstat = status;
549 }
550 } else if (ret == -1 ||
551 vget.vfs_fstype == NULL) {
552 fstype =
553 default_fstype(argv[optind]);
554 status = execute(argv[optind], fstype,
555 Vflg, fd);
556 /* return the highest exit code */
557 if (status > exitstat)
558 exitstat = status;
559 } else
560 vfserror(ret);
561 } else {
562 status = execute(argv[optind], fstype,
563 Vflg, NULL);
564 /* return the highest exit code */
565 if (status > exitstat)
566 exitstat = status;
567 }
568 optind++;
569 }
570 if (fd != NULL)
571 fclose(fd);
572 if ((pflg) && (exitstat == 0)) {
573 fsck_dopreen(&devs, preencnt);
574 }
575 }
576 return (exitstat);
577 }
578
579 static void
fsck_dopreen(struct devlist ** devp,int ndevs)580 fsck_dopreen(struct devlist **devp, int ndevs)
581 {
582 char name[1024];
583 int rc;
584 int i;
585 struct devlist *bl, *bdp;
586 struct devlist *badlist;
587
588 bl = badlist = NULL;
589 while (ndevs > 0) {
590 if (nrun > maxrun)
591 waiter(&bl, &badlist);
592 rc = preen_getdev(name);
593 switch (rc) {
594 case 0:
595 break;
596 case 1:
597 bdp = getdev(name, devp);
598 if (bdp == NULL) {
599 fprintf(stderr,
600 gettext("%s: unknown dev: `%s'\n"),
601 myname, name);
602 exit(1);
603 }
604 bdp->nxt = bl;
605 bl = bdp;
606 startdisk(bdp);
607 ndevs--;
608 break;
609 case 2:
610 waiter(&bl, &badlist);
611 break;
612 default:
613 fprintf(stderr,
614 gettext("%s: bad return `%d' from preen_getdev\n"),
615 myname, rc);
616 break;
617 }
618 }
619 while (bl != NULL) {
620 waiter(&bl, &badlist);
621 }
622
623 if (badlist != NULL)
624 print_badlist(badlist);
625 }
626
627 static void
startdisk(struct devlist * dp)628 startdisk(struct devlist *dp)
629 {
630 pid_t pid;
631
632 nrun++;
633 if ((pid = fork()) == -1) {
634 perror("fork");
635 exit(1);
636 } else if (pid == 0) {
637 exitstat = execute(dp->name, MNTTYPE_UFS, Vflg, NULL);
638 exit(exitstat);
639 } else {
640 dp->pid = pid;
641 }
642 }
643
644 static void
waiter(struct devlist ** blp,struct devlist ** badlist)645 waiter(struct devlist **blp, struct devlist **badlist)
646 {
647 pid_t curpid;
648 int status;
649 struct devlist *bdp, *pbdp;
650
651 curpid = wait(&status);
652 if (curpid == -1) {
653 perror("wait");
654 exit(1);
655 }
656
657 for (pbdp = NULL, bdp = *blp; bdp != NULL; pbdp = bdp, bdp = bdp->nxt) {
658 if (bdp->pid == curpid) {
659 break;
660 }
661 }
662 if (bdp == NULL)
663 return;
664 nrun--;
665
666 if (pbdp)
667 pbdp->nxt = bdp->nxt;
668 else
669 *blp = bdp->nxt;
670 preen_releasedev(bdp->name);
671
672 if (WTERMSIG(status)) {
673 printf(gettext("%s (%s): EXITED WITH SIGNAL %d\n"),
674 bdp->name, bdp->fsname, WTERMSIG(status));
675 status = status&0377 | 8<<8;
676 }
677 if (WHIBYTE(status) != 0) {
678 if (WHIBYTE(status) > exitstat)
679 exitstat = WHIBYTE(status);
680 while (*badlist != NULL)
681 badlist = &(*badlist)->nxt;
682 *badlist = bdp;
683 bdp->nxt = NULL;
684 }
685 }
686
687 static void
print_badlist(struct devlist * lp)688 print_badlist(struct devlist *lp)
689 {
690 int x, len;
691
692 printf(
693 gettext("\nTHE FOLLOWING FILE SYSTEM(S) HAD AN UNEXPECTED INCONSISTENCY:"));
694 for (x = 3; lp != NULL; lp = lp->nxt) {
695 len = strlen(lp->name) + strlen(lp->fsname) + 5;
696 x += len;
697 if (x >= 80) {
698 printf("\n ");
699 x = len + 3;
700 } else {
701 printf(" ");
702 }
703 printf("%s (%s)%s", lp->name, lp->fsname,
704 lp->nxt ? "," : "\n");
705 }
706 }
707
708 /*
709 * allocate and initialize a `devlist' structure
710 */
711 static
712 struct devlist *
newdev(struct vfstab * vfsp)713 newdev(struct vfstab *vfsp)
714 {
715 struct devlist *dp;
716 extern char *strdup();
717
718 dp = (struct devlist *)malloc(sizeof (struct devlist));
719 if (dp == NULL) {
720 fprintf(stderr, gettext("%s: out of memory\n"), myname);
721 exit(1);
722 }
723 dp->name = strdup(vfsp->vfs_fsckdev);
724 dp->fsname = strdup(vfsp->vfs_mountp);
725 if (dp->name == NULL || dp->fsname == NULL) {
726 fprintf(stderr, gettext("%s: out of memory\n"), myname);
727 exit(1);
728 }
729 return (dp);
730 }
731
732 /*
733 * locate the devlist structure in the given list that matches `name'.
734 * If found, the structure is removed from the list, and a pointer to
735 * it is returned. If not, NULL is returned.
736 */
737 static
738 struct devlist *
getdev(char * name,struct devlist ** list)739 getdev(char *name, struct devlist **list)
740 {
741 struct devlist *p, *lp;
742
743 for (lp = NULL, p = *list; p != NULL; lp = p, p = p->nxt) {
744 if (strcmp(p->name, name) == 0)
745 break;
746 }
747
748 if (p != NULL) {
749 if (lp != NULL)
750 lp->nxt = p->nxt;
751 else
752 *list = p->nxt;
753 }
754 return (p);
755 }
756
757 /* see if all numbers */
758 int
numbers(char * yp)759 numbers(char *yp)
760 {
761 if (yp == NULL)
762 return (0);
763 while ('0' <= *yp && *yp <= '9')
764 yp++;
765 if (*yp)
766 return (0);
767 return (1);
768 }
769
770 int
execute(char * fsckdev,char * fstype,int Vflg,FILE * fd)771 execute(char *fsckdev, char *fstype, int Vflg, FILE *fd)
772 {
773 int st;
774 pid_t fk;
775 char full_path[PATH_MAX];
776 char *vfs_path = VFS_PATH;
777 int status = 0;
778
779 nargv[nargc] = fsckdev;
780
781 if (Vflg) {
782 prnt_cmd(stdout, fstype);
783 return (0);
784 }
785
786 if (fd)
787 fcntl(fileno(fd), F_SETFD, 1); /* close on exec */
788
789 if ((fk = fork()) == (pid_t)-1) {
790 fprintf(stderr,
791 gettext("%s: cannot fork. Try again later\n"),
792 myname);
793 perror(myname);
794 exit(1);
795 }
796
797 if (fk == 0) {
798 /* Try to exec the fstype dependent portion of the fsck. */
799 do_exec(fstype, nargv);
800 } else {
801 /* parent waits for child */
802 if (wait(&st) == (pid_t)-1) {
803 fprintf(stderr, gettext("%s: bad wait\n"), myname);
804 perror(myname);
805 exit(1);
806 }
807
808 if ((st & 0xff) == 0x7f) {
809 fprintf(stderr,
810 gettext("%s: warning: the following command"
811 " (process %d) was stopped by signal %d\n"),
812 myname, fk, (st >> 8) & 0xff);
813 prnt_cmd(stderr, fstype);
814 status = ((st >> 8) & 0xff) | 0x80;
815 } else if (st & 0xff) {
816 if (st & 0x80)
817 fprintf(stderr,
818 gettext("%s: warning: the following command"
819 " (process %d) was terminated by signal %d"
820 " and dumped core\n"),
821 myname, fk, st & 0x7f);
822 else
823 fprintf(stderr,
824 gettext("%s: warning: the following command"
825 " (process %d) was terminated by signal %d\n"),
826 myname, fk, st & 0x7f);
827
828 prnt_cmd(stderr, fstype);
829 status = ((st & 0xff) | 0x80);
830 } else if (st & 0xff00)
831 status = (st >> 8) & 0xff;
832 }
833
834 return (status);
835 }
836
837 static void
do_exec(char * fstype,char * nargv[])838 do_exec(char *fstype, char *nargv[])
839 {
840 char full_path[PATH_MAX];
841 char *vfs_path = VFS_PATH;
842
843 if (strlen(fstype) > (size_t)FSTYPE_MAX) {
844 fprintf(stderr,
845 gettext("%s: Fstype %s exceeds %d characters\n"),
846 myname, fstype, FSTYPE_MAX);
847 exit(1);
848 }
849 /* build the full pathname of the fstype dependent command. */
850 sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname);
851
852 /* set the new argv[0] to the filename */
853 nargv[1] = myname;
854 /* Try to exec the fstype dependent portion of the fsck. */
855 execv(full_path, &nargv[1]);
856 if (errno == EACCES) {
857 fprintf(stderr,
858 gettext("%s: cannot execute %s - permission denied\n"),
859 myname, full_path);
860 }
861 if (errno == ENOEXEC) {
862 nargv[0] = "sh";
863 nargv[1] = full_path;
864 execv("/sbin/sh", &nargv[0]);
865 }
866 /* second path to try */
867 vfs_path = VFS_PATH2;
868 /* build the full pathname of the fstype dependent command. */
869 sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname);
870
871 /* set the new argv[0] to the filename */
872 nargv[1] = myname;
873 /* Try to exec the second fstype dependent portion of the fsck. */
874 execv(full_path, &nargv[1]);
875 if (errno == EACCES) {
876 fprintf(stderr,
877 gettext("%s: cannot execute %s - permission denied\n"),
878 myname, full_path);
879 exit(1);
880 }
881 if (errno == ENOEXEC) {
882 nargv[0] = "sh";
883 nargv[1] = full_path;
884 execv("/sbin/sh", &nargv[0]);
885 }
886 fprintf(stderr,
887 gettext("%s: operation not applicable to FSType %s\n"),
888 myname, fstype);
889 exit(1);
890 }
891
892 static void
prnt_cmd(FILE * fd,char * fstype)893 prnt_cmd(FILE *fd, char *fstype)
894 {
895 char **argp;
896
897 fprintf(fd, "%s -F %s", myname, fstype);
898 for (argp = &nargv[2]; *argp; argp++)
899 fprintf(fd, " %s", *argp);
900 fprintf(fd, "\n");
901 }
902
903 static void
vfserror(int flag)904 vfserror(int flag)
905 {
906 switch (flag) {
907 case VFS_TOOLONG:
908 fprintf(stderr,
909 gettext("%s: line in vfstab exceeds %d characters\n"),
910 myname, VFS_LINE_MAX-2);
911 break;
912 case VFS_TOOFEW:
913 fprintf(stderr,
914 gettext("%s: line in vfstab has too few entries\n"),
915 myname);
916 break;
917 case VFS_TOOMANY:
918 fprintf(stderr,
919 gettext("%s: line in vfstab has too many entries\n"),
920 myname);
921 break;
922 }
923 exit(1);
924 }
925
926 static void
usage(void)927 usage(void)
928 {
929 fprintf(stderr,
930 gettext("Usage:\n%s [-F FSType] [-V] [-m] [special ...]\n"
931 "%s [-F FSType] [-V] [-y|Y|n|N]"
932 " [-o specific_options] [special ...]\n"),
933 myname, myname);
934
935 exit(1);
936 }
937