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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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