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