diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-19 19:36:30 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-19 19:36:30 +0000 |
commit | 582dff051459b1394a48dec1f29a29e2442661a0 (patch) | |
tree | 41835a2b323eefb403825db78c033a920f86b602 /util-linux | |
parent | bff06fe02a3d5629b745d799c3b987888070dc20 (diff) | |
download | busybox-w32-582dff051459b1394a48dec1f29a29e2442661a0.tar.gz busybox-w32-582dff051459b1394a48dec1f29a29e2442661a0.tar.bz2 busybox-w32-582dff051459b1394a48dec1f29a29e2442661a0.zip |
volume identification: abolish /proc/partitions and /proc/cdroms
scanning. It does not catch volume managers and such.
Adding even more cruft is bad, so I decided to simply
scan /dev/* for any block devices. See how much better
it finds devices now:
# ./busybox_old blkid
/dev/sda1: LABEL="/boot" UUID="7931e231-dcb4-4b6d-9301-f7354ae24061"
/dev/dm-0: LABEL="Fedora-9-Live-x8" UUID="bb491e1e-1145-4f5b-b0ab-cbd2baf4f15a"
/dev/dm-1: UUID="edc2a920-ef83-437e-ba64-d3b6dc851267"
/dev/sdb1: UUID="6F84-ED0F"
# ./busybox blkid
/dev/sdb1: UUID="6F84-ED0F"
/dev/root: LABEL="Fedora-9-Live-x8" UUID="bb491e1e-1145-4f5b-b0ab-cbd2baf4f15a"
/dev/dm-1: UUID="edc2a920-ef83-437e-ba64-d3b6dc851267"
/dev/dm-0: LABEL="Fedora-9-Live-x8" UUID="bb491e1e-1145-4f5b-b0ab-cbd2baf4f15a"
/dev/sda1: LABEL="/boot" UUID="7931e231-dcb4-4b6d-9301-f7354ae24061"
/dev/mapper/VolGroup00-LogVol01: UUID="edc2a920-ef83-437e-ba64-d3b6dc851267"
/dev/mapper/VolGroup00-LogVol00: LABEL="Fedora-9-Live-x8" UUID="bb491e1e-1145-4f5b-b0ab-cbd2baf4f15a"
function old new delta
static.drive_name_string 12 - -12
append_mount_options 205 190 -15
volume_id_open_node 37 18 -19
uuidcache_check_device 485 257 -228
uuidcache_init 637 36 -601
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 0/4 up/down: 0/-875) Total: -875 bytes
text data bss dec hex filename
792218 592 6648 799458 c32e2 busybox_old
791260 592 6648 798500 c2f24 busybox_unstripped
Diffstat (limited to 'util-linux')
-rw-r--r-- | util-linux/volume_id/get_devname.c | 249 | ||||
-rw-r--r-- | util-linux/volume_id/volume_id.c | 7 | ||||
-rw-r--r-- | util-linux/volume_id/volume_id_internal.h | 2 |
3 files changed, 33 insertions, 225 deletions
diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c index 83c085650..e99c15b02 100644 --- a/util-linux/volume_id/get_devname.c +++ b/util-linux/volume_id/get_devname.c | |||
@@ -22,38 +22,23 @@ static struct uuidCache_s { | |||
22 | 22 | ||
23 | /* Returns !0 on error. | 23 | /* Returns !0 on error. |
24 | * Otherwise, returns malloc'ed strings for label and uuid | 24 | * Otherwise, returns malloc'ed strings for label and uuid |
25 | * (and they can't be NULL, although they can be "") */ | 25 | * (and they can't be NULL, although they can be ""). |
26 | #if !ENABLE_FEATURE_VOLUMEID_ISO9660 | 26 | * NB: closes fd. */ |
27 | #define get_label_uuid(device, label, uuid, iso_only) \ | ||
28 | get_label_uuid(device, label, uuid) | ||
29 | #endif | ||
30 | static int | 27 | static int |
31 | get_label_uuid(const char *device, char **label, char **uuid, int iso_only) | 28 | get_label_uuid(int fd, char **label, char **uuid) |
32 | { | 29 | { |
33 | int rv = 1; | 30 | int rv = 1; |
34 | uint64_t size; | 31 | uint64_t size; |
35 | struct volume_id *vid; | 32 | struct volume_id *vid; |
36 | 33 | ||
37 | vid = volume_id_open_node(device); | 34 | /* fd is owned by vid now */ |
38 | if (!vid) | 35 | vid = volume_id_open_node(fd); |
39 | return rv; | ||
40 | 36 | ||
41 | if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0) | 37 | if (ioctl(/*vid->*/fd, BLKGETSIZE64, &size) != 0) |
42 | size = 0; | 38 | size = 0; |
43 | 39 | ||
44 | #if ENABLE_FEATURE_VOLUMEID_ISO9660 | 40 | if (volume_id_probe_all(vid, 0, size) != 0) |
45 | if ((iso_only ? | ||
46 | volume_id_probe_iso9660(vid, 0) : | ||
47 | volume_id_probe_all(vid, 0, size) | ||
48 | ) != 0 | ||
49 | ) { | ||
50 | goto ret; | ||
51 | } | ||
52 | #else | ||
53 | if (volume_id_probe_all(vid, 0, size) != 0) { | ||
54 | goto ret; | 41 | goto ret; |
55 | } | ||
56 | #endif | ||
57 | 42 | ||
58 | if (vid->label[0] != '\0' || vid->uuid[0] != '\0') { | 43 | if (vid->label[0] != '\0' || vid->uuid[0] != '\0') { |
59 | *label = xstrndup(vid->label, sizeof(vid->label)); | 44 | *label = xstrndup(vid->label, sizeof(vid->label)); |
@@ -62,7 +47,7 @@ get_label_uuid(const char *device, char **label, char **uuid, int iso_only) | |||
62 | rv = 0; | 47 | rv = 0; |
63 | } | 48 | } |
64 | ret: | 49 | ret: |
65 | free_volume_id(vid); | 50 | free_volume_id(vid); /* also closes fd */ |
66 | return rv; | 51 | return rv; |
67 | } | 52 | } |
68 | 53 | ||
@@ -91,204 +76,29 @@ uuidcache_addentry(char *device, /*int major, int minor,*/ char *label, char *uu | |||
91 | /* If get_label_uuid() on device_name returns success, | 76 | /* If get_label_uuid() on device_name returns success, |
92 | * add a cache entry for this device. | 77 | * add a cache entry for this device. |
93 | * If device node does not exist, it will be temporarily created. */ | 78 | * If device node does not exist, it will be temporarily created. */ |
94 | #if !ENABLE_FEATURE_VOLUMEID_ISO9660 | 79 | static int FAST_FUNC |
95 | #define uuidcache_check_device(device_name, ma, mi, iso_only) \ | 80 | uuidcache_check_device(const char *device, |
96 | uuidcache_check_device(device_name, ma, mi) | 81 | struct stat *statbuf, |
97 | #endif | 82 | void *userData UNUSED_PARAM, |
98 | static void | 83 | int depth UNUSED_PARAM) |
99 | uuidcache_check_device(const char *device_name, int ma, int mi, int iso_only) | ||
100 | { | 84 | { |
101 | char *device, *last_slash; | 85 | char *uuid = uuid; /* for compiler */ |
102 | char *uuid, *label; | 86 | char *label = label; |
103 | char *ptr; | 87 | int fd; |
104 | int must_remove = 0; | ||
105 | int added = 0; | ||
106 | |||
107 | last_slash = NULL; | ||
108 | device = xasprintf("/dev/%s", device_name); | ||
109 | if (access(device, F_OK) != 0) { | ||
110 | /* device does not exist, temporarily create */ | ||
111 | int slash_cnt = 0; | ||
112 | |||
113 | if ((ma | mi) < 0) | ||
114 | goto ret; /* we don't know major:minor! */ | ||
115 | |||
116 | ptr = device; | ||
117 | while (*ptr) | ||
118 | if (*ptr++ == '/') | ||
119 | slash_cnt++; | ||
120 | if (slash_cnt > 2) { | ||
121 | // BUG: handles only slash_cnt == 3 case | ||
122 | last_slash = strrchr(device, '/'); | ||
123 | *last_slash = '\0'; | ||
124 | if (mkdir(device, 0644)) { | ||
125 | bb_perror_msg("can't create directory %s", device); | ||
126 | *last_slash = '/'; | ||
127 | last_slash = NULL; /* prevents rmdir */ | ||
128 | } else { | ||
129 | *last_slash = '/'; | ||
130 | } | ||
131 | } | ||
132 | mknod(device, S_IFBLK | 0600, makedev(ma, mi)); | ||
133 | must_remove = 1; | ||
134 | } | ||
135 | 88 | ||
136 | uuid = NULL; | 89 | if (!S_ISBLK(statbuf->st_mode)) |
137 | label = NULL; | 90 | return TRUE; |
138 | if (get_label_uuid(device, &label, &uuid, iso_only) == 0) { | ||
139 | uuidcache_addentry(device, /*ma, mi,*/ label, uuid); | ||
140 | /* "device" is owned by cache now, don't free */ | ||
141 | added = 1; | ||
142 | } | ||
143 | 91 | ||
144 | if (must_remove) | 92 | fd = open(device, O_RDONLY); |
145 | unlink(device); | 93 | if (fd < 0) |
146 | if (last_slash) { | 94 | return TRUE; |
147 | *last_slash = '\0'; | ||
148 | rmdir(device); | ||
149 | } | ||
150 | ret: | ||
151 | if (!added) | ||
152 | free(device); | ||
153 | } | ||
154 | 95 | ||
155 | /* Run uuidcache_check_device() for every device mentioned | 96 | /* get_label_uuid() closes fd in all cases (success & failure) */ |
156 | * in /proc/partitions */ | 97 | if (get_label_uuid(fd, &label, &uuid) == 0) { |
157 | static void | 98 | /* uuidcache_addentry() takes ownership of all three params */ |
158 | uuidcache_init_partitions(void) | 99 | uuidcache_addentry(xstrdup(device), /*ma, mi,*/ label, uuid); |
159 | { | ||
160 | char line[100]; | ||
161 | int ma, mi; | ||
162 | unsigned long long sz; | ||
163 | FILE *procpt; | ||
164 | int firstPass; | ||
165 | int handleOnFirst; | ||
166 | char *chptr; | ||
167 | |||
168 | procpt = xfopen_for_read("/proc/partitions"); | ||
169 | /* | ||
170 | # cat /proc/partitions | ||
171 | major minor #blocks name | ||
172 | |||
173 | 8 0 293036184 sda | ||
174 | 8 1 6835626 sda1 | ||
175 | 8 2 1 sda2 | ||
176 | 8 5 979933 sda5 | ||
177 | 8 6 15623181 sda6 | ||
178 | 8 7 97659103 sda7 | ||
179 | 8 8 171935631 sda8 | ||
180 | */ | ||
181 | for (firstPass = 1; firstPass >= 0; firstPass--) { | ||
182 | fseek(procpt, 0, SEEK_SET); | ||
183 | |||
184 | while (fgets(line, sizeof(line), procpt)) { | ||
185 | /* The original version of this code used sscanf, but | ||
186 | diet's sscanf is quite limited */ | ||
187 | chptr = line; | ||
188 | if (*chptr != ' ') continue; | ||
189 | chptr = skip_whitespace(chptr); | ||
190 | |||
191 | ma = bb_strtou(chptr, &chptr, 0); | ||
192 | if (ma < 0) continue; | ||
193 | chptr = skip_whitespace(chptr); | ||
194 | |||
195 | mi = bb_strtou(chptr, &chptr, 0); | ||
196 | if (mi < 0) continue; | ||
197 | chptr = skip_whitespace(chptr); | ||
198 | |||
199 | sz = bb_strtoull(chptr, &chptr, 0); | ||
200 | if ((long long)sz == -1LL) continue; | ||
201 | chptr = skip_whitespace(chptr); | ||
202 | |||
203 | /* skip extended partitions (heuristic: size 1) */ | ||
204 | if (sz == 1) | ||
205 | continue; | ||
206 | |||
207 | *strchrnul(chptr, '\n') = '\0'; | ||
208 | /* now chptr => device name */ | ||
209 | dbg("/proc/partitions: maj:%d min:%d sz:%llu name:'%s'", | ||
210 | ma, mi, sz, chptr); | ||
211 | if (!chptr[0]) | ||
212 | continue; | ||
213 | |||
214 | /* look only at md devices on first pass */ | ||
215 | handleOnFirst = (chptr[0] == 'm' && chptr[1] == 'd'); | ||
216 | if (firstPass != handleOnFirst) | ||
217 | continue; | ||
218 | |||
219 | /* heuristic: partition name ends in a digit */ | ||
220 | if (isdigit(chptr[strlen(chptr) - 1])) { | ||
221 | uuidcache_check_device(chptr, ma, mi, 0); | ||
222 | } | ||
223 | } | ||
224 | } | 100 | } |
225 | 101 | return TRUE; | |
226 | fclose(procpt); | ||
227 | } | ||
228 | |||
229 | static void | ||
230 | dev_get_major_minor(char *device_name, int *major, int *minor) | ||
231 | { | ||
232 | char dev[16]; | ||
233 | char *dev_path; | ||
234 | char *colon; | ||
235 | int sz; | ||
236 | |||
237 | dev_path = xasprintf("/sys/block/%s/dev", device_name); | ||
238 | sz = open_read_close(dev_path, dev, sizeof(dev) - 1); | ||
239 | if (sz < 0) | ||
240 | goto ret; | ||
241 | dev[sz] = '\0'; | ||
242 | |||
243 | colon = strchr(dev, ':'); | ||
244 | if (!colon) | ||
245 | goto ret; | ||
246 | *major = bb_strtou(dev, NULL, 10); | ||
247 | *minor = bb_strtou(colon + 1, NULL, 10); | ||
248 | |||
249 | ret: | ||
250 | free(dev_path); | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | static void | ||
255 | uuidcache_init_cdroms(void) | ||
256 | { | ||
257 | #define PROC_CDROMS "/proc/sys/dev/cdrom/info" | ||
258 | char line[100]; | ||
259 | int ma, mi; | ||
260 | FILE *proccd; | ||
261 | |||
262 | proccd = fopen_for_read(PROC_CDROMS); | ||
263 | if (!proccd) { | ||
264 | // static smallint warn = 0; | ||
265 | // if (!warn) { | ||
266 | // warn = 1; | ||
267 | // bb_error_msg("can't open %s, UUID and LABEL " | ||
268 | // "conversion cannot be done for CD-Roms", | ||
269 | // PROC_CDROMS); | ||
270 | // } | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | while (fgets(line, sizeof(line), proccd)) { | ||
275 | static const char drive_name_string[] ALIGN1 = "drive name:"; | ||
276 | |||
277 | if (strncmp(line, drive_name_string, sizeof(drive_name_string) - 1) == 0) { | ||
278 | char *device_name; | ||
279 | |||
280 | device_name = strtok(skip_whitespace(line + sizeof(drive_name_string) - 1), " \t\n"); | ||
281 | while (device_name && device_name[0]) { | ||
282 | ma = mi = -1; | ||
283 | dev_get_major_minor(device_name, &ma, &mi); | ||
284 | uuidcache_check_device(device_name, ma, mi, 1); | ||
285 | device_name = strtok(NULL, " \t\n"); | ||
286 | } | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | fclose(proccd); | ||
292 | } | 102 | } |
293 | 103 | ||
294 | static void | 104 | static void |
@@ -297,8 +107,11 @@ uuidcache_init(void) | |||
297 | if (uuidCache) | 107 | if (uuidCache) |
298 | return; | 108 | return; |
299 | 109 | ||
300 | uuidcache_init_partitions(); | 110 | recursive_action("/dev", ACTION_RECURSE, |
301 | uuidcache_init_cdroms(); | 111 | uuidcache_check_device, /* file_action */ |
112 | NULL, /* dir_action */ | ||
113 | NULL, /* userData */ | ||
114 | 0 /* depth */); | ||
302 | } | 115 | } |
303 | 116 | ||
304 | #define UUID 1 | 117 | #define UUID 1 |
diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c index d81f3f94c..6852a8203 100644 --- a/util-linux/volume_id/volume_id.c +++ b/util-linux/volume_id/volume_id.c | |||
@@ -190,19 +190,14 @@ int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size) | |||
190 | } | 190 | } |
191 | 191 | ||
192 | /* open volume by device node */ | 192 | /* open volume by device node */ |
193 | struct volume_id *volume_id_open_node(const char *path) | 193 | struct volume_id *volume_id_open_node(int fd) |
194 | { | 194 | { |
195 | struct volume_id *id; | 195 | struct volume_id *id; |
196 | int fd; | ||
197 | 196 | ||
198 | fd = open(path, O_RDONLY); | ||
199 | if (fd < 0) | ||
200 | return NULL; | ||
201 | id = xzalloc(sizeof(struct volume_id)); | 197 | id = xzalloc(sizeof(struct volume_id)); |
202 | id->fd = fd; | 198 | id->fd = fd; |
203 | ///* close fd on device close */ | 199 | ///* close fd on device close */ |
204 | //id->fd_close = 1; | 200 | //id->fd_close = 1; |
205 | |||
206 | return id; | 201 | return id; |
207 | } | 202 | } |
208 | 203 | ||
diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h index 6619d2c6e..075ddb344 100644 --- a/util-linux/volume_id/volume_id_internal.h +++ b/util-linux/volume_id/volume_id_internal.h | |||
@@ -87,7 +87,7 @@ struct volume_id { | |||
87 | // int fd_close:1; | 87 | // int fd_close:1; |
88 | }; | 88 | }; |
89 | 89 | ||
90 | struct volume_id *volume_id_open_node(const char *path); | 90 | struct volume_id *volume_id_open_node(int fd); |
91 | int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size); | 91 | int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size); |
92 | void free_volume_id(struct volume_id *id); | 92 | void free_volume_id(struct volume_id *id); |
93 | 93 | ||