]>
Commit | Line | Data |
---|---|---|
793e27df TT |
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. | |
efc6f628 | 8 | * |
793e27df TT |
9 | * The base_device() function returns an allocated string which must |
10 | * be freed. | |
efc6f628 | 11 | * |
793e27df | 12 | * Written by Theodore Ts'o, <tytso@mit.edu> |
efc6f628 | 13 | * |
793e27df TT |
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 | */ | |
d1154eb4 | 21 | #include "config.h" |
793e27df TT |
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 | ||
ed1b33e8 | 42 | char *base_device(const char *device) |
793e27df TT |
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; | |
efc6f628 | 62 | |
793e27df TT |
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 | ||
b9fd8c1f TT |
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 | ||
793e27df TT |
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 | |
546a1ff1 | 151 | int main(int argc, char** argv) |
793e27df | 152 | { |
151c49bc | 153 | char *base; |
793e27df TT |
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"); | |
151c49bc | 167 | free(base); |
793e27df TT |
168 | } |
169 | exit(0); | |
170 | } | |
793e27df | 171 | #endif |