]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blobdiff - lib/blkid/devname.c
Fix gcc -Wall warnings
[thirdparty/e2fsprogs.git] / lib / blkid / devname.c
index 7d885515fb3bb7f42771f35e98245ff67b6d2e6c..79d928e8ae2afe8e2a178c7a48edd5529b9b0a23 100644 (file)
  * %End-Header%
  */
 
+#define _GNU_SOURCE 1
+
 #include <stdio.h>
 #include <string.h>
+#include <limits.h>
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
 #include "blkidP.h"
 
+#ifdef HAVE_DEVMAPPER
+#include <libdevmapper.h>
+#endif
+
 /*
  * Find a dev struct in the cache by device name, if available.
  *
@@ -64,6 +71,7 @@ blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
                dev = blkid_new_dev();
                if (!dev)
                        return NULL;
+               dev->bid_time = INT_MIN;
                dev->bid_name = blkid_strdup(devname);
                dev->bid_cache = cache;
                list_add_tail(&dev->bid_devs, &cache->bic_devs);
@@ -71,15 +79,19 @@ blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
        }
 
        if (flags & BLKID_DEV_VERIFY)
-               dev = blkid_verify_devname(cache, dev);
+               dev = blkid_verify(cache, dev);
        return dev;
 }
 
+#ifdef HAVE_DEVMAPPER
+static int dm_device_is_leaf(const dev_t dev);
+#endif
+
 /*
  * Probe a single block device to add to the device cache.
  */
 static void probe_one(blkid_cache cache, const char *ptname,
-                     dev_t devno, int pri)
+                     dev_t devno, int pri, int only_if_new)
 {
        blkid_dev dev = NULL;
        struct list_head *p;
@@ -90,8 +102,14 @@ static void probe_one(blkid_cache cache, const char *ptname,
        list_for_each(p, &cache->bic_devs) {
                blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
                                           bid_devs);
+#ifdef HAVE_DEVMAPPER
+               if (!dm_device_is_leaf(devno))
+                       continue;
+#endif
                if (tmp->bid_devno == devno) {
-                       dev = blkid_verify_devname(cache, tmp);
+                       if (only_if_new)
+                               return;
+                       dev = blkid_verify(cache, tmp);
                        break;
                }
        }
@@ -113,7 +131,8 @@ static void probe_one(blkid_cache cache, const char *ptname,
                    dev->bid_devno == devno)
                        goto set_pri;
 
-               if (stat(device, &st) == 0 && st.st_rdev == devno) {
+               if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) && 
+                   st.st_rdev == devno) {
                        devname = blkid_strdup(device);
                        break;
                }
@@ -129,10 +148,173 @@ static void probe_one(blkid_cache cache, const char *ptname,
 set_pri:
        if (!pri && !strncmp(ptname, "md", 2))
                pri = BLKID_PRI_MD;
-       dev->bid_pri = pri;
+       if (dev)
+               dev->bid_pri = pri;
+       return;
+}
+
+#ifdef HAVE_DEVMAPPER
+static void dm_quiet_log(int level __BLKID_ATTR((unused)), 
+                        const char *file __BLKID_ATTR((unused)), 
+                        int line __BLKID_ATTR((unused)),
+                        const char *f __BLKID_ATTR((unused)), ...)
+{
        return;
 }
 
+/* 
+ * device-mapper support 
+ */
+static int dm_device_has_dep(const dev_t dev, const char *name)
+{
+       struct dm_task *task;
+       struct dm_deps *deps;
+       struct dm_info info;
+       unsigned int i;
+
+       task = dm_task_create(DM_DEVICE_DEPS);
+       if (!task)
+               return 0;
+
+       dm_task_set_name(task, name);
+       dm_task_run(task);
+       dm_task_get_info(task, &info);
+
+       if (!info.exists) {
+               dm_task_destroy(task);
+               return 0;
+       }
+
+       deps = dm_task_get_deps(task);
+       if (!deps || deps->count == 0) {
+               dm_task_destroy(task);
+               return 0;
+       }
+
+       for (i = 0; i < deps->count; i++) {
+               dev_t dep_dev = deps->device[i];
+
+               if (dev == dep_dev) {
+                       dm_task_destroy(task);
+                       return 1;
+               }
+       }
+
+       dm_task_destroy(task);
+       return 0;
+}
+
+static int dm_device_is_leaf(const dev_t dev)
+{
+       struct dm_task *task;
+       struct dm_names *names;
+       unsigned int next = 0;
+       int n, ret = 1;
+
+       dm_log_init(dm_quiet_log);
+       task = dm_task_create(DM_DEVICE_LIST);
+       if (!task)
+               return 1;
+       dm_log_init(0);
+
+       dm_task_run(task);
+       names = dm_task_get_names(task);
+       if (!names || !names->dev) {
+               dm_task_destroy(task);
+               return 1;
+       }
+
+       n = 0;
+       do {
+               names = (struct dm_names *) ((char *)names + next);
+
+               if (dm_device_has_dep(dev, names->name))
+                       ret = 0;
+
+               next = names->next;
+       } while (next);
+
+       dm_task_destroy(task);
+
+       return ret;
+}
+
+static dev_t dm_get_devno(const char *name)
+{
+       struct dm_task *task;
+       struct dm_info info;
+       dev_t ret = 0;
+
+       task = dm_task_create(DM_DEVICE_INFO);
+       if (!task)
+               return ret;
+
+       dm_task_set_name(task, name);
+       dm_task_run(task);
+       dm_task_get_info(task, &info);
+
+       if (!info.exists) {
+               dm_task_destroy(task);
+               return ret;
+       }
+
+       ret = makedev(info.major, info.minor);
+
+       dm_task_destroy(task);
+       
+       return ret;
+}
+
+static void dm_probe_all(blkid_cache cache, int only_if_new)
+{
+       struct dm_task *task;
+       struct dm_names *names;
+       unsigned int next = 0;
+       int n;
+
+       dm_log_init(dm_quiet_log);
+       task = dm_task_create(DM_DEVICE_LIST);
+       if (!task)
+               return;
+       dm_log_init(0);
+
+       dm_task_run(task);
+       names = dm_task_get_names(task);
+       if (!names || !names->dev) {
+               dm_task_destroy(task);
+               return;
+       }
+
+       n = 0;
+       do {
+               int rc;
+               char *device = NULL;
+               dev_t dev = 0;
+
+               names = (struct dm_names *) ((char *)names + next);
+
+               rc = asprintf(&device, "mapper/%s", names->name);
+               if (rc < 0)
+                       goto try_next;
+
+               dev = dm_get_devno(names->name);
+               if (dev == 0)
+                       goto try_next;
+
+               if (!dm_device_is_leaf(dev)) 
+                       goto try_next;
+
+               probe_one(cache, device, dev, BLKID_PRI_DM, only_if_new);
+
+try_next:
+               free(device);
+               next = names->next;
+       } while (next);
+
+       dm_task_destroy(task);
+}
+#endif /* HAVE_DEVMAPPER */
+
 #define PROC_PARTITIONS "/proc/partitions"
 #define VG_DIR         "/proc/lvm/VGs"
 
@@ -169,7 +351,7 @@ static dev_t lvm_get_devno(const char *lvm_device)
        return ret;
 }
 
-static void lvm_probe_all(blkid_cache cache)
+static void lvm_probe_all(blkid_cache cache, int only_if_new)
 {
        DIR             *vg_list;
        struct dirent   *vg_iter;
@@ -220,7 +402,8 @@ static void lvm_probe_all(blkid_cache cache)
                        DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
                                                  lvm_device,
                                                  (unsigned int) dev));
-                       probe_one(cache, lvm_device, dev, BLKID_PRI_LVM);
+                       probe_one(cache, lvm_device, dev, BLKID_PRI_LVM, 
+                                 only_if_new);
                        free(lvm_device);
                }
                closedir(lv_list);
@@ -233,7 +416,7 @@ exit:
 #define PROC_EVMS_VOLUMES "/proc/evms/volumes"
 
 static int
-evms_probe_all(blkid_cache cache)
+evms_probe_all(blkid_cache cache, int only_if_new)
 {
        char line[100];
        int ma, mi, sz, num = 0;
@@ -251,7 +434,8 @@ evms_probe_all(blkid_cache cache)
                DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
                                          device, ma, mi));
 
-               probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS);
+               probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS,
+                         only_if_new);
                num++;
        }
        fclose(procpt);
@@ -261,18 +445,21 @@ evms_probe_all(blkid_cache cache)
 /*
  * Read the device data for all available block devices in the system.
  */
-int blkid_probe_all(blkid_cache cache)
+static int probe_all(blkid_cache cache, int only_if_new)
 {
        FILE *proc;
        char line[1024];
        char ptname0[128], ptname1[128], *ptname = 0;
-       char *ptnames[2] = { ptname0, ptname1 };
+       char *ptnames[2];
        dev_t devs[2];
        int ma, mi;
        unsigned long long sz;
        int lens[2] = { 0, 0 };
        int which = 0, last = 0;
 
+       ptnames[0] = ptname0;
+       ptnames[1] = ptname1;
+
        if (!cache)
                return -BLKID_ERR_PARAM;
 
@@ -280,9 +467,13 @@ int blkid_probe_all(blkid_cache cache)
            time(0) - cache->bic_time < BLKID_PROBE_INTERVAL)
                return 0;
 
-       evms_probe_all(cache);
+       blkid_read_cache(cache);
+#ifdef HAVE_DEVMAPPER
+       dm_probe_all(cache, only_if_new);
+#endif
+       evms_probe_all(cache, only_if_new);
 #ifdef VG_DIR
-       lvm_probe_all(cache);
+       lvm_probe_all(cache, only_if_new);
 #endif
 
        proc = fopen(PROC_PARTITIONS, "r");
@@ -294,7 +485,7 @@ int blkid_probe_all(blkid_cache cache)
                which ^= 1;
                ptname = ptnames[which];
 
-               if (sscanf(line, " %d %d %lld %128[^\n ]",
+               if (sscanf(line, " %d %d %llu %128[^\n ]",
                           &ma, &mi, &sz, ptname) != 4)
                        continue;
                devs[which] = makedev(ma, mi);
@@ -319,7 +510,8 @@ int blkid_probe_all(blkid_cache cache)
                                   ptname, (unsigned int) devs[which]));
 
                        if (sz > 1)
-                               probe_one(cache, ptname, devs[which], 0);
+                               probe_one(cache, ptname, devs[which], 0, 
+                                         only_if_new);
                        lens[which] = 0;
                        lens[last] = 0;
                } else if (lens[last] && strncmp(ptnames[last], ptname,
@@ -327,26 +519,49 @@ int blkid_probe_all(blkid_cache cache)
                        DBG(DEBUG_DEVNAME,
                            printf("whole dev %s, devno 0x%04X\n",
                                   ptnames[last], (unsigned int) devs[last]));
-                       probe_one(cache, ptnames[last], devs[last], 0);
+                       probe_one(cache, ptnames[last], devs[last], 0,
+                                 only_if_new);
                        lens[last] = 0;
                }
        }
 
        /* Handle the last device if it wasn't partitioned */
        if (lens[which])
-               probe_one(cache, ptname, devs[which], 0);
+               probe_one(cache, ptname, devs[which], 0, only_if_new);
 
        fclose(proc);
+       blkid_flush_cache(cache);
+       return 0;
+}
+
+int blkid_probe_all(blkid_cache cache)
+{
+       int ret;
 
+       DBG(DEBUG_PROBE, printf("Begin blkid_probe_all()\n"));
+       ret = probe_all(cache, 0);
        cache->bic_time = time(0);
        cache->bic_flags |= BLKID_BIC_FL_PROBED;
-       return 0;
+       DBG(DEBUG_PROBE, printf("End blkid_probe_all()\n"));
+       return ret;
+}
+
+int blkid_probe_all_new(blkid_cache cache)
+{
+       int ret;
+
+       DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_new()\n"));
+       ret = probe_all(cache, 1);
+       DBG(DEBUG_PROBE, printf("End blkid_probe_all_new()\n"));
+       return ret;
 }
 
+
 #ifdef TEST_PROGRAM
 int main(int argc, char **argv)
 {
        blkid_cache cache = NULL;
+       int ret;
 
        blkid_debug_mask = DEBUG_ALL;
        if (argc != 1) {
@@ -354,8 +569,9 @@ int main(int argc, char **argv)
                        "Probe all devices and exit\n", argv[0]);
                exit(1);
        }
-       if ((cache = blkid_new_cache()) == NULL) {
-               fprintf(stderr, "%s: error creating cache\n", argv[0]);
+       if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
+               fprintf(stderr, "%s: error creating cache (%d)\n",
+                       argv[0], ret);
                exit(1);
        }
        if (blkid_probe_all(cache) < 0)