From 582dff051459b1394a48dec1f29a29e2442661a0 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sun, 19 Oct 2008 19:36:30 +0000 Subject: 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 --- util-linux/volume_id/get_devname.c | 249 ++++-------------------------- util-linux/volume_id/volume_id.c | 7 +- util-linux/volume_id/volume_id_internal.h | 2 +- 3 files changed, 33 insertions(+), 225 deletions(-) (limited to 'util-linux') 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 { /* Returns !0 on error. * Otherwise, returns malloc'ed strings for label and uuid - * (and they can't be NULL, although they can be "") */ -#if !ENABLE_FEATURE_VOLUMEID_ISO9660 -#define get_label_uuid(device, label, uuid, iso_only) \ - get_label_uuid(device, label, uuid) -#endif + * (and they can't be NULL, although they can be ""). + * NB: closes fd. */ static int -get_label_uuid(const char *device, char **label, char **uuid, int iso_only) +get_label_uuid(int fd, char **label, char **uuid) { int rv = 1; uint64_t size; struct volume_id *vid; - vid = volume_id_open_node(device); - if (!vid) - return rv; + /* fd is owned by vid now */ + vid = volume_id_open_node(fd); - if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0) + if (ioctl(/*vid->*/fd, BLKGETSIZE64, &size) != 0) size = 0; -#if ENABLE_FEATURE_VOLUMEID_ISO9660 - if ((iso_only ? - volume_id_probe_iso9660(vid, 0) : - volume_id_probe_all(vid, 0, size) - ) != 0 - ) { - goto ret; - } -#else - if (volume_id_probe_all(vid, 0, size) != 0) { + if (volume_id_probe_all(vid, 0, size) != 0) goto ret; - } -#endif if (vid->label[0] != '\0' || vid->uuid[0] != '\0') { *label = xstrndup(vid->label, sizeof(vid->label)); @@ -62,7 +47,7 @@ get_label_uuid(const char *device, char **label, char **uuid, int iso_only) rv = 0; } ret: - free_volume_id(vid); + free_volume_id(vid); /* also closes fd */ return rv; } @@ -91,204 +76,29 @@ uuidcache_addentry(char *device, /*int major, int minor,*/ char *label, char *uu /* If get_label_uuid() on device_name returns success, * add a cache entry for this device. * If device node does not exist, it will be temporarily created. */ -#if !ENABLE_FEATURE_VOLUMEID_ISO9660 -#define uuidcache_check_device(device_name, ma, mi, iso_only) \ - uuidcache_check_device(device_name, ma, mi) -#endif -static void -uuidcache_check_device(const char *device_name, int ma, int mi, int iso_only) +static int FAST_FUNC +uuidcache_check_device(const char *device, + struct stat *statbuf, + void *userData UNUSED_PARAM, + int depth UNUSED_PARAM) { - char *device, *last_slash; - char *uuid, *label; - char *ptr; - int must_remove = 0; - int added = 0; - - last_slash = NULL; - device = xasprintf("/dev/%s", device_name); - if (access(device, F_OK) != 0) { - /* device does not exist, temporarily create */ - int slash_cnt = 0; - - if ((ma | mi) < 0) - goto ret; /* we don't know major:minor! */ - - ptr = device; - while (*ptr) - if (*ptr++ == '/') - slash_cnt++; - if (slash_cnt > 2) { -// BUG: handles only slash_cnt == 3 case - last_slash = strrchr(device, '/'); - *last_slash = '\0'; - if (mkdir(device, 0644)) { - bb_perror_msg("can't create directory %s", device); - *last_slash = '/'; - last_slash = NULL; /* prevents rmdir */ - } else { - *last_slash = '/'; - } - } - mknod(device, S_IFBLK | 0600, makedev(ma, mi)); - must_remove = 1; - } + char *uuid = uuid; /* for compiler */ + char *label = label; + int fd; - uuid = NULL; - label = NULL; - if (get_label_uuid(device, &label, &uuid, iso_only) == 0) { - uuidcache_addentry(device, /*ma, mi,*/ label, uuid); - /* "device" is owned by cache now, don't free */ - added = 1; - } + if (!S_ISBLK(statbuf->st_mode)) + return TRUE; - if (must_remove) - unlink(device); - if (last_slash) { - *last_slash = '\0'; - rmdir(device); - } - ret: - if (!added) - free(device); -} + fd = open(device, O_RDONLY); + if (fd < 0) + return TRUE; -/* Run uuidcache_check_device() for every device mentioned - * in /proc/partitions */ -static void -uuidcache_init_partitions(void) -{ - char line[100]; - int ma, mi; - unsigned long long sz; - FILE *procpt; - int firstPass; - int handleOnFirst; - char *chptr; - - procpt = xfopen_for_read("/proc/partitions"); -/* -# cat /proc/partitions -major minor #blocks name - - 8 0 293036184 sda - 8 1 6835626 sda1 - 8 2 1 sda2 - 8 5 979933 sda5 - 8 6 15623181 sda6 - 8 7 97659103 sda7 - 8 8 171935631 sda8 -*/ - for (firstPass = 1; firstPass >= 0; firstPass--) { - fseek(procpt, 0, SEEK_SET); - - while (fgets(line, sizeof(line), procpt)) { - /* The original version of this code used sscanf, but - diet's sscanf is quite limited */ - chptr = line; - if (*chptr != ' ') continue; - chptr = skip_whitespace(chptr); - - ma = bb_strtou(chptr, &chptr, 0); - if (ma < 0) continue; - chptr = skip_whitespace(chptr); - - mi = bb_strtou(chptr, &chptr, 0); - if (mi < 0) continue; - chptr = skip_whitespace(chptr); - - sz = bb_strtoull(chptr, &chptr, 0); - if ((long long)sz == -1LL) continue; - chptr = skip_whitespace(chptr); - - /* skip extended partitions (heuristic: size 1) */ - if (sz == 1) - continue; - - *strchrnul(chptr, '\n') = '\0'; - /* now chptr => device name */ - dbg("/proc/partitions: maj:%d min:%d sz:%llu name:'%s'", - ma, mi, sz, chptr); - if (!chptr[0]) - continue; - - /* look only at md devices on first pass */ - handleOnFirst = (chptr[0] == 'm' && chptr[1] == 'd'); - if (firstPass != handleOnFirst) - continue; - - /* heuristic: partition name ends in a digit */ - if (isdigit(chptr[strlen(chptr) - 1])) { - uuidcache_check_device(chptr, ma, mi, 0); - } - } + /* get_label_uuid() closes fd in all cases (success & failure) */ + if (get_label_uuid(fd, &label, &uuid) == 0) { + /* uuidcache_addentry() takes ownership of all three params */ + uuidcache_addentry(xstrdup(device), /*ma, mi,*/ label, uuid); } - - fclose(procpt); -} - -static void -dev_get_major_minor(char *device_name, int *major, int *minor) -{ - char dev[16]; - char *dev_path; - char *colon; - int sz; - - dev_path = xasprintf("/sys/block/%s/dev", device_name); - sz = open_read_close(dev_path, dev, sizeof(dev) - 1); - if (sz < 0) - goto ret; - dev[sz] = '\0'; - - colon = strchr(dev, ':'); - if (!colon) - goto ret; - *major = bb_strtou(dev, NULL, 10); - *minor = bb_strtou(colon + 1, NULL, 10); - - ret: - free(dev_path); - return; -} - -static void -uuidcache_init_cdroms(void) -{ -#define PROC_CDROMS "/proc/sys/dev/cdrom/info" - char line[100]; - int ma, mi; - FILE *proccd; - - proccd = fopen_for_read(PROC_CDROMS); - if (!proccd) { -// static smallint warn = 0; -// if (!warn) { -// warn = 1; -// bb_error_msg("can't open %s, UUID and LABEL " -// "conversion cannot be done for CD-Roms", -// PROC_CDROMS); -// } - return; - } - - while (fgets(line, sizeof(line), proccd)) { - static const char drive_name_string[] ALIGN1 = "drive name:"; - - if (strncmp(line, drive_name_string, sizeof(drive_name_string) - 1) == 0) { - char *device_name; - - device_name = strtok(skip_whitespace(line + sizeof(drive_name_string) - 1), " \t\n"); - while (device_name && device_name[0]) { - ma = mi = -1; - dev_get_major_minor(device_name, &ma, &mi); - uuidcache_check_device(device_name, ma, mi, 1); - device_name = strtok(NULL, " \t\n"); - } - break; - } - } - - fclose(proccd); + return TRUE; } static void @@ -297,8 +107,11 @@ uuidcache_init(void) if (uuidCache) return; - uuidcache_init_partitions(); - uuidcache_init_cdroms(); + recursive_action("/dev", ACTION_RECURSE, + uuidcache_check_device, /* file_action */ + NULL, /* dir_action */ + NULL, /* userData */ + 0 /* depth */); } #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) } /* open volume by device node */ -struct volume_id *volume_id_open_node(const char *path) +struct volume_id *volume_id_open_node(int fd) { struct volume_id *id; - int fd; - fd = open(path, O_RDONLY); - if (fd < 0) - return NULL; id = xzalloc(sizeof(struct volume_id)); id->fd = fd; ///* close fd on device close */ //id->fd_close = 1; - return id; } 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 { // int fd_close:1; }; -struct volume_id *volume_id_open_node(const char *path); +struct volume_id *volume_id_open_node(int fd); int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size); void free_volume_id(struct volume_id *id); -- cgit v1.2.3