X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=misc%2Ffsck.c;h=10cf39f72e20d3ac8e5dacff6b713c9b08e0bb09;hb=04a968579ee8125c617edee27204cf35c0a169c1;hp=349a74cd32e41d5950ed01b703404852e454e33d;hpb=3cb7784f307db3f32b008bacbe87fe385f8543a7;p=tools%2Fe2fsprogs.git diff --git a/misc/fsck.c b/misc/fsck.c index 349a74c..10cf39f 100644 --- a/misc/fsck.c +++ b/misc/fsck.c @@ -53,6 +53,7 @@ #include #include "../version.h" +#include "nls-enable.h" #include "fsck.h" #include "get_device_by_label.h" @@ -73,49 +74,12 @@ static const char *ignored_types[] = { static const char *really_wanted[] = { "minix", "ext2", + "ext3", "xiafs", NULL }; -#ifdef DEV_DSK_DEVICES -static const char *base_devices[] = { - "/dev/dsk/hda", - "/dev/dsk/hdb", - "/dev/dsk/hdc", - "/dev/dsk/hdd", - "/dev/dsk/hd1a", - "/dev/dsk/hd1b", - "/dev/dsk/hd1c", - "/dev/dsk/hd1d", - "/dev/dsk/sda", - "/dev/dsk/sdb", - "/dev/dsk/sdc", - "/dev/dsk/sdd", - "/dev/dsk/sde", - "/dev/dsk/sdf", - "/dev/dsk/sdg", - NULL -}; -#else -static const char *base_devices[] = { - "/dev/hda", - "/dev/hdb", - "/dev/hdc", - "/dev/hdd", - "/dev/hd1a", - "/dev/hd1b", - "/dev/hd1c", - "/dev/hd1d", - "/dev/sda", - "/dev/sdb", - "/dev/sdc", - "/dev/sdd", - "/dev/sde", - "/dev/sdf", - "/dev/sdg", - NULL -}; -#endif +#define BASE_MD "/dev/md" /* * Global variables for options @@ -142,16 +106,6 @@ const char *fsck_prefix_path = "/sbin:/sbin/fs.d:/sbin/fs:/etc/fs:/etc"; char *fsck_path = 0; static int ignore(struct fs_info *); -static char *string_copy(const char *s) -{ - char *ret; - - ret = malloc(strlen(s)+1); - if (ret) - strcpy(ret, s); - return ret; -} - static char *skip_over_blank(char *cp) { while (*cp && isspace(*cp)) @@ -201,6 +155,8 @@ static void free_instance(struct fsck_instance *i) free(i->prog); if (i->device) free(i->device); + if (i->base_device) + free(i->base_device); free(i); return; } @@ -251,19 +207,54 @@ static int parse_fstab_line(char *line, struct fs_info **ret_fs) */ static char *interpret_device(char *spec) { - char *dev = NULL; + char *dev = interpret_spec(spec); + + if (dev) + return dev; + + /* + * Check to see if this was because /proc/partitions isn't + * found. + */ + if (access("/proc/partitions", R_OK) < 0) { + fprintf(stderr, "Couldn't open /proc/partitions: %s\n", + strerror(errno)); + fprintf(stderr, "Is /proc mounted?\n"); + exit(EXIT_ERROR); + } + /* + * Check to see if this is because we're not running as root + */ + if (geteuid()) + fprintf(stderr, + "Must be root to scan for matching filesystems: %s\n", + spec); + else + fprintf(stderr, "Couldn't find matching filesystem: %s\n", + spec); + exit(EXIT_ERROR); +} + +/* + * Interpret filesystem auto type if necessary + */ +static void interpret_type(struct fs_info *fs) +{ + const char *type; - if (!strncmp(spec, "UUID=", 5)) - dev = get_spec_by_uuid(spec+5); - else if (!strncmp(spec, "LABEL=", 6)) - dev = get_spec_by_volume_label(spec+6); - if (dev) { - free(spec); - spec = dev; - } - return spec; + if (strcmp(fs->type, "auto") == 0) { + type = identify_fs(fs->device); + if (type) { + free(fs->type); + fs->type = string_copy(type); + } else + fprintf(stderr, _("Could not determine " + "filesystem type for %s\n"), + fs->device); + } } + /* * Load the filesystem database from /etc/fstab */ @@ -277,7 +268,7 @@ static void load_fs_info(const char *filename) filesys_info = NULL; if ((f = fopen(filename, "r")) == NULL) { - fprintf(stderr, "WARNING: couldn't open %s: %s\n", + fprintf(stderr, _("WARNING: couldn't open %s: %s\n"), filename, strerror(errno)); return; } @@ -287,13 +278,12 @@ static void load_fs_info(const char *filename) break; buf[sizeof(buf)-1] = 0; if (parse_fstab_line(buf, &fs) < 0) { - fprintf(stderr, "WARNING: bad format " - "on line %d of %s\n", lineno, filename); + fprintf(stderr, _("WARNING: bad format " + "on line %d of %s\n"), lineno, filename); continue; } if (!fs) continue; - fs->device = interpret_device(fs->device); if (!filesys_info) filesys_info = fs; else @@ -308,12 +298,10 @@ static void load_fs_info(const char *filename) fclose(f); if (old_fstab) { - fprintf(stderr, "\007\007\007" - "WARNING: Your /etc/fstab does not contain the fsck passno\n"); - fprintf(stderr, - " field. I will kludge around things for you, but you\n"); - fprintf(stderr, - " should fix your /etc/fstab file as soon as you can.\n\n"); + fprintf(stderr, _("\007\007\007" + "WARNING: Your /etc/fstab does not contain the fsck passno\n" + " field. I will kludge around things for you, but you\n" + " should fix your /etc/fstab file as soon as you can.\n\n")); for (fs = filesys_info; fs; fs = fs->next) { fs->passno = 1; @@ -325,12 +313,27 @@ static void load_fs_info(const char *filename) static struct fs_info *lookup(char *filesys) { struct fs_info *fs; + int try_again = 0; /* No filesys name given. */ if (filesys == NULL) return NULL; for (fs = filesys_info; fs; fs = fs->next) { + if (strchr(fs->device, '=')) + try_again++; + if (!strcmp(filesys, fs->device) || + !strcmp(filesys, fs->mountpt)) + break; + } + if (fs && strchr(fs->device, '=')) + fs->device = interpret_device(fs->device); + + if (fs || !try_again) + return fs; + + for (fs = filesys_info; fs; fs = fs->next) { + fs->device = interpret_device(fs->device); if (!strcmp(filesys, fs->device) || !strcmp(filesys, fs->mountpt)) break; @@ -397,7 +400,8 @@ static int execute(const char *type, char *device, char *mntpt, argv[argc++] = string_copy(args[i]); if (progress & !progress_active()) { - if (strcmp(type, "ext2") == 0) { + if ((strcmp(type, "ext2") == 0) || + (strcmp(type, "ext3") == 0)) { argv[argc++] = string_copy("-C0"); inst->flags |= FLAG_PROGRESS; } @@ -408,7 +412,7 @@ static int execute(const char *type, char *device, char *mntpt, s = find_fsck(prog); if (s == NULL) { - fprintf(stderr, "fsck: %s: not found\n", prog); + fprintf(stderr, _("fsck: %s: not found\n"), prog); return ENOENT; } @@ -440,6 +444,7 @@ static int execute(const char *type, char *device, char *mntpt, inst->prog = string_copy(prog); inst->type = string_copy(type); inst->device = string_copy(device); + inst->base_device = base_device(device); inst->start_time = time(0); inst->next = NULL; @@ -490,7 +495,7 @@ static struct fsck_instance *wait_one(NOARGS) continue; if (errno == ECHILD) { fprintf(stderr, - "%s: wait: No more child process?!?\n", + _("%s: wait: No more child process?!?\n"), progname); return NULL; } @@ -512,13 +517,13 @@ static struct fsck_instance *wait_one(NOARGS) if (sig == SIGINT) { status = EXIT_UNCORRECTED; } else { - printf("Warning... %s for device %s exited " - "with signal %d.\n", + printf(_("Warning... %s for device %s exited " + "with signal %d.\n"), inst->prog, inst->device, sig); status = EXIT_ERROR; } } else { - printf("%s %s: status is %x, should never happen.\n", + printf(_("%s %s: status is %x, should never happen.\n"), inst->prog, inst->device, status); status = EXIT_ERROR; } @@ -532,7 +537,8 @@ static struct fsck_instance *wait_one(NOARGS) for (inst2 = instance_list; inst2; inst2 = inst2->next) { if (inst2->flags & FLAG_DONE) continue; - if (strcmp(inst2->type, "ext2")) + if (strcmp(inst2->type, "ext2") && + strcmp(inst2->type, "ext3")) continue; /* * If we've just started the fsck, wait a tiny @@ -547,6 +553,7 @@ static struct fsck_instance *wait_one(NOARGS) } } else kill(inst2->pid, SIGUSR1); + inst2->flags |= FLAG_PROGRESS; break; } } @@ -588,11 +595,14 @@ static void fsck_device(char *device, int interactive) struct fs_info *fsent; int retval; - if (fstype && strncmp(fstype, "no", 2) && !strchr(fstype, ',')) + if (fstype && strncmp(fstype, "no", 2) && + strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) && + !strchr(fstype, ',')) type = fstype; if ((fsent = lookup(device))) { device = fsent->device; + interpret_type(fsent); if (!type) type = fsent->type; } @@ -602,36 +612,150 @@ static void fsck_device(char *device, int interactive) retval = execute(type, device, fsent ? fsent->mountpt : 0, interactive); if (retval) { - fprintf(stderr, "%s: Error %d while executing fsck.%s " - "for %s\n", progname, retval, type, device); + fprintf(stderr, _("%s: Error %d while executing fsck.%s " + "for %s\n"), progname, retval, type, device); } } -/* See if filesystem type matches the list. */ -static int fs_match(char *type, char *fs_type) + +/* + * Deal with the fsck -t argument. + */ +struct fs_type_compile { + char **list; + int *type; + int negate; +} fs_type_compiled; + +#define FS_TYPE_NORMAL 0 +#define FS_TYPE_OPT 1 +#define FS_TYPE_NEGOPT 2 + +static const char *fs_type_syntax_error = +N_("Either all or none of the filesystem types passed to -t must be prefixed\n" + "with 'no' or '!'.\n"); + +static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp) { - int ret = 0, negate = 0; - char list[128]; - char *s; + char *cp, *list, *s; + int num = 2; + int negate, first_negate = 1; + + if (fs_type) { + for (cp=fs_type; *cp; cp++) { + if (*cp == ',') + num++; + } + } - if (!fs_type) return(1); + cmp->list = malloc(num * sizeof(char *)); + cmp->type = malloc(num * sizeof(int)); + if (!cmp->list || !cmp->type) { + fprintf(stderr, _("Couldn't allocate memory for " + "filesystem types\n")); + exit(EXIT_ERROR); + } + memset(cmp->list, 0, num * sizeof(char *)); + memset(cmp->type, 0, num * sizeof(int)); + cmp->negate = 0; - if (strncmp(fs_type, "no", 2) == 0) { - fs_type += 2; - negate = 1; - } - strcpy(list, fs_type); - s = strtok(list, ","); - while(s) { - if (strcmp(s, type) == 0) { - ret = 1; - break; - } - s = strtok(NULL, ","); - } - return(negate ? !ret : ret); + if (!fs_type) + return; + + list = string_copy(fs_type); + num = 0; + s = strtok(list, ","); + while(s) { + negate = 0; + if (strncmp(s, "no", 2) == 0) { + s += 2; + negate = 1; + } else if (*s == '!') { + s++; + negate = 1; + } + if (strcmp(s, "loop") == 0) + /* loop is really short-hand for opts=loop */ + goto loop_special_case; + else if (strncmp(s, "opts=", 5) == 0) { + s += 5; + loop_special_case: + cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT; + } else { + if (first_negate) { + cmp->negate = negate; + first_negate = 0; + } + if ((negate && !cmp->negate) || + (!negate && cmp->negate)) { + fprintf(stderr, _(fs_type_syntax_error)); + exit(EXIT_USAGE); + } + } +#if 0 + printf("Adding %s to list (type %d).\n", s, cmp->type[num]); +#endif + cmp->list[num++] = string_copy(s); + s = strtok(NULL, ","); + } + free(list); } +/* + * This function returns true if a particular option appears in a + * comma-delimited options list + */ +static int opt_in_list(char *opt, char *optlist) +{ + char *list, *s; + + if (!optlist) + return 0; + list = string_copy(optlist); + + s = strtok(list, ","); + while(s) { + if (strcmp(s, opt) == 0) { + free(list); + return 1; + } + s = strtok(NULL, ","); + } + free(list); + return 0; +} + +/* See if the filesystem matches the criteria given by the -t option */ +static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp) +{ + int n, ret = 0, checked_type = 0; + char *cp; + + if (cmp->list == 0 || cmp->list[0] == 0) + return 1; + + for (n=0; cp = cmp->list[n]; n++) { + switch (cmp->type[n]) { + case FS_TYPE_NORMAL: + checked_type++; + if (strcmp(cp, fs->type) == 0) { + ret = 1; + } + break; + case FS_TYPE_NEGOPT: + if (opt_in_list(cp, fs->opts)) + return 0; + break; + case FS_TYPE_OPT: + if (!opt_in_list(cp, fs->opts)) + return 0; + break; + } + } + if (checked_type == 0) + return 1; + return (cmp->negate ? !ret : ret); +} /* Check if we should ignore this filesystem. */ static int ignore(struct fs_info *fs) @@ -645,15 +769,17 @@ static int ignore(struct fs_info *fs) if (fs->passno == 0) return 1; + interpret_type(fs); + /* * If a specific fstype is specified, and it doesn't match, * ignore it. */ - if (!fs_match(fs->type, fstype)) return 1; + if (!fs_match(fs, &fs_type_compiled)) return 1; /* Are we ignoring this type? */ for(ip = ignored_types; *ip; ip++) - if (strcmp(fs->type, *ip) == 0) return(1); + if (strcmp(fs->type, *ip) == 0) return 1; /* Do we really really want to check this fs? */ for(ip = really_wanted; *ip; ip++) @@ -665,9 +791,9 @@ static int ignore(struct fs_info *fs) /* See if the program is available. */ if (find_fsck(fs->type) == NULL) { if (wanted) - fprintf(stderr, "fsck: cannot check %s: fsck.%s not found\n", + fprintf(stderr, _("fsck: cannot check %s: fsck.%s not found\n"), fs->device, fs->type); - return(1); + return 1; } /* We can and want to check this file system type. */ @@ -675,38 +801,39 @@ static int ignore(struct fs_info *fs) } /* - * Return the "base device" given a particular device; this is used to - * assure that we only fsck one partition on a particular drive at any - * one time. Otherwise, the disk heads will be seeking all over the - * place. - */ -static const char *base_device(char *device) -{ - const char **base; - - for (base = base_devices; *base; base++) { - if (!strncmp(*base, device, strlen(*base))) - return *base; - } - return device; -} - -/* * Returns TRUE if a partition on the same disk is already being * checked. */ static int device_already_active(char *device) { struct fsck_instance *inst; - const char *base = base_device(device); + char *base; if (force_all_parallel) return 0; +#ifdef BASE_MD + /* Don't check a soft raid disk with any other disk */ + if (instance_list && + (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) || + !strncmp(device, BASE_MD, sizeof(BASE_MD)-1))) + return 1; +#endif + + base = base_device(device); + /* + * If we don't know the base device, assume that the device is + * already active if there are any fsck instances running. + */ + if (!base) + return (instance_list != 0); for (inst = instance_list; inst; inst = inst->next) { - if (!strcmp(base, base_device(inst->device))) + if (!inst->base_device || !strcmp(base, inst->base_device)) { + free(base); return 1; + } } + free(base); return 0; } @@ -721,34 +848,39 @@ static int check_all(NOARGS) int pass_done; if (verbose) - printf("Checking all file systems.\n"); + printf(_("Checking all file systems.\n")); /* - * Find and check the root filesystem first. + * Do an initial scan over the filesystem; mark filesystems + * which should be ignored as done, and resolve LABEL= and + * UUID= specifications to the real device. + */ + for (fs = filesys_info; fs; fs = fs->next) { + if (ignore(fs)) + fs->flags |= FLAG_DONE; + else + fs->device = interpret_device(fs->device); + } + + /* + * Find and check the root filesystem. */ if (!parallel_root) { for (fs = filesys_info; fs; fs = fs->next) { if (!strcmp(fs->mountpt, "/")) break; } - if (fs && !skip_root && !ignore(fs)) { - fsck_device(fs->device, 1); + if (fs) { + if (!skip_root && !ignore(fs)) { + fsck_device(fs->device, 1); + status |= wait_all(); + if (status > EXIT_NONDESTRUCT) + return status; + } fs->flags |= FLAG_DONE; - status |= wait_all(); - if (status > EXIT_NONDESTRUCT) - return status; } } - if (fs) fs->flags |= FLAG_DONE; - /* - * Mark filesystems that should be ignored as done. - */ - for (fs = filesys_info; fs; fs = fs->next) { - if (ignore(fs)) - fs->flags |= FLAG_DONE; - } - while (not_done_yet) { not_done_yet = 0; pass_done = 1; @@ -786,7 +918,7 @@ static int check_all(NOARGS) } } if (verbose > 1) - printf("--waiting-- (pass %d)\n", passno); + printf(_("--waiting-- (pass %d)\n"), passno); inst = wait_one(); if (inst) { status |= inst->exit_status; @@ -807,7 +939,7 @@ static int check_all(NOARGS) static void usage(NOARGS) { fprintf(stderr, - "Usage: fsck [-ACNPRTV] [-t fstype] [fs-options] filesys\n"); + _("Usage: fsck [-ACNPRTV] [-t fstype] [fs-options] filesys\n")); exit(EXIT_USAGE); } @@ -833,9 +965,9 @@ static void PRS(int argc, char *argv[]) (strncmp(arg, "LABEL=", 6) == 0) || (strncmp(arg, "UUID=", 5) == 0)) { if (num_devices >= MAX_DEVICES) { - fprintf(stderr, "%s: too many devices\n", + fprintf(stderr, _("%s: too many devices\n"), progname); - exit(1); + exit(EXIT_ERROR); } devices[num_devices++] = interpret_device(string_copy(arg)); @@ -843,9 +975,9 @@ static void PRS(int argc, char *argv[]) } if (arg[0] != '-' || opts_for_fsck) { if (num_args >= MAX_ARGS) { - fprintf(stderr, "%s: too many arguments\n", + fprintf(stderr, _("%s: too many arguments\n"), progname); - exit(1); + exit(EXIT_ERROR); } args[num_args++] = string_copy(arg); continue; @@ -886,11 +1018,13 @@ static void PRS(int argc, char *argv[]) case 't': if (arg[j+1]) { fstype = string_copy(arg+j+1); + compile_fs_type(fstype, &fs_type_compiled); goto next_arg; } if ((i+1) < argc) { i++; fstype = string_copy(argv[i]); + compile_fs_type(fstype, &fs_type_compiled); goto next_arg; } usage(); @@ -898,6 +1032,9 @@ static void PRS(int argc, char *argv[]) case '-': opts_for_fsck++; break; + case '?': + usage(); + break; default: options[++opt] = arg[j]; break; @@ -909,9 +1046,9 @@ static void PRS(int argc, char *argv[]) options[++opt] = '\0'; if (num_args >= MAX_ARGS) { fprintf(stderr, - "%s: too many arguments\n", + _("%s: too many arguments\n"), progname); - exit(1); + exit(EXIT_ERROR); } args[num_args++] = string_copy(options); opt = 0; @@ -929,11 +1066,15 @@ int main(int argc, char *argv[]) char *oldpath = getenv("PATH"); const char *fstab; +#ifdef ENABLE_NLS + setlocale(LC_MESSAGES, ""); + bindtextdomain(NLS_CAT_NAME, LOCALEDIR); + textdomain(NLS_CAT_NAME); +#endif PRS(argc, argv); if (!notitle) - printf("Parallelizing fsck version %s (%s)\n", - E2FSPROGS_VERSION, E2FSPROGS_DATE); + printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); fstab = getenv("FSTAB_FILE"); if (!fstab) @@ -958,6 +1099,10 @@ int main(int argc, char *argv[]) if (doall) return check_all(); + if (num_devices == 0) { + fprintf(stderr, _("\nNo devices specified to be checked!\n")); + exit(EXIT_ERROR); + } for (i = 0 ; i < num_devices; i++) { fsck_device(devices[i], interactive); if (serialize) {