]>
Commit | Line | Data |
---|---|---|
22f6a5c5 | 1 | --- e2fsprogs-1.19/misc/get_device_by_label.c.mountlabel Mon Feb 7 19:47:54 2000 |
2 | +++ e2fsprogs-1.19/misc/get_device_by_label.c Wed Aug 9 13:01:21 2000 | |
3 | @@ -7,6 +7,7 @@ | |
4 | * License. | |
5 | * | |
6 | * Taken from aeb's mount, 990619 | |
7 | + * Updated from aeb's mount, 20000725 | |
8 | */ | |
9 | ||
10 | #include <stdio.h> | |
11 | @@ -14,7 +15,6 @@ | |
12 | #include <ctype.h> | |
13 | #include <fcntl.h> | |
14 | #include <unistd.h> | |
15 | -#include "nls-enable.h" | |
16 | #include "get_device_by_label.h" | |
17 | ||
18 | #define PROC_PARTITIONS "/proc/partitions" | |
19 | @@ -30,104 +30,147 @@ | |
20 | }; | |
21 | #define ext2magic(s) ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8)) | |
22 | ||
23 | - | |
24 | -static FILE *procpt; | |
25 | - | |
26 | -static void | |
27 | -procptclose(void) { | |
28 | - if (procpt) | |
29 | - fclose (procpt); | |
30 | - procpt = 0; | |
31 | -} | |
32 | - | |
33 | -static int | |
34 | -procptopen(void) { | |
35 | - return ((procpt = fopen(PROC_PARTITIONS, "r")) != NULL); | |
36 | -} | |
37 | - | |
38 | -static char * | |
39 | -procptnext(void) { | |
40 | - char line[100]; | |
41 | - char *s; | |
42 | - int ma, mi, sz; | |
43 | - static char ptname[100]; | |
44 | - | |
45 | - while (fgets(line, sizeof(line), procpt)) { | |
46 | - if (sscanf (line, " %d %d %d %[^\n]\n", &ma, &mi, &sz, ptname) != 4) | |
47 | - continue; | |
48 | - | |
49 | - /* skip extended partitions (heuristic: size 1) */ | |
50 | - if (sz == 1) | |
51 | - continue; | |
52 | - | |
53 | - /* skip entire disk (minor 0, 64, ... on ide; 0, 16, ... on sd) */ | |
54 | - /* heuristic: partition name ends in a digit */ | |
55 | - for(s = ptname; *s; s++); | |
56 | - if (isdigit(s[-1])) | |
57 | - return ptname; | |
58 | - } | |
59 | - return 0; | |
60 | -} | |
61 | - | |
62 | -#define UUID 1 | |
63 | -#define VOL 2 | |
64 | +static struct uuidCache_s { | |
65 | + struct uuidCache_s *next; | |
66 | + char uuid[16]; | |
67 | + char *label; | |
68 | + char *device; | |
69 | +} *uuidCache = NULL; | |
70 | ||
71 | /* for now, only ext2 is supported */ | |
72 | static int | |
73 | -has_right_label(const char *device, int n, const void *label) { | |
74 | +get_label_uuid(const char *device, char **label, char *uuid) { | |
75 | ||
76 | /* start with a test for ext2, taken from mount_guess_fstype */ | |
77 | + /* should merge these later */ | |
78 | int fd; | |
79 | struct ext2_super_block e2sb; | |
80 | ||
81 | fd = open(device, O_RDONLY); | |
82 | if (fd < 0) | |
83 | - return 0; | |
84 | + return 1; | |
85 | ||
86 | if (lseek(fd, 1024, SEEK_SET) != 1024 | |
87 | || read(fd, (char *) &e2sb, sizeof(e2sb)) != sizeof(e2sb) | |
88 | || (ext2magic(e2sb) != EXT2_SUPER_MAGIC)) { | |
89 | close(fd); | |
90 | - return 0; | |
91 | + return 1; | |
92 | } | |
93 | ||
94 | close(fd); | |
95 | ||
96 | /* superblock is ext2 - now what is its label? */ | |
97 | - if (n == UUID) | |
98 | - return (memcmp(e2sb.s_uuid, label, 16) == 0); | |
99 | - else | |
100 | - return (strncmp(e2sb.s_volume_name, | |
101 | - (const char *) label, 16) == 0); | |
102 | + memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid)); | |
103 | + *label = strdup(e2sb.s_volume_name); | |
104 | + | |
105 | + return 0; | |
106 | } | |
107 | ||
108 | -static char * | |
109 | -get_spec_by_x(int n, const void *t) { | |
110 | - char *pt; | |
111 | +static void | |
112 | +uuidcache_addentry(char *device, char *label, char *uuid) { | |
113 | + struct uuidCache_s *last; | |
114 | + | |
115 | + if (!uuidCache) { | |
116 | + last = uuidCache = malloc(sizeof(*uuidCache)); | |
117 | + } else { | |
118 | + for (last = uuidCache; last->next; last = last->next) ; | |
119 | + last->next = malloc(sizeof(*uuidCache)); | |
120 | + last = last->next; | |
121 | + } | |
122 | + last->next = NULL; | |
123 | + last->device = device; | |
124 | + last->label = label; | |
125 | + memcpy(last->uuid, uuid, sizeof(last->uuid)); | |
126 | +} | |
127 | + | |
128 | +static void | |
129 | +uuidcache_init(void) { | |
130 | + char line[100]; | |
131 | + char *s; | |
132 | + int ma, mi, sz; | |
133 | + static char ptname[100]; | |
134 | + FILE *procpt; | |
135 | + char uuid[16], *label; | |
136 | char device[110]; | |
137 | + int firstPass; | |
138 | + int handleOnFirst; | |
139 | + | |
140 | + if (uuidCache) | |
141 | + return; | |
142 | ||
143 | - if(!procptopen()) | |
144 | - return NULL; | |
145 | - while((pt = procptnext()) != NULL) { | |
146 | - /* Note: this is a heuristic only - there is no reason | |
147 | - why these devices should live in /dev. | |
148 | - Perhaps this directory should be specifiable by option. | |
149 | - One might for example have /devlabel with links to /dev | |
150 | - for the devices that may be accessed in this way. | |
151 | - (This is useful, if the cdrom on /dev/hdc must not | |
152 | - be accessed.) | |
153 | - */ | |
154 | - sprintf(device, "%s/%s", DEVLABELDIR, pt); | |
155 | - if (has_right_label(device, n, t)) { | |
156 | - procptclose(); | |
157 | - return strdup(device); | |
158 | + procpt = fopen(PROC_PARTITIONS, "r"); | |
159 | + if (!procpt) | |
160 | + return; | |
161 | + | |
162 | + for (firstPass = 1; firstPass >= 0; firstPass--) { | |
163 | + fseek(procpt, 0, SEEK_SET); | |
164 | + | |
165 | + while (fgets(line, sizeof(line), procpt)) { | |
166 | + if (sscanf (line, " %d %d %d %[^\n ]", | |
167 | + &ma, &mi, &sz, ptname) != 4) | |
168 | + continue; | |
169 | + | |
170 | + /* skip extended partitions (heuristic: size 1) */ | |
171 | + if (sz == 1) | |
172 | + continue; | |
173 | + | |
174 | + /* look only at md devices on first pass */ | |
175 | + handleOnFirst = !strncmp(ptname, "md", 2); | |
176 | + if (firstPass != handleOnFirst) | |
177 | + continue; | |
178 | + | |
179 | + /* skip entire disk (minor 0, 64, ... on ide; | |
180 | + 0, 16, ... on sd) */ | |
181 | + /* heuristic: partition name ends in a digit */ | |
182 | + | |
183 | + for(s = ptname; *s; s++); | |
184 | + if (isdigit(s[-1])) { | |
185 | + /* | |
186 | + * Note: this is a heuristic only - there is no reason | |
187 | + * why these devices should live in /dev. | |
188 | + * Perhaps this directory should be specifiable by option. | |
189 | + * One might for example have /devlabel with links to /dev | |
190 | + * for the devices that may be accessed in this way. | |
191 | + * (This is useful, if the cdrom on /dev/hdc must not | |
192 | + * be accessed.) | |
193 | + */ | |
194 | + sprintf(device, "%s/%s", DEVLABELDIR, ptname); | |
195 | + if (!get_label_uuid(device, &label, uuid)) | |
196 | + uuidcache_addentry(strdup(device), label, uuid); | |
197 | } | |
198 | + } | |
199 | + } | |
200 | + | |
201 | + fclose(procpt); | |
202 | +} | |
203 | + | |
204 | +#define UUID 1 | |
205 | +#define VOL 2 | |
206 | + | |
207 | +static char * | |
208 | +get_spec_by_x(int n, const char *t) { | |
209 | + struct uuidCache_s *uc; | |
210 | + | |
211 | + uuidcache_init(); | |
212 | + uc = uuidCache; | |
213 | + | |
214 | + while(uc) { | |
215 | + switch (n) { | |
216 | + case UUID: | |
217 | + if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) | |
218 | + return strdup(uc->device); | |
219 | + break; | |
220 | + case VOL: | |
221 | + if (!strcmp(t, uc->label)) | |
222 | + return strdup(uc->device); | |
223 | + break; | |
224 | + } | |
225 | + uc = uc->next; | |
226 | } | |
227 | - procptclose(); | |
228 | return NULL; | |
229 | } | |
230 | ||
231 | -static unsigned char | |
232 | +static u_char | |
233 | fromhex(char c) { | |
234 | if (isdigit(c)) | |
235 | return (c - '0'); | |
236 | @@ -138,10 +181,9 @@ | |
237 | } | |
238 | ||
239 | char * | |
240 | -get_spec_by_uuid(const char *s0) { | |
241 | - unsigned char uuid[16]; | |
242 | +get_spec_by_uuid(const char *s) { | |
243 | + u_char uuid[16]; | |
244 | int i; | |
245 | - const char *s = s0; | |
246 | ||
247 | if (strlen(s) != 36 || | |
248 | s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') | |
249 | @@ -156,11 +198,26 @@ | |
250 | return get_spec_by_x(UUID, uuid); | |
251 | ||
252 | bad_uuid: | |
253 | - fprintf(stderr, _("WARNING: %s: bad UUID"), s0); | |
254 | - return NULL; | |
255 | + fprintf(stderr, ("WARNING: bad UUID")); | |
256 | + return NULL; /* just for gcc */ | |
257 | } | |
258 | ||
259 | char * | |
260 | get_spec_by_volume_label(const char *s) { | |
261 | return get_spec_by_x(VOL, s); | |
262 | +} | |
263 | + | |
264 | +const char * | |
265 | +get_volume_label_by_spec(const char *spec) { | |
266 | + struct uuidCache_s *uc; | |
267 | + | |
268 | + uuidcache_init(); | |
269 | + uc = uuidCache; | |
270 | + | |
271 | + while(uc) { | |
272 | + if (!strcmp(spec, uc->device)) | |
273 | + return uc->label; | |
274 | + uc = uc->next; | |
275 | + } | |
276 | + return NULL; | |
277 | } |