aboutsummaryrefslogtreecommitdiff
path: root/util-linux/volume_id/get_devname.c
diff options
context:
space:
mode:
Diffstat (limited to 'util-linux/volume_id/get_devname.c')
-rw-r--r--util-linux/volume_id/get_devname.c216
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;