fix logic bug inside extroot uuid verification code
[project/fstools.git] / block.c
diff --git a/block.c b/block.c
index a06e200..2e95c03 100644 (file)
--- a/block.c
+++ b/block.c
@@ -587,25 +587,86 @@ static struct blkid_struct_probe* find_block_info(char *uuid, char *label, char
 
 static char* find_mount_point(char *block)
 {
-       FILE *fp = fopen("/proc/mounts", "r");
+       FILE *fp = fopen("/proc/self/mountinfo", "r");
        static char line[256];
        int len = strlen(block);
-       char *point = NULL;
+       char *point = NULL, *pos, *tmp, *cpoint, *devname;
+       struct stat s;
+       int rstat;
+       unsigned int minor, major;
 
-       if(!fp)
+       if (!fp)
                return NULL;
 
+       rstat = stat(block, &s);
+
        while (fgets(line, sizeof(line), fp)) {
-               if (!strncmp(line, block, len)) {
-                       char *p = &line[len + 1];
-                       char *t = strstr(p, " ");
+               pos = strchr(line, ' ');
+               if (!pos)
+                       continue;
 
-                       if (!t) {
-                               fclose(fp);
-                               return NULL;
-                       }
-                       *t = '\0';
-                       point = p;
+               pos = strchr(pos + 1, ' ');
+               if (!pos)
+                       continue;
+
+               tmp = ++pos;
+               pos = strchr(pos, ':');
+               if (!pos)
+                       continue;
+
+               *pos = '\0';
+               major = atoi(tmp);
+               tmp = ++pos;
+               pos = strchr(pos, ' ');
+               if (!pos)
+                       continue;
+
+               *pos = '\0';
+               minor = atoi(tmp);
+               pos = strchr(pos + 1, ' ');
+               if (!pos)
+                       continue;
+               tmp = ++pos;
+
+               pos = strchr(pos, ' ');
+               if (!pos)
+                       continue;
+               *pos = '\0';
+               cpoint = tmp;
+
+               pos = strchr(pos + 1, ' ');
+               if (!pos)
+                       continue;
+
+               pos = strchr(pos + 1, ' ');
+               if (!pos)
+                       continue;
+
+               pos = strchr(pos + 1, ' ');
+               if (!pos)
+                       continue;
+
+               tmp = ++pos;
+               pos = strchr(pos, ' ');
+               if (!pos)
+                       continue;
+
+               *pos = '\0';
+               devname = tmp;
+               if (!strncmp(block, devname, len)) {
+                       point = strdup(cpoint);
+                       break;
+               }
+
+               if (rstat)
+                       continue;
+
+               if (!S_ISBLK(s.st_mode))
+                       continue;
+
+               if (major == major(s.st_rdev) &&
+                   minor == minor(s.st_rdev)) {
+                       point = strdup(cpoint);
                        break;
                }
        }
@@ -700,6 +761,7 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug)
 {
        struct mount *m;
        char *device;
+       char *mp;
 
        if (!pr)
                return -1;
@@ -719,8 +781,10 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug)
        if (hotplug && !auto_mount)
                return -1;
 
-       if (find_mount_point(pr->dev)) {
-               ULOG_ERR("%s is already mounted\n", pr->dev);
+       mp = find_mount_point(pr->dev);
+       if (mp) {
+               ULOG_ERR("%s is already mounted on %s\n", pr->dev, mp);
+               free(mp);
                return -1;
        }
 
@@ -803,6 +867,7 @@ static int umount_device(struct blkid_struct_probe *pr)
                ULOG_INFO("unmounted %s (%s)\n",
                          pr->dev, mp);
 
+       free(mp);
        return err;
 }
 
@@ -828,6 +893,7 @@ static int main_hotplug(int argc, char **argv)
                        ULOG_ERR("umount of %s failed (%d) - %s\n",
                                 mount_point, err, strerror(err));
 
+               free(mount_point);
                return 0;
        } else if (strcmp(action, "add")) {
                ULOG_ERR("Unkown action %s\n", action);
@@ -1042,7 +1108,7 @@ static int check_extroot(char *path)
                                         tag, errno, strerror(errno));
                        fclose(fp);
 
-                       if (*uuid || !strcasecmp(uuid, pr->uuid))
+                       if (*uuid && !strcasecmp(uuid, pr->uuid))
                                return 0;
 
                        ULOG_ERR("extroot: UUID mismatch (root: %s, %s: %s)\n",