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