fsck.c revision 76ea3a2c7fc1b6ff03d566af66c971dbf867be45
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 "ext3", 78 "xiafs", 79 NULL 80}; 81 82#define BASE_MD "/dev/md" 83 84/* 85 * Global variables for options 86 */ 87char *devices[MAX_DEVICES]; 88char *args[MAX_ARGS]; 89int num_devices, num_args; 90 91int verbose = 0; 92int doall = 0; 93int noexecute = 0; 94int serialize = 0; 95int skip_root = 0; 96int like_mount = 0; 97int notitle = 0; 98int parallel_root = 0; 99int progress = 0; 100int force_all_parallel = 0; 101int num_running = 0; 102int max_running = 0; 103volatile int cancel_requested = 0; 104int kill_sent = 0; 105char *progname; 106char *fstype = NULL; 107struct fs_info *filesys_info; 108struct fsck_instance *instance_list; 109const char *fsck_prefix_path = "/sbin:/sbin/fs.d:/sbin/fs:/etc/fs:/etc"; 110char *fsck_path = 0; 111static int ignore(struct fs_info *); 112 113static char *skip_over_blank(char *cp) 114{ 115 while (*cp && isspace(*cp)) 116 cp++; 117 return cp; 118} 119 120static char *skip_over_word(char *cp) 121{ 122 while (*cp && !isspace(*cp)) 123 cp++; 124 return cp; 125} 126 127static void strip_line(char *line) 128{ 129 char *p; 130 131 while (*line) { 132 p = line + strlen(line) - 1; 133 if ((*p == '\n') || (*p == '\r')) 134 *p = 0; 135 else 136 break; 137 } 138} 139 140static char *parse_word(char **buf) 141{ 142 char *word, *next; 143 144 word = *buf; 145 if (*word == 0) 146 return 0; 147 148 word = skip_over_blank(word); 149 next = skip_over_word(word); 150 if (*next) 151 *next++ = 0; 152 *buf = next; 153 return word; 154} 155 156static void parse_escape(char *word) 157{ 158 char *p, *q; 159 int ac, i; 160 161 for (p = word, q = word; *p; p++, q++) { 162 *q = *p; 163 if (*p != '\\') 164 continue; 165 if (*++p == 0) 166 break; 167 if (*p == 't') { 168 *q = '\t'; 169 continue; 170 } 171 if (*p == 'n') { 172 *q = '\n'; 173 continue; 174 } 175 if (!isdigit(*p)) { 176 *q = *p; 177 continue; 178 } 179 ac = 0; 180 for (i = 0; i < 3; i++, p++) { 181 if (!isdigit(*p)) 182 break; 183 ac = (ac * 8) + (*p - '0'); 184 } 185 *q = ac; 186 p--; 187 } 188 *q = 0; 189} 190 191static void free_instance(struct fsck_instance *i) 192{ 193 if (i->prog) 194 free(i->prog); 195 if (i->device) 196 free(i->device); 197 if (i->base_device) 198 free(i->base_device); 199 free(i); 200 return; 201} 202 203static int parse_fstab_line(char *line, struct fs_info **ret_fs) 204{ 205 char *device, *mntpnt, *type, *opts, *freq, *passno, *cp; 206 struct fs_info *fs; 207 208 *ret_fs = 0; 209 strip_line(line); 210 if ((cp = strchr(line, '#'))) 211 *cp = 0; /* Ignore everything after the comment char */ 212 cp = line; 213 214 device = parse_word(&cp); 215 mntpnt = parse_word(&cp); 216 type = parse_word(&cp); 217 opts = parse_word(&cp); 218 freq = parse_word(&cp); 219 passno = parse_word(&cp); 220 221 parse_escape(device); 222 parse_escape(mntpnt); 223 parse_escape(type); 224 parse_escape(opts); 225 parse_escape(freq); 226 parse_escape(passno); 227 228 if (!device) 229 return 0; /* Allow blank lines */ 230 231 if (!mntpnt || !type) 232 return -1; 233 234 if (!(fs = malloc(sizeof(struct fs_info)))) 235 return -1; 236 237 fs->device = string_copy(device); 238 fs->mountpt = string_copy(mntpnt); 239 fs->type = string_copy(type); 240 fs->opts = string_copy(opts ? opts : ""); 241 fs->freq = freq ? atoi(freq) : -1; 242 fs->passno = passno ? atoi(passno) : -1; 243 fs->flags = 0; 244 fs->next = NULL; 245 246 *ret_fs = fs; 247 248 return 0; 249} 250 251/* 252 * Interpret the device name if necessary 253 */ 254static char *interpret_device(char *spec) 255{ 256 char *dev = interpret_spec(spec); 257 258 if (dev) 259 return dev; 260 261 /* 262 * Check to see if this was because /proc/partitions isn't 263 * found. 264 */ 265 if (access("/proc/partitions", R_OK) < 0) { 266 fprintf(stderr, "Couldn't open /proc/partitions: %s\n", 267 strerror(errno)); 268 fprintf(stderr, "Is /proc mounted?\n"); 269 exit(EXIT_ERROR); 270 } 271 /* 272 * Check to see if this is because we're not running as root 273 */ 274 if (geteuid()) 275 fprintf(stderr, 276 "Must be root to scan for matching filesystems: %s\n", 277 spec); 278 else 279 fprintf(stderr, "Couldn't find matching filesystem: %s\n", 280 spec); 281 exit(EXIT_ERROR); 282} 283 284/* 285 * Interpret filesystem auto type if necessary 286 */ 287static void interpret_type(struct fs_info *fs) 288{ 289 const char *type; 290 291 if (strcmp(fs->type, "auto") == 0 || 292 (strchr(fs->type, ',') != 0)) { 293 if (fs && strchr(fs->device, '=')) 294 fs->device = interpret_device(fs->device); 295 type = identify_fs(fs->device, fs->type); 296 if (type) { 297 free(fs->type); 298 fs->type = string_copy(type); 299 } else 300 fprintf(stderr, _("Could not determine " 301 "filesystem type for %s\n"), 302 fs->device); 303 } 304} 305 306 307/* 308 * Load the filesystem database from /etc/fstab 309 */ 310static void load_fs_info(const char *filename) 311{ 312 FILE *f; 313 char buf[1024]; 314 int lineno = 0; 315 int old_fstab = 1; 316 struct fs_info *fs, *fs_last = NULL; 317 318 filesys_info = NULL; 319 if ((f = fopen(filename, "r")) == NULL) { 320 fprintf(stderr, _("WARNING: couldn't open %s: %s\n"), 321 filename, strerror(errno)); 322 return; 323 } 324 while (!feof(f)) { 325 lineno++; 326 if (!fgets(buf, sizeof(buf), f)) 327 break; 328 buf[sizeof(buf)-1] = 0; 329 if (parse_fstab_line(buf, &fs) < 0) { 330 fprintf(stderr, _("WARNING: bad format " 331 "on line %d of %s\n"), lineno, filename); 332 continue; 333 } 334 if (!fs) 335 continue; 336 if (!filesys_info) 337 filesys_info = fs; 338 else 339 fs_last->next = fs; 340 fs_last = fs; 341 if (fs->passno < 0) 342 fs->passno = 0; 343 else 344 old_fstab = 0; 345 } 346 347 fclose(f); 348 349 if (old_fstab) { 350 fprintf(stderr, _("\007\007\007" 351 "WARNING: Your /etc/fstab does not contain the fsck passno\n" 352 " field. I will kludge around things for you, but you\n" 353 " should fix your /etc/fstab file as soon as you can.\n\n")); 354 355 for (fs = filesys_info; fs; fs = fs->next) { 356 fs->passno = 1; 357 } 358 } 359} 360 361/* Lookup filesys in /etc/fstab and return the corresponding entry. */ 362static struct fs_info *lookup(char *filesys) 363{ 364 struct fs_info *fs; 365 int try_again = 0; 366 367 /* No filesys name given. */ 368 if (filesys == NULL) 369 return NULL; 370 371 for (fs = filesys_info; fs; fs = fs->next) { 372 if (strchr(fs->device, '=')) 373 try_again++; 374 if (!strcmp(filesys, fs->device) || 375 !strcmp(filesys, fs->mountpt)) 376 break; 377 } 378 if (fs && strchr(fs->device, '=')) 379 fs->device = interpret_device(fs->device); 380 381 if (fs || !try_again) 382 return fs; 383 384 for (fs = filesys_info; fs; fs = fs->next) { 385 fs->device = interpret_device(fs->device); 386 if (!strcmp(filesys, fs->device) || 387 !strcmp(filesys, fs->mountpt)) 388 break; 389 } 390 391 return fs; 392} 393 394/* Find fsck program for a given fs type. */ 395static char *find_fsck(char *type) 396{ 397 char *s; 398 const char *tpl; 399 static char prog[256]; 400 char *p = string_copy(fsck_path); 401 struct stat st; 402 403 /* Are we looking for a program or just a type? */ 404 tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s"); 405 406 for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) { 407 sprintf(prog, tpl, s, type); 408 if (stat(prog, &st) == 0) break; 409 } 410 free(p); 411 return(s ? prog : NULL); 412} 413 414static int progress_active(NOARGS) 415{ 416 struct fsck_instance *inst; 417 418 for (inst = instance_list; inst; inst = inst->next) { 419 if (inst->flags & FLAG_DONE) 420 continue; 421 if (inst->flags & FLAG_PROGRESS) 422 return 1; 423 } 424 return 0; 425} 426 427/* 428 * Execute a particular fsck program, and link it into the list of 429 * child processes we are waiting for. 430 */ 431static int execute(const char *type, char *device, char *mntpt, 432 int interactive) 433{ 434 char *s, *argv[80], prog[80]; 435 int argc, i; 436 struct fsck_instance *inst, *p; 437 pid_t pid; 438 439 inst = malloc(sizeof(struct fsck_instance)); 440 if (!inst) 441 return ENOMEM; 442 memset(inst, 0, sizeof(struct fsck_instance)); 443 444 sprintf(prog, "fsck.%s", type); 445 argv[0] = string_copy(prog); 446 argc = 1; 447 448 for (i=0; i <num_args; i++) 449 argv[argc++] = string_copy(args[i]); 450 451 if (progress & !progress_active()) { 452 if ((strcmp(type, "ext2") == 0) || 453 (strcmp(type, "ext3") == 0)) { 454 argv[argc++] = string_copy("-C0"); 455 inst->flags |= FLAG_PROGRESS; 456 } 457 } 458 459 argv[argc++] = string_copy(device); 460 argv[argc] = 0; 461 462 s = find_fsck(prog); 463 if (s == NULL) { 464 fprintf(stderr, _("fsck: %s: not found\n"), prog); 465 return ENOENT; 466 } 467 468 if (verbose || noexecute) { 469 printf("[%s (%d) -- %s] ", s, num_running, 470 mntpt ? mntpt : device); 471 for (i=0; i < argc; i++) 472 printf("%s ", argv[i]); 473 printf("\n"); 474 } 475 476 /* Fork and execute the correct program. */ 477 if (noexecute) 478 pid = -1; 479 else if ((pid = fork()) < 0) { 480 perror("fork"); 481 return errno; 482 } else if (pid == 0) { 483 if (!interactive) 484 close(0); 485 (void) execv(s, argv); 486 perror(argv[0]); 487 exit(EXIT_ERROR); 488 } 489 490 for (i=0; i < argc; i++) 491 free(argv[i]); 492 493 inst->pid = pid; 494 inst->prog = string_copy(prog); 495 inst->type = string_copy(type); 496 inst->device = string_copy(device); 497 inst->base_device = base_device(device); 498 inst->start_time = time(0); 499 inst->next = NULL; 500 501 /* 502 * Find the end of the list, so we add the instance on at the end. 503 */ 504 for (p = instance_list; p && p->next; p = p->next); 505 506 if (p) 507 p->next = inst; 508 else 509 instance_list = inst; 510 511 return 0; 512} 513 514/* 515 * Send a signal to all outstanding fsck child processes 516 */ 517static int kill_all(int signum) 518{ 519 struct fsck_instance *inst; 520 int n = 0; 521 522 for (inst = instance_list; inst; inst = inst->next) { 523 if (inst->flags & FLAG_DONE) 524 continue; 525 kill(inst->pid, signum); 526 n++; 527 } 528 return n; 529} 530 531/* 532 * Wait for one child process to exit; when it does, unlink it from 533 * the list of executing child processes, and return it. 534 */ 535static struct fsck_instance *wait_one(int flags) 536{ 537 int status; 538 int sig; 539 struct fsck_instance *inst, *inst2, *prev; 540 pid_t pid; 541 542 if (!instance_list) 543 return NULL; 544 545 if (noexecute) { 546 inst = instance_list; 547 prev = 0; 548#ifdef RANDOM_DEBUG 549 while (inst->next && (random() & 1)) { 550 prev = inst; 551 inst = inst->next; 552 } 553#endif 554 inst->exit_status = 0; 555 goto ret_inst; 556 } 557 558 /* 559 * gcc -Wall fails saving throw against stupidity 560 * (inst and prev are thought to be uninitialized variables) 561 */ 562 inst = prev = NULL; 563 564 do { 565 pid = waitpid(-1, &status, flags); 566 if (cancel_requested && !kill_sent) { 567 kill_all(SIGTERM); 568 kill_sent++; 569 } 570 if ((pid == 0) && (flags & WNOHANG)) 571 return NULL; 572 if (pid < 0) { 573 if ((errno == EINTR) || (errno == EAGAIN)) 574 continue; 575 if (errno == ECHILD) { 576 fprintf(stderr, 577 _("%s: wait: No more child process?!?\n"), 578 progname); 579 return NULL; 580 } 581 perror("wait"); 582 continue; 583 } 584 for (prev = 0, inst = instance_list; 585 inst; 586 prev = inst, inst = inst->next) { 587 if (inst->pid == pid) 588 break; 589 } 590 } while (!inst); 591 592 if (WIFEXITED(status)) 593 status = WEXITSTATUS(status); 594 else if (WIFSIGNALED(status)) { 595 sig = WTERMSIG(status); 596 if (sig == SIGINT) { 597 status = EXIT_UNCORRECTED; 598 } else { 599 printf(_("Warning... %s for device %s exited " 600 "with signal %d.\n"), 601 inst->prog, inst->device, sig); 602 status = EXIT_ERROR; 603 } 604 } else { 605 printf(_("%s %s: status is %x, should never happen.\n"), 606 inst->prog, inst->device, status); 607 status = EXIT_ERROR; 608 } 609 inst->exit_status = status; 610 if (progress && (inst->flags & FLAG_PROGRESS) && 611 !progress_active()) { 612 for (inst2 = instance_list; inst2; inst2 = inst2->next) { 613 if (inst2->flags & FLAG_DONE) 614 continue; 615 if (strcmp(inst2->type, "ext2") && 616 strcmp(inst2->type, "ext3")) 617 continue; 618 /* 619 * If we've just started the fsck, wait a tiny 620 * bit before sending the kill, to give it 621 * time to set up the signal handler 622 */ 623 if (inst2->start_time < time(0)+2) { 624 if (fork() == 0) { 625 sleep(1); 626 kill(inst2->pid, SIGUSR1); 627 exit(0); 628 } 629 } else 630 kill(inst2->pid, SIGUSR1); 631 inst2->flags |= FLAG_PROGRESS; 632 break; 633 } 634 } 635ret_inst: 636 if (prev) 637 prev->next = inst->next; 638 else 639 instance_list = inst->next; 640 if (verbose > 1) 641 printf(_("Finished with %s (exit status %d)\n"), 642 inst->device, inst->exit_status); 643 num_running--; 644 return inst; 645} 646 647/* 648 * Wait until all executing child processes have exited; return the 649 * logical OR of all of their exit code values. 650 */ 651static int wait_all(int flags) 652{ 653 struct fsck_instance *inst; 654 int global_status = 0; 655 656 while ((inst = wait_one(flags))) { 657 global_status |= inst->exit_status; 658 free_instance(inst); 659#ifdef RANDOM_DEBUG 660 if (noexecute && (flags & WNOHANG) && !(random() % 3)) 661 break; 662#endif 663 } 664 return global_status; 665} 666 667/* 668 * Run the fsck program on a particular device 669 * 670 * If the type is specified using -t, and it isn't prefixed with "no" 671 * (as in "noext2") and only one filesystem type is specified, then 672 * use that type regardless of what is specified in /etc/fstab. 673 * 674 * If the type isn't specified by the user, then use either the type 675 * specified in /etc/fstab, or DEFAULT_FSTYPE. 676 */ 677static void fsck_device(char *device, int interactive) 678{ 679 const char *type = 0; 680 struct fs_info *fsent; 681 int retval; 682 683 if (fstype && strncmp(fstype, "no", 2) && 684 strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) && 685 !strchr(fstype, ',')) 686 type = fstype; 687 688 if ((fsent = lookup(device))) { 689 device = fsent->device; 690 interpret_type(fsent); 691 if (!type) 692 type = fsent->type; 693 } 694 if (!type) 695 type = DEFAULT_FSTYPE; 696 697 num_running++; 698 retval = execute(type, device, fsent ? fsent->mountpt : 0, 699 interactive); 700 if (retval) { 701 fprintf(stderr, _("%s: Error %d while executing fsck.%s " 702 "for %s\n"), progname, retval, type, device); 703 num_running--; 704 } 705} 706 707 708/* 709 * Deal with the fsck -t argument. 710 */ 711struct fs_type_compile { 712 char **list; 713 int *type; 714 int negate; 715} fs_type_compiled; 716 717#define FS_TYPE_NORMAL 0 718#define FS_TYPE_OPT 1 719#define FS_TYPE_NEGOPT 2 720 721static const char *fs_type_syntax_error = 722N_("Either all or none of the filesystem types passed to -t must be prefixed\n" 723 "with 'no' or '!'.\n"); 724 725static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp) 726{ 727 char *cp, *list, *s; 728 int num = 2; 729 int negate, first_negate = 1; 730 731 if (fs_type) { 732 for (cp=fs_type; *cp; cp++) { 733 if (*cp == ',') 734 num++; 735 } 736 } 737 738 cmp->list = malloc(num * sizeof(char *)); 739 cmp->type = malloc(num * sizeof(int)); 740 if (!cmp->list || !cmp->type) { 741 fprintf(stderr, _("Couldn't allocate memory for " 742 "filesystem types\n")); 743 exit(EXIT_ERROR); 744 } 745 memset(cmp->list, 0, num * sizeof(char *)); 746 memset(cmp->type, 0, num * sizeof(int)); 747 cmp->negate = 0; 748 749 if (!fs_type) 750 return; 751 752 list = string_copy(fs_type); 753 num = 0; 754 s = strtok(list, ","); 755 while(s) { 756 negate = 0; 757 if (strncmp(s, "no", 2) == 0) { 758 s += 2; 759 negate = 1; 760 } else if (*s == '!') { 761 s++; 762 negate = 1; 763 } 764 if (strcmp(s, "loop") == 0) 765 /* loop is really short-hand for opts=loop */ 766 goto loop_special_case; 767 else if (strncmp(s, "opts=", 5) == 0) { 768 s += 5; 769 loop_special_case: 770 cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT; 771 } else { 772 if (first_negate) { 773 cmp->negate = negate; 774 first_negate = 0; 775 } 776 if ((negate && !cmp->negate) || 777 (!negate && cmp->negate)) { 778 fprintf(stderr, _(fs_type_syntax_error)); 779 exit(EXIT_USAGE); 780 } 781 } 782#if 0 783 printf("Adding %s to list (type %d).\n", s, cmp->type[num]); 784#endif 785 cmp->list[num++] = string_copy(s); 786 s = strtok(NULL, ","); 787 } 788 free(list); 789} 790 791/* 792 * This function returns true if a particular option appears in a 793 * comma-delimited options list 794 */ 795static int opt_in_list(char *opt, char *optlist) 796{ 797 char *list, *s; 798 799 if (!optlist) 800 return 0; 801 list = string_copy(optlist); 802 803 s = strtok(list, ","); 804 while(s) { 805 if (strcmp(s, opt) == 0) { 806 free(list); 807 return 1; 808 } 809 s = strtok(NULL, ","); 810 } 811 free(list); 812 return 0; 813} 814 815/* See if the filesystem matches the criteria given by the -t option */ 816static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp) 817{ 818 int n, ret = 0, checked_type = 0; 819 char *cp; 820 821 if (cmp->list == 0 || cmp->list[0] == 0) 822 return 1; 823 824 for (n=0; (cp = cmp->list[n]); n++) { 825 switch (cmp->type[n]) { 826 case FS_TYPE_NORMAL: 827 checked_type++; 828 if (strcmp(cp, fs->type) == 0) { 829 ret = 1; 830 } 831 break; 832 case FS_TYPE_NEGOPT: 833 if (opt_in_list(cp, fs->opts)) 834 return 0; 835 break; 836 case FS_TYPE_OPT: 837 if (!opt_in_list(cp, fs->opts)) 838 return 0; 839 break; 840 } 841 } 842 if (checked_type == 0) 843 return 1; 844 return (cmp->negate ? !ret : ret); 845} 846 847/* Check if we should ignore this filesystem. */ 848static int ignore(struct fs_info *fs) 849{ 850 const char **ip; 851 int wanted = 0; 852 853 /* 854 * If the pass number is 0, ignore it. 855 */ 856 if (fs->passno == 0) 857 return 1; 858 859 interpret_type(fs); 860 861 /* 862 * If a specific fstype is specified, and it doesn't match, 863 * ignore it. 864 */ 865 if (!fs_match(fs, &fs_type_compiled)) return 1; 866 867 /* Are we ignoring this type? */ 868 for(ip = ignored_types; *ip; ip++) 869 if (strcmp(fs->type, *ip) == 0) return 1; 870 871 /* Do we really really want to check this fs? */ 872 for(ip = really_wanted; *ip; ip++) 873 if (strcmp(fs->type, *ip) == 0) { 874 wanted = 1; 875 break; 876 } 877 878 /* See if the <fsck.fs> program is available. */ 879 if (find_fsck(fs->type) == NULL) { 880 if (wanted) 881 fprintf(stderr, _("fsck: cannot check %s: fsck.%s not found\n"), 882 fs->device, fs->type); 883 return 1; 884 } 885 886 /* We can and want to check this file system type. */ 887 return 0; 888} 889 890/* 891 * Returns TRUE if a partition on the same disk is already being 892 * checked. 893 */ 894static int device_already_active(char *device) 895{ 896 struct fsck_instance *inst; 897 char *base; 898 899 if (force_all_parallel) 900 return 0; 901 902#ifdef BASE_MD 903 /* Don't check a soft raid disk with any other disk */ 904 if (instance_list && 905 (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) || 906 !strncmp(device, BASE_MD, sizeof(BASE_MD)-1))) 907 return 1; 908#endif 909 910 base = base_device(device); 911 /* 912 * If we don't know the base device, assume that the device is 913 * already active if there are any fsck instances running. 914 */ 915 if (!base) 916 return (instance_list != 0); 917 for (inst = instance_list; inst; inst = inst->next) { 918 if (!inst->base_device || !strcmp(base, inst->base_device)) { 919 free(base); 920 return 1; 921 } 922 } 923 free(base); 924 return 0; 925} 926 927/* Check all file systems, using the /etc/fstab table. */ 928static int check_all(NOARGS) 929{ 930 struct fs_info *fs = NULL; 931 int status = EXIT_OK; 932 int not_done_yet = 1; 933 int passno = 1; 934 int pass_done; 935 936 if (verbose) 937 printf(_("Checking all file systems.\n")); 938 939 /* 940 * Do an initial scan over the filesystem; mark filesystems 941 * which should be ignored as done, and resolve LABEL= and 942 * UUID= specifications to the real device. 943 */ 944 for (fs = filesys_info; fs; fs = fs->next) { 945 if (ignore(fs)) 946 fs->flags |= FLAG_DONE; 947 else 948 fs->device = interpret_device(fs->device); 949 } 950 951 /* 952 * Find and check the root filesystem. 953 */ 954 if (!parallel_root) { 955 for (fs = filesys_info; fs; fs = fs->next) { 956 if (!strcmp(fs->mountpt, "/")) 957 break; 958 } 959 if (fs) { 960 if (!skip_root && !ignore(fs)) { 961 fsck_device(fs->device, 1); 962 status |= wait_all(0); 963 if (status > EXIT_NONDESTRUCT) 964 return status; 965 } 966 fs->flags |= FLAG_DONE; 967 } 968 } 969 /* 970 * This is for the bone-headed user who enters the root 971 * filesystem twice. Skip root will skep all root entries. 972 */ 973 if (skip_root) 974 for (fs = filesys_info; fs; fs = fs->next) 975 if (!strcmp(fs->mountpt, "/")) 976 fs->flags |= FLAG_DONE; 977 978 while (not_done_yet) { 979 not_done_yet = 0; 980 pass_done = 1; 981 982 for (fs = filesys_info; fs; fs = fs->next) { 983 if (cancel_requested) 984 break; 985 if (fs->flags & FLAG_DONE) 986 continue; 987 /* 988 * If the filesystem's pass number is higher 989 * than the current pass number, then we don't 990 * do it yet. 991 */ 992 if (fs->passno > passno) { 993 not_done_yet++; 994 continue; 995 } 996 /* 997 * If a filesystem on a particular device has 998 * already been spawned, then we need to defer 999 * this to another pass. 1000 */ 1001 if (device_already_active(fs->device)) { 1002 pass_done = 0; 1003 continue; 1004 } 1005 /* 1006 * Spawn off the fsck process 1007 */ 1008 fsck_device(fs->device, serialize); 1009 fs->flags |= FLAG_DONE; 1010 1011 /* 1012 * Only do one filesystem at a time, or if we 1013 * have a limit on the number of fsck's extant 1014 * at one time, apply that limit. 1015 */ 1016 if (serialize || 1017 (max_running && (num_running >= max_running))) { 1018 pass_done = 0; 1019 break; 1020 } 1021 } 1022 if (cancel_requested) 1023 break; 1024 if (verbose > 1) 1025 printf(_("--waiting-- (pass %d)\n"), passno); 1026 status |= wait_all(pass_done ? 0 : WNOHANG); 1027 if (pass_done) { 1028 if (verbose > 1) 1029 printf("----------------------------------\n"); 1030 passno++; 1031 } else 1032 not_done_yet++; 1033 } 1034 if (cancel_requested && !kill_sent) { 1035 kill_all(SIGTERM); 1036 kill_sent++; 1037 } 1038 status |= wait_all(0); 1039 return status; 1040} 1041 1042static void usage(NOARGS) 1043{ 1044 fprintf(stderr, 1045 _("Usage: fsck [-ACNPRTV] [-t fstype] [fs-options] [filesys ...]\n")); 1046 exit(EXIT_USAGE); 1047} 1048 1049#ifdef HAVE_SIGNAL_H 1050static void signal_cancel(int sig) 1051{ 1052 cancel_requested++; 1053} 1054#endif 1055 1056static void PRS(int argc, char *argv[]) 1057{ 1058 int i, j; 1059 char *arg, *tmp; 1060 char options[128]; 1061 int opt = 0; 1062 int opts_for_fsck = 0; 1063#ifdef HAVE_SIGNAL_H 1064 struct sigaction sa; 1065 1066 /* 1067 * Set up signal action 1068 */ 1069 memset(&sa, 0, sizeof(struct sigaction)); 1070 sa.sa_handler = signal_cancel; 1071 sigaction(SIGINT, &sa, 0); 1072 sigaction(SIGTERM, &sa, 0); 1073#endif 1074 1075 num_devices = 0; 1076 num_args = 0; 1077 instance_list = 0; 1078 1079 progname = argv[0]; 1080 1081 for (i=1; i < argc; i++) { 1082 arg = argv[i]; 1083 if (!arg) 1084 continue; 1085 if ((arg[0] == '/' && !opts_for_fsck) || 1086 (strncmp(arg, "LABEL=", 6) == 0) || 1087 (strncmp(arg, "UUID=", 5) == 0)) { 1088 if (num_devices >= MAX_DEVICES) { 1089 fprintf(stderr, _("%s: too many devices\n"), 1090 progname); 1091 exit(EXIT_ERROR); 1092 } 1093 devices[num_devices++] = 1094 interpret_device(string_copy(arg)); 1095 continue; 1096 } 1097 if (arg[0] != '-' || opts_for_fsck) { 1098 if (num_args >= MAX_ARGS) { 1099 fprintf(stderr, _("%s: too many arguments\n"), 1100 progname); 1101 exit(EXIT_ERROR); 1102 } 1103 args[num_args++] = string_copy(arg); 1104 continue; 1105 } 1106 for (j=1; arg[j]; j++) { 1107 if (opts_for_fsck) { 1108 options[++opt] = arg[j]; 1109 continue; 1110 } 1111 switch (arg[j]) { 1112 case 'A': 1113 doall++; 1114 break; 1115 case 'C': 1116 progress++; 1117 break; 1118 case 'V': 1119 verbose++; 1120 break; 1121 case 'N': 1122 noexecute++; 1123 break; 1124 case 'R': 1125 skip_root++; 1126 break; 1127 case 'T': 1128 notitle++; 1129 break; 1130 case 'M': 1131 like_mount++; 1132 break; 1133 case 'P': 1134 parallel_root++; 1135 break; 1136 case 's': 1137 serialize++; 1138 break; 1139 case 't': 1140 if (fstype) 1141 usage(); 1142 if (arg[j+1]) 1143 tmp = arg+j+1; 1144 else if ((i+1) < argc) 1145 tmp = argv[++i]; 1146 else 1147 usage(); 1148 fstype = string_copy(tmp); 1149 compile_fs_type(fstype, &fs_type_compiled); 1150 goto next_arg; 1151 case '-': 1152 opts_for_fsck++; 1153 break; 1154 case '?': 1155 usage(); 1156 break; 1157 default: 1158 options[++opt] = arg[j]; 1159 break; 1160 } 1161 } 1162 next_arg: 1163 if (opt) { 1164 options[0] = '-'; 1165 options[++opt] = '\0'; 1166 if (num_args >= MAX_ARGS) { 1167 fprintf(stderr, 1168 _("%s: too many arguments\n"), 1169 progname); 1170 exit(EXIT_ERROR); 1171 } 1172 args[num_args++] = string_copy(options); 1173 opt = 0; 1174 } 1175 } 1176 if (getenv("FSCK_FORCE_ALL_PARALLEL")) 1177 force_all_parallel++; 1178 if ((tmp = getenv("FSCK_MAX_INST"))) 1179 max_running = atoi(tmp); 1180} 1181 1182int main(int argc, char *argv[]) 1183{ 1184 int i; 1185 int status = 0; 1186 int interactive = 0; 1187 char *oldpath = getenv("PATH"); 1188 const char *fstab; 1189 1190#ifdef ENABLE_NLS 1191 setlocale(LC_MESSAGES, ""); 1192 setlocale(LC_CTYPE, ""); 1193 bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 1194 textdomain(NLS_CAT_NAME); 1195#endif 1196 PRS(argc, argv); 1197 1198 if (!notitle) 1199 printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); 1200 1201 fstab = getenv("FSTAB_FILE"); 1202 if (!fstab) 1203 fstab = _PATH_MNTTAB; 1204 load_fs_info(fstab); 1205 1206 /* Update our search path to include uncommon directories. */ 1207 if (oldpath) { 1208 fsck_path = malloc (strlen (fsck_prefix_path) + 1 + 1209 strlen (oldpath) + 1); 1210 strcpy (fsck_path, fsck_prefix_path); 1211 strcat (fsck_path, ":"); 1212 strcat (fsck_path, oldpath); 1213 } else { 1214 fsck_path = string_copy(fsck_prefix_path); 1215 } 1216 1217 if ((num_devices == 1) || (serialize)) 1218 interactive = 1; 1219 1220 /* If -A was specified ("check all"), do that! */ 1221 if (doall) 1222 return check_all(); 1223 1224 if (num_devices == 0) { 1225 serialize++; 1226 interactive++; 1227 return check_all(); 1228 } 1229 for (i = 0 ; i < num_devices; i++) { 1230 if (cancel_requested) { 1231 if (!kill_sent) { 1232 kill_all(SIGTERM); 1233 kill_sent++; 1234 } 1235 break; 1236 } 1237 fsck_device(devices[i], interactive); 1238 if (serialize || 1239 (max_running && (num_running >= max_running))) { 1240 struct fsck_instance *inst; 1241 1242 inst = wait_one(0); 1243 if (inst) { 1244 status |= inst->exit_status; 1245 free_instance(inst); 1246 } 1247 if (verbose > 1) 1248 printf("----------------------------------\n"); 1249 } 1250 } 1251 status |= wait_all(0); 1252 free(fsck_path); 1253 return status; 1254} 1255