diff options
Diffstat (limited to 'e2fsprogs')
-rw-r--r-- | e2fsprogs/fsck.c | 261 |
1 files changed, 133 insertions, 128 deletions
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index adaf0c538..627d2be31 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c @@ -46,7 +46,7 @@ //kbuild:lib-$(CONFIG_FSCK) += fsck.o //usage:#define fsck_trivial_usage -//usage: "[-ANPRTV] [-C FD] [-t FSTYPE] [FS_OPTS] [BLOCKDEV]..." +//usage: "[-ANPRTV] [-t FSTYPE] [FS_OPTS] [BLOCKDEV]..." //usage:#define fsck_full_usage "\n\n" //usage: "Check and repair filesystems\n" //usage: "\n -A Walk /etc/fstab and check all filesystems" @@ -55,7 +55,8 @@ //usage: "\n -R With -A, skip the root filesystem" //usage: "\n -T Don't show title on startup" //usage: "\n -V Verbose" -//usage: "\n -C n Write status information to specified filedescriptor" +//DO_PROGRESS_INDICATOR is off: +////usage: "\n -C FD Write status information to specified file descriptor" //usage: "\n -t TYPE List of filesystem types to check" #include "libbb.h" @@ -136,35 +137,42 @@ static const char really_wanted[] ALIGN1 = #define BASE_MD "/dev/md" -static char **args; -static int num_args; -static int verbose; +struct globals { + char **args; + int num_args; + int verbose; #define FS_TYPE_FLAG_NORMAL 0 #define FS_TYPE_FLAG_OPT 1 #define FS_TYPE_FLAG_NEGOPT 2 -static char **fs_type_list; -static uint8_t *fs_type_flag; -static smallint fs_type_negated; - -static smallint noexecute; -static smallint serialize; -static smallint skip_root; -/* static smallint like_mount; */ -static smallint parallel_root; -static smallint force_all_parallel; + char **fs_type_list; + uint8_t *fs_type_flag; + smallint fs_type_negated; + + smallint noexecute; + smallint serialize; + smallint skip_root; + /* smallint like_mount; */ + smallint parallel_root; + smallint force_all_parallel; + smallint kill_sent; #if DO_PROGRESS_INDICATOR -static smallint progress; -static int progress_fd; + smallint progress; + int progress_fd; #endif -static int num_running; -static int max_running; -static char *fstype; -static struct fs_info *filesys_info; -static struct fs_info *filesys_last; -static struct fsck_instance *instance_list; + int num_running; + int max_running; + char *fstype; + struct fs_info *filesys_info; + struct fs_info *filesys_last; + struct fsck_instance *instance_list; +} FIX_ALIASING; +#define G (*(struct globals*)&bb_common_bufsiz1) +#define INIT_G() do { \ + BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \ +} while (0) /* * Return the "base device" given a particular device; this is used to @@ -313,11 +321,11 @@ static struct fs_info *create_fs_device(const char *device, const char *mntpnt, /*fs->flags = 0; */ /*fs->next = NULL; */ - if (!filesys_info) - filesys_info = fs; + if (!G.filesys_info) + G.filesys_info = fs; else - filesys_last->next = fs; - filesys_last = fs; + G.filesys_last->next = fs; + G.filesys_last = fs; return fs; } @@ -327,6 +335,7 @@ static void load_fs_info(const char *filename) { FILE *fstab; struct mntent mte; + char buf[1024]; fstab = setmntent(filename, "r"); if (!fstab) { @@ -335,7 +344,7 @@ static void load_fs_info(const char *filename) } // Loop through entries - while (getmntent_r(fstab, &mte, bb_common_bufsiz1, COMMON_BUFSIZE)) { + while (getmntent_r(fstab, &mte, buf, sizeof(buf))) { //bb_info_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir, // mte.mnt_type, mte.mnt_opts, // mte.mnt_passno); @@ -351,7 +360,7 @@ static struct fs_info *lookup(char *filesys) { struct fs_info *fs; - for (fs = filesys_info; fs; fs = fs->next) { + for (fs = G.filesys_info; fs; fs = fs->next) { if (strcmp(filesys, fs->device) == 0 || (fs->mountpt && strcmp(filesys, fs->mountpt) == 0) ) @@ -366,7 +375,7 @@ static int progress_active(void) { struct fsck_instance *inst; - for (inst = instance_list; inst; inst = inst->next) { + for (inst = G.instance_list; inst; inst = inst->next) { if (inst->flags & FLAG_DONE) continue; if (inst->flags & FLAG_PROGRESS) @@ -382,19 +391,17 @@ static int progress_active(void) */ static void kill_all_if_got_signal(void) { - static smallint kill_sent; - struct fsck_instance *inst; - if (!bb_got_signal || kill_sent) + if (!bb_got_signal || G.kill_sent) return; - for (inst = instance_list; inst; inst = inst->next) { + for (inst = G.instance_list; inst; inst = inst->next) { if (inst->flags & FLAG_DONE) continue; kill(inst->pid, SIGTERM); } - kill_sent = 1; + G.kill_sent = 1; } /* @@ -409,9 +416,9 @@ static int wait_one(int flags) struct fsck_instance *inst, *prev; pid_t pid; - if (!instance_list) + if (!G.instance_list) return -1; - /* if (noexecute) { already returned -1; } */ + /* if (G.noexecute) { already returned -1; } */ while (1) { pid = waitpid(-1, &status, flags); @@ -429,7 +436,7 @@ static int wait_one(int flags) continue; } prev = NULL; - inst = instance_list; + inst = G.instance_list; do { if (inst->pid == pid) goto child_died; @@ -439,9 +446,8 @@ static int wait_one(int flags) } child_died: - if (WIFEXITED(status)) - status = WEXITSTATUS(status); - else if (WIFSIGNALED(status)) { + status = WEXITSTATUS(status); + if (WIFSIGNALED(status)) { sig = WTERMSIG(status); status = EXIT_UNCORRECTED; if (sig != SIGINT) { @@ -450,16 +456,12 @@ static int wait_one(int flags) inst->prog, inst->device, sig); status = EXIT_ERROR; } - } else { - printf("%s %s: status is %x, should never happen\n", - inst->prog, inst->device, status); - status = EXIT_ERROR; } #if DO_PROGRESS_INDICATOR if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) { struct fsck_instance *inst2; - for (inst2 = instance_list; inst2; inst2 = inst2->next) { + for (inst2 = G.instance_list; inst2; inst2 = inst2->next) { if (inst2->flags & FLAG_DONE) continue; if (strcmp(inst2->type, "ext2") != 0 @@ -486,11 +488,11 @@ static int wait_one(int flags) if (prev) prev->next = inst->next; else - instance_list = inst->next; - if (verbose > 1) + G.instance_list = inst->next; + if (G.verbose > 1) printf("Finished with %s (exit status %d)\n", inst->device, status); - num_running--; + G.num_running--; free_instance(inst); return status; @@ -526,51 +528,51 @@ static void execute(const char *type, const char *device, struct fsck_instance *inst; pid_t pid; - args[0] = xasprintf("fsck.%s", type); + G.args[0] = xasprintf("fsck.%s", type); #if DO_PROGRESS_INDICATOR if (progress && !progress_active()) { if (strcmp(type, "ext2") == 0 || strcmp(type, "ext3") == 0 ) { - args[XXX] = xasprintf("-C%d", progress_fd); /* 1 */ + G.args[XXX] = xasprintf("-C%d", progress_fd); /* 1 */ inst->flags |= FLAG_PROGRESS; } } #endif - args[num_args - 2] = (char*)device; - /* args[num_args - 1] = NULL; - already is */ + G.args[G.num_args - 2] = (char*)device; + /* G.args[G.num_args - 1] = NULL; - already is */ - if (verbose || noexecute) { - printf("[%s (%d) -- %s]", args[0], num_running, + if (G.verbose || G.noexecute) { + printf("[%s (%d) -- %s]", G.args[0], G.num_running, mntpt ? mntpt : device); - for (i = 0; args[i]; i++) - printf(" %s", args[i]); + for (i = 0; G.args[i]; i++) + printf(" %s", G.args[i]); bb_putchar('\n'); } /* Fork and execute the correct program. */ pid = -1; - if (!noexecute) { - pid = spawn(args); + if (!G.noexecute) { + pid = spawn(G.args); if (pid < 0) - bb_simple_perror_msg(args[0]); + bb_simple_perror_msg(G.args[0]); } #if DO_PROGRESS_INDICATOR - free(args[XXX]); + free(G.args[XXX]); #endif /* No child, so don't record an instance */ if (pid <= 0) { - free(args[0]); + free(G.args[0]); return; } inst = xzalloc(sizeof(*inst)); inst->pid = pid; - inst->prog = args[0]; + inst->prog = G.args[0]; inst->device = xstrdup(device); inst->base_device = base_device(device); #if DO_PROGRESS_INDICATOR @@ -579,8 +581,8 @@ static void execute(const char *type, const char *device, /* Add to the list of running fsck's. * (was adding to the end, but adding to the front is simpler...) */ - inst->next = instance_list; - instance_list = inst; + inst->next = G.instance_list; + G.instance_list = inst; } /* @@ -599,27 +601,27 @@ static void fsck_device(struct fs_info *fs /*, int interactive */) if (strcmp(fs->type, "auto") != 0) { type = fs->type; - if (verbose > 2) + if (G.verbose > 2) bb_info_msg("using filesystem type '%s' %s", type, "from fstab"); - } else if (fstype - && (fstype[0] != 'n' || fstype[1] != 'o') /* != "no" */ - && !is_prefixed_with(fstype, "opts=") - && !is_prefixed_with(fstype, "loop") - && !strchr(fstype, ',') + } else if (G.fstype + && (G.fstype[0] != 'n' || G.fstype[1] != 'o') /* != "no" */ + && !is_prefixed_with(G.fstype, "opts=") + && !is_prefixed_with(G.fstype, "loop") + && !strchr(G.fstype, ',') ) { - type = fstype; - if (verbose > 2) + type = G.fstype; + if (G.verbose > 2) bb_info_msg("using filesystem type '%s' %s", type, "from -t"); } else { type = "auto"; - if (verbose > 2) + if (G.verbose > 2) bb_info_msg("using filesystem type '%s' %s", type, "(default)"); } - num_running++; + G.num_running++; execute(type, fs->device, fs->mountpt /*, interactive */); } @@ -632,13 +634,13 @@ static int device_already_active(char *device) struct fsck_instance *inst; char *base; - if (force_all_parallel) + if (G.force_all_parallel) return 0; #ifdef BASE_MD /* Don't check a soft raid disk with any other disk */ - if (instance_list - && (is_prefixed_with(instance_list->device, BASE_MD) + if (G.instance_list + && (is_prefixed_with(G.instance_list->device, BASE_MD) || is_prefixed_with(device, BASE_MD)) ) { return 1; @@ -651,9 +653,9 @@ static int device_already_active(char *device) * already active if there are any fsck instances running. */ if (!base) - return (instance_list != NULL); + return (G.instance_list != NULL); - for (inst = instance_list; inst; inst = inst->next) { + for (inst = G.instance_list; inst; inst = inst->next) { if (!inst->base_device || !strcmp(base, inst->base_device)) { free(base); return 1; @@ -698,17 +700,17 @@ static int fs_match(struct fs_info *fs) int n, ret, checked_type; char *cp; - if (!fs_type_list) + if (!G.fs_type_list) return 1; ret = 0; checked_type = 0; n = 0; while (1) { - cp = fs_type_list[n]; + cp = G.fs_type_list[n]; if (!cp) break; - switch (fs_type_flag[n]) { + switch (G.fs_type_flag[n]) { case FS_TYPE_FLAG_NORMAL: checked_type++; if (strcmp(cp, fs->type) == 0) @@ -728,7 +730,7 @@ static int fs_match(struct fs_info *fs) if (checked_type == 0) return 1; - return (fs_type_negated ? !ret : ret); + return (G.fs_type_negated ? !ret : ret); } /* Check if we should ignore this filesystem. */ @@ -764,7 +766,7 @@ static int check_all(void) smallint pass_done; int passno; - if (verbose) + if (G.verbose) puts("Checking all filesystems"); /* @@ -772,17 +774,17 @@ static int check_all(void) * which should be ignored as done, and resolve any "auto" * filesystem types (done as a side-effect of calling ignore()). */ - for (fs = filesys_info; fs; fs = fs->next) + for (fs = G.filesys_info; fs; fs = fs->next) if (ignore(fs)) fs->flags |= FLAG_DONE; /* * Find and check the root filesystem. */ - if (!parallel_root) { - for (fs = filesys_info; fs; fs = fs->next) { + if (!G.parallel_root) { + for (fs = G.filesys_info; fs; fs = fs->next) { if (LONE_CHAR(fs->mountpt, '/')) { - if (!skip_root && !ignore(fs)) { + if (!G.skip_root && !ignore(fs)) { fsck_device(fs /*, 1*/); status |= wait_many(FLAG_WAIT_ALL); if (status > EXIT_NONDESTRUCT) @@ -798,8 +800,8 @@ static int check_all(void) * filesystem listed twice. * "Skip root" will skip _all_ root entries. */ - if (skip_root) - for (fs = filesys_info; fs; fs = fs->next) + if (G.skip_root) + for (fs = G.filesys_info; fs; fs = fs->next) if (LONE_CHAR(fs->mountpt, '/')) fs->flags |= FLAG_DONE; @@ -809,7 +811,7 @@ static int check_all(void) not_done_yet = 0; pass_done = 1; - for (fs = filesys_info; fs; fs = fs->next) { + for (fs = G.filesys_info; fs; fs = fs->next) { if (bb_got_signal) break; if (fs->flags & FLAG_DONE) @@ -835,7 +837,7 @@ static int check_all(void) /* * Spawn off the fsck process */ - fsck_device(fs /*, serialize*/); + fsck_device(fs /*, G.serialize*/); fs->flags |= FLAG_DONE; /* @@ -843,8 +845,8 @@ static int check_all(void) * have a limit on the number of fsck's extant * at one time, apply that limit. */ - if (serialize - || (max_running && (num_running >= max_running)) + if (G.serialize + || (G.num_running >= G.max_running) ) { pass_done = 0; break; @@ -852,12 +854,12 @@ static int check_all(void) } if (bb_got_signal) break; - if (verbose > 1) + if (G.verbose > 1) printf("--waiting-- (pass %d)\n", passno); status |= wait_many(pass_done ? FLAG_WAIT_ALL : FLAG_WAIT_ATLEAST_ONE); if (pass_done) { - if (verbose > 1) + if (G.verbose > 1) puts("----------------------------------"); passno++; } else @@ -885,9 +887,9 @@ static void compile_fs_type(char *fs_type) s++; } - fs_type_list = xzalloc(num * sizeof(fs_type_list[0])); - fs_type_flag = xzalloc(num * sizeof(fs_type_flag[0])); - fs_type_negated = -1; /* not yet known is it negated or not */ + G.fs_type_list = xzalloc(num * sizeof(G.fs_type_list[0])); + G.fs_type_flag = xzalloc(num * sizeof(G.fs_type_flag[0])); + G.fs_type_negated = -1; /* not yet known is it negated or not */ num = 0; s = fs_type; @@ -909,18 +911,18 @@ static void compile_fs_type(char *fs_type) if (is_prefixed_with(s, "opts=")) { s += 5; loop_special_case: - fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT; + G.fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT; } else { - if (fs_type_negated == -1) - fs_type_negated = negate; - if (fs_type_negated != negate) + if (G.fs_type_negated == -1) + G.fs_type_negated = negate; + if (G.fs_type_negated != negate) bb_error_msg_and_die( "either all or none of the filesystem types passed to -t must be prefixed " "with 'no' or '!'"); } - comma = strchr(s, ','); - fs_type_list[num++] = comma ? xstrndup(s, comma-s) : xstrdup(s); - if (!comma) + comma = strchrnul(s, ','); + G.fs_type_list[num++] = xstrndup(s, comma-s); + if (*comma == '\0') break; s = comma + 1; } @@ -928,8 +930,8 @@ static void compile_fs_type(char *fs_type) static char **new_args(void) { - args = xrealloc_vector(args, 2, num_args); - return &args[num_args++]; + G.args = xrealloc_vector(G.args, 2, G.num_args); + return &G.args[G.num_args++]; } int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -946,6 +948,8 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) smallint doall; smallint notitle; + INIT_G(); + /* we want wait() to be interruptible */ signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); signal_no_SA_RESTART_empty_mask(SIGTERM, record_signo); @@ -955,8 +959,8 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) opts_for_fsck = doall = notitle = 0; devices = NULL; num_devices = 0; - new_args(); /* args[0] = NULL, will be replaced by fsck.<type> */ - /* instance_list = NULL; - in bss, so already zeroed */ + new_args(); /* G.args[0] = NULL, will be replaced by fsck.<type> */ + /* G.instance_list = NULL; - in bss, so already zeroed */ while (*++argv) { int j; @@ -1005,13 +1009,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) goto next_arg; #endif case 'V': - verbose++; + G.verbose++; break; case 'N': - noexecute = 1; + G.noexecute = 1; break; case 'R': - skip_root = 1; + G.skip_root = 1; break; case 'T': notitle = 1; @@ -1020,13 +1024,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) like_mount = 1; break; */ case 'P': - parallel_root = 1; + G.parallel_root = 1; break; case 's': - serialize = 1; + G.serialize = 1; break; case 't': - if (fstype) + if (G.fstype) bb_show_usage(); if (arg[++j]) tmp = &arg[j]; @@ -1034,8 +1038,8 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) tmp = *argv; else bb_show_usage(); - fstype = xstrdup(tmp); - compile_fs_type(fstype); + G.fstype = xstrdup(tmp); + compile_fs_type(G.fstype); goto next_arg; case '?': bb_show_usage(); @@ -1056,12 +1060,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) } } if (getenv("FSCK_FORCE_ALL_PARALLEL")) - force_all_parallel = 1; + G.force_all_parallel = 1; tmp = getenv("FSCK_MAX_INST"); + G.max_running = INT_MAX; if (tmp) - max_running = xatoi(tmp); - new_args(); /* args[num_args - 2] will be replaced by <device> */ - new_args(); /* args[num_args - 1] is the last, NULL element */ + G.max_running = xatoi(tmp); + new_args(); /* G.args[G.num_args - 2] will be replaced by <device> */ + new_args(); /* G.args[G.num_args - 1] is the last, NULL element */ if (!notitle) puts("fsck (busybox "BB_VER", "BB_BT")"); @@ -1073,10 +1078,10 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) fstab = "/etc/fstab"; load_fs_info(fstab); - /*interactive = (num_devices == 1) | serialize;*/ + /*interactive = (num_devices == 1) | G.serialize;*/ if (num_devices == 0) - /*interactive =*/ serialize = doall = 1; + /*interactive =*/ G.serialize = doall = 1; if (doall) return check_all(); @@ -1092,13 +1097,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) fs = create_fs_device(devices[i], "", "auto", NULL, -1); fsck_device(fs /*, interactive */); - if (serialize - || (max_running && (num_running >= max_running)) + if (G.serialize + || (G.num_running >= G.max_running) ) { int exit_status = wait_one(0); if (exit_status >= 0) status |= exit_status; - if (verbose > 1) + if (G.verbose > 1) puts("----------------------------------"); } } |