diff --git a/CMakeLists.txt b/CMakeLists.txt index 7169940..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") @@ -34,6 +36,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 c15c05a..96d978e 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,40 +519,86 @@ 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); - 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; + } + + /* 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)) { - 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; + } + + 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; + } + } + } + + 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) { + if (p->ignored) { p = delete_struct_and_get_next(p); continue; } @@ -599,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 ece1677..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 */ @@ -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; }; 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..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 @@ -48,6 +49,7 @@ #include #include +#include #include "extern.h" #include "services.h" @@ -101,6 +103,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"), @@ -152,8 +157,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 " diff --git a/src/util.c b/src/util.c index 6f1f690..8081299 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. @@ -807,9 +824,11 @@ is_pseudofs(const char *type) "devpts", "devtmpfs", "dlmfs", + "fdescfs", "fuse.gvfs-fuse-daemon", "fusectl", "hugetlbfs", + "linprocfs", "mqueue", "nfsd", "none", 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);