@@ -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;
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(-)