1 /* 2 * base_device.c 3 * 4 * Return the "base device" given a particular device; this is used to 5 * assure that we only fsck one partition on a particular drive at any 6 * one time. Otherwise, the disk heads will be seeking all over the 7 * place. If the base device can not be determined, return NULL. 8 * 9 * The base_device() function returns an allocated string which must 10 * be freed. 11 * 12 * Written by Theodore Ts'o, <tytso@mit.edu> 13 * 14 * Copyright (C) 2000 Theodore Ts'o. 15 * 16 * %Begin-Header% 17 * This file may be redistributed under the terms of the GNU Public 18 * License. 19 * %End-Header% 20 */ 21 #include "config.h" 22 #include <stdio.h> 23 #if HAVE_UNISTD_H 24 #include <unistd.h> 25 #endif 26 #if HAVE_STDLIB_H 27 #include <stdlib.h> 28 #endif 29 #include <ctype.h> 30 #include <string.h> 31 32 #include "fsck.h" 33 34 /* 35 * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3 36 * pathames. 37 */ 38 static const char *devfs_hier[] = { 39 "host", "bus", "target", "lun", 0 40 }; 41 42 char *base_device(const char *device) 43 { 44 char *str, *cp; 45 const char **hier, *disk; 46 int len; 47 48 str = malloc(strlen(device)+1); 49 if (!str) 50 return NULL; 51 strcpy(str, device); 52 cp = str; 53 54 /* Skip over /dev/; if it's not present, give up. */ 55 if (strncmp(cp, "/dev/", 5) != 0) 56 goto errout; 57 cp += 5; 58 59 /* Skip over /dev/dsk/... */ 60 if (strncmp(cp, "dsk/", 4) == 0) 61 cp += 4; 62 63 /* 64 * For md devices, we treat them all as if they were all 65 * on one disk, since we don't know how to parallelize them. 66 */ 67 if (cp[0] == 'm' && cp[1] == 'd') { 68 *(cp+2) = 0; 69 return str; 70 } 71 72 /* Handle DAC 960 devices */ 73 if (strncmp(cp, "rd/", 3) == 0) { 74 cp += 3; 75 if (cp[0] != 'c' || cp[2] != 'd' || 76 !isdigit(cp[1]) || !isdigit(cp[3])) 77 goto errout; 78 *(cp+4) = 0; 79 return str; 80 } 81 82 /* Now let's handle /dev/hd* and /dev/sd* devices.... */ 83 if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) { 84 cp += 2; 85 /* If there's a single number after /dev/hd, skip it */ 86 if (isdigit(*cp)) 87 cp++; 88 /* What follows must be an alpha char, or give up */ 89 if (!isalpha(*cp)) 90 goto errout; 91 *(cp + 1) = 0; 92 return str; 93 } 94 95 /* Now let's handle devfs (ugh) names */ 96 len = 0; 97 if (strncmp(cp, "ide/", 4) == 0) 98 len = 4; 99 if (strncmp(cp, "scsi/", 5) == 0) 100 len = 5; 101 if (len) { 102 cp += len; 103 /* 104 * Now we proceed down the expected devfs hierarchy. 105 * i.e., .../host1/bus2/target3/lun4/... 106 * If we don't find the expected token, followed by 107 * some number of digits at each level, abort. 108 */ 109 for (hier = devfs_hier; *hier; hier++) { 110 len = strlen(*hier); 111 if (strncmp(cp, *hier, len) != 0) 112 goto errout; 113 cp += len; 114 while (*cp != '/' && *cp != 0) { 115 if (!isdigit(*cp)) 116 goto errout; 117 cp++; 118 } 119 cp++; 120 } 121 *(cp - 1) = 0; 122 return str; 123 } 124 125 /* Now handle devfs /dev/disc or /dev/disk names */ 126 disk = 0; 127 if (strncmp(cp, "discs/", 6) == 0) 128 disk = "disc"; 129 else if (strncmp(cp, "disks/", 6) == 0) 130 disk = "disk"; 131 if (disk) { 132 cp += 6; 133 if (strncmp(cp, disk, 4) != 0) 134 goto errout; 135 cp += 4; 136 while (*cp != '/' && *cp != 0) { 137 if (!isdigit(*cp)) 138 goto errout; 139 cp++; 140 } 141 *cp = 0; 142 return str; 143 } 144 145 errout: 146 free(str); 147 return NULL; 148 } 149 150 #ifdef DEBUG 151 int main(int argc, char** argv) 152 { 153 const char *base; 154 char buf[256], *cp; 155 156 while (1) { 157 if (fgets(buf, sizeof(buf), stdin) == NULL) 158 break; 159 cp = strchr(buf, '\n'); 160 if (cp) 161 *cp = 0; 162 cp = strchr(buf, '\t'); 163 if (cp) 164 *cp = 0; 165 base = base_device(buf); 166 printf("%s\t%s\n", buf, base ? base : "NONE"); 167 } 168 exit(0); 169 } 170 #endif 171