diff options
Diffstat (limited to 'util-linux/volume_id/get_devname.c')
-rw-r--r-- | util-linux/volume_id/get_devname.c | 216 |
1 files changed, 118 insertions, 98 deletions
diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c index af03d07a3..bb3043cd6 100644 --- a/util-linux/volume_id/get_devname.c +++ b/util-linux/volume_id/get_devname.c @@ -10,22 +10,19 @@ #include "volume_id_internal.h" -#define BLKGETSIZE64 _IOR(0x12,114,size_t) - -#define PROC_PARTITIONS "/proc/partitions" -#define PROC_CDROMS "/proc/sys/dev/cdrom/info" -#define DEVLABELDIR "/dev" -#define SYS_BLOCK "/sys/block" +//#define BLKGETSIZE64 _IOR(0x12,114,size_t) static struct uuidCache_s { struct uuidCache_s *next; - char uuid[16]; +// int major, minor; char *device; char *label; - int major, minor; + char *uc_uuid; /* prefix makes it easier to grep for */ } *uuidCache; -/* for now, only ext2, ext3 and xfs are supported */ +/* 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) @@ -38,15 +35,18 @@ get_label_uuid(const char *device, char **label, char **uuid, int iso_only) struct volume_id *vid; vid = volume_id_open_node(device); + if (!vid) + return rv; - 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) != 0 : - volume_id_probe_all(vid, 0, size) != 0) { + if ((iso_only ? + volume_id_probe_iso9660(vid, 0) : + volume_id_probe_all(vid, 0, size) + ) != 0 + ) { goto ret; } #else @@ -55,10 +55,10 @@ get_label_uuid(const char *device, char **label, char **uuid, int iso_only) } #endif - if (vid->label[0] != '\0') { + if (vid->label[0] != '\0' || vid->uuid[0] != '\0') { *label = xstrndup(vid->label, sizeof(vid->label)); *uuid = xstrndup(vid->uuid, sizeof(vid->uuid)); - printf("Found label %s on %s (uuid:%s)\n", *label, device, *uuid); + dbg("found label '%s', uuid '%s' on %s", *label, *uuid, device); rv = 0; } ret: @@ -66,8 +66,9 @@ get_label_uuid(const char *device, char **label, char **uuid, int iso_only) return rv; } +/* NB: we take ownership of (malloc'ed) label and uuid */ static void -uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid) +uuidcache_addentry(char *device, /*int major, int minor,*/ char *label, char *uuid) { struct uuidCache_s *last; @@ -80,13 +81,16 @@ uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid) last = last->next; } /*last->next = NULL; - xzalloc did it*/ - last->label = label; +// last->major = major; +// last->minor = minor; last->device = device; - last->major = major; - last->minor = minor; - memcpy(last->uuid, uuid, sizeof(last->uuid)); + last->label = label; + last->uc_uuid = uuid; } +/* 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) @@ -94,45 +98,62 @@ uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid) static void uuidcache_check_device(const char *device_name, int ma, int mi, int iso_only) { - char device[110]; - char *uuid = NULL, *label = NULL; + char *device, *last_slash; + char *uuid, *label; char *ptr; - char *deviceDir = NULL; - int mustRemove = 0; - int mustRemoveDir = 0; - int i; + 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! */ - sprintf(device, "%s/%s", DEVLABELDIR, device_name); - if (access(device, F_OK)) { ptr = device; - i = 0; while (*ptr) if (*ptr++ == '/') - i++; - if (i > 2) { - deviceDir = alloca(strlen(device) + 1); - strcpy(deviceDir, device); - ptr = deviceDir + (strlen(device) - 1); - while (*ptr != '/') - *ptr-- = '\0'; - if (mkdir(deviceDir, 0644)) { - printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno); + 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 { - mustRemoveDir = 1; + *last_slash = '/'; } } - mknod(device, S_IFBLK | 0600, makedev(ma, mi)); - mustRemove = 1; + must_remove = 1; + } + + 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 (!get_label_uuid(device, &label, &uuid, iso_only)) - uuidcache_addentry(strdup(device), ma, mi, - label, uuid); - if (mustRemove) unlink(device); - if (mustRemoveDir) rmdir(deviceDir); + if (must_remove) + unlink(device); + if (last_slash) { + *last_slash = '\0'; + rmdir(device); + } + ret: + if (!added) + free(device); } +/* Run uuidcache_check_device() for every device mentioned + * in /proc/partitions */ static void uuidcache_init_partitions(void) { @@ -144,7 +165,7 @@ uuidcache_init_partitions(void) int handleOnFirst; char *chptr; - procpt = xfopen(PROC_PARTITIONS, "r"); + procpt = xfopen("/proc/partitions", "r"); /* # cat /proc/partitions major minor #blocks name @@ -165,7 +186,7 @@ major minor #blocks name diet's sscanf is quite limited */ chptr = line; if (*chptr != ' ') continue; - chptr++; + chptr = skip_whitespace(chptr); ma = bb_strtou(chptr, &chptr, 0); if (ma < 0) continue; @@ -185,6 +206,8 @@ major minor #blocks name *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; @@ -203,36 +226,35 @@ major minor #blocks name fclose(procpt); } -static int +static void dev_get_major_minor(char *device_name, int *major, int *minor) { - char * dev_path; - int fd; - char dev[7]; - char *major_ptr, *minor_ptr; - - dev_path = alloca(strlen(SYS_BLOCK) + strlen(device_name) + 6); - sprintf(dev_path, "%s/%s/dev", SYS_BLOCK, device_name); - - fd = open(dev_path, O_RDONLY); - if (fd < 0) return 1; - full_read(fd, dev, sizeof(dev)); - close(fd); - - major_ptr = dev; - minor_ptr = strchr(dev, ':'); - if (!minor_ptr) return 1; - *minor_ptr++ = '\0'; + 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'; - *major = strtol(major_ptr, NULL, 10); - *minor = strtol(minor_ptr, NULL, 10); + colon = strchr(dev, ':'); + if (!colon) + goto ret; + *major = strtol(dev, NULL, 10); + *minor = strtol(colon + 1, NULL, 10); - return 0; + 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; @@ -250,11 +272,13 @@ uuidcache_init_cdroms(void) } while (fgets(line, sizeof(line), proccd)) { - const char *drive_name_string = "drive name:\t\t"; - if (!strncmp(line, drive_name_string, strlen(drive_name_string))) { + static const char drive_name_string[] ALIGN1 = "drive name:\t\t"; + + if (strncmp(line, drive_name_string, sizeof(drive_name_string) - 1) == 0) { char *device_name; - device_name = strtok(line + strlen(drive_name_string), "\t\n"); + device_name = strtok(line + sizeof(drive_name_string) - 1, "\t\n"); while (device_name) { + 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"); @@ -281,24 +305,24 @@ uuidcache_init(void) #ifdef UNUSED static char * -get_spec_by_x(int n, const char *t, int * majorPtr, int * minorPtr) +get_spec_by_x(int n, const char *t, int *majorPtr, int *minorPtr) { struct uuidCache_s *uc; uuidcache_init(); uc = uuidCache; - while(uc) { + while (uc) { switch (n) { case UUID: - if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) { + if (strcmp(t, uc->uc_uuid) == 0) { *majorPtr = uc->major; *minorPtr = uc->minor; return uc->device; } break; case VOL: - if (!strcmp(t, uc->label)) { + if (strcmp(t, uc->label) == 0) { *majorPtr = uc->major; *minorPtr = uc->minor; return uc->device; @@ -315,26 +339,27 @@ fromhex(char c) { if (isdigit(c)) return (c - '0'); - if (islower(c)) - return (c - 'a' + 10); - return (c - 'A' + 10); + return ((c|0x20) - 'a' + 10); } static char * -get_spec_by_uuid(const char *s, int * major, int * minor) +get_spec_by_uuid(const char *s, int *major, int *minor) { unsigned char uuid[16]; int i; - if (strlen(s) != 36 || - s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') + if (strlen(s) != 36 || s[8] != '-' || s[13] != '-' + || s[18] != '-' || s[23] != '-' + ) { goto bad_uuid; - for (i=0; i<16; i++) { - if (*s == '-') s++; - if (!isxdigit(s[0]) || !isxdigit(s[1])) - goto bad_uuid; - uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1])); - s += 2; + } + for (i = 0; i < 16; i++) { + if (*s == '-') + s++; + if (!isxdigit(s[0]) || !isxdigit(s[1])) + goto bad_uuid; + uuid[i] = ((fromhex(s[0]) << 4) | fromhex(s[1])); + s += 2; } return get_spec_by_x(UUID, (char *)uuid, major, minor); @@ -358,13 +383,7 @@ static int display_uuid_cache(void) u = uuidCache; while (u) { - printf("%s %s ", u->device, u->label); - for (i = 0; i < sizeof(u->uuid); i++) { - if (i == 4 || i == 6 || i == 8 || i == 10) - printf("-"); - printf("%x", u->uuid[i] & 0xff); - } - printf("\n"); + printf("%s %s %s\n", u->device, u->label, u->uc_uuid); u = u->next; } @@ -383,7 +402,8 @@ char *get_devname_from_label(const char *spec) uuidcache_init(); uc = uuidCache; while (uc) { - if (uc->label && !strncmp(spec, uc->label, spec_len)) { +// FIXME: empty label ("LABEL=") matches anything??! + if (uc->label[0] && strncmp(spec, uc->label, spec_len) == 0) { return xstrdup(uc->device); } uc = uc->next; @@ -398,7 +418,7 @@ char *get_devname_from_uuid(const char *spec) uuidcache_init(); uc = uuidCache; while (uc) { - if (!memcmp(spec, uc->uuid, sizeof(uc->uuid))) { + if (strcmp(spec, uc->uc_uuid) == 0) { return xstrdup(uc->device); } uc = uc->next; |