diff mbox

[v2,11/12] kpartx: find_loop_by_file: use sysfs

Message ID 20170515153722.11508-12-mwilck@suse.com (mailing list archive)
State Not Applicable, archived
Delegated to: christophe varoqui
Headers show

Commit Message

Martin Wilck May 15, 2017, 3:37 p.m. UTC
Rather then searching through all of /dev, look up loop devices
in /sys/devices/virtual/block. This is cleaner and more robust
(/dev/loop$Xp$Y symlinks may confuse kpartx).

Signed-off-by: Martin Wilck <mwilck@suse.com>
---
 kpartx/lopart.c | 42 +++++++++++++++++++++++++++++++-----------
 1 file changed, 31 insertions(+), 11 deletions(-)
diff mbox

Patch

diff --git a/kpartx/lopart.c b/kpartx/lopart.c
index 44f0c277..0521d7dc 100644
--- a/kpartx/lopart.c
+++ b/kpartx/lopart.c
@@ -68,25 +68,46 @@  char *find_loop_by_file(const char *filename)
 {
 	DIR *dir;
 	struct dirent *dent;
-	char dev[64], *found = NULL;
+	char dev[64], *found = NULL, *p;
 	int fd;
 	struct stat statbuf;
 	struct loop_info loopinfo;
+	const char VIRT_BLOCK[] = "/sys/devices/virtual/block";
+	char path[PATH_MAX];
 
-	dir = opendir("/dev");
+	dir = opendir(VIRT_BLOCK);
 	if (!dir)
 		return NULL;
 
 	while ((dent = readdir(dir)) != NULL) {
 		if (strncmp(dent->d_name,"loop",4))
 			continue;
-		if (!strcmp(dent->d_name, "loop-control"))
-			continue;
-		sprintf(dev, "/dev/%s", dent->d_name);
 
-		fd = open (dev, O_RDONLY);
+		if (snprintf(path, PATH_MAX, "%s/%s/dev", VIRT_BLOCK,
+			     dent->d_name) >= PATH_MAX)
+			continue;
+
+		fd = open(path, O_RDONLY);
 		if (fd < 0)
-			break;
+			continue;
+
+		if (read(fd, dev, sizeof(dev)) <= 0) {
+			close(fd);
+			continue;
+		}
+
+		close(fd);
+
+		dev[sizeof(dev)-1] = '\0';
+		p = strchr(dev, '\n');
+		if (p != NULL)
+			*p = '\0';
+		if (snprintf(path, PATH_MAX, "/dev/block/%s", dev) >= PATH_MAX)
+			continue;
+
+		fd = open (path, O_RDONLY);
+		if (fd < 0)
+			continue;
 
 		if (fstat (fd, &statbuf) != 0 ||
 		    !S_ISBLK(statbuf.st_mode)) {
@@ -99,13 +120,12 @@  char *find_loop_by_file(const char *filename)
 			continue;
 		}
 
+		close (fd);
+
 		if (0 == strcmp(filename, loopinfo.lo_name)) {
-			close (fd);
-			found = xstrdup(dev);
+			found = realpath(path, NULL);
 			break;
 		}
-
-		close (fd);
 	}
 	closedir(dir);
 	return found;