BADBLOCKS_OBJS= badblocks.o
E2LABEL_OBJS= e2label.o
E2IMAGE_OBJS= e2image.o
-FSCK_OBJS= fsck.o get_device_by_label.o
+FSCK_OBJS= fsck.o get_device_by_label.o base_device.o
SRCS= $(srcdir)/tune2fs.c $(srcdir)/mklost+found.c $(srcdir)/mke2fs.c \
$(srcdir)/chattr.c $(srcdir)/lsattr.c $(srcdir)/dumpe2fs.c \
e2image: $(E2IMAGE_OBJS) $(DEPLIBS)
$(CC) $(ALL_LDFLAGS) -o e2image $(E2IMAGE_OBJS) $(LIBS)
+base_device: base_device.c
+ $(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $< -DDEBUG -o $@
+
+check:: base_device
+ ./base_device < $(srcdir)/base_device.tst > base_device.out
+ cmp $(srcdir)/base_device.tst base_device.out
+
mklost+found: $(MKLPF_OBJS)
$(CC) $(ALL_LDFLAGS) -o mklost+found $(MKLPF_OBJS)
clean:
$(RM) -f $(SPROGS) $(USPROGS) $(UPROGS) $(UMANPAGES) $(SMANPAGES) \
- mke2fs.static \#* *.s *.o *.a *~ core
+ base_device base_device.out mke2fs.static \
+ \#* *.s *.o *.a *~ core
mostlyclean: clean
distclean: clean
--- /dev/null
+/*
+ * base_device.c
+ *
+ * Return the "base device" given a particular device; this is used to
+ * assure that we only fsck one partition on a particular drive at any
+ * one time. Otherwise, the disk heads will be seeking all over the
+ * place. If the base device can not be determined, return NULL.
+ *
+ * The base_device() function returns an allocated string which must
+ * be freed.
+ *
+ * Written by Theodore Ts'o, <tytso@mit.edu>
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <ctype.h>
+#include <string.h>
+
+#include "fsck.h"
+
+/*
+ * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
+ * pathames.
+ */
+static const char *devfs_hier[] = {
+ "host", "bus", "target", "lun", 0
+};
+
+char *base_device(char *device)
+{
+ char *str, *cp;
+ const char **hier, *disk;
+ int len;
+
+ str = malloc(strlen(device)+1);
+ if (!str)
+ return NULL;
+ strcpy(str, device);
+ cp = str;
+
+ /* Skip over /dev/; if it's not present, give up. */
+ if (strncmp(cp, "/dev/", 5) != 0)
+ goto errout;
+ cp += 5;
+
+ /* Skip over /dev/dsk/... */
+ if (strncmp(cp, "dsk/", 4) == 0)
+ cp += 4;
+
+ /*
+ * For md devices, we treat them all as if they were all
+ * on one disk, since we don't know how to parallelize them.
+ */
+ if (cp[0] == 'm' && cp[1] == 'd') {
+ *(cp+2) = 0;
+ return str;
+ }
+
+ /* Now let's handle /dev/hd* and /dev/sd* devices.... */
+ if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {
+ cp += 2;
+ /* If there's a single number after /dev/hd, skip it */
+ if (isdigit(*cp))
+ cp++;
+ /* What follows must be an alpha char, or give up */
+ if (!isalpha(*cp))
+ goto errout;
+ *(cp + 1) = 0;
+ return str;
+ }
+
+ /* Now let's handle devfs (ugh) names */
+ len = 0;
+ if (strncmp(cp, "ide/", 4) == 0)
+ len = 4;
+ if (strncmp(cp, "scsi/", 5) == 0)
+ len = 5;
+ if (len) {
+ cp += len;
+ /*
+ * Now we proceed down the expected devfs hierarchy.
+ * i.e., .../host1/bus2/target3/lun4/...
+ * If we don't find the expected token, followed by
+ * some number of digits at each level, abort.
+ */
+ for (hier = devfs_hier; *hier; hier++) {
+ len = strlen(*hier);
+ if (strncmp(cp, *hier, len) != 0)
+ goto errout;
+ cp += len;
+ while (*cp != '/' && *cp != 0) {
+ if (!isdigit(*cp))
+ goto errout;
+ cp++;
+ }
+ cp++;
+ }
+ *(cp - 1) = 0;
+ return str;
+ }
+
+ /* Now handle devfs /dev/disc or /dev/disk names */
+ disk = 0;
+ if (strncmp(cp, "discs/", 6) == 0)
+ disk = "disc";
+ else if (strncmp(cp, "disks/", 6) == 0)
+ disk = "disk";
+ if (disk) {
+ cp += 6;
+ if (strncmp(cp, disk, 4) != 0)
+ goto errout;
+ cp += 4;
+ while (*cp != '/' && *cp != 0) {
+ if (!isdigit(*cp))
+ goto errout;
+ cp++;
+ }
+ *cp = 0;
+ return str;
+ }
+
+errout:
+ free(str);
+ return NULL;
+}
+
+#ifdef DEBUG
+
+main(int argc, char** argv)
+{
+ const char *base;
+ char buf[256], *cp;
+
+ while (1) {
+ if (fgets(buf, sizeof(buf), stdin) == NULL)
+ break;
+ cp = strchr(buf, '\n');
+ if (cp)
+ *cp = 0;
+ cp = strchr(buf, '\t');
+ if (cp)
+ *cp = 0;
+ base = base_device(buf);
+ printf("%s\t%s\n", buf, base ? base : "NONE");
+ }
+ exit(0);
+}
+
+#endif
NULL
};
-#ifdef DEV_DSK_DEVICES
-static const char *base_devices[] = {
- "/dev/dsk/hda",
- "/dev/dsk/hdb",
- "/dev/dsk/hdc",
- "/dev/dsk/hdd",
- "/dev/dsk/hde",
- "/dev/dsk/hdf",
- "/dev/dsk/hdg",
- "/dev/dsk/hdh",
- "/dev/dsk/hd1a",
- "/dev/dsk/hd1b",
- "/dev/dsk/hd1c",
- "/dev/dsk/hd1d",
- "/dev/dsk/sda",
- "/dev/dsk/sdb",
- "/dev/dsk/sdc",
- "/dev/dsk/sdd",
- "/dev/dsk/sde",
- "/dev/dsk/sdf",
- "/dev/dsk/sdg",
- NULL
-};
-#else
#define BASE_MD "/dev/md"
-static const char *base_devices[] = {
- "/dev/hda",
- "/dev/hdb",
- "/dev/hdc",
- "/dev/hdd",
- "/dev/hde",
- "/dev/hdf",
- "/dev/hdg",
- "/dev/hdh",
- "/dev/hd1a",
- "/dev/hd1b",
- "/dev/hd1c",
- "/dev/hd1d",
- "/dev/sda",
- "/dev/sdb",
- "/dev/sdc",
- "/dev/sdd",
- "/dev/sde",
- "/dev/sdf",
- "/dev/sdg",
- BASE_MD,
- NULL
-};
-#endif
/*
* Global variables for options
free(i->prog);
if (i->device)
free(i->device);
+ if (i->base_device)
+ free(i->base_device);
free(i);
return;
}
inst->prog = string_copy(prog);
inst->type = string_copy(type);
inst->device = string_copy(device);
+ inst->base_device = base_device(device);
inst->start_time = time(0);
inst->next = NULL;
}
/*
- * Return the "base device" given a particular device; this is used to
- * assure that we only fsck one partition on a particular drive at any
- * one time. Otherwise, the disk heads will be seeking all over the
- * place.
- */
-static const char *base_device(char *device)
-{
- const char **base;
-
- for (base = base_devices; *base; base++) {
- if (!strncmp(*base, device, strlen(*base)))
- return *base;
- }
- return device;
-}
-
-/*
* Returns TRUE if a partition on the same disk is already being
* checked.
*/
static int device_already_active(char *device)
{
struct fsck_instance *inst;
- const char *base = base_device(device);
+ char *base;
if (force_all_parallel)
return 0;
return 1;
#endif
+ base = base_device(device);
for (inst = instance_list; inst; inst = inst->next) {
- if (!strcmp(base, base_device(inst->device)))
+ if (!strcmp(base, inst->base_device)) {
+ free(base);
return 1;
+ }
}
+ free(base);
return 0;
}