Imported Upstream version 0.7.6
[platform/upstream/multipath-tools.git] / kpartx / lopart.c
index 2eb3f63..69c1eda 100644 (file)
 #include <fcntl.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <dirent.h>
-#include "sysmacros.h"
+#include <sys/sysmacros.h>
 #include <linux/loop.h>
+#include <limits.h>
 
 #include "lopart.h"
 #include "xstrncpy.h"
 #define LOOP_CTL_GET_FREE       0x4C82
 #endif
 
-#if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) \
-       && !defined (__s390x__)
-#define int2ptr(x)     ((void *) ((int) x))
-#else
-#define int2ptr(x)     ((void *) ((long) x))
-#endif
-
 static char *
 xstrdup (const char *s)
 {
@@ -62,62 +57,53 @@ xstrdup (const char *s)
        return t;
 }
 
-int is_loop_device(const char *device)
-{
-       struct stat statbuf;
-       int loopmajor;
-#if 1
-       loopmajor = 7;
-#else
-       FILE *procdev;
-       char line[100], *cp;
-
-       loopmajor = 0;
-
-       if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
-
-               while (fgets (line, sizeof(line), procdev)) {
-
-                       if ((cp = strstr (line, " loop\n")) != NULL) {
-                               *cp='\0';
-                               loopmajor=atoi(line);
-                               break;
-                       }
-               }
-
-               fclose(procdev);
-       }
-#endif
-       return (loopmajor && stat(device, &statbuf) == 0 &&
-               S_ISBLK(statbuf.st_mode) &&
-               major(statbuf.st_rdev) == loopmajor);
-}
-
 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
 
 char *find_loop_by_file(const char *filename)
 {
        DIR *dir;
        struct dirent *dent;
-       char dev[64], *found = NULL;
-       int fd;
+       char dev[64], *found = NULL, *p;
+       int fd, bytes_read;
        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"))
+
+               if (snprintf(path, PATH_MAX, "%s/%s/dev", VIRT_BLOCK,
+                            dent->d_name) >= PATH_MAX)
                        continue;
-               sprintf(dev, "/dev/%s", dent->d_name);
 
-               fd = open (dev, O_RDONLY);
+               fd = open(path, O_RDONLY);
                if (fd < 0)
-                       break;
+                       continue;
+
+               bytes_read = read(fd, dev, sizeof(dev) - 1);
+               if (bytes_read <= 0) {
+                       close(fd);
+                       continue;
+               }
+
+               close(fd);
+
+               dev[bytes_read] = '\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)) {
@@ -130,13 +116,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;
@@ -260,7 +245,7 @@ int set_loop(const char *device, const char *file, int offset, int *loopro)
        loopinfo.lo_encrypt_type = LO_CRYPT_NONE;
        loopinfo.lo_encrypt_key_size = 0;
 
-       if (ioctl (fd, LOOP_SET_FD, int2ptr(ffd)) < 0) {
+       if (ioctl(fd, LOOP_SET_FD, (void*)(uintptr_t)(ffd)) < 0) {
                perror ("ioctl: LOOP_SET_FD");
                close (fd);
                close (ffd);