1 /* $NetBSD: umount.c,v 1.42 2008/07/20 01:20:23 lukem Exp $ */
4 * Copyright (c) 1980, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1980, 1989, 1993\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)umount.c 8.8 (Berkeley) 5/8/95";
42 __RCSID("$NetBSD: umount.c,v 1.42 2008/07/20 01:20:23 lukem Exp $");
46 #include <sys/param.h>
48 #include <sys/mount.h>
51 #include <sys/socket.h>
55 #include <rpc/pmap_clnt.h>
56 #include <rpc/pmap_prot.h>
57 #include <nfs/rpcv2.h>
67 typedef enum { MNTANY
, MNTON
, MNTFROM
} mntwhat
;
70 #include "mountprog.h"
72 static int fake
, verbose
;
74 static struct addrinfo
*nfshost_ai
= NULL
;
76 static int namematch(const struct addrinfo
*);
77 static int sacmp(const struct sockaddr
*, const struct sockaddr
*);
78 static int xdr_dir(XDR
*, char *);
82 static char *getmntname(const char *, mntwhat
, char **);
83 static int umountfs(const char *, const char **, int);
84 static void usage(void) __dead
;
87 main(int argc
, char *argv
[])
89 int ch
, errs
, all
= 0, raw
= 0;
92 struct statvfs
*mntbuf
;
93 struct addrinfo hints
;
95 const char **typelist
= NULL
;
97 /* Start disks transferring immediately. */
103 #define OPTS "AaFfh:Rt:v"
105 while ((ch
= getopt(argc
, argv
, OPTS
)) != -1)
121 case 'h': /* -h implies -A. */
126 if (typelist
!= NULL
)
127 errx(1, "only one -t option may be specified.");
128 typelist
= makevfslist(optarg
);
141 if ((argc
== 0 && !all
) || (argc
!= 0 && all
) || (all
&& raw
))
145 /* -h implies "-t nfs" if no -t flag. */
146 if ((nfshost
!= NULL
) && (typelist
== NULL
))
147 typelist
= makevfslist("nfs");
149 if (nfshost
!= NULL
) {
150 memset(&hints
, 0, sizeof hints
);
151 getaddrinfo(nfshost
, NULL
, &hints
, &nfshost_ai
);
156 if ((mnts
= getmntinfo(&mntbuf
, ST_NOWAIT
)) == 0) {
160 for (errs
= 0, mnts
--; mnts
> 0; mnts
--) {
161 if (checkvfsname(mntbuf
[mnts
].f_fstypename
, typelist
))
163 if (umountfs(mntbuf
[mnts
].f_mntonname
, typelist
,
169 for (errs
= 0; *argv
!= NULL
; ++argv
)
170 if (umountfs(*argv
, typelist
, raw
) != 0)
176 umountfs(const char *name
, const char **typelist
, int raw
)
179 enum clnt_stat clnt_stat
;
183 struct addrinfo
*ai
= NULL
, hints
;
186 char *type
, rname
[MAXPATHLEN
];
195 if (realpath(name
, rname
) != NULL
) {
198 if (stat(name
, &sb
) == 0) {
199 if (S_ISBLK(sb
.st_mode
))
201 else if (S_ISDIR(sb
.st_mode
))
215 if ((mntpt
= getmntname(name
, MNTON
, &type
)) == NULL
) {
216 warnx("%s: not currently mounted", name
);
221 if ((name
= getmntname(mntpt
, MNTFROM
, &type
)) == NULL
) {
222 warnx("%s: not currently mounted", mntpt
);
227 if ((name
= getmntname(mntpt
, MNTFROM
, &type
)) == NULL
) {
229 if ((mntpt
= getmntname(name
, MNTON
, &type
)) == NULL
) {
230 warnx("%s: not currently mounted", name
);
237 if (checkvfsname(type
, typelist
))
240 (void)memset(&hints
, 0, sizeof hints
);
241 if (!strncmp(type
, MOUNT_NFS
,
242 sizeof(((struct statvfs
*)NULL
)->f_fstypename
))) {
244 /* look for host:mountpoint */
245 if ((delimp
= strrchr(name
, ':')) != NULL
) {
246 int len
= delimp
- name
;
247 hostp
= malloc(len
+ 1);
250 memcpy(hostp
, name
, len
);
253 getaddrinfo(hostp
, NULL
, &hints
, &ai
);
264 (void)printf("%s: unmount from %s\n", name
, mntpt
);
269 if (unmount(mntpt
, fflag
) == -1) {
275 if (ai
!= NULL
&& !(fflag
& MNT_FORCE
)) {
276 clp
= clnt_create(hostp
, RPCPROG_MNT
, RPCMNT_VER1
, "udp");
278 clnt_pcreateerror("Cannot MNT PRC");
281 clp
->cl_auth
= authsys_create_default();
284 clnt_stat
= clnt_call(clp
, RPCMNT_UMOUNT
, xdr_dir
,
285 __UNCONST(name
), xdr_void
, NULL
, try);
286 if (clnt_stat
!= RPC_SUCCESS
) {
287 clnt_perror(clp
, "Bad MNT RPC");
290 auth_destroy(clp
->cl_auth
);
298 getmntname(const char *name
, mntwhat what
, char **type
)
300 static struct statvfs
*mntbuf
;
304 if (mntbuf
== NULL
&&
305 (mntsize
= getmntinfo(&mntbuf
, MNT_NOWAIT
)) == 0) {
309 for (i
= mntsize
- 1; i
>= 0; i
--) {
310 if ((what
== MNTON
) && !strcmp(mntbuf
[i
].f_mntfromname
, name
)) {
312 *type
= mntbuf
[i
].f_fstypename
;
313 return (mntbuf
[i
].f_mntonname
);
315 if ((what
== MNTFROM
) && !strcmp(mntbuf
[i
].f_mntonname
, name
)) {
317 *type
= mntbuf
[i
].f_fstypename
;
318 return (mntbuf
[i
].f_mntfromname
);
326 sacmp(const struct sockaddr
*sa1
, const struct sockaddr
*sa2
)
331 if (sa1
->sa_family
!= sa2
->sa_family
)
334 switch (sa1
->sa_family
) {
336 p1
= &((const struct sockaddr_in
*)sa1
)->sin_addr
;
337 p2
= &((const struct sockaddr_in
*)sa2
)->sin_addr
;
341 p1
= &((const struct sockaddr_in6
*)sa1
)->sin6_addr
;
342 p2
= &((const struct sockaddr_in6
*)sa2
)->sin6_addr
;
344 if (((const struct sockaddr_in6
*)sa1
)->sin6_scope_id
!=
345 ((const struct sockaddr_in6
*)sa2
)->sin6_scope_id
)
352 return memcmp(p1
, p2
, len
);
356 namematch(const struct addrinfo
*ai
)
358 struct addrinfo
*aip
;
360 if (nfshost
== NULL
|| nfshost_ai
== NULL
)
365 while (aip
!= NULL
) {
366 if (sacmp(ai
->ai_addr
, aip
->ai_addr
) == 0)
377 * xdr routines for mount rpc's
380 xdr_dir(XDR
*xdrsp
, char *dirp
)
382 return xdr_string(xdrsp
, &dirp
, RPCMNT_PATHLEN
);
390 (void)fprintf(stderr
,
391 "Usage: %s [-fR] special | node\n", getprogname());
393 (void)fprintf(stderr
,
394 "Usage: %s [-fvFR] [-t fstypelist] special | node\n"
395 "\t %s -a[fvF] [-h host] [-t fstypelist]\n", getprogname(),