update to use vfslist from mount; cleanups for vfsconf
[unix-history] / usr / src / sbin / umount / umount.c
CommitLineData
0fc6e47b 1/*-
3d3434ed
KB
2 * Copyright (c) 1980, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
724216f4 4 *
0fc6e47b 5 * %sccs.include.redist.c%
8c5eec2f
DF
6 */
7
8#ifndef lint
3d3434ed
KB
9static char copyright[] =
10"@(#) Copyright (c) 1980, 1989, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
724216f4 12#endif /* not lint */
8c5eec2f 13
7a6d69cb 14#ifndef lint
ff880b25 15static char sccsid[] = "@(#)umount.c 8.7 (Berkeley) %G%";
724216f4 16#endif /* not lint */
15de4e1e 17
7a6d69cb 18#include <sys/param.h>
4efd8d38 19#include <sys/stat.h>
71799463 20#include <sys/mount.h>
71799463
KM
21#include <sys/time.h>
22#include <sys/socket.h>
23#include <sys/socketvar.h>
d5f8b17b 24
71799463
KM
25#include <netdb.h>
26#include <rpc/rpc.h>
27#include <rpc/pmap_clnt.h>
28#include <rpc/pmap_prot.h>
29#include <nfs/rpcv2.h>
896b9bf5 30
3c64732d 31#include <err.h>
896b9bf5
KB
32#include <fstab.h>
33#include <stdio.h>
3c64732d 34#include <stdlib.h>
896b9bf5 35#include <string.h>
3c64732d 36#include <unistd.h>
cfbe3c25 37
3c64732d 38typedef enum { MNTON, MNTFROM } mntwhat;
651dda56 39
ff880b25 40int fake, fflag, vflag;
d5f8b17b 41char *nfshost;
3c64732d 42
ff880b25
KM
43int checkvfsname __P((const char *, char **));
44char *getmntname __P((char *, mntwhat, char **));
45char **makevfslist __P((char *));
d5f8b17b
KB
46int selected __P((int));
47int namematch __P((struct hostent *));
ff880b25
KM
48int umountall __P((char **));
49int umountfs __P((char *, char **));
d5f8b17b
KB
50void usage __P((void));
51int xdr_dir __P((XDR *, char *));
3c64732d
JSP
52
53int
cfbe3c25 54main(argc, argv)
15de4e1e 55 int argc;
d5f8b17b 56 char *argv[];
cfbe3c25 57{
d5f8b17b 58 int all, ch, errs;
ff880b25 59 char **typelist = NULL;
cfbe3c25 60
d5f8b17b 61 /* Start disks transferring immediately. */
cfbe3c25 62 sync();
d5f8b17b
KB
63
64 all = 0;
65 while ((ch = getopt(argc, argv, "aFfh:t:v")) != EOF)
3c64732d
JSP
66 switch (ch) {
67 case 'a':
d5f8b17b
KB
68 all = 1;
69 break;
70 case 'F':
71 fake = 1;
f6bc1314
KM
72 break;
73 case 'f':
74 fflag = MNT_FORCE;
75 break;
d5f8b17b
KB
76 case 'h': /* -h implies -a. */
77 all = 1;
f6bc1314 78 nfshost = optarg;
f6bc1314 79 break;
3c64732d 80 case 't':
ff880b25
KM
81 if (typelist != NULL)
82 errx(1, "only one -t option may be specified.");
83 typelist = makevfslist(optarg);
3c64732d
JSP
84 break;
85 case 'v':
d5f8b17b 86 vflag = 1;
3c64732d 87 break;
f6bc1314
KM
88 default:
89 usage();
90 /* NOTREACHED */
91 }
92 argc -= optind;
93 argv += optind;
94
d5f8b17b 95 if (argc == 0 && !all || argc != 0 && all)
f6bc1314 96 usage();
3c64732d 97
d5f8b17b
KB
98 /* -h implies "-t nfs" if no -t flag. */
99 if ((nfshost != NULL) && (typelist == NULL))
ff880b25 100 typelist = makevfslist("nfs");
d5f8b17b 101
15de4e1e 102 if (all) {
d5f8b17b
KB
103 if (setfsent() == 0)
104 err(1, "%s", _PATH_FSTAB);
ff880b25 105 errs = umountall(typelist);
d5f8b17b
KB
106 } else
107 for (errs = 0; *argv != NULL; ++argv)
ff880b25 108 if (umountfs(*argv, typelist) != 0)
d5f8b17b
KB
109 errs = 1;
110 exit(errs);
f6bc1314
KM
111}
112
d5f8b17b 113int
ff880b25
KM
114umountall(typelist)
115 char **typelist;
83dfa04a 116{
3c64732d 117 struct fstab *fs;
d5f8b17b
KB
118 int rval, type;
119 char *cp;
ff880b25 120 struct vfsconf vfc;
651dda56 121
d5f8b17b
KB
122 while ((fs = getfsent()) != NULL) {
123 /* Ignore the root. */
651dda56
KM
124 if (strcmp(fs->fs_file, "/") == 0)
125 continue;
d5f8b17b
KB
126 /*
127 * !!!
128 * Historic practice: ignore unknown FSTAB_* fields.
129 */
651dda56
KM
130 if (strcmp(fs->fs_type, FSTAB_RW) &&
131 strcmp(fs->fs_type, FSTAB_RO) &&
132 strcmp(fs->fs_type, FSTAB_RQ))
133 continue;
d5f8b17b 134 /* If an unknown file system type, complain. */
ff880b25 135 if (getvfsbyname(fs->fs_vfstype, &vfc) < 0) {
d5f8b17b
KB
136 warnx("%s: unknown mount type", fs->fs_vfstype);
137 continue;
138 }
ff880b25 139 if (checkvfsname(fs->fs_vfstype, typelist))
d5f8b17b
KB
140 continue;
141
142 /*
143 * We want to unmount the file systems in the reverse order
144 * that they were mounted. So, we save off the file name
145 * in some allocated memory, and then call recursively.
146 */
147 if ((cp = malloc((size_t)strlen(fs->fs_file) + 1)) == NULL)
148 err(1, NULL);
149 (void)strcpy(cp, fs->fs_file);
ff880b25
KM
150 rval = umountall(typelist);
151 return (umountfs(cp, typelist) || rval);
15de4e1e 152 }
d5f8b17b 153 return (0);
83dfa04a 154}
cfbe3c25 155
3c64732d 156int
ff880b25 157umountfs(name, typelist)
15de4e1e 158 char *name;
ff880b25 159 char **typelist;
cfbe3c25 160{
3c64732d 161 enum clnt_stat clnt_stat;
d5f8b17b 162 struct hostent *hp;
71799463 163 struct sockaddr_in saddr;
d5f8b17b 164 struct stat sb;
71799463 165 struct timeval pertry, try;
d5f8b17b 166 CLIENT *clp;
ff880b25
KM
167 int so;
168 char *type, *delimp, *hostp, *mntpt, rname[MAXPATHLEN];
3c64732d
JSP
169
170 if (realpath(name, rname) == NULL) {
171 warn("%s", rname);
b27a0fee 172 return (1);
3c64732d
JSP
173 }
174
175 name = rname;
cfbe3c25 176
d5f8b17b
KB
177 if (stat(name, &sb) < 0) {
178 if (((mntpt = getmntname(name, MNTFROM, &type)) == NULL) &&
179 ((mntpt = getmntname(name, MNTON, &type)) == NULL)) {
3c64732d 180 warnx("%s: not currently mounted", name);
d5f8b17b 181 return (1);
6aa97e2e 182 }
d5f8b17b
KB
183 } else if (S_ISBLK(sb.st_mode)) {
184 if ((mntpt = getmntname(name, MNTON, &type)) == NULL) {
3c64732d 185 warnx("%s: not currently mounted", name);
d5f8b17b 186 return (1);
6aa97e2e 187 }
d5f8b17b 188 } else if (S_ISDIR(sb.st_mode)) {
4efd8d38 189 mntpt = name;
d5f8b17b 190 if ((name = getmntname(mntpt, MNTFROM, &type)) == NULL) {
3c64732d 191 warnx("%s: not currently mounted", mntpt);
d5f8b17b 192 return (1);
6aa97e2e 193 }
4efd8d38 194 } else {
3c64732d 195 warnx("%s: not a directory or special device", name);
d5f8b17b 196 return (1);
cfbe3c25 197 }
f6bc1314 198
ff880b25 199 if (checkvfsname(type, typelist))
b27a0fee 200 return (1);
d5f8b17b 201
24c290cf 202 hp = NULL;
ff880b25 203 if (!strcmp(type, "nfs")) {
24c290cf
JSP
204 if ((delimp = strchr(name, '@')) != NULL) {
205 hostp = delimp + 1;
206 *delimp = '\0';
207 hp = gethostbyname(hostp);
208 *delimp = '@';
209 } else if ((delimp = strchr(name, ':')) != NULL) {
210 *delimp = '\0';
211 hostp = name;
212 hp = gethostbyname(hostp);
213 name = delimp + 1;
214 *delimp = ':';
215 }
216 }
217
d5f8b17b 218 if (!namematch(hp))
b27a0fee 219 return (1);
f6bc1314 220
d5f8b17b
KB
221 if (vflag)
222 (void)printf("%s: unmount from %s\n", name, mntpt);
223 if (fake)
4efd8d38 224 return (0);
d5f8b17b
KB
225
226 if (unmount(mntpt, fflag) < 0) {
227 warn("%s", mntpt);
228 return (1);
4efd8d38 229 }
f6bc1314 230
d5f8b17b 231 if ((hp != NULL) && !(fflag & MNT_FORCE)) {
4efd8d38 232 *delimp = '\0';
d5f8b17b 233 memset(&saddr, 0, sizeof(saddr));
4efd8d38
KM
234 saddr.sin_family = AF_INET;
235 saddr.sin_port = 0;
d5f8b17b 236 memmove(&saddr.sin_addr, hp->h_addr, hp->h_length);
4efd8d38
KM
237 pertry.tv_sec = 3;
238 pertry.tv_usec = 0;
d5f8b17b
KB
239 so = RPC_ANYSOCK;
240 if ((clp = clntudp_create(&saddr,
241 RPCPROG_MNT, RPCMNT_VER1, pertry, &so)) == NULL) {
4efd8d38
KM
242 clnt_pcreateerror("Cannot MNT PRC");
243 return (1);
71799463 244 }
4efd8d38
KM
245 clp->cl_auth = authunix_create_default();
246 try.tv_sec = 20;
247 try.tv_usec = 0;
d5f8b17b
KB
248 clnt_stat = clnt_call(clp,
249 RPCMNT_UMOUNT, xdr_dir, name, xdr_void, (caddr_t)0, try);
4efd8d38
KM
250 if (clnt_stat != RPC_SUCCESS) {
251 clnt_perror(clp, "Bad MNT RPC");
252 return (1);
71799463 253 }
4efd8d38
KM
254 auth_destroy(clp->cl_auth);
255 clnt_destroy(clp);
760b60ac 256 }
d5f8b17b 257 return (0);
cfbe3c25 258}
71799463 259
4efd8d38 260char *
f6bc1314 261getmntname(name, what, type)
4efd8d38 262 char *name;
3c64732d 263 mntwhat what;
ff880b25 264 char **type;
4efd8d38 265{
0c6d0430 266 struct statfs *mntbuf;
d5f8b17b 267 int i, mntsize;
4efd8d38 268
52f4d3d5 269 if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
3c64732d
JSP
270 warn("getmntinfo");
271 return (NULL);
4efd8d38 272 }
4efd8d38 273 for (i = 0; i < mntsize; i++) {
d5f8b17b 274 if ((what == MNTON) && !strcmp(mntbuf[i].f_mntfromname, name)) {
f6bc1314 275 if (type)
ff880b25 276 *type = mntbuf[i].f_fstypename;
4efd8d38 277 return (mntbuf[i].f_mntonname);
f6bc1314 278 }
d5f8b17b 279 if ((what == MNTFROM) && !strcmp(mntbuf[i].f_mntonname, name)) {
f6bc1314 280 if (type)
ff880b25 281 *type = mntbuf[i].f_fstypename;
4efd8d38 282 return (mntbuf[i].f_mntfromname);
f6bc1314 283 }
4efd8d38 284 }
3c64732d 285 return (NULL);
4efd8d38
KM
286}
287
3c64732d 288int
d5f8b17b 289namematch(hp)
f6bc1314 290 struct hostent *hp;
f6bc1314 291{
d5f8b17b 292 char *cp, **np;
f6bc1314 293
d5f8b17b 294 if ((hp == NULL) || (nfshost == NULL))
3c64732d
JSP
295 return (1);
296
f6bc1314 297 if (strcasecmp(nfshost, hp->h_name) == 0)
3c64732d
JSP
298 return (1);
299
d5f8b17b 300 if ((cp = strchr(hp->h_name, '.')) != NULL) {
f6bc1314
KM
301 *cp = '\0';
302 if (strcasecmp(nfshost, hp->h_name) == 0)
3c64732d 303 return (1);
f6bc1314
KM
304 }
305 for (np = hp->h_aliases; *np; np++) {
306 if (strcasecmp(nfshost, *np) == 0)
3c64732d 307 return (1);
d5f8b17b 308 if ((cp = strchr(*np, '.')) != NULL) {
f6bc1314
KM
309 *cp = '\0';
310 if (strcasecmp(nfshost, *np) == 0)
3c64732d 311 return (1);
f6bc1314
KM
312 }
313 }
3c64732d 314 return (0);
f6bc1314
KM
315}
316
71799463
KM
317/*
318 * xdr routines for mount rpc's
319 */
3c64732d 320int
71799463
KM
321xdr_dir(xdrsp, dirp)
322 XDR *xdrsp;
323 char *dirp;
324{
325 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
326}
d5f8b17b
KB
327
328void
329usage()
330{
331 (void)fprintf(stderr,
332 "usage: %s\n %s\n",
333 "umount [-fv] [-t fstypelist] special | node",
334 "umount -a[fv] [-h host] [-t fstypelist]");
335 exit(1);
336}