Commit Diff


commit - 5691dc7beee507ca2ad0613a57614a4b3ca27778
commit + 1115ad3a8de82a7059b834dc980d31c3d43c2c7b
blob - 10c92f0d6fdfa6daf4c5dccf63f1bb0e395991a2
blob + e063ce55e231c9aeb46fa18f868804d10676bf15
--- ChangeLog.md
+++ ChangeLog.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http
 - Options:
   - `-a` print all fields
   - `-i` don't print fancy unicode characters
+  - `-U` print the DUID
   
 ### Changed
 - Merge "LABEL" and "MOUNT" fields into "LABEL/MOUNT"
blob - 1ef83eb3d61e0e09ef7275d2d68b570e933fa988
blob + 33ea632f20af5cceeffa5d25d564049f4b0bdf09
--- README.md
+++ README.md
@@ -18,7 +18,9 @@ doas make unroot
   Workaround: `make unroot`
 
 ## TODO
-- [-] `lsblk sd0`
+- [x] `lsblk sd0`
 - [ ] `lsblk sd0a`
+- [ ] open(2) -> opendev(3)
 - [ ] Add an option to make the output script-friendly (like -c for CSV).
 - [ ] Maybe: Display the child device of a RAID partition
+- [x] Show the DUID
blob - 97fe11442ac141c1fe3c9ba8438c3fa3c2a948f2
blob + 5522b5feb7c45bc31c82dc06e8a5d292b28b637a
--- lsblk.8
+++ lsblk.8
@@ -16,7 +16,7 @@
 lsblk \- list block devices
 .SH SYNOPSIS
 .B lsblk
-[\fB-Vainu\fR]
+[\fB-ainUuV\fR]
 [\fIdisk ...\fR]
 .SH DESCRIPTION
 The
@@ -40,6 +40,9 @@ don't print fancy unicode characters, only print ASCII
 .B \-n
 don't print the header.
 .TP
+.B \-U
+also print the disklabel UID.
+.TP
 .B \-u
 also print the filesystem usage of each partition
 and the disklabel usage of each disk.
@@ -47,8 +50,8 @@ and the disklabel usage of each disk.
 Note: The disklabel usage is calculated by
 summing the size of all (except "c") partitions.
 
-Note 2: There may be a small deviance in the filesystem usage,
-please consult df(1) for more correct numbers.
+Note 2: lsblk shows the total amount of free space,
+including space reserved for /root.
 
 .SH EXIT STATUS
 The
blob - 84187fdbb1200e69cf048b6cc320cc0c799e7432
blob + 060bc89a75870ac5592955670542c92e70c69d89
--- lsblk.c
+++ lsblk.c
@@ -134,11 +134,12 @@ static void print_size (uint64_t sz)
 
 enum {
     FIELD_NAME      = 0x01,
-    FIELD_SIZE      = 0x02,
-    FIELD_USED      = 0x04,
-    FIELD_FREE      = 0x08,
-    FIELD_TYPE      = 0x10,
-    FIELD_LMNT      = 0x20,
+    FIELD_DUID      = 0x02,
+    FIELD_SIZE      = 0x04,
+    FIELD_USED      = 0x08,
+    FIELD_FREE      = 0x10,
+    FIELD_TYPE      = 0x20,
+    FIELD_LMNT      = 0x40,
 
     FIELD_DEFAULT   = FIELD_NAME | FIELD_SIZE | FIELD_TYPE | FIELD_LMNT,
 };
@@ -149,7 +150,7 @@ enum {
 };
 
 struct my_partinfo {
-    char name[5];
+    char letter;
     uint64_t size;
     uint64_t fssize;
     uint64_t free;
@@ -164,6 +165,7 @@ struct my_diskinfo {
     uint64_t size;
     uint64_t used;
     uint8_t num_parts;
+    u_char duid[8];
     struct my_partinfo parts[MAXPARTITIONS];
 };
 
@@ -172,6 +174,9 @@ static void print_header (int fields)
     if (fields & FIELD_NAME)
         printf ("%-6s ", "NAME");
 
+    if (fields & FIELD_DUID)
+        printf ("%-18s ", "DUID");
+
     if (fields & FIELD_SIZE)
         printf ("%-4s ", "SIZE");
 
@@ -190,13 +195,30 @@ static void print_header (int fields)
     putchar ('\n');
 }
 
-static void print_part (const struct my_partinfo *part, int fields, int options, bool last)
+static void print_duid (const u_char *duid)
 {
+    for (size_t i = 0; i < 8; ++i) {
+        printf ("%02x", duid[i]);
+    }
+}
+
+static void print_part (
+    const struct my_diskinfo *disk,
+    const struct my_partinfo *part,
+    int fields,
+    int options,
+    bool last
+) {
     if (fields & FIELD_NAME) {
         const char *prefix = (options & OPT_NOUNICODE) ? "  " : (last ? "└─" : "├─");
-        printf ("%s%s ", prefix, part->name);
+        printf ("%s%s%c ", prefix, disk->name, part->letter);
     }
 
+    if (fields & FIELD_DUID) {
+        print_duid (disk->duid);
+        printf (".%c ", part->letter);
+    }
+
     if (fields & FIELD_SIZE)
         print_size (part->size);
 
@@ -230,6 +252,11 @@ static void print_disk (const struct my_diskinfo *disk
     if (fields & FIELD_NAME)
         printf ("%s    ", disk->name);
 
+    if (fields & FIELD_DUID) {
+        print_duid (disk->duid);
+        printf ("   ");
+    }
+
     if (fields & FIELD_SIZE)
         print_size (disk->size);
 
@@ -249,7 +276,7 @@ static void print_disk (const struct my_diskinfo *disk
     putchar ('\n');
 
     for (uint8_t i = 0; i < disk->num_parts; ++i)
-        print_part (&disk->parts[i], fields, options, i == (disk->num_parts - 1));
+        print_part (disk, &disk->parts[i], fields, options, i == (disk->num_parts - 1));
 }
 
 static const struct statfs *find_mount (const char *dev)
@@ -299,13 +326,14 @@ static struct my_diskinfo read_disk (const char *name)
     memcpy (disk.type, label.d_typename, 16);
     stripdisk (disk.type);
     memcpy (disk.label, label.d_packname, 16);
+    memcpy (disk.duid, label.d_uid, sizeof disk.duid);
     disk.num_parts = 0;
 
     for (uint16_t i = 0; i < label.d_npartitions; ++i) {
         const struct partition *p = &label.d_partitions[i];
         const struct statfs *mnt;
         struct my_partinfo part;
-        char path[5 + 4 + 1];
+        char *path;
 
         bzero (&part, sizeof part);
 
@@ -314,12 +342,10 @@ static struct my_diskinfo read_disk (const char *name)
         if (!part.size)
             continue;
 
-        memcpy (part.name, disk.name, 3);
-        part.name[3] = 'a' + i;
-        part.name[4] = '\0';
-
-        snprintf (path, sizeof path, "/dev/%s", part.name);
+        part.letter = 'a' + i;
+        asprintf (&path, "/dev/%s%c", disk.name, part.letter);
         mnt = find_mount (path);
+        free (path);
 
         if (mnt) {
             const uint64_t bs = mnt->f_bsize;
@@ -339,7 +365,7 @@ static struct my_diskinfo read_disk (const char *name)
 
 static int usage (void)
 {
-    fputs ("Usage: lsblk [-Vainu] [disk...]\n", stderr);
+    fputs ("Usage: lsblk [-ainUuV] [disk...]\n", stderr);
     return 1;
 }
 
@@ -355,11 +381,8 @@ int main (int argc, char *argv[])
     if (unveil (NULL, NULL) == -1)
         die ("unveil()");
 
-    while ((option = getopt (argc, argv, ":Vainu")) != -1) {
+    while ((option = getopt (argc, argv, ":ainUuV")) != -1) {
         switch (option) {
-        case 'V':
-            puts ("lsblk-" VERSION);
-            return 0;
         case 'a':
             fields = -1;
             break;
@@ -369,9 +392,15 @@ int main (int argc, char *argv[])
         case 'n':
             options |= OPT_NOHEADER;
             break;
+        case 'U':
+            fields |= FIELD_DUID;
+            break;
         case 'u':
             fields |= FIELD_USED | FIELD_FREE;
             break;
+        case 'V':
+            puts ("lsblk-" VERSION);
+            return 0;
         default:
             return usage ();
         }