2 * umount(8) for Linux 0.99 - jrs, 1993
13 #include <sys/mount.h>
14 #include "mount_constants.h"
16 #include "getusername.h"
17 #include "pathnames.h"
24 #if defined(MNT_FORCE)
25 /* Interesting ... it seems libc knows about MNT_FORCE and presumably
26 about umount2 as well -- need not do anything */
29 /* Does the present kernel source know about umount2? */
30 #include <linux/unistd.h>
33 static int umount2(const char *path, int flags);
35 _syscall2(int, umount2, const char *, path, int, flags);
37 #else /* __NR_umount2 */
40 umount2(const char *path, int flags) {
41 fprintf(stderr, _("umount: compiled without support for -f\n"));
45 #endif /* __NR_umount2 */
47 #if !defined(MNT_FORCE)
48 /* dare not try to include <linux/mount.h> -- lots of errors */
52 #endif /* MNT_FORCE */
54 #if !defined(MNT_DETACH)
59 /* True if we are allowed to call /sbin/umount.${FSTYPE} */
60 int external_allowed = 1;
62 /* Nonzero for force umount (-f). There is kernel support since 2.1.116. */
65 /* Nonzero for lazy umount (-l). There is kernel support since 2.4.11. */
68 /* When umount fails, attempt a read-only remount (-r). */
71 /* Don't write a entry in /etc/mtab (-n). */
74 /* Call losetup -d for each unmounted loop device. */
77 /* True if (ruid != euid) or (0 != ruid), i.e. only "user" umounts permitted. */
80 /* Last error message */
81 int complained_err = 0;
82 char *complained_dev = NULL;
85 * check_special_umountprog()
86 * If there is a special umount program for this type, exec it.
87 * returns: 0: no exec was done, 1: exec was done, status has result
90 check_special_umountprog(const char *spec, const char *node,
91 const char *type, int *status) {
96 if (!external_allowed)
99 if (type == NULL || strcmp(type, "none") == 0)
102 if (strlen(type) < 100) {
103 sprintf(umountprog, "/sbin/umount.%s", type);
104 if (stat(umountprog, &statbuf) == 0) {
110 if(setgid(getgid()) < 0)
111 die(EX_FAIL, _("umount: cannot set group id: %s"), strerror(errno));
113 if(setuid(getuid()) < 0)
114 die(EX_FAIL, _("umount: cannot set user id: %s"), strerror(errno));
116 umountargs[i++] = umountprog;
117 umountargs[i++] = xstrdup(node);
119 umountargs[i++] = "-n";
121 umountargs[i++] = "-l";
123 umountargs[i++] = "-f";
125 umountargs[i++] = "-v";
127 umountargs[i++] = "-r";
128 umountargs[i] = NULL;
129 execv(umountprog, umountargs);
130 exit(1); /* exec failed */
131 } else if (res != -1) {
134 *status = (WIFEXITED(st) ? WEXITSTATUS(st)
139 error(_("umount: cannot fork: %s"),
147 /* complain about a failed umount */
148 static void complain(int err, const char *dev) {
150 if (complained_err == err && complained_dev && dev &&
151 strcmp(dev, complained_dev) == 0)
154 complained_err = err;
155 free(complained_dev);
156 complained_dev = xstrdup(dev);
160 error (_("umount: %s: invalid block device"), dev); break;
162 error (_("umount: %s: not mounted"), dev); break;
164 error (_("umount: %s: can't write superblock"), dev); break;
166 /* Let us hope fstab has a line "proc /proc ..."
167 and not "none /proc ..."*/
168 error (_("umount: %s: device is busy.\n"
169 " (In some cases useful info about processes that use\n"
170 " the device is found by lsof(8) or fuser(1))"), dev);
173 error (_("umount: %s: not found"), dev); break;
175 error (_("umount: %s: must be superuser to umount"), dev); break;
177 error (_("umount: %s: block devices not permitted on fs"), dev); break;
179 error (_("umount: %s: %s"), dev, strerror (err)); break;
183 /* Umount a single device. Return a status code, so don't exit
184 on a non-fatal error. We lock/unlock around each umount. */
186 umount_one (const char *spec, const char *node, const char *type,
187 const char *opts, struct mntentchn *mc) {
195 /* Special case for root. As of 0.99pl10 we can (almost) unmount root;
196 the kernel will remount it readonly so that we can carry on running
197 afterwards. The readonly remount is illegal if any files are opened
198 for writing at the time, so we can't update mtab for an unmount of
199 root. As it is only really a remount, this doesn't matter too
200 much. [sct May 29, 1993] */
201 isroot = (streq (node, "/") || streq (node, "root")
202 || streq (node, "rootfs"));
207 * Call umount.TYPE for types that require a separate umount program.
208 * All such special things must occur isolated in the types string.
210 if (check_special_umountprog(spec, node, type, &status))
214 * Ignore the option "-d" for non-loop devices and loop devices with
215 * LO_FLAGS_AUTOCLEAR flag.
217 if (delloop && is_loop_device(spec) && !is_loop_autoclear(spec))
221 res = umount2 (node, MNT_DETACH);
227 if (force) { /* only supported for NFS */
228 res = umount2 (node, MNT_FORCE);
233 if (errno == ENOSYS) {
235 printf(_("no umount2, trying umount...\n"));
245 if (res < 0 && remount && umnt_err == EBUSY) {
246 /* Umount failed - let us try a remount */
247 res = mount(spec, node, NULL,
248 MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
250 struct my_mntent remnt;
252 _("umount: %s busy - remounted read-only\n"),
254 remnt.mnt_type = remnt.mnt_fsname = NULL;
255 remnt.mnt_dir = xstrdup(node);
256 remnt.mnt_opts = xstrdup("ro");
258 update_mtab(node, &remnt);
260 } else if (errno != EBUSY) { /* hmm ... */
263 _("umount: could not remount %s read-only\n"),
270 /* Umount succeeded */
272 printf (_("%s umounted\n"), spec);
274 /* Free any loop devices that we allocated ourselves */
278 /* old style mtab line? */
279 if (streq(mc->m.mnt_type, "loop")) {
284 /* new style mtab line? */
285 optl = mc->m.mnt_opts ? xstrdup(mc->m.mnt_opts) : "";
286 for (optl = strtok (optl, ","); optl;
287 optl = strtok (NULL, ",")) {
288 if (!strncmp(optl, "loop=", 5)) {
295 * If option "-o loop=spec" occurs in mtab,
296 * note the mount point, and delete mtab line.
298 if ((mc = getmntoptfile (spec)) != NULL)
299 node = mc->m.mnt_dir;
302 /* Also free loop devices when -d flag is given */
312 (umnt_err == 0 || umnt_err == EINVAL || umnt_err == ENOENT)) {
313 update_mtab (node, NULL);
319 complain(umnt_err, node);
324 * umount_one_bw: unmount FILE that has last occurrence MC0
327 * 1. People who boot a system with a bad fstab root entry
328 * will get an incorrect "/dev/foo on /" in mtab.
329 * If later /dev/foo is actually mounted elsewhere,
330 * it will occur twice in mtab.
331 * 2. With overmounting one can get the situation that
332 * the same filename is used as mount point twice.
333 * In both cases, it is best to try the last occurrence first.
336 umount_one_bw (const char *file, struct mntentchn *mc0) {
337 struct mntentchn *mc;
342 res = umount_one(mc->m.mnt_fsname, mc->m.mnt_dir,
343 mc->m.mnt_type, mc->m.mnt_opts, mc);
344 mc = getmntdirbackward(file, mc);
348 res = umount_one(mc->m.mnt_fsname, mc->m.mnt_dir,
349 mc->m.mnt_type, mc->m.mnt_opts, mc);
350 mc = getmntdevbackward(file, mc);
355 /* Unmount all filesystems of type VFSTYPES found in mtab. Since we are
356 concurrently updating mtab after every successful umount, we have to
357 slurp in the entire file before we start. This isn't too bad, because
358 in any case it's important to umount mtab entries in reverse order
359 to mount, e.g. /usr/spool before /usr. */
361 umount_all (char *types, char *test_opts) {
362 struct mntentchn *mc, *hd;
367 die (2, _("umount: cannot find list of filesystems to unmount"));
368 for (mc = hd->prev; mc != hd; mc = mc->prev) {
369 if (matching_type (mc->m.mnt_type, types)
370 && matching_opts (mc->m.mnt_opts, test_opts)) {
371 errors |= umount_one (mc->m.mnt_fsname, mc->m.mnt_dir,
372 mc->m.mnt_type, mc->m.mnt_opts, mc);
380 static struct option longopts[] =
382 { "all", 0, 0, 'a' },
383 { "force", 0, 0, 'f' },
384 { "help", 0, 0, 'h' },
385 { "no-mtab", 0, 0, 'n' },
386 { "test-opts", 1, 0, 'O' },
387 { "verbose", 0, 0, 'v' },
388 { "version", 0, 0, 'V' },
389 { "read-only", 0, 0, 'r' },
390 { "types", 1, 0, 't' },
395 usage (FILE *fp, int n)
397 fprintf (fp, _("Usage: umount -h | -V\n"
398 " umount -a [-d] [-f] [-r] [-n] [-v] [-t vfstypes] [-O opts]\n"
399 " umount [-d] [-f] [-r] [-n] [-v] special | node...\n"));
404 * Look for an option in a comma-separated list
407 contains(const char *list, const char *s) {
410 while (list && *list) {
411 if (strncmp(list, s, n) == 0 &&
412 (list[n] == 0 || list[n] == ','))
414 while (*list && *list++ != ',') ;
420 * If list contains "user=peter" and we ask for "user=", return "peter"
423 get_value(const char *list, const char *s) {
427 while (list && *list) {
428 if (strncmp(list, s, n) == 0) {
430 while (*s && *s != ',')
432 return xstrndup(t, s-t);
434 while (*list && *list++ != ',') ;
439 /* check if @mc contains a loop device which is associated
440 * with the @file in fs
443 is_valid_loop(struct mntentchn *mc, struct mntentchn *fs)
445 unsigned long long offset = 0;
448 /* check if it begins with /dev/loop */
449 if (strncmp(mc->m.mnt_fsname, _PATH_DEV_LOOP,
450 sizeof(_PATH_DEV_LOOP) - 1))
453 /* check for loop option in fstab */
454 if (!contains(fs->m.mnt_opts, "loop"))
457 /* check for offset option in fstab */
458 p = get_value(fs->m.mnt_opts, "offset=");
460 offset = strtoull(p, NULL, 10);
462 /* check association */
463 if (loopfile_used_with((char *) mc->m.mnt_fsname,
464 fs->m.mnt_fsname, offset) == 1) {
466 printf(_("device %s is associated with %s\n"),
467 mc->m.mnt_fsname, fs->m.mnt_fsname);
472 printf(_("device %s is not associated with %s\n"),
473 mc->m.mnt_fsname, fs->m.mnt_fsname);
478 umount_file (char *arg) {
479 struct mntentchn *mc, *fs;
480 const char *file, *options;
481 int fstab_has_user, fstab_has_users, fstab_has_owner, fstab_has_group;
484 if (!*arg) { /* "" would be expanded to `pwd` */
485 die(2, _("Cannot umount \"\"\n"));
489 file = canonicalize(arg); /* mtab paths are canonicalized */
491 printf(_("Trying to umount %s\n"), file);
493 mc = getmntdirbackward(file, NULL);
495 mc = getmntdevbackward(file, NULL);
497 struct mntentchn *mc1;
499 mc1 = getmntdirbackward(mc->m.mnt_dir, NULL);
501 /* 'mc1' must exist, though not necessarily
502 equals to `mc'. Otherwise we go mad. */
504 _("umount: confused when analyzing mtab"));
506 if (strcmp(file, mc1->m.mnt_fsname)) {
507 /* Something was stacked over `file' on the
509 die(EX_FAIL, _("umount: cannot umount %s -- %s is "
510 "mounted over it on the same point."),
511 file, mc1->m.mnt_fsname);
516 printf(_("Could not find %s in mtab\n"), file);
519 char *mtab_user = NULL;
523 _("umount: %s is not mounted (according to mtab)"),
526 * uhelper - unprivileged umount helper
527 * -- external umount (for example HAL mounts)
529 if (external_allowed) {
530 char *uhelper = NULL;
533 uhelper = get_value(mc->m.mnt_opts, "uhelper=");
536 if (check_special_umountprog(arg, arg,
542 /* The 2.4 kernel will generally refuse to mount the same
543 filesystem on the same mount point, but will accept NFS.
544 So, unmounting must be possible. */
545 if (!is_mounted_once(file) && strcmp(mc->m.mnt_type,"nfs"))
547 _("umount: it seems %s is mounted multiple times"),
550 /* If fstab contains the two lines
551 /dev/sda1 /mnt/zip auto user,noauto 0 0
552 /dev/sda4 /mnt/zip auto user,noauto 0 0
553 then "mount /dev/sda4" followed by "umount /mnt/zip"
554 used to fail. So, we must not look for file, but for
555 the pair (dev,file) in fstab. */
556 fs = getfs_by_devdir(mc->m.mnt_fsname, mc->m.mnt_dir);
558 fs = getfs_by_dir(file);
559 if (!fs && !getfs_by_spec(file))
561 _("umount: %s is not in the fstab "
562 "(and you are not root)"),
565 /* spec could be a file which is loop mounted */
566 if (fs && !is_valid_loop(mc, fs))
567 die (2, _("umount: %s mount disagrees with "
572 * User mounting and unmounting is allowed only
573 * if fstab contains one of the options `user',
574 * `users' or `owner' or `group'.
576 * The option `users' allows arbitrary users to mount
577 * and unmount - this may be a security risk.
579 * The options `user', `owner' and `group' only allow
580 * unmounting by the user that mounted (visible in mtab).
583 options = fs->m.mnt_opts;
586 fstab_has_user = contains(options, "user");
587 fstab_has_users = contains(options, "users");
588 fstab_has_owner = contains(options, "owner");
589 fstab_has_group = contains(options, "group");
595 if (!ok && (fstab_has_user || fstab_has_owner ||
597 char *user = getusername();
599 options = mc->m.mnt_opts;
602 mtab_user = get_value(options, "user=");
604 if (user && mtab_user && streq (user, mtab_user))
608 die (2, _("umount: only %s can unmount %s from %s"),
609 mtab_user ? mtab_user : "root",
610 fs->m.mnt_fsname, fs->m.mnt_dir);
614 return umount_one_bw (file, mc);
616 return umount_one (arg, arg, arg, arg, NULL);
620 main (int argc, char *argv[]) {
623 char *types = NULL, *test_opts = NULL, *p;
627 setlocale(LC_ALL, "");
628 bindtextdomain(PACKAGE, LOCALEDIR);
632 if ((p = strrchr(progname, '/')) != NULL)
637 while ((c = getopt_long (argc, argv, "adfhlnrit:O:vV",
638 longopts, NULL)) != -1)
640 case 'a': /* umount everything */
644 case 'd': /* do losetup -d for unmounted loop devices */
647 case 'f': /* force umount */
653 case 'l': /* lazy umount */
656 case 'n': /* do not write in /etc/mtab */
659 case 'O': /* specify file system options */
662 case 'r': /* remount read-only if umount fails */
665 case 'v': /* make noise */
668 case 'V': /* version */
669 printf ("umount (%s)\n", PACKAGE_STRING);
671 case 't': /* specify file system type */
675 external_allowed = 0;
685 const uid_t ruid = getuid();
686 const uid_t euid = geteuid();
688 /* if we're really root and aren't running setuid */
689 if (((uid_t)0 == ruid) && (ruid == euid)) {
694 if (restricted && (all || types || nomtab || force || remount)) {
695 die (2, _("umount: only root can do that"));
704 /* nodev stuff: sysfs, usbfs, oprofilefs, ... */
706 types = "noproc,nodevfs,nodevpts,nosysfs,norpc_pipefs,nonfsd";
707 result = umount_all (types, test_opts);
708 } else if (argc < 1) {
710 } else while (argc--) {
711 result += umount_file(*argv++);
713 exit (result); /* nonzero on at least one failure */