blob: aad2ba0581de2c24cc7521a38a14336126ca3268 [file] [log] [blame]
Theodore Ts'o793e27d2000-12-03 06:33:56 +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.
Theodore Ts'oefc6f622008-08-27 23:07:54 -04008 *
Theodore Ts'o793e27d2000-12-03 06:33:56 +00009 * The base_device() function returns an allocated string which must
10 * be freed.
Theodore Ts'oefc6f622008-08-27 23:07:54 -040011 *
Theodore Ts'o793e27d2000-12-03 06:33:56 +000012 * Written by Theodore Ts'o, <tytso@mit.edu>
Theodore Ts'oefc6f622008-08-27 23:07:54 -040013 *
Theodore Ts'o793e27d2000-12-03 06:33:56 +000014 * 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 */
37static const char *devfs_hier[] = {
38 "host", "bus", "target", "lun", 0
39};
40
Theodore Ts'oed1b33e2003-03-01 19:29:01 -050041char *base_device(const char *device)
Theodore Ts'o793e27d2000-12-03 06:33:56 +000042{
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;
Theodore Ts'oefc6f622008-08-27 23:07:54 -040061
Theodore Ts'o793e27d2000-12-03 06:33:56 +000062 /*
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
Theodore Ts'ob9fd8c12000-12-29 03:10:45 +000071 /* 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
Theodore Ts'o793e27d2000-12-03 06:33:56 +000081 /* 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
144errout:
145 free(str);
146 return NULL;
147}
148
149#ifdef DEBUG
Theodore Ts'o546a1ff2002-03-07 23:52:56 -0500150int main(int argc, char** argv)
Theodore Ts'o793e27d2000-12-03 06:33:56 +0000151{
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}
Theodore Ts'o793e27d2000-12-03 06:33:56 +0000169#endif