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