]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: store only canonical devnames to the cache
authorKarel Zak <kzak@redhat.com>
Thu, 26 May 2016 10:02:12 +0000 (12:02 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 26 May 2016 10:15:26 +0000 (12:15 +0200)
Let's try to use symlink:

 # ls -la /dev/block/8\:1
 # lrwxrwxrwx 1 root root 7 May 25 16:42 /dev/block/8:1 -> ../sda1

 # blkid /dev/block/8:1
 /dev/block/8:3: LABEL="HOME" UUID="196972ad-3b13-4bba-ac54-4cb3f7b409a4" TYPE="ext4" PARTUUID="6073277f-87bc-43ff-bcfd-724c4484a63a"

unfortunately the symlink is stored to the cache:

 <device DEVNO="0x0803" TIME="1464253300.715279" LABEL="HOME" UUID="196972ad-3b13-4bba-ac54-4cb3f7b409a4" TYPE="ext4" PARTUUID="6073277f-87bc-43ff-bcfd-724c4484a63a">/dev/block/8:3</device>

next time if you ask for LABEL=HOME the answer will be /dev/block/8:3
rather than /dev/sda3.

It seems better to canonicalize the paths we store to the cache.

Unfortunately if you ask for /dev/block/8:3 then you probably expect
that blkid_dev_devname() returns the same path. This patch introduces
dev->bid_xname, this is the path used by application (and never stored
in the cache).

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1332779
Signed-off-by: Karel Zak <kzak@redhat.com>
libblkid/src/blkidP.h
libblkid/src/dev.c
libblkid/src/devname.c

index e298b41dd137163778a83dda1bcdb25ebf4835d7..68204233d23ce103ddfaee6b000739545ff04e4f 100644 (file)
@@ -42,7 +42,8 @@ struct blkid_struct_dev
        struct list_head        bid_devs;       /* All devices in the cache */
        struct list_head        bid_tags;       /* All tags for this device */
        blkid_cache             bid_cache;      /* Dev belongs to this cache */
-       char                    *bid_name;      /* Device inode pathname */
+       char                    *bid_name;      /* Device real pathn (as used in cache) */
+       char                    *bid_xname;     /* Device path as used by application (maybe symlink..) */
        char                    *bid_type;      /* Preferred device TYPE */
        int                     bid_pri;        /* Device priority */
        dev_t                   bid_devno;      /* Device major/minor number */
index f35895da9862bb92327df8b12eb981237e4d9915..b5ad0f1150e285653bed0aec4987650ef13782c2 100644 (file)
@@ -58,16 +58,23 @@ void blkid_free_dev(blkid_dev dev)
                                           bit_tags);
                blkid_free_tag(tag);
        }
+       free(dev->bid_xname);
        free(dev->bid_name);
        free(dev);
 }
 
 /*
- * Given a blkid device, return its name
+ * Given a blkid device, return its name. The function returns the name
+ * previously used for blkid_get_dev(). This name does not have to be canonical
+ * (real path) name, but for example symlink.
  */
 const char *blkid_dev_devname(blkid_dev dev)
 {
-       return dev ? dev->bid_name : NULL;
+       if (!dev)
+               return NULL;
+       if (dev->bid_xname)
+               return dev->bid_xname;
+       return dev->bid_name;
 }
 
 void blkid_debug_dump_dev(blkid_dev dev)
index dbbe5b54d78accb7e21db0733e927f56842ad6af..2e5f4f1514185f049d2c8d7580cd880903567616 100644 (file)
@@ -50,28 +50,55 @@ blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
 {
        blkid_dev dev = NULL, tmp;
        struct list_head *p, *pnext;
+       char *cn = NULL;
 
        if (!cache || !devname)
                return NULL;
 
+       /* search by name */
        list_for_each(p, &cache->bic_devs) {
                tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
                if (strcmp(tmp->bid_name, devname))
                        continue;
-
-               DBG(DEVNAME, ul_debug("found devname %s in cache", tmp->bid_name));
                dev = tmp;
                break;
        }
 
+       /* try canonicalize the name */
+       if (!dev && (cn = canonicalize_path(devname))) {
+               if (strcmp(cn, devname) != 0) {
+                       DBG(DEVNAME, ul_debug("search cannonical %s", cn));
+                       list_for_each(p, &cache->bic_devs) {
+                               tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
+                               if (strcmp(tmp->bid_name, cn))
+                                       continue;
+                               dev = tmp;
+
+                               /* update name returned by blkid_dev_devname() */
+                               free(dev->bid_xname);
+                               dev->bid_xname = strdup(devname);
+                               break;
+                       }
+               } else {
+                       free(cn);
+                       cn = NULL;
+               }
+       }
+
        if (!dev && (flags & BLKID_DEV_CREATE)) {
                if (access(devname, F_OK) < 0)
-                       return NULL;
+                       goto done;
                dev = blkid_new_dev();
                if (!dev)
-                       return NULL;
+                       goto done;
                dev->bid_time = INT_MIN;
-               dev->bid_name = strdup(devname);
+               if (cn) {
+                       dev->bid_name = cn;
+                       dev->bid_xname = strdup(devname);
+                       cn = NULL;      /* see free() below */
+               } else
+                       dev->bid_name = strdup(devname);
+
                dev->bid_cache = cache;
                list_add_tail(&dev->bid_devs, &cache->bic_devs);
                cache->bic_flags |= BLKID_BIC_FL_CHANGED;
@@ -80,7 +107,7 @@ blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
        if (flags & BLKID_DEV_VERIFY) {
                dev = blkid_verify(cache, dev);
                if (!dev || !(dev->bid_flags & BLKID_BID_FL_VERIFIED))
-                       return dev;
+                       goto done;
                /*
                 * If the device is verified, then search the blkid
                 * cache for any entries that match on the type, uuid,
@@ -111,6 +138,10 @@ blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
                                blkid_free_dev(dev2);
                }
        }
+done:
+       if (dev)
+               DBG(DEVNAME, ul_debug("%s requested, found %s in cache", devname, dev->bid_name));
+       free(cn);
        return dev;
 }