aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-10-19 19:36:30 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-10-19 19:36:30 +0000
commit582dff051459b1394a48dec1f29a29e2442661a0 (patch)
tree41835a2b323eefb403825db78c033a920f86b602
parentbff06fe02a3d5629b745d799c3b987888070dc20 (diff)
downloadbusybox-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
-rw-r--r--editors/diff.c2
-rw-r--r--libbb/make_directory.c2
-rw-r--r--util-linux/volume_id/get_devname.c249
-rw-r--r--util-linux/volume_id/volume_id.c7
-rw-r--r--util-linux/volume_id/volume_id_internal.h2
5 files changed, 35 insertions, 227 deletions
diff --git a/editors/diff.c b/editors/diff.c
index 64ad6511d..0e96c8496 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -1189,7 +1189,7 @@ static char **get_recursive_dirlist(char *path)
1189 recursive_action(path, ACTION_RECURSE|ACTION_FOLLOWLINKS, 1189 recursive_action(path, ACTION_RECURSE|ACTION_FOLLOWLINKS,
1190 add_to_dirlist, /* file_action */ 1190 add_to_dirlist, /* file_action */
1191 NULL, /* dir_action */ 1191 NULL, /* dir_action */
1192 (void*)(strlen(path) + 1), 1192 (void*)(ptrdiff_t)(strlen(path) + 1),
1193 0); 1193 0);
1194 } else { 1194 } else {
1195 DIR *dp; 1195 DIR *dp;
diff --git a/libbb/make_directory.c b/libbb/make_directory.c
index df0b4a13d..391493cda 100644
--- a/libbb/make_directory.c
+++ b/libbb/make_directory.c
@@ -71,7 +71,7 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
71 } 71 }
72 /* Since the directory exists, don't attempt to change 72 /* Since the directory exists, don't attempt to change
73 * permissions if it was the full target. Note that 73 * permissions if it was the full target. Note that
74 * this is not an error conditon. */ 74 * this is not an error condition. */
75 if (!c) { 75 if (!c) {
76 umask(mask); 76 umask(mask);
77 return 0; 77 return 0;
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
30static int 27static int
31get_label_uuid(const char *device, char **label, char **uuid, int iso_only) 28get_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 79static int FAST_FUNC
95#define uuidcache_check_device(device_name, ma, mi, iso_only) \ 80uuidcache_check_device(const char *device,
96 uuidcache_check_device(device_name, ma, mi) 81 struct stat *statbuf,
97#endif 82 void *userData UNUSED_PARAM,
98static void 83 int depth UNUSED_PARAM)
99uuidcache_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) {
157static void 98 /* uuidcache_addentry() takes ownership of all three params */
158uuidcache_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
171major 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
229static void
230dev_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
254static void
255uuidcache_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
294static void 104static 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 */
193struct volume_id *volume_id_open_node(const char *path) 193struct 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
90struct volume_id *volume_id_open_node(const char *path); 90struct volume_id *volume_id_open_node(int fd);
91int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size); 91int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size);
92void free_volume_id(struct volume_id *id); 92void free_volume_id(struct volume_id *id);
93 93