From fcd192014c8bbc0466bcdd4195b3d14c0ce006f9 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Fri, 29 Jul 2016 19:50:20 +0200 Subject: [PATCH 1/8] Instead of deleting ignored items immediately, mark them up. This allows filters that look at other items. --- src/dfc.c | 18 +++++++++++++----- src/list.h | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/dfc.c b/src/dfc.c index c15c05a..2fd91e0 100644 --- a/src/dfc.c +++ b/src/dfc.c @@ -535,28 +535,36 @@ disp(struct list *lst, const char *fstfilter, const char *fsnfilter, if (qflag) lst->head = msort(lst->head); - p = lst->head; + for (p = lst->head; p; p = p->next) { + /* ignored unless proven otherwise */ + p->ignored = 1; - while (p != NULL) { /* ignore when needed */ if (!aflag && (is_mnt_ignore(p) == 1)) { - p = delete_struct_and_get_next(p); continue; } /* filtering on fs type */ if (tflag && (fsfilter(p->fstype, fstfilter, nmt) == 0)) { - p = delete_struct_and_get_next(p); continue; } /* filtering on fs name */ if (pflag && (fsfilter(p->fsname, fsnfilter, nmn) == 0)) { - p = delete_struct_and_get_next(p); continue; } /* skip remote file systems */ if (lflag && is_remote(p)) { + continue; + } + + p->ignored = 0; + } + + p = lst->head; + + while (p != NULL) { + if (p->ignored) { p = delete_struct_and_get_next(p); continue; } diff --git a/src/list.h b/src/list.h index ece1677..c1a870e 100644 --- a/src/list.h +++ b/src/list.h @@ -133,6 +133,7 @@ struct fsmntinfo { fsfilcnt_t favail; /* # of available inodes */ #endif /* __sun */ + int ignored; /* pointer to the next element of the list */ struct fsmntinfo *next; }; From e92b8305a457c458850f83aba69bd64c2a70783a Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Fri, 29 Jul 2016 20:12:00 +0200 Subject: [PATCH 2/8] Show every filesystem only once, unless -a is given. They were listed multiple times when bind mounts or btrfs/zfs subvolumes are in use. And in those cases, a single filesystem is often mounted many, many times. Filesystems whose backing store is not an absolute path are assumed to be unique. This is not always correct (they can be bind-mounted). In case of duplicates, the mount with a shorter path is considered more important. --- src/dfc.c | 24 ++++++++++++++++++++++++ src/util.c | 17 +++++++++++++++++ src/util.h | 1 + 3 files changed, 42 insertions(+) diff --git a/src/dfc.c b/src/dfc.c index 2fd91e0..0768575 100644 --- a/src/dfc.c +++ b/src/dfc.c @@ -561,6 +561,30 @@ disp(struct list *lst, const char *fstfilter, const char *fsnfilter, p->ignored = 0; } + for (p = lst->head; p; p = p->next) { + if (aflag || p->ignored) + continue; + + /* doesn't have a device backing store? */ + if (p->fsname[0] != '/') + continue; + + struct fsmntinfo *r; + for (r = lst->head; r; r = r->next) { + if (p != r && !r->ignored && !strcmp(p->fsname, r->fsname)) + switch (lencmp(p, r)) + { + case -1: + default: + /* mounted twice on same dir? */ + r->ignored = 1; + break; + case 1: + p->ignored = 1; + } + } + } + p = lst->head; while (p != NULL) { diff --git a/src/util.c b/src/util.c index 6f1f690..f119176 100644 --- a/src/util.c +++ b/src/util.c @@ -477,6 +477,23 @@ msort(struct fsmntinfo *fmi) return fmi; } +/* + * Compare lengths of mount points, then their paths. + * -1,0,1 are returned as in *cmp. + */ +int +lencmp(struct fsmntinfo *a, struct fsmntinfo *b) +{ + size_t la = strlen(a->mntdir); + size_t lb = strlen(b->mntdir); + + if (la < lb) + return -1; + if (la > lb) + return 1; + return strcmp(a->mntdir, b->mntdir); +} + /* * Get the with of TTY and retun it. * 0 is returned if stdout is not a tty. diff --git a/src/util.h b/src/util.h index e90d25b..d71f17c 100644 --- a/src/util.h +++ b/src/util.h @@ -54,6 +54,7 @@ double cvrt(double n); int fsfilter(const char *fs, const char *filter, int nm); int cmp(struct fsmntinfo *a, struct fsmntinfo *b); struct fsmntinfo * msort(struct fsmntinfo *fmi); +int lencmp(struct fsmntinfo *a, struct fsmntinfo *b); int getttywidth(void); void init_maxwidths(void); int get_req_width(double fs_size); From 50eb2eca8ee4458b04337784d9930b815ac67992 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Fri, 29 Jul 2016 20:40:59 +0200 Subject: [PATCH 3/8] Hide /run mounts unless they're more than half full, unless -a is given. On modern Debian-based systems there's usually 3 of them, on Fedora 23 4. I'm not sure what's the good place to put this code in, as you prefer to separate logic from presentation. It doesn't fit into is_mnt_ignore() as it's used by some distributions at least on linux, freebsd and hurd and that function is platform-specific. --- src/dfc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/dfc.c b/src/dfc.c index 0768575..c54810f 100644 --- a/src/dfc.c +++ b/src/dfc.c @@ -544,6 +544,11 @@ disp(struct list *lst, const char *fstfilter, const char *fsnfilter, continue; } + /* ignore /run mounts unless they're dangerously full */ + if (!aflag && !strncmp(p->mntdir, "/run", 4) && p->perctused < 50) { + continue; + } + /* filtering on fs type */ if (tflag && (fsfilter(p->fstype, fstfilter, nmt) == 0)) { continue; From fc71744aedb5ea171b230b73725802a54965b609 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Fri, 29 Jul 2016 20:55:49 +0200 Subject: [PATCH 4/8] Fix the tty width check looking at filesystems ignored by -t, -p or -l. It obeyed only is_mnt_ignore(). --- src/dfc.c | 31 ++++++++++++++++++------------- src/platform/services-bsd.c | 2 -- src/platform/services-linux.c | 2 -- src/platform/services-solaris.c | 2 -- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/dfc.c b/src/dfc.c index c54810f..dff3e0c 100644 --- a/src/dfc.c +++ b/src/dfc.c @@ -55,6 +55,7 @@ struct maxwidths max; int aflag, bflag, cflag, dflag, eflag, fflag, hflag, iflag, lflag, mflag, nflag, oflag, pflag, qflag, sflag, tflag, uflag, vflag, wflag; int Mflag, Tflag, Wflag; +int tty_width; char unitflag; int @@ -63,7 +64,6 @@ main(int argc, char *argv[]) struct list queue; struct display sdisp; int ch; - int tty_width; int ret = EXIT_SUCCESS; char *fsnfilter = NULL; char *fstfilter = NULL; @@ -419,10 +419,6 @@ main(int argc, char *argv[]) /* fetch information about the currently mounted filesystems */ fetch_info(&queue); - /* cannot display all information if tty is too narrow */ - if (!fflag && tty_width > 0 && !eflag) - auto_adjust(tty_width); - /* actually displays the info we have got */ disp(&queue, fstfilter, fsnfilter, &sdisp); @@ -523,14 +519,6 @@ disp(struct list *lst, const char *fstfilter, const char *fsnfilter, } } - /* only required for html, json and tex export */ - if (sdisp->init) - sdisp->init(); - - /* legend on top */ - if (!nflag) - sdisp->print_header(); - /* sort the list */ if (qflag) lst->head = msort(lst->head); @@ -590,6 +578,23 @@ disp(struct list *lst, const char *fstfilter, const char *fsnfilter, } } + for (p = lst->head; p; p = p->next) { + if (!p->ignored) + update_maxwidth(p); + } + + /* cannot display all information if tty is too narrow */ + if (!fflag && tty_width > 0 && !eflag) + auto_adjust(tty_width); + + /* only required for html, json and tex export */ + if (sdisp->init) + sdisp->init(); + + /* legend on top */ + if (!nflag) + sdisp->print_header(); + p = lst->head; while (p != NULL) { diff --git a/src/platform/services-bsd.c b/src/platform/services-bsd.c index 6cef0c0..6081956 100644 --- a/src/platform/services-bsd.c +++ b/src/platform/services-bsd.c @@ -165,8 +165,6 @@ fetch_info(struct list *lst) /* enqueue the element into the queue */ enqueue(lst, *fmi); - - update_maxwidth(fmi); } free(fmi); } diff --git a/src/platform/services-linux.c b/src/platform/services-linux.c index 1a4a492..99683dd 100644 --- a/src/platform/services-linux.c +++ b/src/platform/services-linux.c @@ -152,8 +152,6 @@ fetch_info(struct list *lst) /* enqueue the element into the queue */ enqueue(lst, *fmi); - - update_maxwidth(fmi); } /* we need to close the mtab file now */ if (fclose(mtab) == EOF) diff --git a/src/platform/services-solaris.c b/src/platform/services-solaris.c index 25e39e5..cab79b2 100644 --- a/src/platform/services-solaris.c +++ b/src/platform/services-solaris.c @@ -148,8 +148,6 @@ fetch_info(struct list *lst) fmi->next = NULL; enqueue(lst, *fmi); - - update_maxwidth(fmi); } if (ret > 0) { (void)fprintf(stderr, "An error occured while reading the " From aa44e723484a3cecaf71683eec9429b45879f47d Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Fri, 29 Jul 2016 21:06:17 +0200 Subject: [PATCH 5/8] Silently ignore EACCESS on statvfs(). So does regular df. --- src/platform/services-linux.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/platform/services-linux.c b/src/platform/services-linux.c index 99683dd..7ec4e23 100644 --- a/src/platform/services-linux.c +++ b/src/platform/services-linux.c @@ -48,6 +48,7 @@ #include #include +#include #include "extern.h" #include "services.h" @@ -101,6 +102,9 @@ fetch_info(struct list *lst) continue; /* get infos from statvfs */ if (statvfs(entbuf->mnt_dir, &vfsbuf) == -1) { + /* show only "real" errors, not lack of permissions */ + if (errno == EACCES) + continue; /* display a warning when a FS cannot be stated */ (void)fprintf(stderr, _("WARNING: %s was skipped " "because it could not be stated"), From 40722239080e6c7362c62878c43c3a79cd4eeaf9 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Fri, 29 Jul 2016 21:33:45 +0200 Subject: [PATCH 6/8] Fix build failure on Hurd. This reuses the "linux" platform, as everything you use there is glibc rather than linux specific. --- CMakeLists.txt | 2 ++ src/dfc.c | 2 +- src/list.h | 2 +- src/platform/services-linux.c | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7169940..a89f107 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,8 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") set(BSD true) elseif(${CMAKE_SYSTEM_NAME} MATCHES "SunOS") set(SOLARIS true) +elseif(${CMAKE_SYSTEM_NAME} MATCHES "GNU") + set(LINUX true) else() message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}") endif() diff --git a/src/dfc.c b/src/dfc.c index dff3e0c..96d978e 100644 --- a/src/dfc.c +++ b/src/dfc.c @@ -641,7 +641,7 @@ disp(struct list *lst, const char *fstfilter, const char *fsnfilter, if (iflag) { ifitot += (double)p->files; ifatot += (double)p->favail; -#if defined(__linux__) +#if defined(__linux__) || defined(__GLIBC__) sdisp->print_inodes((uint64_t)(p->files), (uint64_t)(p->favail)); #else diff --git a/src/list.h b/src/list.h index c1a870e..74a645b 100644 --- a/src/list.h +++ b/src/list.h @@ -55,7 +55,7 @@ struct fsmntinfo { double used; /* fs used size */ /* infos to get from statvfs(3) */ -#if defined(__linux__) +#if defined(__linux__) || defined(__GLIBC__) int flags; /* XXX: does not exist on Linux */ unsigned long bsize; /* file system block size */ unsigned long frsize; /* fragment size */ diff --git a/src/platform/services-linux.c b/src/platform/services-linux.c index 7ec4e23..292da99 100644 --- a/src/platform/services-linux.c +++ b/src/platform/services-linux.c @@ -34,13 +34,14 @@ * * Linux implemention of services. */ -#ifdef __linux__ #include #include #include #include +#if defined(__linux__) || defined(__GLIBC__) + #ifdef NLS_ENABLED #include #include From 3f0e559de5e6547844455b443f5d530178e92f85 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sat, 30 Jul 2016 00:50:12 +0200 Subject: [PATCH 7/8] Fix build failure on kFreeBSD. Like Hurd, this uses "linux" despite the real platform being FreeBSD, as it's libc that matters. --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a89f107..3924ece 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,8 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(BSD true) elseif(${CMAKE_SYSTEM_NAME} MATCHES "DragonFly") set(BSD true) +elseif(${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD") + set(LINUX true) elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") set(BSD true) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") From 7b1af231b970adc7f7945f8b8d9d648e41e856d5 Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Sat, 30 Jul 2016 00:53:53 +0200 Subject: [PATCH 8/8] Include linprocfs and fdescfs among pseudo filesystems. A kfreebsd, and I guess sometimes real FreeBSD, thingy. --- src/util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util.c b/src/util.c index f119176..8081299 100644 --- a/src/util.c +++ b/src/util.c @@ -824,9 +824,11 @@ is_pseudofs(const char *type) "devpts", "devtmpfs", "dlmfs", + "fdescfs", "fuse.gvfs-fuse-daemon", "fusectl", "hugetlbfs", + "linprocfs", "mqueue", "nfsd", "none",