In xgetmountlist(), keep track of whether we could stat or not, so we
can distinguish an actual device 0:0 from a failed stat/statvfs.

Also switch to FLAG() and capitalize POSIX.
---
 lib/lib.h         |  1 +
 lib/portability.c | 12 ++++-------
 toys/posix/df.c   | 55 ++++++++++++++++++++++++++++-------------------
 3 files changed, 38 insertions(+), 30 deletions(-)
From f931aa2af384be7a041bd6ce14ec4bb2b1ce89bf Mon Sep 17 00:00:00 2001
From: Elliott Hughes <[email protected]>
Date: Fri, 12 Feb 2021 17:19:48 -0800
Subject: [PATCH] df: -a should even show mounts we couldn't stat.

In xgetmountlist(), keep track of whether we could stat or not, so we
can distinguish an actual device 0:0 from a failed stat/statvfs.

Also switch to FLAG() and capitalize POSIX.
---
 lib/lib.h         |  1 +
 lib/portability.c | 12 ++++-------
 toys/posix/df.c   | 55 ++++++++++++++++++++++++++++-------------------
 3 files changed, 38 insertions(+), 30 deletions(-)

diff --git a/lib/lib.h b/lib/lib.h
index f9c04281..8b58baad 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -390,6 +390,7 @@ struct mtab_list {
   struct mtab_list *next, *prev;
   struct stat stat;
   struct statvfs statvfs;
+  int stat_failed;
   char *dir;
   char *device;
   char *opts;
diff --git a/lib/portability.c b/lib/portability.c
index 0c364c29..3dd78170 100644
--- a/lib/portability.c
+++ b/lib/portability.c
@@ -75,8 +75,8 @@ struct mtab_list *xgetmountlist(char *path)
 
     // Collect details about mounted filesystem.
     // Don't report errors, just leave data zeroed.
-    stat(me->f_mntonname, &(mt->stat));
-    statvfs(me->f_mntonname, &(mt->statvfs));
+    if (stat(me->f_mntonname, &(mt->stat))) mt->stat_failed++;
+    if (statvfs(me->f_mntonname, &(mt->statvfs))) mt->stat_failed++;
 
     // Remember information from struct statfs.
     mt->dir = stpcpy(mt->type, me->f_fstypename)+1;
@@ -156,10 +156,6 @@ struct mtab_list *xgetmountlist(char *path)
 
   if (!(fp = setmntent(p, "r"))) perror_exit("bad %s", p);
 
-  // The "test" part of the loop is done before the first time through and
-  // again after each "increment", so putting the actual load there avoids
-  // duplicating it. If the load was NULL, the loop stops.
-
   while ((me = getmntent(fp))) {
     mt = xzalloc(sizeof(struct mtab_list) + strlen(me->mnt_fsname) +
       strlen(me->mnt_dir) + strlen(me->mnt_type) + strlen(me->mnt_opts) + 4);
@@ -168,8 +164,8 @@ struct mtab_list *xgetmountlist(char *path)
     // Collect details about mounted filesystem
     // Don't report errors, just leave data zeroed
     if (!path) {
-      stat(me->mnt_dir, &(mt->stat));
-      statvfs(me->mnt_dir, &(mt->statvfs));
+      if (stat(me->mnt_dir, &(mt->stat))) mt->stat_failed++;
+      if (statvfs(me->mnt_dir, &(mt->statvfs))) mt->stat_failed++;
     }
 
     // Remember information from /proc/mounts
diff --git a/toys/posix/df.c b/toys/posix/df.c
index 53d99f56..6005657e 100644
--- a/toys/posix/df.c
+++ b/toys/posix/df.c
@@ -24,7 +24,7 @@ config DF
     -i	Show inodes instead of blocks
     -t type	Display only filesystems of this type
 
-    Pedantic provides a slightly less useful output format dictated by Posix,
+    Pedantic provides a slightly less useful output format dictated by POSIX,
     and sets the units to 512 bytes instead of the default 1024 bytes.
 */
 
@@ -59,15 +59,15 @@ static void show_header()
   // The filesystem column is always at least this wide.
   if (TT.column_widths[0] < 14) TT.column_widths[0] = 14;
 
-  if ((toys.optflags & (FLAG_H|FLAG_h))) {
-    xprintf((toys.optflags&FLAG_i) ?
+  if (FLAG(H) || FLAG(h)) {
+    xprintf(FLAG(i) ?
             "%-*sInodes  IUsed  IFree IUse%% Mounted on\n" :
             "%-*s Size  Used Avail Use%% Mounted on\n",
             TT.column_widths[0], "Filesystem");
   } else {
     const char *item_label, *used_label, *free_label, *use_label;
 
-    if (toys.optflags & FLAG_i) {
+    if (FLAG(i)) {
       item_label = "Inodes";
       used_label = "IUsed";
       free_label = "IFree";
@@ -76,7 +76,7 @@ static void show_header()
       item_label = TT.units == 512 ? "512-blocks" : "1K-blocks";
       used_label = "Used";
       free_label = "Available";
-      use_label = toys.optflags & FLAG_P ? "Capacity" : "Use%";
+      use_label = FLAG(P) ? "Capacity" : "Use%";
     }
 
     measure_column(1, item_label);
@@ -114,11 +114,11 @@ static void show_mt(struct mtab_list *mt, int measuring)
   }
 
   // If we don't have -a, skip synthetic filesystems
-  if (!(toys.optflags & FLAG_a) && !mt->statvfs.f_blocks) return;
+  if (!FLAG(a) && !mt->statvfs.f_blocks) return;
 
   // Figure out how much total/used/free space this filesystem has,
   // forcing 64-bit math because filesystems are big now.
-  if (toys.optflags & FLAG_i) {
+  if (FLAG(i)) {
     size = mt->statvfs.f_files;
     used = mt->statvfs.f_files - mt->statvfs.f_ffree;
     avail = getuid() ? mt->statvfs.f_favail : mt->statvfs.f_ffree;
@@ -145,17 +145,27 @@ static void show_mt(struct mtab_list *mt, int measuring)
   } else {
     if (!TT.header_shown) show_header();
 
-    if (toys.optflags & (FLAG_H|FLAG_h)) {
-      char *size_str = toybuf, *used_str = toybuf+64, *avail_str = toybuf+128;
-      int hr_flags = (toys.optflags & FLAG_H) ? HR_1000 : 0;
-      int w = 4 + !!(toys.optflags & FLAG_i);
-
-      human_readable(size_str, size, hr_flags);
-      human_readable(used_str, used, hr_flags);
-      human_readable(avail_str, avail, hr_flags);
-      xprintf("%-*s %*s  %*s  %*s %*llu%% %s\n",
+    if (FLAG(H) || FLAG(h)) {
+      char *size_str = toybuf, *used_str = toybuf+64, *avail_str = toybuf+128,
+           *pc_str = toybuf+192;
+      int hr_flags = FLAG(H) ? HR_1000 : 0;
+      int w = 4 + !!FLAG(i);
+
+      if (mt->stat_failed) {
+        size_str = used_str = avail_str = pc_str = "-";
+      } else {
+        human_readable(size_str, size, hr_flags);
+        human_readable(used_str, used, hr_flags);
+        human_readable(avail_str, avail, hr_flags);
+        sprintf(pc_str, "%llu%%", percent);
+      }
+      xprintf("%-*s %*s  %*s  %*s %*s %s\n",
         TT.column_widths[0], device,
-        w, size_str, w, used_str, w, avail_str, w-1, percent, mt->dir);
+        w, size_str, w, used_str, w, avail_str, w-1, pc_str, mt->dir);
+    } else if (mt->stat_failed) {
+      xprintf("%-*s %*s %*s %*s  %*s %s\n", TT.column_widths[0], "-",
+        TT.column_widths[1], "-", TT.column_widths[2], "-",
+        TT.column_widths[3], "-", TT.column_widths[4], "-", mt->dir);
     } else xprintf("%-*s %*llu %*llu %*llu %*llu%% %s\n",
         TT.column_widths[0], device,
         TT.column_widths[1], size,
@@ -173,11 +183,11 @@ void df_main(void)
   struct mtab_list *mt, *mtstart, *mtend;
   int measuring;
 
-  if (toys.optflags & (FLAG_H|FLAG_h)) {
+  if (FLAG(H) || FLAG(h)) {
     TT.units = 1;
   } else {
     // Units are 512 bytes if you select "pedantic" without "kilobytes".
-    TT.units = toys.optflags & FLAG_P ? 512 : 1024;
+    TT.units = FLAG(P) ? 512 : 1024;
   }
 
   if (!(mtstart = xgetmountlist(0))) return;
@@ -216,7 +226,7 @@ void df_main(void)
       struct mtab_list *mt2, *mt3;
 
       // 0:0 is LANANA null device
-      if (!mt->stat.st_dev) continue;
+      if (!mt->stat.st_dev && !mt->stat_failed) continue;
 
       // Filter out overmounts.
       mt3 = mt;
@@ -224,7 +234,7 @@ void df_main(void)
         if (mt->stat.st_dev == mt2->stat.st_dev) {
           // For --bind mounts, show earliest mount
           if (!strcmp(mt->device, mt2->device)) {
-            if (!(toys.optflags & FLAG_a)) mt3->stat.st_dev = 0;
+            if (!FLAG(a)) mt3->stat.st_dev = 0;
             mt3 = mt2;
           } else mt2->stat.st_dev = 0;
         }
@@ -235,7 +245,8 @@ void df_main(void)
     for (measuring = 1; measuring >= 0; --measuring) {
       // Cosmetic: show filesystems in creation order.
       for (mt = mtstart; mt; mt = mt->next) {
-        if (mt->stat.st_dev) show_mt(mt, measuring);
+        if (mt->stat_failed || mt->stat.st_dev)
+          show_mt(mt, measuring);
       }
     }
   }
-- 
2.30.0.478.g8a0d178c01-goog

_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to