]> err.no Git - util-linux/commitdiff
libblkid: add blkid_probe_all_removable()
authorKarel Zak <kzak@redhat.com>
Mon, 1 Feb 2010 13:23:55 +0000 (14:23 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 1 Feb 2010 13:23:55 +0000 (14:23 +0100)
The libblkid probing is based on devices from /proc/partitions by
default. This file usually does not contain removable devices (e.g.
CDROMs) and this kind of devices are invisible for libblkid.

The blkid_probe_all_removable() function adds removable block devices
to blkid cache. The probing is based on information from the /sys
directory. The devices which were detected by this function won't be
written to blkid.tab cache file.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=533874
Signed-off-by: Karel Zak <kzak@redhat.com>
include/pathnames.h
shlibs/blkid/src/blkid.h.in
shlibs/blkid/src/blkid.sym
shlibs/blkid/src/blkidP.h
shlibs/blkid/src/devname.c
shlibs/blkid/src/save.c

index efe5c3bc8b2caf9d0d115ca21e1009a335f8baa4..9c4eb009b60acc798f1d5f2576e091a9a1144856 100644 (file)
@@ -76,6 +76,8 @@
 #define _PATH_PROC_PARTITIONS  "/proc/partitions"
 #define _PATH_PROC_DEVICES     "/proc/devices"
 
+#define _PATH_SYS_BLOCK                "/sys/block"
+
 #ifndef _PATH_MOUNTED
 # ifdef MOUNTED                                        /* deprecated */
 #  define _PATH_MOUNTED                MOUNTED
index febb43728981b5df20b1dab276330db5911b88b3..4e53b39feaba7cd885b2116b0f9df602d4eae9f7 100644 (file)
@@ -142,6 +142,7 @@ extern int blkid_devno_to_wholedisk(dev_t dev, char *diskname,
 /* devname.c */
 extern int blkid_probe_all(blkid_cache cache);
 extern int blkid_probe_all_new(blkid_cache cache);
+extern int blkid_probe_all_removable(blkid_cache cache);
 extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
                               int flags);
 
index 972555266db94d6dd1768e47770ee75a0323b22c..4d01aa201b7a94e476d82af54e6f6e181cada839 100644 (file)
@@ -114,3 +114,11 @@ global:
        blkid_topology_get_optimal_io_size;
        blkid_topology_get_physical_sector_size;
 } BLKID_2.15;
+
+/*
+ * version(s) since util-linux-ng 2.18
+ */
+BLKID_2.18 {
+global:
+       blkid_probe_all_removable;
+} BLKID_2.17;
index 4d21304e3d4348cfa30372cf7fa5cad64d19b231..d15b53058bc8642fe5eaebf257a79863ffdbc472 100644 (file)
@@ -51,6 +51,7 @@ struct blkid_struct_dev
 
 #define BLKID_BID_FL_VERIFIED  0x0001  /* Device data validated from disk */
 #define BLKID_BID_FL_INVALID   0x0004  /* Device is invalid */
+#define BLKID_BID_FL_REMOVABLE 0x0008  /* Device added by blkid_probe_all_removable() */
 
 /*
  * Each tag defines a NAME=value pair for a particular device.  The tags
index d048c722259782adfec9a18bea9ee8d138d86220..5d6da8918956a13b6846fb411e9a36dd090a7318 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include <fcntl.h>
 #if HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
@@ -38,7 +39,9 @@
 #include <time.h>
 
 #include "blkidP.h"
+
 #include "canonicalize.h"              /* $(top_srcdir)/include */
+#include "pathnames.h"
 
 /*
  * Find a dev struct in the cache by device name, if available.
@@ -157,7 +160,7 @@ static int is_dm_leaf(const char *devname)
  * 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, int only_if_new)
+                     dev_t devno, int pri, int only_if_new, int removable)
 {
        blkid_dev dev = NULL;
        struct list_head *p, *pnext;
@@ -237,6 +240,8 @@ set_pri:
                                dev->bid_pri += 5;
                } else if (!strncmp(ptname, "md", 2))
                        dev->bid_pri = BLKID_PRI_MD;
+               if (removable)
+                       dev->bid_flags |= BLKID_BID_FL_REMOVABLE;
        }
        return;
 }
@@ -328,7 +333,7 @@ static void lvm_probe_all(blkid_cache cache, int only_if_new)
                                                  lvm_device,
                                                  (unsigned int) dev));
                        probe_one(cache, lvm_device, dev, BLKID_PRI_LVM,
-                                 only_if_new);
+                                 only_if_new, 0);
                        free(lvm_device);
                }
                closedir(lv_list);
@@ -360,7 +365,7 @@ evms_probe_all(blkid_cache cache, int only_if_new)
                                          device, ma, mi));
 
                probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS,
-                         only_if_new);
+                         only_if_new, 0);
                num++;
        }
        fclose(procpt);
@@ -408,7 +413,7 @@ ubi_probe_all(blkid_cache cache, int only_if_new)
                                continue;
                        DBG(DEBUG_DEVNAME, printf("UBI vol %s/%s: devno 0x%04X\n",
                                  *dirname, name, (int) dev));
-                       probe_one(cache, name, dev, BLKID_PRI_UBI, only_if_new);
+                       probe_one(cache, name, dev, BLKID_PRI_UBI, only_if_new, 0);
                }
                closedir(dir);
        }
@@ -485,7 +490,7 @@ static int probe_all(blkid_cache cache, int only_if_new)
 
                        if (sz > 1)
                                probe_one(cache, ptname, devs[which], 0,
-                                         only_if_new);
+                                         only_if_new, 0);
                        lens[which] = 0;        /* mark as checked */
                }
 
@@ -522,20 +527,81 @@ static int probe_all(blkid_cache cache, int only_if_new)
                            printf("whole dev %s, devno 0x%04X\n",
                                   ptnames[last], (unsigned int) devs[last]));
                        probe_one(cache, ptnames[last], devs[last], 0,
-                                 only_if_new);
+                                 only_if_new, 0);
                        lens[last] = 0;
                }
        }
 
        /* Handle the last device if it wasn't partitioned */
        if (lens[which])
-               probe_one(cache, ptname, devs[which], 0, only_if_new);
+               probe_one(cache, ptname, devs[which], 0, only_if_new, 0);
 
        fclose(proc);
        blkid_flush_cache(cache);
        return 0;
 }
 
+/* Don't use it by default -- it's pretty slow (because cdroms, floppy, ...)
+ */
+static int probe_all_removable(blkid_cache cache)
+{
+       DIR *dir;
+       struct dirent *d;
+       char buf[PATH_MAX];
+
+       if (!cache)
+               return -BLKID_ERR_PARAM;
+
+       dir = opendir(_PATH_SYS_BLOCK);
+       if (!dir)
+               return -BLKID_ERR_PROC;
+
+       while((d = readdir(dir))) {
+               int fd, rc, ma, mi;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+               if (d->d_type != DT_UNKNOWN && d->d_type != DT_LNK)
+                       continue;
+#endif
+               if (d->d_name[0] == '.' &&
+                   ((d->d_name[1] == 0) ||
+                    ((d->d_name[1] == '.') && (d->d_name[2] == 0))))
+                       continue;
+
+               snprintf(buf, sizeof(buf), "%s/removable", d->d_name);
+               fd = blkid_openat(dir, _PATH_SYS_BLOCK, buf, O_RDONLY);
+               if (fd < 0)
+                       continue;
+
+               rc = read(fd, buf, 1);
+               close(fd);
+
+               if (rc != 1 || *buf != '1')
+                       continue;               /* not removable device */
+
+               /* get devno */
+               snprintf(buf, sizeof(buf), "%s/dev", d->d_name);
+               fd = blkid_openat(dir, _PATH_SYS_BLOCK, buf, O_RDONLY);
+               if (fd < 0)
+                       continue;
+
+               rc = read(fd, buf, sizeof(buf));
+               close(fd);
+
+               if (rc < 3)
+                       continue;               /* M:N */
+               buf[rc] = '\0';
+               if (sscanf(buf, "%d:%d", &ma, &mi) != 2)
+                       continue;
+
+               probe_one(cache, d->d_name, makedev(ma, mi), 0, 0, 1);
+       }
+
+       closedir(dir);
+       return 0;
+}
+
+
 /**
  * blkid_probe_all:
  * @cache: cache handler
@@ -574,6 +640,33 @@ int blkid_probe_all_new(blkid_cache cache)
        return ret;
 }
 
+/**
+ * blkid_probe_all_removable:
+ * @cache: cache handler
+ *
+ * The libblkid probing is based on devices from /proc/partitions by default.
+ * This file usually does not contain removable devices (e.g. CDROMs) and this kind
+ * of devices are invisible for libblkid.
+ *
+ * This function adds removable block devices to @cache (probing is based on
+ * information from the /sys directory). Don't forget that removable devices
+ * (floppies, CDROMs, ...) could be pretty slow. It's very bad idea to call
+ * this function by default.
+ *
+ * Note that devices which were detected by this function won't be written to
+ * blkid.tab cache file.
+ *
+ * Returns: 0 on success, or number less than zero in case of error.
+ */
+int blkid_probe_all_removable(blkid_cache cache)
+{
+       int ret;
+
+       DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_removable()\n"));
+       ret = probe_all_removable(cache);
+       DBG(DEBUG_PROBE, printf("End blkid_probe_all_removable()\n"));
+       return ret;
+}
 
 #ifdef TEST_PROGRAM
 int main(int argc, char **argv)
@@ -595,6 +688,9 @@ int main(int argc, char **argv)
        if (blkid_probe_all(cache) < 0)
                printf("%s: error probing devices\n", argv[0]);
 
+       if (blkid_probe_all_removable(cache) < 0)
+               printf("%s: error probing removable devices\n", argv[0]);
+
        blkid_put_cache(cache);
        return (0);
 }
index c61373d508382f437eacf15740fa650ed91ce3bf..a1583ecca095542b39024dc127738547d677498b 100644 (file)
@@ -119,7 +119,7 @@ int blkid_flush_cache(blkid_cache cache)
 
        list_for_each(p, &cache->bic_devs) {
                blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
-               if (!dev->bid_type)
+               if (!dev->bid_type || (dev->bid_flags & BLKID_BID_FL_REMOVABLE))
                        continue;
                if ((ret = save_dev(dev, file)) < 0)
                        break;