From: H. Peter Anvin Date: Wed, 8 Feb 2012 18:15:50 +0000 (-0800) Subject: extlinux: use sysfs to find the device node if need be X-Git-Tag: syslinux-4.06-pre2~15 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=07f7e9b8005ee8c1879589d9b606c157f28f9f25;p=platform%2Fupstream%2Fsyslinux.git extlinux: use sysfs to find the device node if need be If neither /proc/mounts nor /etc/mtab contains a functional pointer to the device node for the installer, try to see if we can find the device node by looking for a symlink in /sys/dev/block. Signed-off-by: H. Peter Anvin --- diff --git a/extlinux/main.c b/extlinux/main.c index af87da2..5da89e2 100644 --- a/extlinux/main.c +++ b/extlinux/main.c @@ -873,6 +873,54 @@ static const char *find_device(const char *mtab_file, dev_t dev) } #endif +/* + * On newer Linux kernels we can use sysfs to get a backwards mapping + * from device names to standard filenames + */ +static const char *find_device_sysfs(dev_t dev) +{ + char sysname[64]; + char linkname[PATH_MAX]; + ssize_t llen; + char *p, *q; + char *buf = NULL; + struct stat st; + + snprintf(sysname, sizeof sysname, "/sys/dev/block/%u:%u", + major(dev), minor(dev)); + + llen = readlink(sysname, linkname, sizeof linkname); + if (llen < 0 || llen >= sizeof linkname) + goto err; + + linkname[llen] = '\0'; + + p = strrchr(linkname, '/'); + p = p ? p+1 : linkname; /* Leave basename */ + + buf = q = malloc(strlen(p) + 6); + if (!buf) + goto err; + + memcpy(q, "/dev/", 5); + q += 5; + + while (*p) { + *q++ = (*p == '!') ? '/' : *p; + p++; + } + + *q = '\0'; + + if (!stat(buf, &st) && st.st_dev == dev) + return buf; /* Found it! */ + +err: + if (buf) + free(buf); + return NULL; +} + static const char *get_devname(const char *path) { const char *devname = NULL; @@ -887,21 +935,26 @@ static const char *get_devname(const char *path) fprintf(stderr, "%s: statfs %s: %s\n", program, path, strerror(errno)); return devname; } + #ifdef __KLIBC__ - /* klibc doesn't have getmntent and friends; instead, just create - a new device with the appropriate device type */ - snprintf(devname_buf, sizeof devname_buf, "/tmp/dev-%u:%u", - major(st.st_dev), minor(st.st_dev)); + devname = find_device_sysfs(st.st_dev); - if (mknod(devname_buf, S_IFBLK | 0600, st.st_dev)) { - fprintf(stderr, "%s: cannot create device %s\n", program, devname); - return devname; + if (!devname) { + /* klibc doesn't have getmntent and friends; instead, just create + a new device with the appropriate device type */ + snprintf(devname_buf, sizeof devname_buf, "/tmp/dev-%u:%u", + major(st.st_dev), minor(st.st_dev)); + + if (mknod(devname_buf, S_IFBLK | 0600, st.st_dev)) { + fprintf(stderr, "%s: cannot create device %s\n", program, devname); + return devname; + } + + atexit(device_cleanup); /* unlink the device node on exit */ + devname = devname_buf; } - atexit(device_cleanup); /* unlink the device node on exit */ - devname = devname_buf; - #else devname = find_device("/proc/mounts", st.st_dev); @@ -910,11 +963,14 @@ static const char *get_devname(const char *path) devname = find_device("/etc/mtab", st.st_dev); } if (!devname) { + devname = find_device_sysfs(st.st_dev); + fprintf(stderr, "%s: cannot find device for path %s\n", program, path); return devname; } fprintf(stderr, "%s is device %s\n", path, devname); + #endif return devname; }