Commit Diff


commit - 4d8e470cd10c08b876c3e336e9b0cf7fd4886b4d
commit + 7c38b724e9cf37eda0a682776bf255a2fecca043
blob - 52ac4241cf3ded520b6b444b6c6b3f43c09a3784
blob + e0ad28be6592c25705e73fb742e3679d95679e26
--- ChangeLog.md
+++ ChangeLog.md
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](http
 - Use err(3) instead of die()
 - Use opendev(3) instead of open(2)
 - Sort drives by name
+- Dynamic padding of output
 
 ### Removed
 - Options:
blob - 084ec3cda9ac1b0305f463d7195f892c976d7abf
blob + efe7acbfe3aedd6f35039740dc8261d1e4961759
--- README.md
+++ README.md
@@ -21,7 +21,7 @@ doas make unroot
 - [x] `lsblk sd0`
 - [ ] `lsblk sd0a`
 - [ ] `lsblk -f duid,size`
-- [ ] Don't use manual padding.
+- [x] Don't use manual padding.
 - [ ] Support disks that have more than 2 letters, like `vnd0`
 - [x] Sort drives by name
 - [ ] Add an option to make the output script-friendly (like -c for CSV).
blob - ca98c5850b44dfca7a1c2ae4c5d66f80a9431e72
blob + 6ea37c84af0cea4280740df6659015248522108c
--- lsblk.c
+++ lsblk.c
@@ -16,6 +16,7 @@
 #define _XOPEN_SOURCE 700
 #define _BSD_SOURCE 1
 #define DKTYPENAMES
+#define WSDEBUG 0
 #include <stddef.h>
 #include <dev/biovar.h>
 #include <sys/cdefs.h>
@@ -161,10 +162,20 @@ struct my_diskinfo {
     const char *raidstatus; // If this is a RAID device
 };
 
-static void print_header (int fields)
+struct padding {
+    int name;
+    /* duid = 8 */
+    /* size = 4 */
+    /* used = 4 */
+    /* free = 4 */
+    int type;
+    int comment;
+};
+
+static void print_header (int fields, const struct padding *p)
 {
     if (fields & FIELD_NAME)
-        printf ("%-7s ", "NAME");
+        printf ("%-*s ", p->name, "NAME");
 
     if (fields & FIELD_DUID)
         printf ("%-18s ", "DUID");
@@ -179,11 +190,15 @@ static void print_header (int fields)
         printf ("%-4s ", "FREE");
 
     if (fields & FIELD_TYPE)
-        printf ("%-8s ", "TYPE");
+        printf ("%-*s ", p->type, "TYPE");
 
     if (fields & FIELD_COMMENT)
-        printf ("COMMENT ");
+        printf ("%-*s ", p->comment, "COMMENT");
 
+#if WSDEBUG
+    putchar ('X');
+#endif
+
     putchar ('\n');
 }
 
@@ -194,17 +209,25 @@ static void print_duid (const u_char *duid)
     }
 }
 
-static void print_disk (const struct my_diskinfo *disk, int fields, int options, const char *raidstatus);
+static void print_disk (const struct my_diskinfo *, int, int, const char *, const struct padding *);
 static void print_part (
     const struct my_diskinfo *disk,
     const struct my_partinfo *part,
     int fields,
     int options,
-    bool last
+    bool last,
+    const struct padding *p
 ) {
     if (fields & FIELD_NAME) {
         const char *prefix = (options & OPT_NOUNICODE) ? "  " : (last ? "└─" : "├─");
-        printf ("%s%s%c  ", prefix, disk->name, part->letter);
+        printf (
+            "%s%s%c%-*s ",
+            prefix,
+            disk->name,
+            part->letter,
+            p->name - 2 - (int)strlen (disk->name) - 1,
+            ""
+        );
     }
 
     if (fields & FIELD_DUID) {
@@ -232,25 +255,38 @@ static void print_part (
     }
 
     if (fields & FIELD_TYPE)
-        printf ("%-8.16s ", part->fstype);
+        printf ("%-*s ", p->type, part->fstype);
 
-    if (fields & FIELD_COMMENT && part->mount)
-        printf ("%s ", part->mount);
+    if (fields & FIELD_COMMENT)
+        printf ("%-*s ", p->comment, part->mount ? part->mount : "");
 
+#if WSDEBUG
+    putchar ('X');
+#endif
+
     putchar ('\n');
 
     if (part->sub) {
-        printf ("│ └─");
-        print_disk (part->sub, fields, options, part->raidstatus);
+        print_disk (part->sub, fields, options, part->raidstatus, p);
     }
 }
 
-static void print_disk (const struct my_diskinfo *disk, int fields, int options, const char *raidstatus)
-{
+static void print_disk (
+    const struct my_diskinfo *disk,
+    int fields,
+    int options,
+    const char *raidstatus,
+    const struct padding *p
+) {
     if (fields & FIELD_NAME) {
-        printf ("%s ", disk->name);
-        if (!raidstatus)
-            printf ("    ");
+        const char *prefix = raidstatus ? "│ └─" : "";
+
+        printf (
+            "%s%-*s ",
+            prefix,
+            p->name - (int)strlen (prefix),
+            disk->name
+        );
     }
 
     if (fields & FIELD_DUID) {
@@ -267,25 +303,34 @@ static void print_disk (const struct my_diskinfo *disk
     if (fields & FIELD_FREE)
         print_size (disk->size - disk->used);
 
-    // Pad only upto 8 characters because most disk types are <=8 bytes long.
     if (fields & FIELD_TYPE)
-        printf ("%-8.16s ", disk->type);
+        printf ("%-*.16s ", p->type, disk->type);
 
     if (fields & FIELD_COMMENT) {
         if (raidstatus) {
-            printf ("%s ", raidstatus);
+            printf ("%-*s ", p->comment, raidstatus);
         } else if (disk->raidstatus) {
-            printf ("%.16s (%s) ", disk->label, disk->raidstatus);
+            printf (
+                "%.16s (%s)%*s ",
+                disk->label,
+                disk->raidstatus,
+                p->comment - (int)strnlen (disk->label, sizeof disk->label) - (int)strlen (disk->raidstatus) - 3,
+                ""
+            );
         } else {
-            printf ("%.16s ", disk->label);
+            printf ("%-*.16s ", p->comment, disk->label);
         }
     }
 
+#if WSDEBUG
+    putchar ('X');
+#endif
+
     putchar ('\n');
 
     if (!raidstatus) {
         for (uint8_t i = 0; i < disk->num_parts; ++i)
-            print_part (disk, &disk->parts[i], fields, options, i == (disk->num_parts - 1));
+            print_part (disk, &disk->parts[i], fields, options, i == (disk->num_parts - 1), p);
     }
 }
 
@@ -482,6 +527,42 @@ static int usage (void)
     return 1;
 }
 
+static void pad_update (int *pad, int newval)
+{
+    if (newval > *pad)
+        *pad = newval;
+}
+
+static void pad_disk (struct padding *p, const struct my_diskinfo *disk)
+{
+    size_t len_disk;
+    int comment;
+
+    len_disk = strnlen (disk->name, sizeof disk->name);
+    comment = strnlen (disk->label, sizeof disk->label);
+    if (disk->raidstatus)
+        comment += strlen (disk->raidstatus) + 3;
+
+    pad_update (&p->name, len_disk);
+    pad_update (&p->type, strnlen (disk->type, sizeof disk->type));
+    pad_update (&p->comment, comment);
+
+    for (int i = 0; i < disk->num_parts; ++i) {
+        const struct my_partinfo *part = &disk->parts[i];
+
+        pad_update (&p->name, len_disk + 3);
+        pad_update (&p->type, strlen (part->fstype));
+
+        if (part->sub) {
+            pad_update (&p->name, strnlen (part->sub->name, sizeof part->sub->name) + 4);
+            pad_update (&p->comment, strlen (part->raidstatus));
+        } else if (part->mount) {
+            pad_update (&p->comment, strlen (part->mount));
+        }
+    }
+}
+
+
 static int compare_disk (const void *p1, const void *p2)
 {
     const struct my_diskinfo *d1 = p1;
@@ -577,11 +658,20 @@ int main (int argc, char *argv[])
         }
     }
 
+    struct padding p = {
+        .name = strlen ("NAME"),
+        .type = strlen ("TYPE"),
+        .comment = strlen ("COMMENT"),
+    };
+
+    for (size_t i = 0; i < num_disks; ++i)
+        pad_disk (&p, &disks[i]);
+
     if (!(options & OPT_NOHEADER))
-        print_header (fields);
+        print_header (fields, &p);
 
     for (size_t i = 0; i < num_disks; ++i) {
-        print_disk (&disks[i], fields, options, false);
+        print_disk (&disks[i], fields, options, NULL, &p);
     }
 
     return 0;