Whamcloud - gitweb
AOSP: tune2fs, resize2fs: make ramdisk binaries.
[tools/e2fsprogs.git] / misc / base_device.c
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         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                 free(base);
168         }
169         exit(0);
170 }
171 #endif