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