blob: d81bb0952f3ff5ac0aacbd1e6c32881b4f5afa9e [file] [log] [blame]
Mike Frysinger7a121e92005-05-09 22:09:00 +00001/*
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 */
34static const char *devfs_hier[] = {
35 "host", "bus", "target", "lun", 0
36};
37#endif
38
39char *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
144errout:
145 free(str);
146 return NULL;
147}