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