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