fsck.c revision d9c56d3ca0bee11e3446ff7e12e3124d28e298a7
1/* 2 * pfsck --- A generic, parallelizing front-end for the fsck program. 3 * It will automatically try to run fsck programs in parallel if the 4 * devices are on separate spindles. It is based on the same ideas as 5 * the generic front end for fsck by David Engel and Fred van Kempen, 6 * but it has been completely rewritten from scratch to support 7 * parallel execution. 8 * 9 * Written by Theodore Ts'o, <tytso@mit.edu> 10 * 11 * Usage: fsck [-ACVRNTM] [-s] [-t fstype] [fs-options] device 12 * 13 * Miquel van Smoorenburg (miquels@drinkel.ow.org) 20-Oct-1994: 14 * o Changed -t fstype to behave like with mount when -A (all file 15 * systems) or -M (like mount) is specified. 16 * o fsck looks if it can find the fsck.type program to decide 17 * if it should ignore the fs type. This way more fsck programs 18 * can be added without changing this front-end. 19 * o -R flag skip root file system. 20 * 21 * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o. 22 * 23 * %Begin-Header% 24 * This file may be redistributed under the terms of the GNU Public 25 * License. 26 * %End-Header% 27 */ 28 29#include <sys/types.h> 30#include <sys/wait.h> 31#include <sys/signal.h> 32#include <sys/stat.h> 33#include <limits.h> 34#include <stdio.h> 35#include <ctype.h> 36#include <string.h> 37#include <time.h> 38#if HAVE_STDLIB_H 39#include <stdlib.h> 40#endif 41#if HAVE_ERRNO_H 42#include <errno.h> 43#endif 44#if HAVE_PATHS_H 45#include <paths.h> 46#endif 47#if HAVE_UNISTD_H 48#include <unistd.h> 49#endif 50#if HAVE_ERRNO_H 51#include <errno.h> 52#endif 53#include <malloc.h> 54 55#include "../version.h" 56#include "nls-enable.h" 57#include "fsck.h" 58#include "get_device_by_label.h" 59 60#ifndef _PATH_MNTTAB 61#define _PATH_MNTTAB "/etc/fstab" 62#endif 63 64static const char *ignored_types[] = { 65 "ignore", 66 "iso9660", 67 "nfs", 68 "proc", 69 "sw", 70 "swap", 71 NULL 72}; 73 74static const char *really_wanted[] = { 75 "minix", 76 "ext2", 77 "xiafs", 78 NULL 79}; 80 81#ifdef DEV_DSK_DEVICES 82static const char *base_devices[] = { 83 "/dev/dsk/hda", 84 "/dev/dsk/hdb", 85 "/dev/dsk/hdc", 86 "/dev/dsk/hdd", 87 "/dev/dsk/hd1a", 88 "/dev/dsk/hd1b", 89 "/dev/dsk/hd1c", 90 "/dev/dsk/hd1d", 91 "/dev/dsk/sda", 92 "/dev/dsk/sdb", 93 "/dev/dsk/sdc", 94 "/dev/dsk/sdd", 95 "/dev/dsk/sde", 96 "/dev/dsk/sdf", 97 "/dev/dsk/sdg", 98 NULL 99}; 100#else 101static const char *base_devices[] = { 102 "/dev/hda", 103 "/dev/hdb", 104 "/dev/hdc", 105 "/dev/hdd", 106 "/dev/hd1a", 107 "/dev/hd1b", 108 "/dev/hd1c", 109 "/dev/hd1d", 110 "/dev/sda", 111 "/dev/sdb", 112 "/dev/sdc", 113 "/dev/sdd", 114 "/dev/sde", 115 "/dev/sdf", 116 "/dev/sdg", 117 NULL 118}; 119#endif 120 121/* 122 * Global variables for options 123 */ 124char *devices[MAX_DEVICES]; 125char *args[MAX_ARGS]; 126int num_devices, num_args; 127 128int verbose = 0; 129int doall = 0; 130int noexecute = 0; 131int serialize = 0; 132int skip_root = 0; 133int like_mount = 0; 134int notitle = 0; 135int parallel_root = 0; 136int progress = 0; 137int force_all_parallel = 0; 138char *progname; 139char *fstype = NULL; 140struct fs_info *filesys_info; 141struct fsck_instance *instance_list; 142const char *fsck_prefix_path = "/sbin:/sbin/fs.d:/sbin/fs:/etc/fs:/etc"; 143char *fsck_path = 0; 144static int ignore(struct fs_info *); 145 146static char *string_copy(const char *s) 147{ 148 char *ret; 149 150 ret = malloc(strlen(s)+1); 151 if (ret) 152 strcpy(ret, s); 153 return ret; 154} 155 156static char *skip_over_blank(char *cp) 157{ 158 while (*cp && isspace(*cp)) 159 cp++; 160 return cp; 161} 162 163static char *skip_over_word(char *cp) 164{ 165 while (*cp && !isspace(*cp)) 166 cp++; 167 return cp; 168} 169 170static void strip_line(char *line) 171{ 172 char *p; 173 174 while (*line) { 175 p = line + strlen(line) - 1; 176 if ((*p == '\n') || (*p == '\r')) 177 *p = 0; 178 else 179 break; 180 } 181} 182 183static char *parse_word(char **buf) 184{ 185 char *word, *next; 186 187 word = *buf; 188 if (*word == 0) 189 return 0; 190 191 word = skip_over_blank(word); 192 next = skip_over_word(word); 193 if (*next) 194 *next++ = 0; 195 *buf = next; 196 return word; 197} 198 199static void free_instance(struct fsck_instance *i) 200{ 201 if (i->prog) 202 free(i->prog); 203 if (i->device) 204 free(i->device); 205 free(i); 206 return; 207} 208 209static int parse_fstab_line(char *line, struct fs_info **ret_fs) 210{ 211 char *device, *mntpnt, *type, *opts, *freq, *passno, *cp; 212 struct fs_info *fs; 213 214 *ret_fs = 0; 215 strip_line(line); 216 if ((cp = strchr(line, '#'))) 217 *cp = 0; /* Ignore everything after the comment char */ 218 cp = line; 219 220 device = parse_word(&cp); 221 mntpnt = parse_word(&cp); 222 type = parse_word(&cp); 223 opts = parse_word(&cp); 224 freq = parse_word(&cp); 225 passno = parse_word(&cp); 226 227 if (!device) 228 return 0; /* Allow blank lines */ 229 230 if (!mntpnt || !type) 231 return -1; 232 233 if (!(fs = malloc(sizeof(struct fs_info)))) 234 return -1; 235 236 fs->device = string_copy(device); 237 fs->mountpt = string_copy(mntpnt); 238 fs->type = string_copy(type); 239 fs->opts = string_copy(opts ? opts : ""); 240 fs->freq = freq ? atoi(freq) : -1; 241 fs->passno = passno ? atoi(passno) : -1; 242 fs->flags = 0; 243 fs->next = NULL; 244 245 *ret_fs = fs; 246 247 return 0; 248} 249 250/* 251 * Interpret the device name if necessary 252 */ 253static char *interpret_device(char *spec) 254{ 255 char *dev = NULL; 256 257 if (!strncmp(spec, "UUID=", 5)) 258 dev = get_spec_by_uuid(spec+5); 259 else if (!strncmp(spec, "LABEL=", 6)) 260 dev = get_spec_by_volume_label(spec+6); 261 else 262 return spec; 263 if (dev) { 264 free(spec); 265 return (dev); 266 } 267 /* 268 * Check to see if this was because /proc/partitions isn't 269 * found. 270 */ 271 if (access("/proc/partitions", R_OK) < 0) { 272 fprintf(stderr, "Couldn't open /proc/partitions: %s\n", 273 strerror(errno)); 274 fprintf(stderr, "Is /proc mounted?\n"); 275 exit(1); 276 } 277 return spec; 278} 279 280/* 281 * Load the filesystem database from /etc/fstab 282 */ 283static void load_fs_info(const char *filename) 284{ 285 FILE *f; 286 char buf[1024]; 287 int lineno = 0; 288 int old_fstab = 1; 289 struct fs_info *fs, *fs_last = NULL; 290 291 filesys_info = NULL; 292 if ((f = fopen(filename, "r")) == NULL) { 293 fprintf(stderr, _("WARNING: couldn't open %s: %s\n"), 294 filename, strerror(errno)); 295 return; 296 } 297 while (!feof(f)) { 298 lineno++; 299 if (!fgets(buf, sizeof(buf), f)) 300 break; 301 buf[sizeof(buf)-1] = 0; 302 if (parse_fstab_line(buf, &fs) < 0) { 303 fprintf(stderr, _("WARNING: bad format " 304 "on line %d of %s\n"), lineno, filename); 305 continue; 306 } 307 if (!fs) 308 continue; 309 fs->device = interpret_device(fs->device); 310 if (!filesys_info) 311 filesys_info = fs; 312 else 313 fs_last->next = fs; 314 fs_last = fs; 315 if (fs->passno < 0) 316 fs->passno = 0; 317 else 318 old_fstab = 0; 319 } 320 321 fclose(f); 322 323 if (old_fstab) { 324 fprintf(stderr, _("\007\007\007" 325 "WARNING: Your /etc/fstab does not contain the fsck passno\n" 326 " field. I will kludge around things for you, but you\n" 327 " should fix your /etc/fstab file as soon as you can.\n\n")); 328 329 for (fs = filesys_info; fs; fs = fs->next) { 330 fs->passno = 1; 331 } 332 } 333} 334 335/* Lookup filesys in /etc/fstab and return the corresponding entry. */ 336static struct fs_info *lookup(char *filesys) 337{ 338 struct fs_info *fs; 339 340 /* No filesys name given. */ 341 if (filesys == NULL) 342 return NULL; 343 344 for (fs = filesys_info; fs; fs = fs->next) { 345 if (!strcmp(filesys, fs->device) || 346 !strcmp(filesys, fs->mountpt)) 347 break; 348 } 349 350 return fs; 351} 352 353/* Find fsck program for a given fs type. */ 354static char *find_fsck(char *type) 355{ 356 char *s; 357 const char *tpl; 358 static char prog[256]; 359 char *p = string_copy(fsck_path); 360 struct stat st; 361 362 /* Are we looking for a program or just a type? */ 363 tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s"); 364 365 for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) { 366 sprintf(prog, tpl, s, type); 367 if (stat(prog, &st) == 0) break; 368 } 369 free(p); 370 return(s ? prog : NULL); 371} 372 373static int progress_active(NOARGS) 374{ 375 struct fsck_instance *inst; 376 377 for (inst = instance_list; inst; inst = inst->next) { 378 if (inst->flags & FLAG_DONE) 379 continue; 380 if (inst->flags & FLAG_PROGRESS) 381 return 1; 382 } 383 return 0; 384} 385 386/* 387 * Execute a particular fsck program, and link it into the list of 388 * child processes we are waiting for. 389 */ 390static int execute(const char *type, char *device, char *mntpt, 391 int interactive) 392{ 393 char *s, *argv[80], prog[80]; 394 int argc, i; 395 struct fsck_instance *inst, *p; 396 pid_t pid; 397 398 inst = malloc(sizeof(struct fsck_instance)); 399 if (!inst) 400 return ENOMEM; 401 memset(inst, 0, sizeof(struct fsck_instance)); 402 403 sprintf(prog, "fsck.%s", type); 404 argv[0] = string_copy(prog); 405 argc = 1; 406 407 for (i=0; i <num_args; i++) 408 argv[argc++] = string_copy(args[i]); 409 410 if (progress & !progress_active()) { 411 if (strcmp(type, "ext2") == 0) { 412 argv[argc++] = string_copy("-C0"); 413 inst->flags |= FLAG_PROGRESS; 414 } 415 } 416 417 argv[argc++] = string_copy(device); 418 argv[argc] = 0; 419 420 s = find_fsck(prog); 421 if (s == NULL) { 422 fprintf(stderr, _("fsck: %s: not found\n"), prog); 423 return ENOENT; 424 } 425 426 if (verbose || noexecute) { 427 printf("[%s -- %s] ", s, mntpt ? mntpt : device); 428 for (i=0; i < argc; i++) 429 printf("%s ", argv[i]); 430 printf("\n"); 431 } 432 433 /* Fork and execute the correct program. */ 434 if (noexecute) 435 pid = -1; 436 else if ((pid = fork()) < 0) { 437 perror("fork"); 438 return errno; 439 } else if (pid == 0) { 440 if (!interactive) 441 close(0); 442 (void) execv(s, argv); 443 perror(argv[0]); 444 exit(EXIT_ERROR); 445 } 446 447 for (i=0; i < argc; i++) 448 free(argv[i]); 449 450 inst->pid = pid; 451 inst->prog = string_copy(prog); 452 inst->type = string_copy(type); 453 inst->device = string_copy(device); 454 inst->start_time = time(0); 455 inst->next = NULL; 456 457 /* 458 * Find the end of the list, so we add the instance on at the end. 459 */ 460 for (p = instance_list; p && p->next; p = p->next); 461 462 if (p) 463 p->next = inst; 464 else 465 instance_list = inst; 466 467 return 0; 468} 469 470/* 471 * Wait for one child process to exit; when it does, unlink it from 472 * the list of executing child processes, and return it. 473 */ 474static struct fsck_instance *wait_one(NOARGS) 475{ 476 int status; 477 int sig; 478 struct fsck_instance *inst, *inst2, *prev; 479 pid_t pid; 480 481 if (!instance_list) 482 return NULL; 483 484 if (noexecute) { 485 inst = instance_list; 486 instance_list = inst->next; 487 inst->exit_status = 0; 488 return(inst); 489 } 490 491 /* 492 * gcc -Wall fails saving throw against stupidity 493 * (inst and prev are thought to be uninitialized variables) 494 */ 495 inst = prev = NULL; 496 497 do { 498 pid = wait(&status); 499 if (pid < 0) { 500 if ((errno == EINTR) || (errno == EAGAIN)) 501 continue; 502 if (errno == ECHILD) { 503 fprintf(stderr, 504 _("%s: wait: No more child process?!?\n"), 505 progname); 506 return NULL; 507 } 508 perror("wait"); 509 continue; 510 } 511 for (prev = 0, inst = instance_list; 512 inst; 513 prev = inst, inst = inst->next) { 514 if (inst->pid == pid) 515 break; 516 } 517 } while (!inst); 518 519 if (WIFEXITED(status)) 520 status = WEXITSTATUS(status); 521 else if (WIFSIGNALED(status)) { 522 sig = WTERMSIG(status); 523 if (sig == SIGINT) { 524 status = EXIT_UNCORRECTED; 525 } else { 526 printf(_("Warning... %s for device %s exited " 527 "with signal %d.\n"), 528 inst->prog, inst->device, sig); 529 status = EXIT_ERROR; 530 } 531 } else { 532 printf(_("%s %s: status is %x, should never happen.\n"), 533 inst->prog, inst->device, status); 534 status = EXIT_ERROR; 535 } 536 inst->exit_status = status; 537 if (prev) 538 prev->next = inst->next; 539 else 540 instance_list = inst->next; 541 if (progress && (inst->flags & FLAG_PROGRESS) && 542 !progress_active()) { 543 for (inst2 = instance_list; inst2; inst2 = inst2->next) { 544 if (inst2->flags & FLAG_DONE) 545 continue; 546 if (strcmp(inst2->type, "ext2")) 547 continue; 548 /* 549 * If we've just started the fsck, wait a tiny 550 * bit before sending the kill, to give it 551 * time to set up the signal handler 552 */ 553 if (inst2->start_time < time(0)+2) { 554 if (fork() == 0) { 555 sleep(1); 556 kill(inst2->pid, SIGUSR1); 557 exit(0); 558 } 559 } else 560 kill(inst2->pid, SIGUSR1); 561 break; 562 } 563 } 564 return inst; 565} 566 567/* 568 * Wait until all executing child processes have exited; return the 569 * logical OR of all of their exit code values. 570 */ 571static int wait_all(NOARGS) 572{ 573 struct fsck_instance *inst; 574 int global_status = 0; 575 576 while (instance_list) { 577 inst = wait_one(); 578 if (!inst) 579 break; 580 global_status |= inst->exit_status; 581 free_instance(inst); 582 } 583 return global_status; 584} 585 586/* 587 * Run the fsck program on a particular device 588 * 589 * If the type is specified using -t, and it isn't prefixed with "no" 590 * (as in "noext2") and only one filesystem type is specified, then 591 * use that type regardless of what is specified in /etc/fstab. 592 * 593 * If the type isn't specified by the user, then use either the type 594 * specified in /etc/fstab, or DEFAULT_FSTYPE. 595 */ 596static void fsck_device(char *device, int interactive) 597{ 598 const char *type = 0; 599 struct fs_info *fsent; 600 int retval; 601 602 if (fstype && strncmp(fstype, "no", 2) && !strchr(fstype, ',')) 603 type = fstype; 604 605 if ((fsent = lookup(device))) { 606 device = fsent->device; 607 if (!type) 608 type = fsent->type; 609 } 610 if (!type) 611 type = DEFAULT_FSTYPE; 612 613 retval = execute(type, device, fsent ? fsent->mountpt : 0, 614 interactive); 615 if (retval) { 616 fprintf(stderr, _("%s: Error %d while executing fsck.%s " 617 "for %s\n"), progname, retval, type, device); 618 } 619} 620 621/* See if filesystem type matches the list. */ 622static int fs_match(char *type, char *fs_type) 623{ 624 int ret = 0, negate = 0; 625 char list[128]; 626 char *s; 627 628 if (!fs_type) return(1); 629 630 if (strncmp(fs_type, "no", 2) == 0) { 631 fs_type += 2; 632 negate = 1; 633 } 634 strcpy(list, fs_type); 635 s = strtok(list, ","); 636 while(s) { 637 if (strcmp(s, type) == 0) { 638 ret = 1; 639 break; 640 } 641 s = strtok(NULL, ","); 642 } 643 return(negate ? !ret : ret); 644} 645 646 647/* Check if we should ignore this filesystem. */ 648static int ignore(struct fs_info *fs) 649{ 650 const char **ip; 651 int wanted = 0; 652 653 /* 654 * If the pass number is 0, ignore it. 655 */ 656 if (fs->passno == 0) 657 return 1; 658 659 /* 660 * If a specific fstype is specified, and it doesn't match, 661 * ignore it. 662 */ 663 if (!fs_match(fs->type, fstype)) return 1; 664 665 /* Are we ignoring this type? */ 666 for(ip = ignored_types; *ip; ip++) 667 if (strcmp(fs->type, *ip) == 0) return(1); 668 669 /* Do we really really want to check this fs? */ 670 for(ip = really_wanted; *ip; ip++) 671 if (strcmp(fs->type, *ip) == 0) { 672 wanted = 1; 673 break; 674 } 675 676 /* See if the <fsck.fs> program is available. */ 677 if (find_fsck(fs->type) == NULL) { 678 if (wanted) 679 fprintf(stderr, _("fsck: cannot check %s: fsck.%s not found\n"), 680 fs->device, fs->type); 681 return(1); 682 } 683 684 /* We can and want to check this file system type. */ 685 return 0; 686} 687 688/* 689 * Return the "base device" given a particular device; this is used to 690 * assure that we only fsck one partition on a particular drive at any 691 * one time. Otherwise, the disk heads will be seeking all over the 692 * place. 693 */ 694static const char *base_device(char *device) 695{ 696 const char **base; 697 698 for (base = base_devices; *base; base++) { 699 if (!strncmp(*base, device, strlen(*base))) 700 return *base; 701 } 702 return device; 703} 704 705/* 706 * Returns TRUE if a partition on the same disk is already being 707 * checked. 708 */ 709static int device_already_active(char *device) 710{ 711 struct fsck_instance *inst; 712 const char *base = base_device(device); 713 714 if (force_all_parallel) 715 return 0; 716 717 for (inst = instance_list; inst; inst = inst->next) { 718 if (!strcmp(base, base_device(inst->device))) 719 return 1; 720 } 721 return 0; 722} 723 724/* Check all file systems, using the /etc/fstab table. */ 725static int check_all(NOARGS) 726{ 727 struct fs_info *fs = NULL; 728 struct fsck_instance *inst; 729 int status = EXIT_OK; 730 int not_done_yet = 1; 731 int passno = 1; 732 int pass_done; 733 734 if (verbose) 735 printf(_("Checking all file systems.\n")); 736 737 /* 738 * Find and check the root filesystem first. 739 */ 740 if (!parallel_root) { 741 for (fs = filesys_info; fs; fs = fs->next) { 742 if (!strcmp(fs->mountpt, "/")) 743 break; 744 } 745 if (fs && !skip_root && !ignore(fs)) { 746 fsck_device(fs->device, 1); 747 fs->flags |= FLAG_DONE; 748 status |= wait_all(); 749 if (status > EXIT_NONDESTRUCT) 750 return status; 751 } 752 } 753 if (fs) fs->flags |= FLAG_DONE; 754 755 /* 756 * Mark filesystems that should be ignored as done. 757 */ 758 for (fs = filesys_info; fs; fs = fs->next) { 759 if (ignore(fs)) 760 fs->flags |= FLAG_DONE; 761 } 762 763 while (not_done_yet) { 764 not_done_yet = 0; 765 pass_done = 1; 766 767 for (fs = filesys_info; fs; fs = fs->next) { 768 if (fs->flags & FLAG_DONE) 769 continue; 770 /* 771 * If the filesystem's pass number is higher 772 * than the current pass number, then we don't 773 * do it yet. 774 */ 775 if (fs->passno > passno) { 776 not_done_yet++; 777 continue; 778 } 779 /* 780 * If a filesystem on a particular device has 781 * already been spawned, then we need to defer 782 * this to another pass. 783 */ 784 if (device_already_active(fs->device)) { 785 pass_done = 0; 786 continue; 787 } 788 /* 789 * Spawn off the fsck process 790 */ 791 fsck_device(fs->device, serialize); 792 fs->flags |= FLAG_DONE; 793 794 if (serialize) { 795 pass_done = 0; 796 break; /* Only do one filesystem at a time */ 797 } 798 } 799 if (verbose > 1) 800 printf(_("--waiting-- (pass %d)\n"), passno); 801 inst = wait_one(); 802 if (inst) { 803 status |= inst->exit_status; 804 free_instance(inst); 805 } 806 if (pass_done) { 807 status |= wait_all(); 808 if (verbose > 1) 809 printf("----------------------------------\n"); 810 passno++; 811 } else 812 not_done_yet++; 813 } 814 status |= wait_all(); 815 return status; 816} 817 818static void usage(NOARGS) 819{ 820 fprintf(stderr, 821 _("Usage: fsck [-ACNPRTV] [-t fstype] [fs-options] filesys\n")); 822 exit(EXIT_USAGE); 823} 824 825static void PRS(int argc, char *argv[]) 826{ 827 int i, j; 828 char *arg; 829 char options[128]; 830 int opt = 0; 831 int opts_for_fsck = 0; 832 833 num_devices = 0; 834 num_args = 0; 835 instance_list = 0; 836 837 progname = argv[0]; 838 839 for (i=1; i < argc; i++) { 840 arg = argv[i]; 841 if (!arg) 842 continue; 843 if ((arg[0] == '/' && !opts_for_fsck) || 844 (strncmp(arg, "LABEL=", 6) == 0) || 845 (strncmp(arg, "UUID=", 5) == 0)) { 846 if (num_devices >= MAX_DEVICES) { 847 fprintf(stderr, _("%s: too many devices\n"), 848 progname); 849 exit(1); 850 } 851 devices[num_devices++] = 852 interpret_device(string_copy(arg)); 853 continue; 854 } 855 if (arg[0] != '-' || opts_for_fsck) { 856 if (num_args >= MAX_ARGS) { 857 fprintf(stderr, _("%s: too many arguments\n"), 858 progname); 859 exit(1); 860 } 861 args[num_args++] = string_copy(arg); 862 continue; 863 } 864 for (j=1; arg[j]; j++) { 865 if (opts_for_fsck) { 866 options[++opt] = arg[j]; 867 continue; 868 } 869 switch (arg[j]) { 870 case 'A': 871 doall++; 872 break; 873 case 'C': 874 progress++; 875 break; 876 case 'V': 877 verbose++; 878 break; 879 case 'N': 880 noexecute++; 881 break; 882 case 'R': 883 skip_root++; 884 break; 885 case 'T': 886 notitle++; 887 break; 888 case 'M': 889 like_mount++; 890 break; 891 case 'P': 892 parallel_root++; 893 break; 894 case 's': 895 serialize++; 896 break; 897 case 't': 898 if (arg[j+1]) { 899 fstype = string_copy(arg+j+1); 900 goto next_arg; 901 } 902 if ((i+1) < argc) { 903 i++; 904 fstype = string_copy(argv[i]); 905 goto next_arg; 906 } 907 usage(); 908 break; 909 case '-': 910 opts_for_fsck++; 911 break; 912 default: 913 options[++opt] = arg[j]; 914 break; 915 } 916 } 917 next_arg: 918 if (opt) { 919 options[0] = '-'; 920 options[++opt] = '\0'; 921 if (num_args >= MAX_ARGS) { 922 fprintf(stderr, 923 _("%s: too many arguments\n"), 924 progname); 925 exit(1); 926 } 927 args[num_args++] = string_copy(options); 928 opt = 0; 929 } 930 } 931 if (getenv("FSCK_FORCE_ALL_PARALLEL")) 932 force_all_parallel++; 933} 934 935int main(int argc, char *argv[]) 936{ 937 int i; 938 int status = 0; 939 int interactive = 0; 940 char *oldpath = getenv("PATH"); 941 const char *fstab; 942 943#ifdef ENABLE_NLS 944 setlocale(LC_MESSAGES, ""); 945 bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 946 textdomain(NLS_CAT_NAME); 947#endif 948 PRS(argc, argv); 949 950 if (!notitle) 951 printf(_("Parallelizing fsck version %s (%s)\n"), 952 E2FSPROGS_VERSION, E2FSPROGS_DATE); 953 954 fstab = getenv("FSTAB_FILE"); 955 if (!fstab) 956 fstab = _PATH_MNTTAB; 957 load_fs_info(fstab); 958 959 /* Update our search path to include uncommon directories. */ 960 if (oldpath) { 961 fsck_path = malloc (strlen (fsck_prefix_path) + 1 + 962 strlen (oldpath) + 1); 963 strcpy (fsck_path, fsck_prefix_path); 964 strcat (fsck_path, ":"); 965 strcat (fsck_path, oldpath); 966 } else { 967 fsck_path = string_copy(fsck_prefix_path); 968 } 969 970 if ((num_devices == 1) || (serialize)) 971 interactive = 1; 972 973 /* If -A was specified ("check all"), do that! */ 974 if (doall) 975 return check_all(); 976 977 for (i = 0 ; i < num_devices; i++) { 978 fsck_device(devices[i], interactive); 979 if (serialize) { 980 struct fsck_instance *inst; 981 982 inst = wait_one(); 983 if (inst) { 984 status |= inst->exit_status; 985 free_instance(inst); 986 } 987 } 988 } 989 status |= wait_all(); 990 free(fsck_path); 991 return status; 992} 993