* %End-Header%
*/
+/* All filesystem specific hooks have been removed.
+ * If filesystem cannot be determined, we will execute
+ * "fsck.auto". Currently this also happens if you specify
+ * UUID=xxx or LABEL=xxx as an object to check.
+ * Detection code for that is also probably has to be in fsck.auto.
+ *
+ * In other words, this is _really_ is just a driver program which
+ * spawns actual fsck.something for each filesystem to check.
+ * It doesn't guess filesystem types from on-disk format.
+ */
+
#include "busybox.h"
#define EXIT_OK 0
#define EXIT_USAGE 16
#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
-#ifndef DEFAULT_FSTYPE
-#define DEFAULT_FSTYPE "ext2"
-#endif
-
/*
- * Internal structure for mount tabel entries.
+ * Internal structure for mount table entries.
*/
struct fs_info {
static smallint notitle;
static smallint parallel_root;
static smallint force_all_parallel;
+
+/* "progress indicator" code is somewhat buggy and ext[23] specific.
+ * We should be filesystem agnostic. IOW: there should be a well-defined
+ * API for fsck.something, NOT ad-hoc hacks in generic fsck. */
+#define DO_PROGRESS_INDICATOR 0
+#if DO_PROGRESS_INDICATOR
static smallint progress;
static int progress_fd;
+#endif
+
static int num_running;
static int max_running;
static char *fstype;
static int parse_fstab_line(char *line, struct fs_info **ret_fs)
{
- /*char *dev;*/
char *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
struct fs_info *fs;
parse_escape(freq);
parse_escape(passno);
- /*
- dev = blkid_get_devname(cache, device, NULL);
- if (dev)
- device = dev;*/
-
if (strchr(type, ','))
type = NULL;
fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
- freq ? atoi(freq) : -1,
- passno ? atoi(passno) : -1);
- /*if (dev)
- free(dev);*/
-
+ freq ? atoi(freq) : -1,
+ passno ? atoi(passno) : -1);
*ret_fs = fs;
return 0;
}
-#if 0
-static void interpret_type(struct fs_info *fs)
-{
- char *t;
-
- if (strcmp(fs->type, "auto") != 0)
- return;
- t = blkid_get_tag_value(cache, "TYPE", fs->device);
- if (t) {
- free(fs->type);
- fs->type = t;
- }
-}
-#endif
-#define interpret_type(fs) ((void)0)
-
/* Load the filesystem database from /etc/fstab */
static void load_fs_info(const char *filename)
{
return fs;
}
+#if DO_PROGRESS_INDICATOR
static int progress_active(void)
{
struct fsck_instance *inst;
}
return 0;
}
+#endif
+
/*
* Send a signal to all outstanding fsck child processes
{
int status;
int sig;
- struct fsck_instance *inst, *inst2, *prev;
+ struct fsck_instance *inst, *prev;
pid_t pid;
if (!instance_list)
status = WEXITSTATUS(status);
else if (WIFSIGNALED(status)) {
sig = WTERMSIG(status);
- if (sig == SIGINT) {
- status = EXIT_UNCORRECTED;
- } else {
- printf("Warning... %s for device %s exited "
- "with signal %d.\n",
- inst->prog, inst->device, sig);
+ status = EXIT_UNCORRECTED;
+ if (sig != SIGINT) {
+ printf("Warning... %s %s exited "
+ "with signal %d\n",
+ inst->prog, inst->device, sig);
status = EXIT_ERROR;
}
} else {
- printf("%s %s: status is %x, should never happen.\n",
- inst->prog, inst->device, status);
+ printf("%s %s: status is %x, should never happen\n",
+ inst->prog, inst->device, status);
status = EXIT_ERROR;
}
inst->exit_status = status;
+
+#if DO_PROGRESS_INDICATOR
if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) {
+ struct fsck_instance *inst2;
for (inst2 = instance_list; inst2; inst2 = inst2->next) {
if (inst2->flags & FLAG_DONE)
continue;
break;
}
}
+#endif
+
ret_inst:
if (prev)
prev->next = inst->next;
* Execute a particular fsck program, and link it into the list of
* child processes we are waiting for.
*/
-static int execute(const char *type, const char *device, const char *mntpt,
+static void execute(const char *type, const char *device, const char *mntpt,
int interactive)
{
char *argv[num_args + 4]; /* see count below: */
int argc;
int i;
- struct fsck_instance *inst, *p;
+ struct fsck_instance *inst;
pid_t pid;
inst = xzalloc(sizeof(*inst));
argv[i+1] = args[i]; /* num_args */
argc = num_args + 1;
+#if DO_PROGRESS_INDICATOR
if (progress && !progress_active()) {
if (strcmp(type, "ext2") == 0
|| strcmp(type, "ext3") == 0
inst->flags |= FLAG_PROGRESS;
}
}
+#endif
argv[argc++] = xstrdup(device); /* 1 */
argv[argc] = NULL; /* 1 */
bb_perror_msg_and_die("fork");
if (pid == 0) {
/* Child */
- if (!interactive)
+ if (!interactive) {
+ /* NB: e2fsck will complain because of this!
+ * Use "fsck -s" to avoid... */
close(0);
+ }
execvp(argv[0], argv);
bb_perror_msg_and_die("%s", argv[0]);
}
inst->device = xstrdup(device);
inst->base_device = base_device(device);
inst->start_time = time(NULL);
- inst->next = NULL;
- /*
- * Find the end of the list, so we add the instance on at the end.
- */
- if (!instance_list) {
- instance_list = inst;
- return 0;
- }
- p = instance_list;
- while (p->next)
- p = p->next;
- p->next = inst;
- return 0;
+ /* 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;
}
/*
* use that type regardless of what is specified in /etc/fstab.
*
* If the type isn't specified by the user, then use either the type
- * specified in /etc/fstab, or DEFAULT_FSTYPE.
+ * specified in /etc/fstab, or "auto".
*/
static void fsck_device(struct fs_info *fs, int interactive)
{
const char *type;
- int retval;
- interpret_type(fs);
-
- type = DEFAULT_FSTYPE;
- if (strcmp(fs->type, "auto") != 0)
+ if (strcmp(fs->type, "auto") != 0) {
type = fs->type;
- else if (fstype
+ if (verbose > 2)
+ bb_info_msg("using filesystem type '%s' %s",
+ type, "from fstab");
+ } else if (fstype
&& (fstype[0] != 'n' || fstype[1] != 'o') /* != "no" */
&& strncmp(fstype, "opts=", 5) != 0
&& strncmp(fstype, "loop", 4) != 0
&& !strchr(fstype, ',')
- )
+ ) {
type = fstype;
+ if (verbose > 2)
+ bb_info_msg("using filesystem type '%s' %s",
+ type, "from -t");
+ } else {
+ type = "auto";
+ if (verbose > 2)
+ bb_info_msg("using filesystem type '%s' %s",
+ type, "(default)");
+ }
num_running++;
- retval = execute(type, fs->device, fs->mountpt, interactive);
- if (retval) {
- bb_error_msg("error %d while executing fsck.%s for %s",
- retval, type, fs->device);
- num_running--;
- }
+ execute(type, fs->device, fs->mountpt, interactive);
}
/*
if (fs->passno == 0)
return 1;
- interpret_type(fs);
-
/*
* If a specific fstype is specified, and it doesn't match,
* ignore it.
/* Are we ignoring this type? */
if (index_in_str_array(ignored_types, fs->type) >= 0)
return 1;
-#if 0
- /* Do we really really want to check this fs? */
- wanted = index_in_str_array(really_wanted, fs->type) >= 0;
-
- /* See if the <fsck.fs> program is available. */
- s = find_fsck(fs->type);
- if (s == NULL) {
- if (wanted)
- bb_error_msg("cannot check %s: fsck.%s not found",
- fs->device, fs->type);
- return 1;
- }
- free(s);
-#endif
+
/* We can and want to check this file system type. */
return 0;
}
int optpos = 0;
int opts_for_fsck = 0;
-/* in bss
+ /* in bss, so already zeroed
num_devices = 0;
num_args = 0;
instance_list = NULL;
-*/
+ */
/* TODO: getopt32 */
for (i = 1; i < argc; i++) {
arg = argv[i];
+
/* "/dev/blk" or "/path" or "UUID=xxx" or "LABEL=xxx" */
if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
-#if 0
- char *dev;
- dev = blkid_get_devname(cache, arg, NULL);
- if (!dev && strchr(arg, '=')) {
- /*
- * Check to see if we failed because
- * /proc/partitions isn't found.
- */
- if (access("/proc/partitions", R_OK) < 0) {
- bb_perror_msg_and_die(
-"cannot open /proc/partitions (is /proc mounted?)");
- }
- /*
- * Check to see if this is because
- * we're not running as root
- */
- if (geteuid())
- bb_error_msg_and_die(
-"must be root to scan for matching filesystems: %s", arg);
- else
- bb_error_msg_and_die(
-"cannot find matching filesystem: %s", arg);
- }
- devices = xrealloc(devices, (num_devices+1) * sizeof(devices[0]));
- devices[num_devices++] = dev ? dev : xstrdup(arg);
-#endif
// FIXME: must check that arg is a blkdev, or resolve
// "/path", "UUID=xxx" or "LABEL=xxx" into block device name
+// ("UUID=xxx"/"LABEL=xxx" can probably shifted to fsck.auto duties)
devices = xrealloc(devices, (num_devices+1) * sizeof(devices[0]));
devices[num_devices++] = xstrdup(arg);
continue;
}
+
if (arg[0] != '-' || opts_for_fsck) {
args = xrealloc(args, (num_args+1) * sizeof(args[0]));
args[num_args++] = xstrdup(arg);
continue;
}
+
for (j = 1; arg[j]; j++) {
if (opts_for_fsck) {
optpos++;
case 'A':
doall = 1;
break;
+#if DO_PROGRESS_INDICATOR
case 'C':
progress = 1;
if (arg[++j]) { /* -Cn */
/* -C n */
progress_fd = xatoi_u(argv[++i]);
goto next_arg;
+#endif
case 'V':
verbose++;
break;
int fsck_main(int argc, char *argv[])
{
int i, status = 0;
- int interactive = 0;
+ int interactive;
const char *fstab;
struct fs_info *fs;
struct sigaction sa;
- /*
- * Set up signal action
- */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = signal_cancel;
sigaction(SIGINT, &sa, 0);
sigaction(SIGTERM, &sa, 0);
setbuf(stdout, NULL);
- /*setvbuf(stdout, NULL, _IONBF, BUFSIZ);*/
- /*setvbuf(stderr, NULL, _IONBF, BUFSIZ);*/
- /*blkid_get_cache(&cache, NULL);*/
parse_args(argc, argv);
if (!notitle)
fstab = "/etc/fstab";
load_fs_info(fstab);
- if (num_devices == 1 || serialize)
- interactive = 1;
+ interactive = (num_devices == 1) | serialize;
/* If -A was specified ("check all"), do that! */
if (doall)
kill_all_if_cancel_requested();
break;
}
+
fs = lookup(devices[i]);
- if (!fs) {
+ if (!fs)
fs = create_fs_device(devices[i], 0, "auto", 0, -1, -1);
- }
fsck_device(fs, interactive);
+
if (serialize
|| (max_running && (num_running >= max_running))
) {
}
}
status |= wait_many(FLAG_WAIT_ALL);
- /*blkid_put_cache(cache);*/
return status;
}