From 793e27df7312d5b217c172387f71fd581ed30c82 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 3 Dec 2000 06:33:56 +0000 Subject: [PATCH] ChangeLog, Makefile.in, base_device.c, base_device.tst, fsck.c, fsck.h: fsck.c (device_already_active): Change to use new version of base_device() which now returns dynamically allocated memory. base_device.c (base_device): New version moved from fsck.c which now understands ugly devfs names. (Debian bug #65181) base_device.tst: Test case for base_device.c --- misc/ChangeLog | 11 +++ misc/Makefile.in | 12 +++- misc/base_device.c | 161 +++++++++++++++++++++++++++++++++++++++++++ misc/base_device.tst | 16 +++++ misc/fsck.c | 76 +++----------------- misc/fsck.h | 3 +- 6 files changed, 209 insertions(+), 70 deletions(-) create mode 100644 misc/base_device.c create mode 100644 misc/base_device.tst diff --git a/misc/ChangeLog b/misc/ChangeLog index a51329a6..dcdaaca0 100644 --- a/misc/ChangeLog +++ b/misc/ChangeLog @@ -1,3 +1,14 @@ +2000-12-03 + + * fsck.c (device_already_active): Change to use new version of + base_device() which now returns dynamically allocated + memory. + + * base_device.c (base_device): New version moved from fsck.c which + now understands ugly devfs names. (Debian bug #65181) + + * base_device.tst: Test case for base_device.c + 2000-12-02 * fsck.8.in: Add clarification that filesystems with a fs_passno diff --git a/misc/Makefile.in b/misc/Makefile.in index a4d0e442..e9897a35 100644 --- a/misc/Makefile.in +++ b/misc/Makefile.in @@ -29,7 +29,7 @@ DUMPE2FS_OBJS= dumpe2fs.o 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 \ @@ -61,6 +61,13 @@ e2label: $(E2LABEL_OBJS) 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) @@ -169,7 +176,8 @@ uninstall: 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 diff --git a/misc/base_device.c b/misc/base_device.c new file mode 100644 index 00000000..03008cbc --- /dev/null +++ b/misc/base_device.c @@ -0,0 +1,161 @@ +/* + * 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, + * + * Copyright (C) 2000 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#include +#include + +#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 diff --git a/misc/base_device.tst b/misc/base_device.tst new file mode 100644 index 00000000..609a58d1 --- /dev/null +++ b/misc/base_device.tst @@ -0,0 +1,16 @@ +/dev/hda7 /dev/hda +/dev/sda1 /dev/sda +/dev/hda /dev/hda +/dev/sda /dev/sda +/dev/dsk/hda6 /dev/dsk/hda +/dev/dsk/sda5 /dev/dsk/sda +/dev/md4 /dev/md +/dev/md/4 /dev/md +/dev/ide/host0/bus1/target2/lun3 /dev/ide/host0/bus1/target2/lun3 +/dev/ide/host0/bus1/target2/lun3/part10 /dev/ide/host0/bus1/target2/lun3 +/dev/ide/host0/bus1/target2/lun3/ /dev/ide/host0/bus1/target2/lun3 +/dev/disks/disk2/part2 /dev/disks/disk2 +/dev/disks/disk2/ /dev/disks/disk2 +/dev/disks/disk2 /dev/disks/disk2 +/dev/discs/disc1/part10 /dev/discs/disc1 +/dev/discs/disc1/ /dev/discs/disc1 diff --git a/misc/fsck.c b/misc/fsck.c index 95a58d83..8fc46106 100644 --- a/misc/fsck.c +++ b/misc/fsck.c @@ -79,55 +79,7 @@ static const char *really_wanted[] = { 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 @@ -213,6 +165,8 @@ static void free_instance(struct fsck_instance *i) free(i->prog); if (i->device) free(i->device); + if (i->base_device) + free(i->base_device); free(i); return; } @@ -486,6 +440,7 @@ static int execute(const char *type, char *device, char *mntpt, 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; @@ -722,23 +677,6 @@ static int ignore(struct fs_info *fs) return 0; } -/* - * 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. @@ -746,7 +684,7 @@ static const char *base_device(char *device) 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; @@ -759,10 +697,14 @@ static int device_already_active(char *device) 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; } diff --git a/misc/fsck.h b/misc/fsck.h index 693f9efd..9fdbce43 100644 --- a/misc/fsck.h +++ b/misc/fsck.h @@ -53,8 +53,9 @@ struct fsck_instance { char * prog; char * type; char * device; + char * base_device; struct fsck_instance *next; }; - +extern char *base_device(char *device);