• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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  */
37 static const char *devfs_hier[] = {
38 	"host", "bus", "target", "lun", 0
39 };
40 
base_device(const char * device)41 char *base_device(const char *device)
42 {
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;
61 
62 	/*
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 
71 	/* 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 
81 	/* 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 
144 errout:
145 	free(str);
146 	return NULL;
147 }
148 
149 #ifdef DEBUG
main(int argc,char ** argv)150 int main(int argc, char** argv)
151 {
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 }
169 #endif
170