]> err.no Git - util-linux/commitdiff
libblkid: add blkid_devno_to_wholedisk()
authorKarel Zak <kzak@redhat.com>
Wed, 16 Sep 2009 09:37:08 +0000 (11:37 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 16 Sep 2009 09:37:08 +0000 (11:37 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/blkid/src/blkid.h
shlibs/blkid/src/blkid.sym
shlibs/blkid/src/devno.c

index a4328a7db07f0e9fee4f9259daebe7592cd69361..326c37ce17fcfa71f158577d45047686dba14132 100644 (file)
@@ -72,6 +72,8 @@ extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
 
 /* devno.c */
 extern char *blkid_devno_to_devname(dev_t devno);
+extern int blkid_devno_to_wholedisk(dev_t dev, char *diskname,
+                        size_t len, dev_t *diskdevno);
 
 /* devname.c */
 extern int blkid_probe_all(blkid_cache cache);
index 86eae1a3f0fb57b8e281da6783672073354c2a60..4c2f1c2e295f4e237945eecf37491fc35bbb6a6b 100644 (file)
@@ -71,6 +71,7 @@ global:
  */
 BLKID_2.17 {
 global:
+       blkid_devno_to_wholedisk;
        blkid_do_fullprobe;
        blkid_probe_enable_superblocks;
        blkid_probe_filter_superblocks_type;
index 8ffdb835d37c96422b5b6b05bd64b31797803fd3..c84f01ec8e6bfe405566c829368a5b35dd91af31 100644 (file)
@@ -133,10 +133,21 @@ void blkid__scan_dir(char *dirname, dev_t devno, struct dir_list **list,
 /* Directories where we will try to search for device numbers */
 static const char *devdirs[] = { "/devices", "/devfs", "/dev", NULL };
 
-/*
+/**
+ * SECTION: misc
+ * @title: Miscellaneous utils
+ * @short_description: mix of various utils for low-level and high-level API
+ */
+
+/**
+ * blkid_devno_to_devname:
+ * @devno: device number
+ *
  * This function finds the pathname to a block device with a given
- * device number.  It returns a pointer to allocated memory to the
- * pathname on success, and NULL on failure.
+ * device number.
+ *
+ * Returns: a pointer to allocated memory to the pathname on success,
+ * and NULL on failure.
  */
 char *blkid_devno_to_devname(dev_t devno)
 {
@@ -186,6 +197,138 @@ char *blkid_devno_to_devname(dev_t devno)
        return devname;
 }
 
+
+/* returns basename and keeps dirname in the @path */
+static char *stripoff_last_component(char *path)
+{
+       char *p = strrchr(path, '/');
+
+       if (!p)
+               return NULL;
+       *p = '\0';
+       return ++p;
+}
+
+/**
+ * blkid_devno_to_wholedisk:
+ * @dev: device number
+ * @diskname: buffer to return diskname (or NULL)
+ * @len: diskname buffer size (or 0)
+ * @diskdevno: pointer to returns devno of entire disk (or NULL)
+ *
+ * This function uses sysfs to convert the @devno device number to the *name*
+ * of the whole disk. The function DOES NOT return full device name. The @dev
+ * argument could be partition or whole disk -- both is converted.
+ *
+ * For example: sda1, 0x0801 --> sda, 0x0800
+ *
+ * For conversion to the full disk *path* use blkid_devno_to_devname(), for
+ * example:
+ *
+ * <informalexample>
+ *  <programlisting>
+ *
+ *     dev_t dev = 0x0801, disk;               // sda1 = 8:1
+ *     char *diskpath, diskname[32];
+ *
+ *     blkid_devno_to_wholedisk(dev, diskname, sizeof(diskname), &disk);
+ *     diskpath = blkid_devno_to_devname(disk);
+ *
+ *     // print "0x0801: sda, /dev/sda, 8:0
+ *     printf("0x%x: %s, %s, %d:%d\n",
+ *             dev, diskname, diskpath, major(disk), minor(disk));
+ *
+ *     free(diskpath);
+ *
+ *  </programlisting>
+ * </informalexample>
+ *
+ * Returns: 0 on success or -1 in case of error.
+ */
+int blkid_devno_to_wholedisk(dev_t dev, char *diskname,
+                       size_t len, dev_t *diskdevno)
+{
+       char path[PATH_MAX];
+       char linkpath[PATH_MAX];
+       struct stat info;
+       char *name;
+       int rc, linklen;
+
+       if (!dev)
+               goto err;
+
+       /* check if dev is a partition */
+       rc = snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/partition",
+                       major(dev), minor(dev));
+       if (rc < 0 || rc + 1 > sizeof(path))
+               goto err;
+
+       rc = stat(path, &info);         /* 'rc == 0' means partitioned dev */
+
+        /* aka dirname (remove "/partition" from the path*/
+       stripoff_last_component(path);
+
+       /*
+        * Unpartitioned device:
+        *      - readlink /sys/dev/block/8:0 = ../../block/sda
+        *      - basename ../../block/sda    = sda
+        *
+        * Partitioned device:
+        *      - readlink /sys/dev/block/8:1   = ../../block/sda/sda1
+        *      - dirname  ../../block/sda/sda1 = ../../block/sda
+        *      - basename ../../block/sda      = sda
+        */
+       linklen = readlink(path, linkpath, sizeof(linkpath));
+       if (linklen < 0)
+               goto err;
+       linkpath[linklen] = '\0';
+
+       if (rc == 0)
+               /* partitioned device */
+               stripoff_last_component(linkpath);      /* dirname */
+
+       name = stripoff_last_component(linkpath);       /* basename */
+       if (!name)
+               goto err;
+
+       if (diskname && len) {
+               strncpy(diskname, name, len);
+               diskname[len - 1] = '\0';
+       }
+
+       if (diskdevno) {
+               int maj, min;
+               FILE *f;
+
+               /* read wholedisk devno */
+               rc = snprintf(path, sizeof(path), "/sys/dev/block/%s/dev", name);
+               if (rc < 0 || rc + 1 > sizeof(path))
+                       goto err;
+
+               f = fopen(path, "r");
+               if (!f)
+                       goto err;
+
+               rc = fscanf(f, "%d:%d", &maj, &min);
+               fclose(f);
+               if (rc != 2)
+                       goto err;
+
+               *diskdevno = makedev(maj, min);
+       }
+
+       DBG(DEBUG_DEVNO,
+           printf("found entire diskname for devno 0x%04llx as %s\n",
+           (long long) dev, name));
+       return 0;
+err:
+       DBG(DEBUG_DEVNO,
+           printf("failed to convert 0x%04llx to wholedisk name, errno=%d\n",
+           (long long) dev, errno));
+       return -1;
+}
+
+
 #ifdef TEST_PROGRAM
 int main(int argc, char** argv)
 {