]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - mount/umount.c
2 * A umount(8) for Linux 0.99.
3 * umount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
5 * Wed Sep 14 22:43:54 1994: Sebastian Lederer
6 * (lederer@next-pc.informatik.uni-bonn.de) added support for sending an
7 * unmount RPC call to the server when an NFS-filesystem is unmounted.
9 * Tue Sep 26 16:33:09 1995: Added patches from Greg Page (greg@caldera.com)
10 * so that NetWare filesystems can be unmounted.
12 * 951213: Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>:
13 * Ignore any RPC errors, so that you can umount an nfs mounted filesystem
14 * if the server is down.
16 * 960223: aeb - several minor changes
17 * 960324: aeb - added some changes from Rob Leslie <rob@mars.org>
18 * 960823: aeb - also try umount(spec) when umount(node) fails
19 * 970307: aeb - canonise names from fstab
20 * 970726: aeb - remount read-only in cases where umount fails
21 * 980810: aeb - umount2 support
22 * 981222: aeb - If mount point or special file occurs several times
23 * in mtab, try them all, with last one tried first
24 * - Differentiate "user" and "users" key words in fstab
32 #include <sys/mount.h>
33 #include "mount_constants.h"
35 #include "getusername.h"
41 #include <sys/socket.h>
45 #include <rpc/pmap_clnt.h>
46 #include <rpc/pmap_prot.h>
48 #include <arpa/inet.h>
51 static int umount2(const char *path
, int flags
);
54 /* Interesting ... it seems libc knows about MNT_FORCE and presumably
55 about umount2 as well -- need not do anything */
58 /* Does the present kernel source know about umount2? */
59 #include <linux/unistd.h>
61 _syscall2(int, umount2
, const char *, path
, int, flags
);
62 #else /* __NR_umount2 */
64 umount2(const char *path
, int flags
) {
65 fprintf(stderr
, "umount: compiled without support for -f\n");
69 #endif /* __NR_umount2 */
71 /* dare not try to include <linux/mount.h> -- lots of errors */
74 #endif /* MNT_FORCE */
76 /* Nonzero for force umount (-f). There is kernel support since 2.1.116. */
79 /* When umount fails, attempt a read-only remount (-r). */
82 /* Don't write a entry in /etc/mtab (-n). */
85 /* Nonzero for chatty (-v). This is a nonstandard flag (not in BSD). */
88 /* True if ruid != euid. */
92 static int xdr_dir(XDR
*xdrsp
, char *dirp
)
94 return (xdr_string(xdrsp
, &dirp
, MNTPATHLEN
));
98 nfs_umount_rpc_call(const char *spec
, const char *opts
)
100 register CLIENT
*clp
;
101 struct sockaddr_in saddr
;
102 struct timeval pertry
, try;
103 enum clnt_stat clnt_stat
;
104 int so
= RPC_ANYSOCK
;
105 struct hostent
*hostp
;
110 if (spec
== NULL
|| (p
= strchr(spec
,':')) == NULL
)
112 hostname
= xstrndup(spec
, p
-spec
);
113 dirname
= xstrdup(p
+1);
115 printf("host: %s, directory: %s\n", hostname
, dirname
);
118 if (opts
&& (p
= strstr(opts
, "addr="))) {
124 while (*q
&& *q
!= ',') q
++;
125 hostname
= xstrndup(p
,q
-p
);
128 if (hostname
[0] >= '0' && hostname
[0] <= '9')
129 saddr
.sin_addr
.s_addr
= inet_addr(hostname
);
131 if ((hostp
= gethostbyname(hostname
)) == NULL
) {
132 fprintf(stderr
, "umount: can't get address for %s\n",
136 if (hostp
->h_length
> sizeof(struct in_addr
)) {
137 fprintf(stderr
, "umount: got bad hostp->h_length\n");
138 hostp
->h_length
= sizeof(struct in_addr
);
140 memcpy(&saddr
.sin_addr
, hostp
->h_addr
, hostp
->h_length
);
143 saddr
.sin_family
= AF_INET
;
147 if ((clp
= clntudp_create(&saddr
, MOUNTPROG
, MOUNTVERS
,
148 pertry
, &so
)) == NULL
) {
149 clnt_pcreateerror("Cannot MOUNTPROG RPC");
152 clp
->cl_auth
= authunix_create_default();
155 clnt_stat
= clnt_call(clp
, MOUNTPROC_UMNT
,
156 (xdrproc_t
) xdr_dir
, dirname
,
157 (xdrproc_t
) xdr_void
, (caddr_t
) 0,
160 if (clnt_stat
!= RPC_SUCCESS
) {
161 clnt_perror(clp
, "Bad UMNT RPC");
164 auth_destroy(clp
->cl_auth
);
169 #endif /* HAVE_NFS */
171 /* complain about a failed umount */
172 static void complain(int err
, const char *dev
) {
175 error ("umount: %s: invalid block device", dev
); break;
177 error ("umount: %s: not mounted", dev
); break;
179 error ("umount: %s: can't write superblock", dev
); break;
181 /* Let us hope fstab has a line "proc /proc ..."
182 and not "none /proc ..."*/
183 error ("umount: %s: device is busy", dev
); break;
185 error ("umount: %s: not found", dev
); break;
187 error ("umount: %s: must be superuser to umount", dev
); break;
189 error ("umount: %s: block devices not permitted on fs", dev
); break;
191 error ("umount: %s: %s", dev
, strerror (err
)); break;
195 /* Umount a single device. Return a status code, so don't exit
196 on a non-fatal error. We lock/unlock around each umount. */
198 umount_one (const char *spec
, const char *node
, const char *type
,
199 const char *opts
, struct mntentchn
*mc
)
201 int umnt_err
, umnt_err2
;
205 /* Special case for root. As of 0.99pl10 we can (almost) unmount root;
206 the kernel will remount it readonly so that we can carry on running
207 afterwards. The readonly remount is illegal if any files are opened
208 for writing at the time, so we can't update mtab for an unmount of
209 root. As it is only really a remount, this doesn't matter too
210 much. [sct May 29, 1993] */
211 isroot
= (streq (node
, "/") || streq (node
, "root")
212 || streq (node
, "rootfs"));
217 /* Ignore any RPC errors, so that you can umount the filesystem
218 if the server is down. */
219 if (strcasecmp(type
, "nfs") == 0)
220 nfs_umount_rpc_call(spec
, opts
);
224 umnt_err
= umnt_err2
= 0;
226 /* completely untested - 2.1.116 only has some support in nfs case */
227 /* probably this won't work */
228 int flags
= MNT_FORCE
;
230 res
= umount2 (node
, flags
);
233 if (errno
== ENOSYS
) {
235 printf("no umount2, trying umount...\n");
243 /* A device might have been mounted on a node that has since
244 been deleted or renamed, so if node fails, also try spec. */
245 /* if (umnt_err == ENOENT || umnt_err == EINVAL) */
246 if (umnt_err
!= EBUSY
&& strcmp(node
, spec
)) {
248 printf ("could not umount %s - trying %s instead\n",
253 /* Do not complain about remote NFS mount points */
254 if (errno
== ENOENT
&& index(spec
, ':'))
259 if (res
< 0 && remount
&& (umnt_err
== EBUSY
|| umnt_err2
== EBUSY
)) {
260 /* Umount failed - let us try a remount */
261 res
=mount(spec
, node
, NULL
, MS_MGC_VAL
| MS_REMOUNT
| MS_RDONLY
, NULL
);
264 fprintf(stderr
, "umount: %s busy - remounted read-only\n", spec
);
265 remnt
.mnt_type
= remnt
.mnt_fsname
= NULL
;
266 remnt
.mnt_dir
= xstrdup(node
);
267 remnt
.mnt_opts
= "ro";
268 update_mtab(node
, &remnt
);
270 } else if (errno
!= EBUSY
) { /* hmm ... */
272 fprintf(stderr
, "umount: could not remount %s read-only\n",
278 /* Umount succeeded, update mtab. */
280 printf ("%s umounted\n", spec
);
282 if (!nomtab
&& mtab_is_writable()) {
283 /* Special stuff for loop devices */
287 /* old style mtab line? */
288 if (streq(mc
->mnt_type
, "loop"))
292 /* new style mtab line? */
293 optl
= mc
->mnt_opts
? xstrdup(mc
->mnt_opts
) : "";
294 for (optl
= strtok (optl
, ","); optl
; optl
= strtok (NULL
, ",")) {
295 if (!strncmp(optl
, "loop=", 5)) {
296 if (del_loop(optl
+5))
302 /* maybe spec is a loop device? */
303 /* no del_loop() - just delete it from mtab */
304 if ((mc
= getmntoptfile (spec
)) != NULL
)
309 update_mtab (node
, NULL
);
315 /* Umount or del_loop failed, complain, but don't die. */
317 /* remove obsolete entry */
318 if (umnt_err
== EINVAL
|| umnt_err
== ENOENT
)
319 update_mtab (node
, NULL
);
323 complain(umnt_err2
, spec
);
324 if (umnt_err
&& umnt_err
!= umnt_err2
)
325 complain(umnt_err
, node
);
331 * 1. People who boot a system with a bad fstab root entry
332 * will get an incorrect "/dev/foo on /" in mtab.
333 * If later /dev/foo is actually mounted elsewhere,
334 * it will occur twice in mtab.
335 * 2. With overmounting one can get the situation that
336 * the same filename is used as mount point twice.
337 * In both cases, it is best to try the last occurrence first.
340 umount_one_bw (const char *file
, struct mntentchn
*mc
) {
344 res
= umount_one(mc
->mnt_fsname
, mc
->mnt_dir
,
345 mc
->mnt_type
, mc
->mnt_opts
, mc
);
346 mc
= getmntfilesbackward (file
, mc
);
351 /* Unmount all filesystems of type VFSTYPES found in mtab. Since we are
352 concurrently updating mtab after every succesful umount, we have to
353 slurp in the entire file before we start. This isn't too bad, because
354 in any case it's important to umount mtab entries in reverse order
355 to mount, e.g. /usr/spool before /usr. */
357 umount_all (string_list types
) {
358 struct mntentchn
*mc
, *hd
;
363 die (2, "umount: cannot find list of filesystems to unmount");
364 for (mc
= hd
->prev
; mc
!= hd
; mc
= mc
->prev
) {
365 if (matching_type (mc
->mnt_type
, types
)) {
366 errors
|= umount_one (mc
->mnt_fsname
, mc
->mnt_dir
,
367 mc
->mnt_type
, mc
->mnt_opts
, mc
);
375 extern char version
[];
376 static struct option longopts
[] =
378 { "all", 0, 0, 'a' },
379 { "force", 0, 0, 'f' },
380 { "help", 0, 0, 'h' },
381 { "no-mtab", 0, 0, 'n' },
382 { "verbose", 0, 0, 'v' },
383 { "version", 0, 0, 'V' },
384 { "read-only", 0, 0, 'r' },
385 { "types", 1, 0, 't' },
389 char *usage_string
= "\
390 Usage: umount [-hV]\n\
391 umount -a [-f] [-r] [-n] [-v] [-t vfstypes]\n\
392 umount [-f] [-r] [-n] [-v] special | node...\n\
396 usage (FILE *fp
, int n
)
398 fprintf (fp
, "%s", usage_string
);
405 main (int argc
, char *argv
[])
409 string_list types
= NULL
;
411 struct mntentchn
*mc
, *fs
;
415 while ((c
= getopt_long (argc
, argv
, "afhnrt:vV",
416 longopts
, NULL
)) != EOF
)
418 case 'a': /* umount everything */
421 case 'f': /* force umount */
427 case 'n': /* do not write in /etc/mtab */
430 case 'r': /* remount read-only if umount fails */
433 case 'v': /* make noise */
436 case 'V': /* version */
437 printf ("umount: %s\n", version
);
439 case 't': /* specify file system type */
440 types
= parse_list (optarg
);
449 if (getuid () != geteuid ())
452 if (all
|| types
|| nomtab
|| force
)
453 die (2, "umount: only root can do that");
461 types
= parse_list(xstrdup("noproc"));
462 result
= umount_all (types
);
463 } else if (argc
< 1) {
465 } else while (argc
--) {
466 file
= canonicalize (*argv
); /* mtab paths are canonicalized */
468 printf("Trying to umount %s\n", file
);
470 mc
= getmntfilesbackward (file
, NULL
);
472 printf("Could not find %s in mtab\n", file
);
476 die (2, "umount: %s is not mounted (according to mtab)", file
);
477 if (getmntfilesbackward (file
, mc
))
478 die (2, "umount: it seems %s is mounted multiple times", file
);
479 if (!(fs
= getfsspec (file
)) && !(fs
= getfsfile (file
)))
480 die (2, "umount: %s is not in the fstab (and you are not root)",
482 if ((!streq (mc
->mnt_fsname
, fs
->mnt_fsname
) &&
483 !streq (mc
->mnt_fsname
, canonicalize (fs
->mnt_fsname
)))
484 || (!streq (mc
->mnt_dir
, fs
->mnt_dir
) &&
485 !streq (mc
->mnt_dir
, canonicalize (fs
->mnt_dir
)))) {
486 die (2, "umount: %s mount disagrees with the fstab", file
);
489 /* User mounting and unmounting is allowed only
490 if fstab contains the option `user' or `users' */
491 /* The option `users' allows arbitrary users to mount
492 and unmount - this may be a security risk. */
493 /* The option `user' only allows unmounting by the user
495 /* A convenient side effect is that the user who mounted
496 is visible in mtab. */
497 options
= parse_list (fs
->mnt_opts
);
499 if (streq (car (options
), "user") ||
500 streq (car (options
), "users"))
502 options
= cdr (options
);
505 die (2, "umount: only root can unmount %s from %s",
506 fs
->mnt_fsname
, fs
->mnt_dir
);
507 if (streq (car (options
), "user")) {
508 char *user
= getusername();
510 options
= parse_list (mc
->mnt_opts
);
512 char *co
= car (options
);
513 if (!strncmp(co
, "user=", 5)) {
514 if (!user
|| !streq(co
+5,user
))
515 die(2, "umount: only %s can unmount %s from %s",
516 co
+5, fs
->mnt_fsname
, fs
->mnt_dir
);
519 options
= cdr (options
);
525 result
= umount_one_bw (file
, mc
);
527 result
= umount_one (*argv
, *argv
, *argv
, *argv
, NULL
);