From 464df1d5e5ab1322e2dd0a7796939fff1aeefa9a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 17:49:25 +0200 Subject: Adding upstream version 1.47.0. Signed-off-by: Daniel Baumann --- misc/base_device.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 misc/base_device.c (limited to 'misc/base_device.c') diff --git a/misc/base_device.c b/misc/base_device.c new file mode 100644 index 0000000..814a479 --- /dev/null +++ b/misc/base_device.c @@ -0,0 +1,171 @@ +/* + * 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 "config.h" +#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 + * pathnames. + */ +static const char *devfs_hier[] = { + "host", "bus", "target", "lun", 0 +}; + +char *base_device(const 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; + } + + /* Handle DAC 960 devices */ + if (strncmp(cp, "rd/", 3) == 0) { + cp += 3; + if (cp[0] != 'c' || cp[2] != 'd' || + !isdigit(cp[1]) || !isdigit(cp[3])) + goto errout; + *(cp+4) = 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 +int main(int argc, char** argv) +{ + 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"); + free(base); + } + exit(0); +} +#endif -- cgit v1.2.3