]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - misc-utils/lsblk-properties.c
Merge branch 'PR/libmount-utab-event' of github.com:karelzak/util-linux-work
[thirdparty/util-linux.git] / misc-utils / lsblk-properties.c
index a4fdeb5bd9c4b52a0fef502bb832f2f04f52723e..dc6f2896c968c378bb7cd18cced4cb10cedb099a 100644 (file)
@@ -9,6 +9,8 @@
 #include "xalloc.h"
 #include "mangle.h"
 #include "path.h"
+#include "nls.h"
+#include "strutils.h"
 
 #include "lsblk.h"
 
@@ -22,6 +24,7 @@ void lsblk_device_free_properties(struct lsblk_devprop *p)
                return;
 
        free(p->fstype);
+       free(p->fsversion);
        free(p->uuid);
        free(p->ptuuid);
        free(p->pttype);
@@ -29,10 +32,13 @@ void lsblk_device_free_properties(struct lsblk_devprop *p)
        free(p->parttype);
        free(p->partuuid);
        free(p->partlabel);
+       free(p->partn);
        free(p->wwn);
        free(p->serial);
        free(p->model);
        free(p->partflags);
+       free(p->idlink);
+       free(p->revision);
 
        free(p->mode);
        free(p->owner);
@@ -48,9 +54,17 @@ static struct lsblk_devprop *get_properties_by_udev(struct lsblk_device *dev
        return NULL;
 }
 #else
+
+#define LSBLK_UDEV_BYID_PREFIX "/dev/disk/by-id/"
+#define LSBLK_UDEV_BYID_PREFIXSZ (sizeof(LSBLK_UDEV_BYID_PREFIX) - 1)
+
 static struct lsblk_devprop *get_properties_by_udev(struct lsblk_device *ld)
 {
        struct udev_device *dev;
+       struct udev_list_entry *le;
+       const char *data;
+       struct lsblk_devprop *prop;
+       size_t len;
 
        if (ld->udev_requested)
                return ld->properties;
@@ -61,58 +75,94 @@ static struct lsblk_devprop *get_properties_by_udev(struct lsblk_device *ld)
                goto done;
 
        dev = udev_device_new_from_subsystem_sysname(udev, "block", ld->name);
-       if (dev) {
-               const char *data;
-               struct lsblk_devprop *prop;
+       if (!dev)
+               goto done;
 
-               if (ld->properties)
-                       lsblk_device_free_properties(ld->properties);
-               prop = ld->properties = xcalloc(1, sizeof(*ld->properties));
+       DBG(DEV, ul_debugobj(ld, "%s: found udev properties", ld->name));
 
-               if ((data = udev_device_get_property_value(dev, "ID_FS_LABEL_ENC"))) {
-                       prop->label = xstrdup(data);
-                       unhexmangle_string(prop->label);
-               }
-               if ((data = udev_device_get_property_value(dev, "ID_FS_UUID_ENC"))) {
-                       prop->uuid = xstrdup(data);
-                       unhexmangle_string(prop->uuid);
-               }
-               if ((data = udev_device_get_property_value(dev, "ID_PART_TABLE_UUID")))
-                       prop->ptuuid = xstrdup(data);
-               if ((data = udev_device_get_property_value(dev, "ID_PART_TABLE_TYPE")))
-                       prop->pttype = xstrdup(data);
-               if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_NAME"))) {
-                       prop->partlabel = xstrdup(data);
-                       unhexmangle_string(prop->partlabel);
-               }
-               if ((data = udev_device_get_property_value(dev, "ID_FS_TYPE")))
-                       prop->fstype = xstrdup(data);
-               if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_TYPE")))
-                       prop->parttype = xstrdup(data);
-               if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_UUID")))
-                       prop->partuuid = xstrdup(data);
-               if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_FLAGS")))
-                       prop->partflags = xstrdup(data);
-
-               data = udev_device_get_property_value(dev, "ID_WWN_WITH_EXTENSION");
-               if (!data)
-                       data = udev_device_get_property_value(dev, "ID_WWN");
-               if (data)
-                       prop->wwn = xstrdup(data);
+       if (ld->properties)
+               lsblk_device_free_properties(ld->properties);
+       prop = ld->properties = xcalloc(1, sizeof(*ld->properties));
 
+       if ((data = udev_device_get_property_value(dev, "ID_FS_LABEL_ENC"))) {
+               prop->label = xstrdup(data);
+               unhexmangle_string(prop->label);
+       }
+       if ((data = udev_device_get_property_value(dev, "ID_FS_UUID_ENC"))) {
+               prop->uuid = xstrdup(data);
+               unhexmangle_string(prop->uuid);
+       }
+       if ((data = udev_device_get_property_value(dev, "ID_PART_TABLE_UUID")))
+               prop->ptuuid = xstrdup(data);
+       if ((data = udev_device_get_property_value(dev, "ID_PART_TABLE_TYPE")))
+               prop->pttype = xstrdup(data);
+       if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_NAME"))) {
+               prop->partlabel = xstrdup(data);
+               unhexmangle_string(prop->partlabel);
+       }
+       if ((data = udev_device_get_property_value(dev, "ID_FS_TYPE")))
+               prop->fstype = xstrdup(data);
+       if ((data = udev_device_get_property_value(dev, "ID_FS_VERSION")))
+               prop->fsversion = xstrdup(data);
+       if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_TYPE")))
+               prop->parttype = xstrdup(data);
+       if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_UUID")))
+               prop->partuuid = xstrdup(data);
+       if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_NUMBER")))
+               prop->partn = xstrdup(data);
+       if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_FLAGS")))
+               prop->partflags = xstrdup(data);
+
+       data = udev_device_get_property_value(dev, "ID_WWN_WITH_EXTENSION");
+       if (!data)
+               data = udev_device_get_property_value(dev, "ID_WWN");
+       if (data)
+               prop->wwn = xstrdup(data);
+
+       data = udev_device_get_property_value(dev, "SCSI_IDENT_SERIAL");        /* sg3_utils do not use I_D prefix */
+       if (!data)
                data = udev_device_get_property_value(dev, "ID_SCSI_SERIAL");
-               if(!data)
-                       data = udev_device_get_property_value(dev, "ID_SERIAL_SHORT");
-               if (data)
-                       prop->serial = xstrdup(data);
+       if(!data)
+               data = udev_device_get_property_value(dev, "ID_SERIAL_SHORT");
+       if(!data)
+               data = udev_device_get_property_value(dev, "ID_SERIAL");
+       if (data) {
+               prop->serial = xstrdup(data);
+               normalize_whitespace((unsigned char *) prop->serial);
+       }
+
+       if ((data = udev_device_get_property_value(dev, "ID_REVISION")))
+               prop->revision = xstrdup(data);
+
+       if ((data = udev_device_get_property_value(dev, "ID_MODEL_ENC"))) {
+               prop->model = xstrdup(data);
+               unhexmangle_string(prop->model);
+               normalize_whitespace((unsigned char *) prop->model);
+       } else if ((data = udev_device_get_property_value(dev, "ID_MODEL"))) {
+               prop->model = xstrdup(data);
+               normalize_whitespace((unsigned char *) prop->model);
+       }
 
-               if ((data = udev_device_get_property_value(dev, "ID_MODEL")))
-                       prop->model = xstrdup(data);
+       /* select the shortest udev by-id symlink */
+       len = 0;
+       udev_list_entry_foreach(le, udev_device_get_devlinks_list_entry(dev)) {
+               const char *name = udev_list_entry_get_name(le);
+               size_t sz;
 
-               udev_device_unref(dev);
-               DBG(DEV, ul_debugobj(ld, "%s: found udev properties", ld->name));
+               if (!name || !startswith(name,  LSBLK_UDEV_BYID_PREFIX))
+                       continue;
+               name += LSBLK_UDEV_BYID_PREFIXSZ;
+               if (!*name)
+                       continue;
+               sz = strlen(name);
+               if (!len || sz < len) {
+                       len = sz;
+                       free(prop->idlink);
+                       prop->idlink = xstrdup(name);
+               }
        }
 
+       udev_device_unref(dev);
 done:
        ld->udev_requested = 1;
 
@@ -132,7 +182,7 @@ static int lookup(char *buf, char *pattern, char **value)
                return 0;
 
        len = strlen(pattern);
-       if (strncmp(buf, pattern, len))
+       if (strncmp(buf, pattern, len) != 0)
                return 0;
 
        p = buf + len;
@@ -174,7 +224,7 @@ static struct lsblk_devprop *get_properties_by_file(struct lsblk_device *ld)
                return NULL;
        if (ul_path_set_prefix(pc, lsblk->sysroot) != 0)
                goto done;
-       if (ul_path_stat(pc, &sb, ld->filename) != 0 || !S_ISREG(sb.st_mode))
+       if (ul_path_stat(pc, &sb, 0, ld->filename) != 0 || !S_ISREG(sb.st_mode))
                goto done;
 
        fp = ul_path_fopen(pc, "r", ld->filename);
@@ -196,14 +246,19 @@ static struct lsblk_devprop *get_properties_by_file(struct lsblk_device *ld)
                else if (lookup(buf, "ID_PART_TABLE_UUID", &prop->ptuuid)) ;
                else if (lookup(buf, "ID_PART_TABLE_TYPE", &prop->pttype)) ;
                else if (lookup(buf, "ID_FS_TYPE", &prop->fstype)) ;
+               else if (lookup(buf, "ID_FS_VERSION", &prop->fsversion)) ;
                else if (lookup(buf, "ID_PART_ENTRY_TYPE", &prop->parttype)) ;
                else if (lookup(buf, "ID_PART_ENTRY_UUID", &prop->partuuid)) ;
                else if (lookup(buf, "ID_PART_ENTRY_FLAGS", &prop->partflags)) ;
+               else if (lookup(buf, "ID_PART_ENTRY_NUMBER", &prop->partn)) ;
                else if (lookup(buf, "ID_MODEL", &prop->model)) ;
                else if (lookup(buf, "ID_WWN_WITH_EXTENSION", &prop->wwn)) ;
                else if (lookup(buf, "ID_WWN", &prop->wwn)) ;
+               else if (lookup(buf, "SCSI_IDENT_SERIAL", &prop->serial)) ;     /* serial from sg3_utils */
                else if (lookup(buf, "ID_SCSI_SERIAL", &prop->serial)) ;
                else if (lookup(buf, "ID_SERIAL_SHORT", &prop->serial)) ;
+               else if (lookup(buf, "ID_SERIAL", &prop->serial)) ;
+               else if (lookup(buf, "ID_REVISION", &prop->revision)) ;
 
                /* lsblk specific */
                else if (lookup(buf, "MODE", &prop->mode)) ;
@@ -265,6 +320,8 @@ static struct lsblk_devprop *get_properties_by_blkid(struct lsblk_device *dev)
                        prop->pttype = xstrdup(data);
                if (!blkid_probe_lookup_value(pr, "LABEL", &data, NULL))
                        prop->label = xstrdup(data);
+               if (!blkid_probe_lookup_value(pr, "VERSION", &data, NULL))
+                       prop->fsversion = xstrdup(data);
                if (!blkid_probe_lookup_value(pr, "PART_ENTRY_TYPE", &data, NULL))
                        prop->parttype = xstrdup(data);
                if (!blkid_probe_lookup_value(pr, "PART_ENTRY_UUID", &data, NULL))
@@ -273,6 +330,8 @@ static struct lsblk_devprop *get_properties_by_blkid(struct lsblk_device *dev)
                        prop->partlabel = xstrdup(data);
                if (!blkid_probe_lookup_value(pr, "PART_ENTRY_FLAGS", &data, NULL))
                        prop->partflags = xstrdup(data);
+               if (!blkid_probe_lookup_value(pr, "PART_ENTRY_NUMBER", &data, NULL))
+                       prop->partn = xstrdup(data);
 
                DBG(DEV, ul_debugobj(dev, "%s: found blkid properties", dev->name));
        }
@@ -305,3 +364,66 @@ void lsblk_properties_deinit(void)
        udev_unref(udev);
 #endif
 }
+
+
+
+/*
+ * Partition types
+ */
+struct lsblk_parttype {
+       unsigned int    code;           /* type as number or zero */
+       char            *name;          /* description */
+       char            *typestr;       /* type as string or NULL */
+};
+
+static const struct lsblk_parttype mbr_types[] =
+{
+       #include "pt-mbr-partnames.h"
+};
+
+#define DEF_GUID(_u, _n) \
+       { \
+               .typestr = (_u), \
+               .name = (_n),    \
+       }
+static const struct lsblk_parttype gpt_types[] =
+{
+       #include "pt-gpt-partnames.h"
+};
+
+const char *lsblk_parttype_code_to_string(const char *code, const char *pttype)
+{
+       size_t i;
+
+       if (!code || !pttype)
+               return NULL;
+
+       if (strcmp(pttype, "dos") == 0 || strcmp(pttype, "mbr") == 0) {
+               char *end = NULL;
+               unsigned int xcode;
+
+               errno = 0;
+               xcode = strtol(code, &end, 16);
+
+               if (errno || *end != '\0')
+                       return NULL;
+
+               for (i = 0; i < ARRAY_SIZE(mbr_types); i++) {
+                       const struct lsblk_parttype *t = &mbr_types[i];
+
+                       if (t->name && t->code == xcode)
+                               return t->name;
+               }
+
+       } else if (strcmp(pttype, "gpt") == 0) {
+               for (i = 0; i < ARRAY_SIZE(gpt_types); i++) {
+                       const struct lsblk_parttype *t = &gpt_types[i];
+
+                       if (t->name && t->typestr &&
+                           strcasecmp(code, t->typestr) == 0)
+                               return t->name;
+               }
+       }
+
+       return NULL;
+}