aboutsummaryrefslogtreecommitdiff
path: root/sutils/fsck.c
diff options
context:
space:
mode:
Diffstat (limited to 'sutils/fsck.c')
-rw-r--r--sutils/fsck.c174
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. */