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 2007 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 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <stdio.h> 33 #include <errno.h> 34 #include <limits.h> 35 #include <fcntl.h> 36 #include <string.h> 37 #include <sys/types.h> 38 #include <sys/stat.h> 39 #include <sys/wait.h> 40 #include <sys/vfstab.h> 41 #include <sys/mntent.h> 42 #include <locale.h> 43 #include <libintl.h> 44 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 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 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 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 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 struct vfstab vget, vref; 221 int preencnt = 0; 222 struct devlist *dp, *devs = NULL; 223 int status; 224 225 (void) setlocale(LC_ALL, ""); 226 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 227 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 228 #endif 229 (void) textdomain(TEXT_DOMAIN); 230 231 myname = strrchr(argv[0], '/'); 232 if (myname) 233 myname++; 234 else 235 myname = argv[0]; 236 237 while ((cc = getopt(argc, argv, "?F:mnNo:vVyY")) != -1) { 238 switch (cc) { 239 case '?': 240 questflg++; 241 if (questflg > 1) 242 usage(); 243 nargv[nargc++] = "-?"; 244 CHECK(nargc, ARGV_MAX); 245 break; 246 case 'F': 247 Fflg++; 248 /* check for more that one -F */ 249 if (Fflg > 1) { 250 fprintf(stderr, 251 gettext("%s: more than one fstype specified\n"), 252 myname); 253 usage(); 254 } 255 fstype = optarg; 256 if (strlen(fstype) > (size_t)FSTYPE_MAX) { 257 fprintf(stderr, 258 gettext("%s: Fstype %s exceeds %d characters\n"), 259 myname, fstype, FSTYPE_MAX); 260 exit(1); 261 } 262 break; 263 case 'm': 264 sanity++; 265 OPTION("-m"); 266 case 'n': 267 OPTION("-n"); 268 case 'N': 269 OPTION("-N"); 270 case 'o': 271 subopt = optarg; 272 while (*subopt != '\0') { 273 if (*subopt == 'p') { 274 pflg++; 275 break; 276 } 277 subopt++; 278 } 279 OPTARG("-o"); 280 case 'v': 281 OPTION("-v"); 282 case 'V': 283 Vflg++; 284 if (Vflg > 1) 285 usage(); 286 break; 287 case 'y': 288 OPTION("-y"); 289 case 'Y': 290 OPTION("-Y"); 291 } 292 optarg = NULL; 293 } 294 295 /* copy '--' to specific */ 296 if (strcmp(argv[optind-1], "--") == 0) { 297 nargv[nargc++] = argv[optind-1]; 298 CHECK(nargc, ARGV_MAX); 299 } 300 301 if (questflg) { 302 if (Fflg) { 303 nargc = 2; 304 nargv[nargc++] = "-?"; 305 nargv[nargc] = NULL; 306 do_exec(fstype, nargv); 307 } 308 usage(); 309 } 310 311 if ((sanity) && (options > 1)) { 312 usage(); 313 } 314 315 if (optind == argc) { /* no device name is specified */ 316 if (fstype == NULL) { 317 if ((argc > 2) && (sanity)) { 318 usage(); 319 } 320 } 321 /* 322 * Try to check UFS filesystems first, then check other 323 * filesystems if they exist. 324 * Note: Parallel checking is only available in UFS for now. 325 */ 326 if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) { 327 if ((fd = fopen(vfstab, "r")) == NULL) { 328 fprintf(stderr, 329 gettext("%s: cannot open vfstab\n"), 330 myname); 331 exit(1); 332 } 333 while ((ret = mygetvfsent(fd, &vget)) == 0) { 334 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) && 335 numbers(vget.vfs_fsckpass)) { 336 other_than_ufs ++; 337 continue; 338 } 339 if (numbers(vget.vfs_fsckpass)) 340 mnt_passno = atoi(vget.vfs_fsckpass); 341 else 342 continue; 343 if (mnt_passno < 1) 344 continue; 345 if (pflg == 0 || mnt_passno == 1) { 346 status = execute(vget.vfs_fsckdev, 347 MNTTYPE_UFS, Vflg, fd); 348 /* return the highest exit code */ 349 if (status > exitstat) 350 exitstat = status; 351 } else if (preen_addev(vget.vfs_fsckdev) == 0) { 352 preencnt++; 353 dp = newdev(&vget); 354 dp->nxt = devs; 355 devs = dp; 356 } else { 357 /* 358 * preening setup failed, so 359 * execute serially here... 360 */ 361 fprintf(stderr, 362 gettext("%s: preen_addev error\n"), 363 myname); 364 status = execute(vget.vfs_fsckdev, 365 MNTTYPE_UFS, Vflg, fd); 366 /* return the highest exit code */ 367 if (status > exitstat) 368 exitstat = status; 369 } 370 } 371 fclose(fd); 372 if (ret > 0) 373 vfserror(ret); 374 if (pflg && exitstat == 0) { 375 fsck_dopreen(&devs, preencnt); 376 } 377 } 378 else 379 other_than_ufs = 1; 380 381 if (other_than_ufs) { 382 if ((fd = fopen(vfstab, "r")) == NULL) { 383 fprintf(stderr, 384 gettext("%s: cannot open vfstab\n"), 385 myname); 386 exit(1); 387 } 388 while ((ret = mygetvfsent(fd, &vget)) == 0) 389 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) && 390 numbers(vget.vfs_fsckpass) && 391 vget.vfs_fsckdev != NULL && 392 (fstype == NULL || 393 strcmp(fstype, vget.vfs_fstype) == 0)) { 394 status = execute(vget.vfs_fsckdev, 395 vget.vfs_fstype, Vflg, fd); 396 /* return the highest exit code */ 397 if (status > exitstat) 398 exitstat = status; 399 } 400 fclose(fd); 401 if (ret > 0) 402 vfserror(ret); 403 } 404 405 } else { /* device name is specified */ 406 if (fstype == NULL && (fd = fopen(vfstab, "r")) == NULL) { 407 fprintf(stderr, gettext("%s: cannot open vfstab\n"), 408 myname); 409 exit(1); 410 } 411 while (optind < argc) { 412 /* 413 * If "-F FStype" is specified, use that fs type. 414 * Otherwise, determine the fs type from /etc/vfstab 415 * if the entry exists. Otherwise, determine the 416 * local or remote fs type from /etc/default/df 417 * or /etc/dfs/fstypes respectively. 418 */ 419 if (fstype == NULL) { 420 if ((argc > 3) && (sanity)) { 421 usage(); 422 } 423 /* must check for both special && raw devices */ 424 vfsnull(&vref); 425 426 /* 427 * Find the vfstab entry for this device. 428 * arg_hint tells us what to try to match, 429 * based on the type of the last arg. If 430 * arg_hint equals UNKNOWN, then we're not 431 * sure of the type and need to fallthrough 432 * all 3 possibilities for vfstab lookup. 433 * Try it as a mountpt first, since that's 434 * what mountall gives us. 435 */ 436 try_again: 437 switch (arg_hint) { 438 case UNKNOWN: 439 /* FALLTHROUGH */ 440 441 case MOUNTPT: 442 vref.vfs_mountp = argv[optind]; 443 if ((ret = mygetvfsany(fd, &vget, 444 &vref)) == -1 || 445 vget.vfs_fstype == NULL) { 446 447 vref.vfs_mountp = NULL; 448 rewind(fd); 449 450 if (arg_hint == MOUNTPT) { 451 arg_hint = UNKNOWN; 452 goto try_again; 453 } 454 /* FALLTHROUGH */ 455 } else { 456 /* Found it */ 457 if (vget.vfs_fsckdev != NULL) { 458 argv[optind] = 459 vget.vfs_fsckdev; 460 } 461 arg_hint = MOUNTPT; 462 break; 463 } 464 465 case FSCKDEV: 466 vref.vfs_fsckdev = argv[optind]; 467 if ((ret = mygetvfsany(fd, &vget, 468 &vref)) == -1 || 469 vget.vfs_fstype == NULL) { 470 471 vref.vfs_fsckdev = NULL; 472 rewind(fd); 473 474 if (arg_hint == FSCKDEV) { 475 arg_hint = UNKNOWN; 476 goto try_again; 477 } 478 /* FALLTHROUGH */ 479 } else { 480 /* Found it */ 481 arg_hint = FSCKDEV; 482 break; 483 } 484 485 case SPECIAL: 486 vref.vfs_special = argv[optind]; 487 if ((ret = mygetvfsany(fd, &vget, 488 &vref)) == -1 || 489 vget.vfs_fstype == NULL) { 490 491 vref.vfs_special = NULL; 492 rewind(fd); 493 494 if (arg_hint == SPECIAL) { 495 arg_hint = UNKNOWN; 496 goto try_again; 497 } 498 /* FALLTHROUGH */ 499 } else { 500 /* Found it */ 501 arg_hint = SPECIAL; 502 break; 503 } 504 } 505 506 if (ret == 0 && vget.vfs_fstype) { 507 if ((pflg) && (strcmp(vget.vfs_fstype, 508 MNTTYPE_UFS) == 0) && (preen_addev( 509 vget.vfs_fsckdev) == 0)) { 510 preencnt++; 511 dp = newdev(&vget); 512 dp->nxt = devs; 513 devs = dp; 514 } else { 515 status = execute(argv[optind], 516 vget.vfs_fstype, Vflg, fd); 517 if (status > exitstat) 518 exitstat = status; 519 } 520 } else if (ret == -1 || 521 vget.vfs_fstype == NULL) { 522 fstype = 523 default_fstype(argv[optind]); 524 status = execute(argv[optind], fstype, 525 Vflg, fd); 526 /* return the highest exit code */ 527 if (status > exitstat) 528 exitstat = status; 529 } else 530 vfserror(ret); 531 } else { 532 status = execute(argv[optind], fstype, 533 Vflg, NULL); 534 /* return the highest exit code */ 535 if (status > exitstat) 536 exitstat = status; 537 } 538 optind++; 539 } 540 if (fd != NULL) 541 fclose(fd); 542 if ((pflg) && (exitstat == 0)) { 543 fsck_dopreen(&devs, preencnt); 544 } 545 } 546 return (exitstat); 547 } 548 549 static void 550 fsck_dopreen(struct devlist **devp, int ndevs) 551 { 552 char name[1024]; 553 int rc; 554 int i; 555 struct devlist *bl, *bdp; 556 struct devlist *badlist; 557 558 bl = badlist = NULL; 559 while (ndevs > 0) { 560 if (nrun > maxrun) 561 waiter(&bl, &badlist); 562 rc = preen_getdev(name); 563 switch (rc) { 564 case 0: 565 break; 566 case 1: 567 bdp = getdev(name, devp); 568 if (bdp == NULL) { 569 fprintf(stderr, 570 gettext("%s: unknown dev: `%s'\n"), 571 myname, name); 572 exit(1); 573 } 574 bdp->nxt = bl; 575 bl = bdp; 576 startdisk(bdp); 577 ndevs--; 578 break; 579 case 2: 580 waiter(&bl, &badlist); 581 break; 582 default: 583 fprintf(stderr, 584 gettext("%s: bad return `%d' from preen_getdev\n"), 585 myname, rc); 586 break; 587 } 588 } 589 while (bl != NULL) { 590 waiter(&bl, &badlist); 591 } 592 593 if (badlist != NULL) 594 print_badlist(badlist); 595 } 596 597 static void 598 startdisk(struct devlist *dp) 599 { 600 pid_t pid; 601 602 nrun++; 603 if ((pid = fork()) == -1) { 604 perror("fork"); 605 exit(1); 606 } else if (pid == 0) { 607 exitstat = execute(dp->name, MNTTYPE_UFS, Vflg, NULL); 608 exit(exitstat); 609 } else { 610 dp->pid = pid; 611 } 612 } 613 614 static void 615 waiter(struct devlist **blp, struct devlist **badlist) 616 { 617 pid_t curpid; 618 int status; 619 struct devlist *bdp, *pbdp; 620 621 curpid = wait(&status); 622 if (curpid == -1) { 623 perror("wait"); 624 exit(1); 625 } 626 627 for (pbdp = NULL, bdp = *blp; bdp != NULL; pbdp = bdp, bdp = bdp->nxt) { 628 if (bdp->pid == curpid) { 629 break; 630 } 631 } 632 if (bdp == NULL) 633 return; 634 nrun--; 635 636 if (pbdp) 637 pbdp->nxt = bdp->nxt; 638 else 639 *blp = bdp->nxt; 640 preen_releasedev(bdp->name); 641 642 if (WTERMSIG(status)) { 643 printf(gettext("%s (%s): EXITED WITH SIGNAL %d\n"), 644 bdp->name, bdp->fsname, WTERMSIG(status)); 645 status = status&0377 | 8<<8; 646 } 647 if (WHIBYTE(status) != 0) { 648 if (WHIBYTE(status) > exitstat) 649 exitstat = WHIBYTE(status); 650 while (*badlist != NULL) 651 badlist = &(*badlist)->nxt; 652 *badlist = bdp; 653 bdp->nxt = NULL; 654 } 655 } 656 657 static void 658 print_badlist(struct devlist *lp) 659 { 660 int x, len; 661 662 printf( 663 gettext("\nTHE FOLLOWING FILE SYSTEM(S) HAD AN UNEXPECTED INCONSISTENCY:")); 664 for (x = 3; lp != NULL; lp = lp->nxt) { 665 len = strlen(lp->name) + strlen(lp->fsname) + 5; 666 x += len; 667 if (x >= 80) { 668 printf("\n "); 669 x = len + 3; 670 } else { 671 printf(" "); 672 } 673 printf("%s (%s)%s", lp->name, lp->fsname, 674 lp->nxt ? "," : "\n"); 675 } 676 } 677 678 /* 679 * allocate and initialize a `devlist' structure 680 */ 681 static 682 struct devlist * 683 newdev(struct vfstab *vfsp) 684 { 685 struct devlist *dp; 686 extern char *strdup(); 687 688 dp = (struct devlist *)malloc(sizeof (struct devlist)); 689 if (dp == NULL) { 690 fprintf(stderr, gettext("%s: out of memory\n"), myname); 691 exit(1); 692 } 693 dp->name = strdup(vfsp->vfs_fsckdev); 694 dp->fsname = strdup(vfsp->vfs_mountp); 695 if (dp->name == NULL || dp->fsname == NULL) { 696 fprintf(stderr, gettext("%s: out of memory\n"), myname); 697 exit(1); 698 } 699 return (dp); 700 } 701 702 /* 703 * locate the devlist structure in the given list that matches `name'. 704 * If found, the structure is removed from the list, and a pointer to 705 * it is returned. If not, NULL is returned. 706 */ 707 static 708 struct devlist * 709 getdev(char *name, struct devlist **list) 710 { 711 struct devlist *p, *lp; 712 713 for (lp = NULL, p = *list; p != NULL; lp = p, p = p->nxt) { 714 if (strcmp(p->name, name) == 0) 715 break; 716 } 717 718 if (p != NULL) { 719 if (lp != NULL) 720 lp->nxt = p->nxt; 721 else 722 *list = p->nxt; 723 } 724 return (p); 725 } 726 727 /* see if all numbers */ 728 int 729 numbers(char *yp) 730 { 731 if (yp == NULL) 732 return (0); 733 while ('0' <= *yp && *yp <= '9') 734 yp++; 735 if (*yp) 736 return (0); 737 return (1); 738 } 739 740 int 741 execute(char *fsckdev, char *fstype, int Vflg, FILE *fd) 742 { 743 int st; 744 pid_t fk; 745 char full_path[PATH_MAX]; 746 char *vfs_path = VFS_PATH; 747 int status = 0; 748 749 nargv[nargc] = fsckdev; 750 751 if (Vflg) { 752 prnt_cmd(stdout, fstype); 753 return (0); 754 } 755 756 if (fd) 757 fcntl(fileno(fd), F_SETFD, 1); /* close on exec */ 758 759 if ((fk = fork()) == (pid_t)-1) { 760 fprintf(stderr, 761 gettext("%s: cannot fork. Try again later\n"), 762 myname); 763 perror(myname); 764 exit(1); 765 } 766 767 if (fk == 0) { 768 /* Try to exec the fstype dependent portion of the fsck. */ 769 do_exec(fstype, nargv); 770 } else { 771 /* parent waits for child */ 772 if (wait(&st) == (pid_t)-1) { 773 fprintf(stderr, gettext("%s: bad wait\n"), myname); 774 perror(myname); 775 exit(1); 776 } 777 778 if ((st & 0xff) == 0x7f) { 779 fprintf(stderr, 780 gettext("%s: warning: the following command" 781 " (process %d) was stopped by signal %d\n"), 782 myname, fk, (st >> 8) & 0xff); 783 prnt_cmd(stderr, fstype); 784 status = ((st >> 8) & 0xff) | 0x80; 785 } else if (st & 0xff) { 786 if (st & 0x80) 787 fprintf(stderr, 788 gettext("%s: warning: the following command" 789 " (process %d) was terminated by signal %d" 790 " and dumped core\n"), 791 myname, fk, st & 0x7f); 792 else 793 fprintf(stderr, 794 gettext("%s: warning: the following command" 795 " (process %d) was terminated by signal %d\n"), 796 myname, fk, st & 0x7f); 797 798 prnt_cmd(stderr, fstype); 799 status = ((st & 0xff) | 0x80); 800 } else if (st & 0xff00) 801 status = (st >> 8) & 0xff; 802 } 803 804 return (status); 805 } 806 807 static void 808 do_exec(char *fstype, char *nargv[]) 809 { 810 char full_path[PATH_MAX]; 811 char *vfs_path = VFS_PATH; 812 813 if (strlen(fstype) > (size_t)FSTYPE_MAX) { 814 fprintf(stderr, 815 gettext("%s: Fstype %s exceeds %d characters\n"), 816 myname, fstype, FSTYPE_MAX); 817 exit(1); 818 } 819 /* build the full pathname of the fstype dependent command. */ 820 sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname); 821 822 /* set the new argv[0] to the filename */ 823 nargv[1] = myname; 824 /* Try to exec the fstype dependent portion of the fsck. */ 825 execv(full_path, &nargv[1]); 826 if (errno == EACCES) { 827 fprintf(stderr, 828 gettext("%s: cannot execute %s - permission denied\n"), 829 myname, full_path); 830 } 831 if (errno == ENOEXEC) { 832 nargv[0] = "sh"; 833 nargv[1] = full_path; 834 execv("/sbin/sh", &nargv[0]); 835 } 836 /* second path to try */ 837 vfs_path = VFS_PATH2; 838 /* build the full pathname of the fstype dependent command. */ 839 sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname); 840 841 /* set the new argv[0] to the filename */ 842 nargv[1] = myname; 843 /* Try to exec the second fstype dependent portion of the fsck. */ 844 execv(full_path, &nargv[1]); 845 if (errno == EACCES) { 846 fprintf(stderr, 847 gettext("%s: cannot execute %s - permission denied\n"), 848 myname, full_path); 849 exit(1); 850 } 851 if (errno == ENOEXEC) { 852 nargv[0] = "sh"; 853 nargv[1] = full_path; 854 execv("/sbin/sh", &nargv[0]); 855 } 856 fprintf(stderr, 857 gettext("%s: operation not applicable to FSType %s\n"), 858 myname, fstype); 859 exit(1); 860 } 861 862 static void 863 prnt_cmd(FILE *fd, char *fstype) 864 { 865 char **argp; 866 867 fprintf(fd, "%s -F %s", myname, fstype); 868 for (argp = &nargv[2]; *argp; argp++) 869 fprintf(fd, " %s", *argp); 870 fprintf(fd, "\n"); 871 } 872 873 static void 874 vfserror(int flag) 875 { 876 switch (flag) { 877 case VFS_TOOLONG: 878 fprintf(stderr, 879 gettext("%s: line in vfstab exceeds %d characters\n"), 880 myname, VFS_LINE_MAX-2); 881 break; 882 case VFS_TOOFEW: 883 fprintf(stderr, 884 gettext("%s: line in vfstab has too few entries\n"), 885 myname); 886 break; 887 case VFS_TOOMANY: 888 fprintf(stderr, 889 gettext("%s: line in vfstab has too many entries\n"), 890 myname); 891 break; 892 } 893 exit(1); 894 } 895 896 static void 897 usage(void) 898 { 899 fprintf(stderr, 900 gettext("Usage:\n%s [-F FSType] [-V] [-m] [special ...]\n" 901 "%s [-F FSType] [-V] [-y|Y|n|N]" 902 " [-o specific_options] [special ...]\n"), 903 myname, myname); 904 905 exit(1); 906 } 907