volume identification: abolish /proc/partitions and /proc/cdroms
authorDenis Vlasenko <vda.linux@googlemail.com>
Sun, 19 Oct 2008 19:36:30 +0000 (19:36 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sun, 19 Oct 2008 19:36:30 +0000 (19:36 -0000)
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

editors/diff.c
libbb/make_directory.c
util-linux/volume_id/get_devname.c
util-linux/volume_id/volume_id.c
util-linux/volume_id/volume_id_internal.h

index 64ad6511dad75710bd97b8140235c985167695ba..0e96c8496c12f880d4565a99944088dfc9deb798 100644 (file)
@@ -1189,7 +1189,7 @@ static char **get_recursive_dirlist(char *path)
                recursive_action(path, ACTION_RECURSE|ACTION_FOLLOWLINKS,
                                        add_to_dirlist, /* file_action */
                                        NULL, /* dir_action */
-                                       (void*)(strlen(path) + 1),
+                                       (void*)(ptrdiff_t)(strlen(path) + 1),
                                        0);
        } else {
                DIR *dp;
index df0b4a13d49562d0f7056f69e77dc6d1362f53fc..391493cda8f2d5bb6a4567d75f73d1f7797c232a 100644 (file)
@@ -71,7 +71,7 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
                        }
                        /* Since the directory exists, don't attempt to change
                         * permissions if it was the full target.  Note that
-                        * this is not an error conditon. */
+                        * this is not an error condition. */
                        if (!c) {
                                umask(mask);
                                return 0;
index 83c085650dd4b4ae3b7a7a16e987f119cd6ead19..e99c15b02dc37a46dbcbed75816751d7c956c09a 100644 (file)
@@ -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
index d81f3f94cfbdf54595d411f82cf1983388567a8c..6852a8203d9f2393ff8e698395b2e0959b0b0f1a 100644 (file)
@@ -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;
 }
 
index 6619d2c6ed27cd5a327270459c37a8a000d04c90..075ddb344fca8eb0cd3f6c86c998ebedd6afc822 100644 (file)
@@ -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);