10f66f451Sopenharmony_ci/* umount.c - Unmount a mount point. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2012 Rob Landley <rob@landley.net> 40f66f451Sopenharmony_ci * 50f66f451Sopenharmony_ci * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/umount.html 60f66f451Sopenharmony_ci * 70f66f451Sopenharmony_ci * Note: -n (/etc/mtab) is obsolete, /proc/mounts replaced it. Neither chroot 80f66f451Sopenharmony_ci * nor per-process mount namespaces can work sanely with mtab. The kernel 90f66f451Sopenharmony_ci * tracks mount points now, a userspace application can't do so anymore. 100f66f451Sopenharmony_ci 110f66f451Sopenharmony_ciUSE_UMOUNT(NEWTOY(umount, "cndDflrat*v[!na]", TOYFLAG_BIN|TOYFLAG_STAYROOT)) 120f66f451Sopenharmony_ci 130f66f451Sopenharmony_ciconfig UMOUNT 140f66f451Sopenharmony_ci bool "umount" 150f66f451Sopenharmony_ci default y 160f66f451Sopenharmony_ci help 170f66f451Sopenharmony_ci usage: umount [-a [-t TYPE[,TYPE...]]] [-f] [DIR...] 180f66f451Sopenharmony_ci 190f66f451Sopenharmony_ci Unmount the listed filesystems. 200f66f451Sopenharmony_ci 210f66f451Sopenharmony_ci -a Unmount all mounts in /proc/mounts instead of command line list 220f66f451Sopenharmony_ci -t Restrict "all" to mounts of TYPE (or use "noTYPE" to skip) 230f66f451Sopenharmony_ci*/ 240f66f451Sopenharmony_ci 250f66f451Sopenharmony_ci#define FOR_umount 260f66f451Sopenharmony_ci#include "toys.h" 270f66f451Sopenharmony_ci 280f66f451Sopenharmony_ciGLOBALS( 290f66f451Sopenharmony_ci struct arg_list *t; 300f66f451Sopenharmony_ci 310f66f451Sopenharmony_ci char *types; 320f66f451Sopenharmony_ci) 330f66f451Sopenharmony_ci 340f66f451Sopenharmony_ci// todo (done?) 350f66f451Sopenharmony_ci// borrow df code to identify filesystem? 360f66f451Sopenharmony_ci// umount -a from fstab 370f66f451Sopenharmony_ci// umount when getpid() not 0, according to fstab 380f66f451Sopenharmony_ci// lookup mount: losetup -d, bind, file, block 390f66f451Sopenharmony_ci// loopback delete 400f66f451Sopenharmony_ci// fstab -o user 410f66f451Sopenharmony_ci 420f66f451Sopenharmony_ci// TODO 430f66f451Sopenharmony_ci// swapon, swapoff 440f66f451Sopenharmony_ci 450f66f451Sopenharmony_cistatic void do_umount(char *dir, char *dev, int flags) 460f66f451Sopenharmony_ci{ 470f66f451Sopenharmony_ci if (!umount2(dir, flags)) { 480f66f451Sopenharmony_ci if (toys.optflags & FLAG_v) xprintf("%s unmounted\n", dir); 490f66f451Sopenharmony_ci 500f66f451Sopenharmony_ci // Attempt to disassociate loopback device. This ioctl should be ignored 510f66f451Sopenharmony_ci // for anything else, because lanana allocated ioctl range 'L' to loopback 520f66f451Sopenharmony_ci if (dev && !(toys.optflags & FLAG_D)) { 530f66f451Sopenharmony_ci int lfd = open(dev, O_RDONLY); 540f66f451Sopenharmony_ci 550f66f451Sopenharmony_ci if (lfd != -1) { 560f66f451Sopenharmony_ci // This is LOOP_CLR_FD, fetching it from headers is awkward 570f66f451Sopenharmony_ci if (!ioctl(lfd, 0x4C01) && (toys.optflags & FLAG_v)) 580f66f451Sopenharmony_ci xprintf("%s cleared\n", dev); 590f66f451Sopenharmony_ci close(lfd); 600f66f451Sopenharmony_ci } 610f66f451Sopenharmony_ci } 620f66f451Sopenharmony_ci xprintf("umount ok\n"); 630f66f451Sopenharmony_ci return; 640f66f451Sopenharmony_ci } 650f66f451Sopenharmony_ci 660f66f451Sopenharmony_ci if (toys.optflags & FLAG_r) { 670f66f451Sopenharmony_ci if (!mount("", dir, "", MS_REMOUNT|MS_RDONLY, "")) { 680f66f451Sopenharmony_ci if (toys.optflags & FLAG_v) xprintf("%s remounted ro\n", dir); 690f66f451Sopenharmony_ci return; 700f66f451Sopenharmony_ci } 710f66f451Sopenharmony_ci } 720f66f451Sopenharmony_ci 730f66f451Sopenharmony_ci perror_msg_raw(dir); 740f66f451Sopenharmony_ci} 750f66f451Sopenharmony_ci 760f66f451Sopenharmony_civoid umount_main(void) 770f66f451Sopenharmony_ci{ 780f66f451Sopenharmony_ci char **optargs, *pm = "/proc/mounts"; 790f66f451Sopenharmony_ci struct mtab_list *mlsave = 0, *mlrev = 0, *ml; 800f66f451Sopenharmony_ci int flags=0; 810f66f451Sopenharmony_ci 820f66f451Sopenharmony_ci if (!toys.optc && !(toys.optflags & FLAG_a)) 830f66f451Sopenharmony_ci help_exit("Need 1 arg or -a"); 840f66f451Sopenharmony_ci 850f66f451Sopenharmony_ci if (toys.optflags & FLAG_f) flags |= MNT_FORCE; 860f66f451Sopenharmony_ci if (toys.optflags & FLAG_l) flags |= MNT_DETACH; 870f66f451Sopenharmony_ci 880f66f451Sopenharmony_ci // Load /proc/mounts and get a reversed list (newest first) 890f66f451Sopenharmony_ci // We use the list both for -a, and to umount /dev/name or do losetup -d 900f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_n) && !access(pm, R_OK)) 910f66f451Sopenharmony_ci mlrev = dlist_terminate(mlsave = xgetmountlist(pm)); 920f66f451Sopenharmony_ci 930f66f451Sopenharmony_ci // Unmount all: loop through mounted filesystems, skip -t, unmount the rest 940f66f451Sopenharmony_ci if (toys.optflags & FLAG_a) { 950f66f451Sopenharmony_ci char *typestr = 0; 960f66f451Sopenharmony_ci struct arg_list *tal; 970f66f451Sopenharmony_ci 980f66f451Sopenharmony_ci for (tal = TT.t; tal; tal = tal->next) comma_collate(&typestr, tal->arg); 990f66f451Sopenharmony_ci for (ml = mlrev; ml; ml = ml->prev) 1000f66f451Sopenharmony_ci if (mountlist_istype(ml, typestr)) do_umount(ml->dir, ml->device, flags); 1010f66f451Sopenharmony_ci if (CFG_TOYBOX_FREE) { 1020f66f451Sopenharmony_ci free(typestr); 1030f66f451Sopenharmony_ci llist_traverse(mlsave, free); 1040f66f451Sopenharmony_ci } 1050f66f451Sopenharmony_ci // TODO: under what circumstances do we umount non-absolute path? 1060f66f451Sopenharmony_ci } else for (optargs = toys.optargs; *optargs; optargs++) { 1070f66f451Sopenharmony_ci char *abs = xabspath(*optargs, 0); 1080f66f451Sopenharmony_ci 1090f66f451Sopenharmony_ci for (ml = abs ? mlrev : 0; ml; ml = ml->prev) { 1100f66f451Sopenharmony_ci if (!strcmp(ml->dir, abs)) break; 1110f66f451Sopenharmony_ci if (!strcmp(ml->device, abs)) { 1120f66f451Sopenharmony_ci free(abs); 1130f66f451Sopenharmony_ci abs = ml->dir; 1140f66f451Sopenharmony_ci break; 1150f66f451Sopenharmony_ci } 1160f66f451Sopenharmony_ci } 1170f66f451Sopenharmony_ci 1180f66f451Sopenharmony_ci do_umount(abs ? abs : *optargs, ml ? ml->device : 0, flags); 1190f66f451Sopenharmony_ci if (ml && abs != ml->dir) free(abs); 1200f66f451Sopenharmony_ci } 1210f66f451Sopenharmony_ci} 122