diff options
Diffstat (limited to 'sutils/fsck.c')
-rw-r--r-- | sutils/fsck.c | 179 |
1 files changed, 168 insertions, 11 deletions
diff --git a/sutils/fsck.c b/sutils/fsck.c index 28ea5f77..57b323f4 100644 --- a/sutils/fsck.c +++ b/sutils/fsck.c @@ -50,6 +50,7 @@ #include <error.h> #include <argp.h> #include <argz.h> +#include <fnmatch.h> #include <assert.h> #include <version.h> @@ -95,6 +96,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; @@ -157,6 +159,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) { @@ -220,6 +233,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"); @@ -392,20 +415,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; @@ -447,7 +468,7 @@ 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}, + {"fstab", 'F', "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, @@ -455,8 +476,14 @@ options[] = {"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"}, + {"exclude-root",'R',0, 0, + "Exclude root (/) filesystem from " _PATH_MNTTAB " list"}, + {"exclude", 'X', "PATTERN", 0, "Exclude directories matching PATTERN"}, + {"dry-run", 'N', 0, 0, "Don't check, just show what would be done"}, + {"fstype", 't', "TYPE", 0, "Check only filesystems of given type(s)"}, + {"all", 'A', 0, 0, "Check all filesystem in " _PATH_MNTTAB}, + {0, 0, 0, 0, "In --preen mode, the following also apply:", 2}, {"silent", 's', 0, 0, "Only print diagostic messages"}, {"quiet", 'q', 0, OPTION_ALIAS | OPTION_HIDDEN }, {0, 0} @@ -474,10 +501,15 @@ main (int argc, char **argv) int flags = 0; char *names = 0; size_t names_len = 0; + char *exclude = 0; + size_t exclude_len = 0; + char *include_types = 0, *exclude_types = 0; + size_t exclude_types_len = 0, include_types_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 */ + int do_all = 0; error_t parse_opt (int key, char *arg, struct argp_state *state) { @@ -490,11 +522,13 @@ 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 'A': do_all = 1; break; + case 'F': fstab_path = arg; break; case 'D': _debug = 1; break; case 'l': max_parallel = atoi (arg); - if (! max_parallel) + if (max_parallel < 1) argp_error (state, "%s: Invalid value for --max-parellel", arg); break; case 'S': @@ -505,6 +539,28 @@ main (int argc, char **argv) if (err) argp_failure (state, 100, ENOMEM, "%s", arg); break; + case 'R': + arg = "/"; + /* FALLTHROUGH */ + case 'X': + err = argz_add (&exclude, &exclude_len, arg); + if (err) + argp_failure (state, 100, ENOMEM, "%s", arg); + break; + case 't': + { + char *p; + while ((p = strsep (&arg, ",")) != 0) + { + if (!strncasecmp (p, "no", 2)) + err = argz_add (&exclude_types, &exclude_types_len, p + 2); + else + err = argz_add (&include_types, &include_types_len, p); + if (err) + argp_failure (state, 100, ENOMEM, "%s", arg); + } + } + break; default: return ARGP_ERR_UNKNOWN; } @@ -532,6 +588,13 @@ main (int argc, char **argv) { char *name; + if (do_all) + error (2, 0, "filesystem arguments not allowed with --all"); + else if (exclude) + error (2, 0, "--exclude not allowed with filesystem arguments"); + else if (include_types || exclude_types) + error (2, 0, "--fstype not allowed with filesystem arguments"); + debug ("Reading %s...", _PATH_MOUNTED); err = fstab_read (fstab, _PATH_MOUNTED); if (err && err != ENOENT) @@ -553,8 +616,102 @@ main (int argc, char **argv) else /* Fsck everything in /etc/fstab. */ { - check = fstab; flags |= FSCK_F_AUTO; + + if (exclude == 0 && include_types == 0 && exclude_types == 0) + check = fstab; + else + { + struct fs *fs; + + err = fstab_create (types, &check); + if (err) + error (105, err, "fstab_create"); + + /* For each excluded type (i.e. `-t notype'), clobber the + fstype entry's program with an empty string to mark it. */ + if (exclude_types) + { + const char *tn; + struct fstype *type; + for (tn = exclude_types; tn; + tn = argz_next (exclude_types, exclude_types_len, tn)) + { + err = fstypes_get (types, tn, &type); + if (err) + error (106, err, "fstypes_get"); + free (type->program); + type->program = strdup (""); + } + } + + if (include_types) + { + const char *tn; + struct fstypes *wanttypes; + + /* We will copy the types we want to include into a fresh + list in WANTTYPES. Since we specify no search formats, + `fstypes_get' applied to WANTTYPES can only create + elements with a null `program' field. */ + err = fstypes_create (0, 0, &wanttypes); + if (err) + error (102, err, "fstypes_create"); + + for (tn = include_types; tn; + tn = argz_next (include_types, include_types_len, tn)) + { + struct fstype *type; + err = fstypes_get (types, tn, &type); + if (err) + error (106, err, "fstypes_get"); + if (type->program == 0) + error (0, 0, "requested filesystem type `%s' unknown", tn); + else + { + struct fstype *newtype = malloc (sizeof *newtype); + newtype->name = strdup (type->name); + newtype->program = strdup (type->program); + newtype->next = wanttypes->entries; + wanttypes->entries = newtype; + } + } + + /* fstypes_free (types); */ + types = wanttypes; + } + + for (fs = fstab->entries; fs; fs = fs->next) + { + const char *ptn; + struct fstype *type; + + err = fs_type (fs, &type); + if (err || include_types) + { + err = fstypes_get (types, fs->mntent.mnt_type, &type); + if (err) + error (106, err, "fstypes_get"); + if (exclude_types || include_types) + continue; + } + if (include_types && type->program == 0) + continue; /* Freshly created, was not in WANTTYPES. */ + if (type->program != 0 && type->program[0] == '\0') + continue; /* This type is marked as excluded. */ + + for (ptn = exclude; ptn; + ptn = argz_next (exclude, exclude_len, ptn)) + if (fnmatch (ptn, fs->mntent.mnt_dir, 0) == 0) + break; + if (ptn) /* An exclude pattern matched. */ + continue; + + err = fstab_add_fs (check, fs, 0); + if (err) + error (107, err, "fstab_add_fs"); + } + } } if (max_parallel <= 0) |