From 62309b345a6fb6cb68d6ca766fe95e227f890eea Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Wed, 18 May 2011 17:25:21 +0000 Subject: [PATCH] Simplify device path scan and avoid stat(); git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@526 36d66b0a-2a48-0410-832c-cd162a569da5 --- ChangeLog | 1 + lib/libdevmapper.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 072fee6..2aafddf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 2011-05-17 Milan Broz * Fix keyfile=- processing in create command (1.3.0). + * Simplify device path status check. 2011-05-03 Milan Broz * Do not ignore size argument for create command (1.2.0). diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index e3472c5..8e58860 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -259,7 +259,7 @@ static char *__lookup_dev(char *path, dev_t dev, int dir_level, const int max_le return result; } -static char *lookup_dev(const char *dev_id) +static char *lookup_dev_old(const char *dev_id) { uint32_t major, minor; dev_t dev; @@ -290,6 +290,66 @@ static char *lookup_dev(const char *dev_id) return result; } +/* Return path to DM device */ +static char *dm_device_path(const char *dev_id) +{ + int major, minor; + struct dm_task *dmt; + const char *name; + char path[PATH_MAX]; + + if (sscanf(dev_id, "%d:%d", &major, &minor) != 2) + return NULL; + + if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) + return NULL; + if (!dm_task_set_minor(dmt, minor) || + !dm_task_set_major(dmt, major) || + !dm_task_run(dmt) || + !(name = dm_task_get_name(dmt))) { + dm_task_destroy(dmt); + return NULL; + } + + if (snprintf(path, sizeof(path), "/dev/mapper/%s", name) < 0) + path[0] = '\0'; + + dm_task_destroy(dmt); + + return strdup(path); +} + +static char *lookup_dev(const char *dev_id) +{ + char link[PATH_MAX], path[PATH_MAX], *devname; + struct stat st; + ssize_t len; + + if (snprintf(path, sizeof(path), "/sys/dev/block/%s", dev_id) < 0) + return NULL; + + len = readlink(path, link, sizeof(link)); + if (len < 0) { + if (stat("/sys/dev/block", &st) < 0) + return lookup_dev_old(dev_id); + return NULL; + } + + link[len] = '\0'; + devname = strrchr(link, '/'); + if (!devname) + return NULL; + devname++; + + if (!strncmp(devname, "dm-", 3)) + return dm_device_path(dev_id); + + if (snprintf(path, sizeof(path), "/dev/%s", devname) < 0) + return NULL; + + return strdup(path); +} + static int _dev_read_ahead(const char *dev, uint32_t *read_ahead) { int fd, r = 0; -- 2.7.4