diff options
Diffstat (limited to 'sutils/fsck.c')
-rw-r--r-- | sutils/fsck.c | 174 |
1 files changed, 84 insertions, 90 deletions
diff --git a/sutils/fsck.c b/sutils/fsck.c index ec2628ba..1ab9caa5 100644 --- a/sutils/fsck.c +++ b/sutils/fsck.c @@ -1,8 +1,8 @@ /* Hurd-aware fsck wrapper - Copyright (C) 1996 Free Software Foundation, Inc. + Copyright (C) 1996, 97, 98, 99 Free Software Foundation, Inc. - Written by Miles Bader <miles@gnu.ai.mit.edu> + Written by Miles Bader <miles@gnu.org> This file is part of the GNU Hurd. @@ -28,7 +28,7 @@ -n Automatically answer no to all questions -f Check even if clean -s Only print diagostic messages - + They should also return exit-status codes as following: 0 Filesystem was clean @@ -41,7 +41,7 @@ Although it knows something about the hurd, this fsck still uses /etc/fstab, and is generally not very integrated. That will have to wait - until the appropiate mechanisms for doing so are decided. */ + until the appropriate mechanisms for doing so are decided. */ #include <stdlib.h> #include <string.h> @@ -51,10 +51,12 @@ #include <argp.h> #include <argz.h> #include <assert.h> +#include <version.h> #include "fstab.h" -char *argp_program_version = "fsck 1.0 (GNU " HURD_RELEASE ")"; +const char *argp_program_version = STANDARD_HURD_VERSION (fsck); + /* for debugging */ static int _debug = 0; @@ -93,6 +95,7 @@ static int _debug = 0; #define FSCK_F_VERBOSE 0x100 #define FSCK_F_WRITABLE 0x200 /* Make writable after fscking. */ #define FSCK_F_AUTO 0x400 /* Do all filesystems in fstab. */ +#define FSCK_F_DRYRUN 0x800 /* Don't actually do anything. */ static int got_sigquit = 0, got_sigint = 0; @@ -110,7 +113,7 @@ struct fsck { struct fs *fs; /* Filesystem being fscked. */ int pid; /* Pid for process. */ - int make_writable :1; /* Make writable after fscking if possible. */ + int make_writable; /* Make writable after fscking if possible. */ struct fsck *next, **self; }; @@ -155,6 +158,17 @@ fs_start_fsck (struct fs *fs, int flags) *argp++ = fs->mntent.mnt_fsname; *argp = 0; + if (flags & FSCK_F_DRYRUN) + { + char *argz; + size_t argz_len; + argz_create (argv, &argz, &argz_len); + argz_stringify (argz, argz_len, ' '); + puts (argz); + free (argz); + return 0; + } + pid = fork (); if (pid < 0) { @@ -209,7 +223,7 @@ fscks_start_fsck (struct fscks *fscks, struct fs *fs) fs_debug (fs, "Checking mounted state"); err = fs_mounted (fs, &mounted); CK (err, "%s: Cannot check mounted state", fs->mntent.mnt_dir); - + if (mounted) { int readonly; @@ -218,6 +232,16 @@ fscks_start_fsck (struct fscks *fscks, struct fs *fs) err = fs_readonly (fs, &readonly); CK (err, "%s: Cannot check readonly state", fs->mntent.mnt_dir); + if (fscks->flags & FSCK_F_DRYRUN) + { + if (! readonly) + { + printf ("%s: writable filesystem %s would be made read-only\n", + program_invocation_name, fs->mntent.mnt_dir); + readonly = 1; + } + } + if (! readonly) { fs_debug (fs, "Making readonly"); @@ -272,7 +296,10 @@ fsck_cleanup (struct fsck *fsck, int remount, int make_writable) error_t err = 0; struct fs *fs = fsck->fs; - *fsck->self = fsck->next; /* Remove from chain. */ + /* Remove from chain. */ + *fsck->self = fsck->next; + if (fsck->next) + fsck->next->self = fsck->self; fs_debug (fs, "Cleaning up after fsck (remount = %d, make_writable = %d)", remount, make_writable); @@ -322,7 +349,7 @@ fscks_wait (struct fscks *fscks) debug ("Waiting..."); - do + do pid = wait (&wstatus); while (pid < 0 && errno == EINTR); @@ -387,20 +414,18 @@ fsck (struct fstab *fstab, int flags, int max_parallel) summary_status = status; } - /* Do in pass order; if in automatic mode, we skip pass 0. */ - for (pass = autom ? 1 : 0; pass >= 0; pass = fstab_next_pass (fstab, pass)) + /* Do in pass order; pass 0 is never run, it is reserved for "off". */ + for (pass = 1; pass > 0; pass = fstab_next_pass (fstab, pass)) /* Submit all filesystems in the given pass, up to MAX_PARALLEL at a time. There should currently be no fscks running. */ { debug ("Pass %d", pass); - /* Do pass 0 filesystems one at a time. */ - fscks.free_slots = (pass == 0 ? 1 : max_parallel); + fscks.free_slots = max_parallel; /* Try and fsck every filesystem in this pass. */ for (fs = fstab->entries; fs; fs = fs->next) - if (fs->mntent.mnt_passno == pass - && !(autom && hasmntopt (&fs->mntent, "noauto"))) + if (fs->mntent.mnt_passno == pass) /* FS is applicable for this pass. */ { struct fstype *type; @@ -421,8 +446,11 @@ fsck (struct fstab *fstab, int flags, int max_parallel) merge_status (fscks_wait (&fscks)); merge_status (fscks_start_fsck (&fscks, fs)); } - else + else if (autom) fs_debug (fs, "Not fsckable"); + else + error (0, 0, "%s: %s: Not a fsckable filesystem type", + fs->mntent.mnt_dir, fs->mntent.mnt_type); } /* Now wait for them all to finish. */ @@ -433,48 +461,44 @@ fsck (struct fstab *fstab, int flags, int max_parallel) return summary_status; } -static const struct argp_option -options[] = +static const struct argp_option options[] = { {"preen", 'p', 0, 0, "Terse automatic mode", 1}, {"yes", 'y', 0, 0, "Automatically answer yes to all questions"}, {"no", 'n', 0, 0, "Automatically answer no to all questions"}, - {"fstab", 't', "FILE", 0, "File to use instead of " _PATH_MNTTAB}, {"parallel", 'l', "NUM", 0, "Limit the number of parallel checks to NUM"}, {"verbose", 'v', 0, 0, "Print informational messages"}, {"writable", 'w', 0, 0, "Make RW filesystems writable after fscking, if possible"}, {"debug", 'D', 0, OPTION_HIDDEN }, - {"search-fmts",'S', "FMTS", 0, - "`:' separated list of formats to use for finding fsck programs"}, - {0, 0, 0, 0, "In --preen mode, the following also apply:", 2}, {"force", 'f', 0, 0, "Check even if clean"}, - {"silent", 's', 0, 0, "Only print diagostic messages"}, + + {"dry-run", 'N', 0, 0, "Don't check, just show what would be done"}, + {0, 0, 0, 0, "In --preen mode, the following also apply:", 2}, + {"silent", 's', 0, 0, "Print only diagnostic messages"}, {"quiet", 'q', 0, OPTION_ALIAS | OPTION_HIDDEN }, {0, 0} }; -static const char *args_doc = "[ DEVICE|FSYS... ]"; -static const char *doc = 0; +static const char doc[] = "Filesystem consistency check and repair"; +static const char args_doc[] = "[ DEVICE|FSYS... ]"; + int main (int argc, char **argv) { - error_t err; - struct fstab *fstab, *check; - struct fstypes *types; + struct fstab *check; int status; /* exit status */ int flags = 0; - char *names = 0; - size_t names_len = 0; - char *search_fmts = FSCK_SEARCH_FMTS; - size_t search_fmts_len = sizeof FSCK_SEARCH_FMTS; - char *fstab_path = _PATH_MNTTAB; int max_parallel = -1; /* -1 => use default */ error_t parse_opt (int key, char *arg, struct argp_state *state) { + struct fstab_argp_params *params = state->input; switch (key) { + case ARGP_KEY_INIT: + state->child_inputs[0] = params; /* pass down to fstab_argp parser */ + break; case 'p': flags |= FSCK_F_PREEN; break; case 'y': flags |= FSCK_F_YES; break; case 'n': flags |= FSCK_F_NO; break; @@ -482,79 +506,49 @@ main (int argc, char **argv) case 's': flags |= FSCK_F_SILENT; break; case 'v': flags |= FSCK_F_VERBOSE; break; case 'w': flags |= FSCK_F_WRITABLE; break; - case 't': fstab_path = arg; break; + case 'N': flags |= FSCK_F_DRYRUN; break; case 'D': _debug = 1; break; case 'l': max_parallel = atoi (arg); - if (! max_parallel) - argp_error (state, "%s: Invalid value for --max-parellel", arg); - break; - case 'S': - argz_create_sep (arg, ':', &search_fmts, &search_fmts_len); + if (max_parallel < 1) + argp_error (state, "%s: Invalid value for --max-parallel", arg); break; - case ARGP_KEY_ARG: - err = argz_add (&names, &names_len, arg); - if (err) - argp_failure (state, 100, ENOMEM, "%s", arg); + case ARGP_KEY_NO_ARGS: + if (flags & FSCK_F_PREEN) + params->do_all = 1; + else if (!params->do_all) + { + argp_usage (state); + return EINVAL; + } break; default: return ARGP_ERR_UNKNOWN; } return 0; } - struct argp argp = {options, parse_opt, args_doc, doc}; - - argp_parse (&argp, argc, argv, 0, 0, 0); - - err = fstypes_create (search_fmts, search_fmts_len, &types); - if (err) - error (102, err, "fstypes_create"); - - err = fstab_create (types, &fstab); - if (err) - error (101, err, "fstab_create"); - - debug ("Reading %s...", fstab_path); - err = fstab_read (fstab, fstab_path); - if (err) - error (103, err, "%s", fstab_path); + static const struct argp_child kids[] = + { { &fstab_argp, 0, + "Filesystem selection (default is all in " _PATH_MNTTAB "):", 2 }, + { 0 } }; + struct argp argp = { options, parse_opt, args_doc, doc, kids }; + struct fstab_argp_params fstab_params; - if (names) - /* Fsck specified filesystems; also look at /var/run/mtab. */ - { - char *name; - - debug ("Reading %s...", _PATH_MOUNTED); - err = fstab_read (fstab, _PATH_MOUNTED); - if (err && err != ENOENT) - error (104, err, "%s", _PATH_MOUNTED); + argp_parse (&argp, argc, argv, 0, 0, &fstab_params); - err = fstab_create (types, &check); - if (err) - error (105, err, "fstab_create"); + check = fstab_argp_create (&fstab_params, + FSCK_SEARCH_FMTS, sizeof FSCK_SEARCH_FMTS); + if (fstab_params.do_all) + flags |= FSCK_F_AUTO; - for (name = names; name; name = argz_next (names, names_len, name)) - { - struct fs *fs = fstab_find (fstab, name); - if (! fs) - error (106, 0, "%s: Unknown device or filesystem", name); - fs_debug (fs, "Adding to checked filesystems"); - fstab_add_fs (check, fs, 0); - } - } - else - /* Fsck everything in /etc/fstab. */ + if (max_parallel <= 0) { - check = fstab; - flags |= FSCK_F_AUTO; + if (flags & FSCK_F_PREEN) + max_parallel = 100; /* In preen mode, do lots in parallel. */ + else + max_parallel = 1; /* Do one at a time to keep output rational. */ } - if (max_parallel <= 0) - if (flags & FSCK_F_PREEN) - max_parallel = 100; /* In preen mode, do lots in parallel. */ - else - max_parallel = 1; /* Do one at a time to keep output rational. */ - /* If the user send a SIGQUIT (usually ^\), then do all checks, but regardless of their outcome, return a status that will cause the automatic reboot to stop after fscking is complete. */ |