aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2014-07-05 23:26:05 -0500
committerRob Landley <rob@landley.net>2014-07-05 23:26:05 -0500
commit36f6dea7ea3c9973910f38af61a58f20513b95c8 (patch)
tree1bd51ddc93010c82dec5219a7a51a4e2a92a4912
parent15e02f09549e34e839a6b74fdfb3c1d1974bb635 (diff)
downloadtoybox-36f6dea7ea3c9973910f38af61a58f20513b95c8.tar.gz
Try to lookup all umounts in /proc/mounts so we can auto-zap loopback devices.
-rw-r--r--toys/lsb/umount.c84
1 files changed, 56 insertions, 28 deletions
diff --git a/toys/lsb/umount.c b/toys/lsb/umount.c
index d1a2c69d..002ffd68 100644
--- a/toys/lsb/umount.c
+++ b/toys/lsb/umount.c
@@ -8,7 +8,7 @@
* nor per-process mount namespaces can work sanely with mtab. The kernel
* tracks mount points now, a userspace application can't do so anymore.
-USE_UMOUNT(NEWTOY(umount, "ndDflrat*v", TOYFLAG_BIN|TOYFLAG_STAYROOT))
+USE_UMOUNT(NEWTOY(umount, "ndDflrat*v[!na]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
config UMOUNT
bool "umount"
@@ -19,11 +19,12 @@ config UMOUNT
Unmount the listed filesystems.
-a Unmount all mounts in /proc/mounts instead of command line list
- -t Restrict "all" to mounts of TYPE (or use "noTYPE" to skip)
-D Don't free loopback device(s).
-f Force unmount.
-l Lazy unmount (detach from filesystem now, close when last user does).
+ -n Don't use /proc/mounts
-r Remount read only if unmounting fails.
+ -t Restrict "all" to mounts of TYPE (or use "noTYPE" to skip)
-v Verbose
*/
@@ -63,19 +64,16 @@ void comma_collate(char **old, char *new)
*old = temp;
}
-void arg_comma_collate(char **old, struct arg_list *arg)
-{
- while (arg) {
- comma_collate(old, arg->arg);
- arg = arg->next;
- }
-}
-
+// iterate through strings in a comma separated list.
+// returns start of next entry or NULL if none
+// sets *len to length of entry (not including comma)
+// advances *list to start of next entry
char *comma_iterate(char **list, int *len)
{
char *start = *list, *end;
if (!*list) return 0;
+
if (!(end = strchr(*list, ','))) {
*len = strlen(*list);
*list = 0;
@@ -84,25 +82,42 @@ char *comma_iterate(char **list, int *len)
return start;
}
-static void do_umount(char *dir, int flags)
+static void do_umount(char *dir, char *dev, int flags)
{
if (!umount2(dir, flags)) {
- if (toys.optflags & FLAG_v) printf("%s unmounted", dir);
+ if (toys.optflags & FLAG_v) xprintf("%s unmounted\n", dir);
+
+ // Attempt to disassociate loopback device. This ioctl should be ignored
+ // for anything else, because lanana allocated ioctl range 'L' to loopback
+ if (dev && !(toys.optflags & FLAG_D)) {
+ int lfd = open(dev, O_RDONLY);
+
+ if (lfd != -1) {
+ // This is LOOP_CLR_FD, fetching it from headers is awkward
+ if (!ioctl(lfd, 0x4C01) && (toys.optflags & FLAG_v))
+ xprintf("%s cleared\n", dev);
+ close(lfd);
+ }
+ }
+
return;
}
+
if (toys.optflags & FLAG_r) {
if (!mount("", dir, "", MS_REMOUNT|MS_RDONLY, "")) {
- if (toys.optflags & FLAG_v) printf("%s remounted ro", dir);
+ if (toys.optflags & FLAG_v) xprintf("%s remounted ro\n", dir);
return;
}
}
+
perror_msg("%s", dir);
}
void umount_main(void)
{
+ char **optargs, *pm = "/proc/mounts";
+ struct mtab_list *mlsave = 0, *mlrev = 0, *ml;
int flags=0;
- char **optargs;
if (!toys.optc && !(toys.optflags & FLAG_a))
error_exit("Need 1 arg or -a");
@@ -110,27 +125,26 @@ void umount_main(void)
if (toys.optflags & FLAG_f) flags |= MNT_FORCE;
if (toys.optflags & FLAG_l) flags |= MNT_DETACH;
- for (optargs = toys.optargs; *optargs; optargs++) do_umount(*optargs, flags);
+ // Load /proc/mounts and get a reversed list (newest first)
+ // We use the list both for -a, and to umount /dev/name or do losetup -d
+ if (!(toys.optflags & FLAG_n) && !access(pm, R_OK))
+ mlrev = dlist_terminate(mlsave = xgetmountlist(pm));
+ // Unmount all: loop through mounted filesystems, skip -t, unmount the rest
if (toys.optflags & FLAG_a) {
- struct mtab_list *mlsave, *ml;
char *typestr = 0;
-
- if (TT.t) arg_comma_collate(&typestr, TT.t);
-
- // Loop through mounted filesystems
- mlsave = xgetmountlist(0);
- ml = ml->prev;
-
- for (ml = dlist_terminate(mlsave); ml; ml = ml->prev) {
- if (TT.t) {
+ struct arg_list *tal;
+
+ for (tal = TT.t; tal; tal = tal->next) comma_collate(&typestr, tal->arg);
+ for (ml = mlrev; ml; ml = ml->prev) {
+ if (typestr) {
char *type, *types = typestr;
int len, skip = strncmp(types, "no", 2);
- // Loop through -t filters
for (;;) {
if (!(type = comma_iterate(&types, &len))) break;
if (!skip) {
+ // If one -t starts with "no", the rest must too
if (strncmp(type, "no", 2)) error_exit("bad -t");
if (!strncmp(type+2, ml->type, len-2)) {
skip = 1;
@@ -143,13 +157,27 @@ void umount_main(void)
}
if (skip) continue;
}
- do_umount(ml->dir, flags);
+
+ do_umount(ml->dir, ml->device, flags);
}
if (CFG_TOYBOX_FREE) {
free(typestr);
llist_traverse(mlsave, free);
}
+ // TODO: under what circumstances do we umount non-absolute path?
+ } else for (optargs = toys.optargs; *optargs; optargs++) {
+ char *abs = xabspath(*optargs, 0);
+
+ for (ml = abs ? mlrev : 0; ml; ml = ml->prev) {
+ if (!strcmp(ml->dir, abs)) break;
+ if (!strcmp(ml->device, abs)) {
+ free(abs);
+ abs = ml->dir;
+ break;
+ }
+ }
- return;
+ do_umount(abs ? abs : *optargs, ml ? ml->device : 0, flags);
+ if (ml && abs != ml->dir) free(abs);
}
}