# HG changeset patch # User Rob Landley # Date 1401358922 18000 # Node ID 4d898affda0c50ab98f5be4412e748f3216af260 # Parent b2cc738d3cfcefb6bc6ede7e7acf16754c67a92e Switch mtab_list to doubly linked so we can traverse in either order. Convert umount and df. Add dlist_terminate() to break lists for traversal in either direction. diff -r b2cc738d3cfc -r 4d898affda0c lib/getmountlist.c --- a/lib/getmountlist.c Tue May 27 07:56:51 2014 -0500 +++ b/lib/getmountlist.c Thu May 29 05:22:02 2014 -0500 @@ -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; + dlist_add_nomalloc((void *)&mtlist, (void *)mt); - // 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'"); + // 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; diff -r b2cc738d3cfc -r 4d898affda0c lib/lib.h --- a/lib/lib.h Tue May 27 07:56:51 2014 -0500 +++ b/lib/lib.h Thu May 29 05:22:02 2014 -0500 @@ -31,6 +31,7 @@ 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 @@ // getmountlist.c struct mtab_list { - struct mtab_list *next; + struct mtab_list *next, *prev; struct stat stat; struct statvfs statvfs; char *dir; diff -r b2cc738d3cfc -r 4d898affda0c lib/llist.c --- a/lib/llist.c Tue May 27 07:56:51 2014 -0500 +++ b/lib/llist.c Thu May 29 05:22:02 2014 -0500 @@ -85,3 +85,17 @@ 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 -r b2cc738d3cfc -r 4d898affda0c toys/lsb/umount.c --- a/toys/lsb/umount.c Tue May 27 07:56:51 2014 -0500 +++ b/toys/lsb/umount.c Thu May 29 05:22:02 2014 -0500 @@ -119,7 +119,10 @@ 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 -r b2cc738d3cfc -r 4d898affda0c toys/posix/df.c --- a/toys/posix/df.c Tue May 27 07:56:51 2014 -0500 +++ b/toys/posix/df.c Thu May 29 05:22:02 2014 -0500 @@ -95,7 +95,7 @@ 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 @@ 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 @@ // 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); }