]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - misc-utils/lsblk.c
dmesg: add --follow-new
[thirdparty/util-linux.git] / misc-utils / lsblk.c
index 2ad2a4339227b838f8bca0b7799bdcd7b77f283e..3f21dcee2bfbb84b3ff72dfbd12460a49226768e 100644 (file)
@@ -72,12 +72,14 @@ enum {
        COL_FSTYPE,
        COL_FSUSED,
        COL_FSUSEPERC,
+       COL_FSVERSION,
        COL_TARGET,
        COL_LABEL,
        COL_UUID,
        COL_PTUUID,
        COL_PTTYPE,
        COL_PARTTYPE,
+       COL_PARTTYPENAME,
        COL_PARTLABEL,
        COL_PARTUUID,
        COL_PARTFLAGS,
@@ -115,6 +117,7 @@ enum {
        COL_REV,
        COL_VENDOR,
        COL_ZONED,
+       COL_DAX
 };
 
 /* basic table settings */
@@ -158,6 +161,7 @@ static struct colinfo infos[] = {
        [COL_FSTYPE]    = { "FSTYPE", 0.1, SCOLS_FL_TRUNC, N_("filesystem type") },
        [COL_FSUSED]    = { "FSUSED", 5, SCOLS_FL_RIGHT, N_("filesystem size used") },
        [COL_FSUSEPERC] = { "FSUSE%", 3, SCOLS_FL_RIGHT, N_("filesystem use percentage") },
+       [COL_FSVERSION] = { "FSVER", 0.1, SCOLS_FL_TRUNC, N_("filesystem version") },
 
        [COL_TARGET] = { "MOUNTPOINT", 0.10, SCOLS_FL_TRUNC, N_("where the device is mounted") },
        [COL_LABEL]  = { "LABEL",   0.1, 0, N_("filesystem LABEL") },
@@ -166,7 +170,8 @@ static struct colinfo infos[] = {
        [COL_PTUUID] = { "PTUUID",  36,  0, N_("partition table identifier (usually UUID)") },
        [COL_PTTYPE] = { "PTTYPE",  0.1, 0, N_("partition table type") },
 
-       [COL_PARTTYPE]  = { "PARTTYPE",  36,  0, N_("partition type UUID") },
+       [COL_PARTTYPE]  = { "PARTTYPE",  36,  0, N_("partition type code or UUID") },
+       [COL_PARTTYPENAME]  = { "PARTTYPENAME",  0.1,  0, N_("partition type name") },
        [COL_PARTLABEL] = { "PARTLABEL", 0.1, 0, N_("partition LABEL") },
        [COL_PARTUUID]  = { "PARTUUID",  36,  0, N_("partition UUID") },
        [COL_PARTFLAGS] = { "PARTFLAGS",  36,  0, N_("partition flags") },
@@ -204,6 +209,7 @@ static struct colinfo infos[] = {
        [COL_REV]    = { "REV",   4, SCOLS_FL_RIGHT, N_("device revision") },
        [COL_VENDOR] = { "VENDOR", 0.1, SCOLS_FL_TRUNC, N_("device vendor") },
        [COL_ZONED]  = { "ZONED", 0.3, 0, N_("zone model") },
+       [COL_DAX]    = { "DAX", 1, SCOLS_FL_RIGHT, N_("dax-capable device"), COLTYPE_BOOL },
 };
 
 struct lsblk *lsblk;   /* global handler */
@@ -676,12 +682,13 @@ static int is_removable_device(struct lsblk_device *dev, struct lsblk_device *pa
                if (!pc)
                        goto done;
 
+               /* dev is partition and parent is whole-disk  */
                if (pc == parent->sysfs)
-                       /* dev is partition and parent is whole-disk  */
                        dev->removable = is_removable_device(parent, NULL);
-               else
-                       /* parent is something else, use sysfs parent */
-                       ul_path_scanf(pc, "removable", "%d", &dev->removable);
+
+               /* parent is something else, use sysfs parent */
+               else if (ul_path_scanf(pc, "removable", "%d", &dev->removable) != 1)
+                       dev->removable = 0;
        }
 done:
        if (dev->removable == -1)
@@ -710,7 +717,7 @@ static char *device_get_data(
                int id,                                 /* column ID (COL_*) */
                uint64_t *sortdata)                     /* returns sort data as number */
 {
-       struct lsblk_devprop *prop;
+       struct lsblk_devprop *prop = NULL;
        char *str = NULL;
 
        switch(id) {
@@ -729,30 +736,42 @@ static char *device_get_data(
                        str = xstrdup(dev->filename);
                break;
        case COL_OWNER:
-       {
-               struct stat *st = device_get_stat(dev);
-               struct passwd *pw = st ? getpwuid(st->st_uid) : NULL;
-               if (pw)
-                       str = xstrdup(pw->pw_name);
+               if (lsblk->sysroot)
+                       prop = lsblk_device_get_properties(dev);
+               if (prop && prop->owner) {
+                       str = xstrdup(prop->owner);
+               } else {
+                       struct stat *st = device_get_stat(dev);
+                       struct passwd *pw = st ? getpwuid(st->st_uid) : NULL;
+                       if (pw)
+                               str = xstrdup(pw->pw_name);
+               }
                break;
-       }
        case COL_GROUP:
-       {
-               struct stat *st = device_get_stat(dev);
-               struct group *gr = st ? getgrgid(st->st_gid) : NULL;
-               if (gr)
-                       str = xstrdup(gr->gr_name);
+               if (lsblk->sysroot)
+                       prop = lsblk_device_get_properties(dev);
+               if (prop && prop->group) {
+                       str = xstrdup(prop->group);
+               } else {
+                       struct stat *st = device_get_stat(dev);
+                       struct group *gr = st ? getgrgid(st->st_gid) : NULL;
+                       if (gr)
+                               str = xstrdup(gr->gr_name);
+               }
                break;
-       }
        case COL_MODE:
-       {
-               struct stat *st = device_get_stat(dev);
-               char md[11] = { '\0' };
+               if (lsblk->sysroot)
+                       prop = lsblk_device_get_properties(dev);
+               if (prop && prop->mode) {
+                       str = xstrdup(prop->mode);
+               } else {
+                       struct stat *st = device_get_stat(dev);
+                       char md[11] = { '\0' };
 
-               if (st)
-                       str = xstrdup(xstrmode(st->st_mode, md));
+                       if (st)
+                               str = xstrdup(xstrmode(st->st_mode, md));
+               }
                break;
-       }
        case COL_MAJMIN:
                if (is_parsable(lsblk))
                        xasprintf(&str, "%u:%u", dev->maj, dev->min);
@@ -772,9 +791,20 @@ static char *device_get_data(
        case COL_FSUSEPERC:
                str = get_vfs_attribute(dev, id);
                break;
+       case COL_FSVERSION:
+               prop = lsblk_device_get_properties(dev);
+               if (prop && prop->fsversion)
+                       str = xstrdup(prop->fsversion);
+               break;
        case COL_TARGET:
-               str = xstrdup(lsblk_device_get_mountpoint(dev));
+       {
+               char *s = lsblk_device_get_mountpoint(dev);
+               if (s)
+                       str = xstrdup(s);
+               else
+                       str = NULL;
                break;
+       }
        case COL_LABEL:
                prop = lsblk_device_get_properties(dev);
                if (prop && prop->label)
@@ -800,6 +830,15 @@ static char *device_get_data(
                if (prop && prop->parttype)
                        str = xstrdup(prop->parttype);
                break;
+       case COL_PARTTYPENAME:
+               prop = lsblk_device_get_properties(dev);
+               if (prop && prop->parttype && prop->pttype) {
+                       const char *x = lsblk_parttype_code_to_string(
+                                               prop->parttype, prop->pttype);
+                       if (x)
+                               str = xstrdup(x);
+               }
+               break;
        case COL_PARTLABEL:
                prop = lsblk_device_get_properties(dev);
                if (prop && prop->partlabel)
@@ -994,6 +1033,9 @@ static char *device_get_data(
        case COL_ZONED:
                ul_path_read_string(dev->sysfs, &str, "queue/zoned");
                break;
+       case COL_DAX:
+               ul_path_read_string(dev->sysfs, &str, "queue/dax");
+               break;
        };
 
        return str;
@@ -1018,8 +1060,11 @@ static void device_to_scols(
        DBG(DEV, ul_debugobj(dev, "add '%s' to scols", dev->name));
        ON_DBG(DEV, if (ul_path_isopen_dirfd(dev->sysfs)) ul_debugobj(dev, " %s ---> is open!", dev->name));
 
-       /* Do not print device more than one in --list mode */
-       if (!(lsblk->flags & LSBLK_TREE) && dev->is_printed)
+       if (!parent && dev->wholedisk)
+               parent = dev->wholedisk;
+
+       /* Do not print device more than once on --list if tree order is not requested */
+       if (!(lsblk->flags & LSBLK_TREE) && !lsblk->force_tree_order && dev->is_printed)
                return;
 
        if (lsblk->merge && list_count_entries(&dev->parents) > 1) {
@@ -1118,6 +1163,11 @@ static int initialize_device(struct lsblk_device *dev,
        DBG(DEV, ul_debugobj(dev, "initialize %s [wholedisk=%p %s]",
                        name, wholedisk, wholedisk ? wholedisk->name : ""));
 
+       if (sysfs_devname_is_hidden(lsblk->sysroot, name)) {
+               DBG(DEV, ul_debugobj(dev, "%s: hidden, ignore", name));
+               return -1;
+       }
+
        dev->name = xstrdup(name);
 
        if (wholedisk) {
@@ -1388,7 +1438,7 @@ static int __process_one_device(struct lsblk_devtree *tr, char *devname, dev_t d
        char buf[PATH_MAX + 1], *name = NULL, *diskname = NULL;
        int real_part = 0, rc = -EINVAL;
 
-       if (devno == 0) {
+       if (devno == 0 && devname) {
                struct stat st;
 
                DBG(DEV, ul_debug("%s: reading alone device", devname));
@@ -1398,8 +1448,12 @@ static int __process_one_device(struct lsblk_devtree *tr, char *devname, dev_t d
                        goto leave;
                }
                devno = st.st_rdev;
-       } else
+       } else if (devno) {
                DBG(DEV, ul_debug("%d:%d: reading alone device", major(devno), minor(devno)));
+       } else {
+               assert(devno || devname);
+               return -EINVAL;
+       }
 
        /* TODO: sysfs_devno_to_devname() internally initializes path_cxt, it
         * would be better to use ul_new_sysfs_path() + sysfs_blkdev_get_name()
@@ -1475,6 +1529,7 @@ leave:
 
 static int process_one_device(struct lsblk_devtree *tr, char *devname)
 {
+       assert(devname);
        return __process_one_device(tr, devname, 0);
 }
 
@@ -1903,6 +1958,7 @@ int main(int argc, char *argv[])
                case 'f':
                        add_uniq_column(COL_NAME);
                        add_uniq_column(COL_FSTYPE);
+                       add_uniq_column(COL_FSVERSION);
                        add_uniq_column(COL_LABEL);
                        add_uniq_column(COL_UUID);
                        add_uniq_column(COL_FSAVAIL);
@@ -1998,8 +2054,9 @@ int main(int argc, char *argv[])
                 * /sys is no more sorted */
                lsblk->sort_id = COL_MAJMIN;
 
-       /* For --inverse --list we still follow parent->child relation */
-       if (lsblk->inverse && !(lsblk->flags & LSBLK_TREE))
+       /* For --{inverse,raw,pairs} --list we still follow parent->child relation */
+       if (!(lsblk->flags & LSBLK_TREE)
+           && (lsblk->inverse || lsblk->flags & LSBLK_EXPORT || lsblk->flags & LSBLK_RAW))
                lsblk->force_tree_order = 1;
 
        if (lsblk->sort_id >= 0 && column_id_to_number(lsblk->sort_id) < 0) {