diff options
| -rw-r--r-- | lib/getmountlist.c | 21 | ||||
| -rw-r--r-- | lib/lib.h | 3 | ||||
| -rw-r--r-- | lib/llist.c | 14 | ||||
| -rw-r--r-- | toys/lsb/umount.c | 5 | ||||
| -rw-r--r-- | toys/posix/df.c | 33 | 
5 files changed, 49 insertions, 27 deletions
| diff --git a/lib/getmountlist.c b/lib/getmountlist.c index d5a392d6..0b7ff06b 100644 --- a/lib/getmountlist.c +++ b/lib/getmountlist.c @@ -11,25 +11,28 @@  struct mtab_list *xgetmountlist(char *path)  { -  struct mtab_list *mtlist, *mt; +  struct mtab_list *mtlist = 0, *mt;    struct mntent *me;    FILE *fp; +  char *p = path ? path : "/proc/mounts"; -  if (!path) path = "/proc/mounts"; -  if (!(fp = setmntent(path, "r"))) perror_exit("bad %s", 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. -  for (mtlist = 0; (me = getmntent(fp)); mtlist = mt) { +  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); -    mt->next = mtlist; - -    // Collect details about mounted filesystem (don't bother for /etc/fstab). -    if (stat(me->mnt_dir, &(mt->stat)) || statvfs(me->mnt_dir, &(mt->statvfs))) -      perror_msg("stat '%s'"); +    dlist_add_nomalloc((void *)&mtlist, (void *)mt); + +    // 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)); +    }      // Remember information from /proc/mounts      mt->dir = stpcpy(mt->type, me->mnt_type)+1; @@ -31,6 +31,7 @@ void *llist_pop(void *list);  // actually void **list  void *dlist_pop(void *list);  // actually struct double_list **list  void dlist_add_nomalloc(struct double_list **list, struct double_list *new);  struct double_list *dlist_add(struct double_list **list, char *data); +void *dlist_terminate(void *list);  // args.c  void get_optflags(void); @@ -162,7 +163,7 @@ int xsocket(int domain, int type, int protocol);  // getmountlist.c  struct mtab_list { -  struct mtab_list *next; +  struct mtab_list *next, *prev;    struct stat stat;    struct statvfs statvfs;    char *dir; diff --git a/lib/llist.c b/lib/llist.c index 2d5bc97a..6b4b8f2c 100644 --- a/lib/llist.c +++ b/lib/llist.c @@ -85,3 +85,17 @@ struct double_list *dlist_add(struct double_list **list, char *data)    return new;  } + +// Terminate circular list for traversal in either direction. Returns end *. +void *dlist_terminate(void *list) +{ +  struct double_list *end = list; + +  if (!list) return 0; + +  end = end->prev; +  end->next->prev = 0; +  end->next = 0; + +  return end; +} diff --git a/toys/lsb/umount.c b/toys/lsb/umount.c index cc40f144..d1a2c69d 100644 --- a/toys/lsb/umount.c +++ b/toys/lsb/umount.c @@ -119,7 +119,10 @@ void umount_main(void)      if (TT.t) arg_comma_collate(&typestr, TT.t);      // Loop through mounted filesystems -    for (mlsave = ml = xgetmountlist(0); ml; ml = ml->next) { +    mlsave = xgetmountlist(0); +    ml = ml->prev; + +    for (ml = dlist_terminate(mlsave); ml; ml = ml->prev) {        if (TT.t) {          char *type, *types = typestr;          int len, skip = strncmp(types, "no", 2); diff --git a/toys/posix/df.c b/toys/posix/df.c index 7fab4281..afb296b2 100644 --- a/toys/posix/df.c +++ b/toys/posix/df.c @@ -95,7 +95,7 @@ static void show_mt(struct mtab_list *mt)  void df_main(void)  { -  struct mtab_list *mt, *mt2, *mtlist; +  struct mtab_list *mt, *mtstart, *mtend;    // Handle -P and -k    TT.units = 1024; @@ -106,7 +106,8 @@ void df_main(void)        TT.units);    } else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on"); -  mtlist = xgetmountlist(0); +  if (!(mtstart = xgetmountlist(0))) return; +  mtend = dlist_terminate(mtstart);    // If we have a list of filesystems on the command line, loop through them.    if (*toys.optargs) { @@ -123,36 +124,36 @@ void df_main(void)        // Find and display this filesystem.  Use _last_ hit in case of        // overmounts (which is first hit in the reversed list). -      mt2 = NULL; -      for (mt = mtlist; mt; mt = mt->next) { +      for (mt = mtend; mt; mt = mt->prev) {          if (st.st_dev == mt->stat.st_dev) { -          mt2 = mt; +          show_mt(mt);            break;          }        } -      show_mt(mt2);      }    } else { -    // Get and loop through mount list. - -    for (mt = mtlist; mt; mt = mt->next) { +    // Loop through mount list to filter out overmounts. +    for (mt = mtend; mt; mt = mt->prev) {        struct mtab_list *mt2, *mt3; +      // 0:0 is LANANA null device        if (!mt->stat.st_dev) continue;        // Filter out overmounts.        mt3 = mt; -      for (mt2 = mt->next; mt2; mt2 = mt2->next) { +      for (mt2 = mt->prev; mt2; mt2 = mt2->prev) {          if (mt->stat.st_dev == mt2->stat.st_dev) { -          // For --bind mounts, take last match -          if (!strcmp(mt->device, mt2->device)) mt3 = mt2; -          // Filter out overmounts -          mt2->stat.st_dev = 0; +          // For --bind mounts, take show earliest mount +          if (!strcmp(mt->device, mt2->device)) { +            if (!toys.optflags & FLAG_a) mt3->stat.st_dev = 0; +            mt3 = mt2; +          } else mt2->stat.st_dev = 0;          }        } -      show_mt(mt3);      } +    // Cosmetic: show filesystems in creation order +    for (mt = mtstart; mt; mt = mt->next) if (mt->stat.st_dev) show_mt(mt);    } -  if (CFG_TOYBOX_FREE) llist_traverse(mtlist, free); +  if (CFG_TOYBOX_FREE) llist_traverse(mtstart, free);  } | 
