summaryrefslogtreecommitdiffstats
path: root/sbin/fsck/fsck.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/fsck/fsck.c')
-rw-r--r--sbin/fsck/fsck.c113
1 files changed, 93 insertions, 20 deletions
diff --git a/sbin/fsck/fsck.c b/sbin/fsck/fsck.c
index a4d241a..09d1804 100644
--- a/sbin/fsck/fsck.c
+++ b/sbin/fsck/fsck.c
@@ -78,10 +78,11 @@ struct entry {
static char *options = NULL;
static int flags = 0;
+static int forceflag = 0;
int main __P((int, char *[]));
-static int checkfs __P((const char *, const char *, const char *, void *,
+static int checkfs __P((const char *, const char *, const char *, char *,
pid_t *));
static int selected __P((const char *));
static void addoption __P((char *));
@@ -92,7 +93,7 @@ static void catopt __P((char **, const char *));
static void mangle __P((char *, int *, const char ***, int *));
static const char *getfslab __P((const char *));
static void usage __P((void));
-static void *isok __P((struct fstab *));
+static int isok __P((struct fstab *));
int
main(argc, argv)
@@ -110,8 +111,14 @@ main(argc, argv)
TAILQ_INIT(&selhead);
TAILQ_INIT(&opthead);
- while ((i = getopt(argc, argv, "dvpfnyl:t:T:")) != -1)
+ while ((i = getopt(argc, argv, "BdvpfFnyl:t:T:")) != -1)
switch (i) {
+ case 'B':
+ if (flags & CHECK_BACKGRD)
+ errx(1, "Cannot specify -B and -F.");
+ flags |= DO_BACKGRD;
+ break;
+
case 'd':
flags |= CHECK_DEBUG;
break;
@@ -120,16 +127,27 @@ main(argc, argv)
flags |= CHECK_VERBOSE;
break;
+ case 'F':
+ if (flags & DO_BACKGRD)
+ errx(1, "Cannot specify -B and -F.");
+ flags |= CHECK_BACKGRD;
+ break;
+
case 'p':
flags |= CHECK_PREEN;
/*FALLTHROUGH*/
case 'n':
- case 'f':
case 'y':
globopt[1] = i;
catopt(&options, globopt);
break;
+ case 'f':
+ forceflag = 1;
+ globopt[1] = i;
+ catopt(&options, globopt);
+ break;
+
case 'l':
warnx("Ignoring obsolete -l option\n");
break;
@@ -165,8 +183,9 @@ main(argc, argv)
for (; argc--; argv++) {
- const char *spec, *type, *cp;
- char device[MAXPATHLEN];
+ const char *spec, *mntpt, *type, *cp;
+ char device[MAXPATHLEN];
+ struct statfs *mntp;
spec = *argv;
cp = strrchr(spec, '/');
@@ -175,48 +194,98 @@ main(argc, argv)
_PATH_DEV, spec);
spec = device;
}
+ mntp = getmntpt(spec);
+ if (mntp != NULL) {
+ spec = mntp->f_mntfromname;
+ mntpt = mntp->f_mntonname;
+ }
if ((fs = getfsfile(spec)) == NULL &&
(fs = getfsspec(spec)) == NULL) {
if (vfstype == NULL)
vfstype = getfslab(spec);
type = vfstype;
- }
- else {
+ devcheck(spec);
+ } else {
spec = fs->fs_spec;
type = fs->fs_vfstype;
+ mntpt = fs->fs_file;
if (BADTYPE(fs->fs_type))
errx(1, "%s has unknown file system type.",
spec);
}
+ if ((flags & CHECK_BACKGRD) &&
+ checkfs(type, spec, mntpt, "-F", NULL) == 0) {
+ printf("%s: DEFER FOR BACKGROUND CHECKING\n", *argv);
+ continue;
+ }
+ if ((flags & DO_BACKGRD) && forceflag == 0 &&
+ checkfs(type, spec, mntpt, "-F", NULL) != 0)
+ continue;
- rval |= checkfs(type, devcheck(spec), *argv, NULL, NULL);
+ rval |= checkfs(type, spec, mntpt, NULL, NULL);
}
return rval;
}
-static void *
+static int
isok(fs)
struct fstab *fs;
{
- if (fs->fs_passno == 0)
- return NULL;
+ int i;
+ if (fs->fs_passno == 0)
+ return (0);
if (BADTYPE(fs->fs_type))
- return NULL;
-
+ return (0);
if (!selected(fs->fs_vfstype))
- return NULL;
-
- return fs;
+ return (0);
+ /*
+ * If the -B flag has been given, then process the needed
+ * background checks. Background checks cannot be run on
+ * filesystems that will be mounted read-only or that were
+ * not mounted at boot time (typically those marked `noauto').
+ * If these basic tests are passed, check with the filesystem
+ * itself to see if it is willing to do background checking
+ * by invoking its check program with the -F flag.
+ */
+ if (flags & DO_BACKGRD) {
+ if (!strcmp(fs->fs_type, FSTAB_RO))
+ return (0);
+ if (getmntpt(fs->fs_spec) == NULL)
+ return (0);
+ if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", 0))
+ return (0);
+ return (1);
+ }
+ /*
+ * If the -F flag has been given, then consider deferring the
+ * check to background. Background checks cannot be run on
+ * filesystems that will be mounted read-only or that will
+ * not be mounted at boot time (e.g., marked `noauto'). If
+ * these basic tests are passed, check with the filesystem
+ * itself to see if it is willing to defer to background
+ * checking by invoking its check program with the -F flag.
+ */
+ if ((flags & CHECK_BACKGRD) == 0 || !strcmp(fs->fs_type, FSTAB_RO))
+ return (1);
+ for (i = strlen(fs->fs_mntops) - 6; i >= 0; i--)
+ if (!strncmp(&fs->fs_mntops[i], "noauto", 6))
+ break;
+ if (i >= 0)
+ return (1);
+ if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", NULL) != 0)
+ return (1);
+ printf("%s: DEFER FOR BACKGROUND CHECKING\n", fs->fs_spec);
+ return (0);
}
static int
-checkfs(pvfstype, spec, mntpt, auxarg, pidp)
+checkfs(pvfstype, spec, mntpt, auxopt, pidp)
const char *pvfstype, *spec, *mntpt;
- void *auxarg;
+ char *auxopt;
pid_t *pidp;
{
/* List of directories containing fsck_xxx subcommands. */
@@ -256,6 +325,10 @@ checkfs(pvfstype, spec, mntpt, auxarg, pidp)
catopt(&optbuf, options);
if (extra)
catopt(&optbuf, extra);
+ if (auxopt)
+ catopt(&optbuf, auxopt);
+ else if (flags & DO_BACKGRD)
+ catopt(&optbuf, "-B");
maxargc = 64;
argv = emalloc(sizeof(char *) * maxargc);
@@ -285,7 +358,7 @@ checkfs(pvfstype, spec, mntpt, auxarg, pidp)
return (1);
case 0: /* Child. */
- if (flags & CHECK_DEBUG)
+ if ((flags & CHECK_DEBUG) && auxopt == NULL)
_exit(0);
/* Go find an executable. */
OpenPOWER on IntegriCloud