xref: /freebsd-src/usr.sbin/autofs/automount.c (revision 4d65a7c6951cea0333f1a0c1b32c38489cdfa6c5)
13914ddf8SEdward Tomasz Napierala /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3abdd3945SEdward Tomasz Napierala  *
43914ddf8SEdward Tomasz Napierala  * Copyright (c) 2014 The FreeBSD Foundation
53914ddf8SEdward Tomasz Napierala  *
63914ddf8SEdward Tomasz Napierala  * This software was developed by Edward Tomasz Napierala under sponsorship
73914ddf8SEdward Tomasz Napierala  * from the FreeBSD Foundation.
83914ddf8SEdward Tomasz Napierala  *
93914ddf8SEdward Tomasz Napierala  * Redistribution and use in source and binary forms, with or without
103914ddf8SEdward Tomasz Napierala  * modification, are permitted provided that the following conditions
113914ddf8SEdward Tomasz Napierala  * are met:
123914ddf8SEdward Tomasz Napierala  * 1. Redistributions of source code must retain the above copyright
133914ddf8SEdward Tomasz Napierala  *    notice, this list of conditions and the following disclaimer.
143914ddf8SEdward Tomasz Napierala  * 2. Redistributions in binary form must reproduce the above copyright
153914ddf8SEdward Tomasz Napierala  *    notice, this list of conditions and the following disclaimer in the
163914ddf8SEdward Tomasz Napierala  *    documentation and/or other materials provided with the distribution.
173914ddf8SEdward Tomasz Napierala  *
183914ddf8SEdward Tomasz Napierala  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
193914ddf8SEdward Tomasz Napierala  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
203914ddf8SEdward Tomasz Napierala  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
213914ddf8SEdward Tomasz Napierala  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
223914ddf8SEdward Tomasz Napierala  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
233914ddf8SEdward Tomasz Napierala  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
243914ddf8SEdward Tomasz Napierala  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
253914ddf8SEdward Tomasz Napierala  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
263914ddf8SEdward Tomasz Napierala  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
273914ddf8SEdward Tomasz Napierala  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
283914ddf8SEdward Tomasz Napierala  * SUCH DAMAGE.
293914ddf8SEdward Tomasz Napierala  *
303914ddf8SEdward Tomasz Napierala  */
313914ddf8SEdward Tomasz Napierala 
323914ddf8SEdward Tomasz Napierala #include <sys/types.h>
333914ddf8SEdward Tomasz Napierala #include <sys/time.h>
343914ddf8SEdward Tomasz Napierala #include <sys/ioctl.h>
353914ddf8SEdward Tomasz Napierala #include <sys/param.h>
363914ddf8SEdward Tomasz Napierala #include <sys/linker.h>
373914ddf8SEdward Tomasz Napierala #include <sys/mount.h>
383914ddf8SEdward Tomasz Napierala #include <sys/socket.h>
393914ddf8SEdward Tomasz Napierala #include <sys/stat.h>
403914ddf8SEdward Tomasz Napierala #include <sys/wait.h>
413914ddf8SEdward Tomasz Napierala #include <sys/utsname.h>
423914ddf8SEdward Tomasz Napierala #include <assert.h>
433914ddf8SEdward Tomasz Napierala #include <ctype.h>
443914ddf8SEdward Tomasz Napierala #include <errno.h>
453914ddf8SEdward Tomasz Napierala #include <fcntl.h>
463914ddf8SEdward Tomasz Napierala #include <libgen.h>
47592d6e85SEdward Tomasz Napierala #include <libutil.h>
483914ddf8SEdward Tomasz Napierala #include <netdb.h>
493914ddf8SEdward Tomasz Napierala #include <signal.h>
503914ddf8SEdward Tomasz Napierala #include <stdbool.h>
513914ddf8SEdward Tomasz Napierala #include <stdint.h>
523914ddf8SEdward Tomasz Napierala #include <stdio.h>
533914ddf8SEdward Tomasz Napierala #include <stdlib.h>
543914ddf8SEdward Tomasz Napierala #include <string.h>
553914ddf8SEdward Tomasz Napierala #include <unistd.h>
563914ddf8SEdward Tomasz Napierala 
573914ddf8SEdward Tomasz Napierala #include "common.h"
583914ddf8SEdward Tomasz Napierala #include "mntopts.h"
593914ddf8SEdward Tomasz Napierala 
603914ddf8SEdward Tomasz Napierala static int
unmount_by_statfs(const struct statfs * sb,bool force)613914ddf8SEdward Tomasz Napierala unmount_by_statfs(const struct statfs *sb, bool force)
623914ddf8SEdward Tomasz Napierala {
633914ddf8SEdward Tomasz Napierala 	char *fsid_str;
643914ddf8SEdward Tomasz Napierala 	int error, ret, flags;
653914ddf8SEdward Tomasz Napierala 
663914ddf8SEdward Tomasz Napierala 	ret = asprintf(&fsid_str, "FSID:%d:%d",
673914ddf8SEdward Tomasz Napierala 	    sb->f_fsid.val[0], sb->f_fsid.val[1]);
683914ddf8SEdward Tomasz Napierala 	if (ret < 0)
693914ddf8SEdward Tomasz Napierala 		log_err(1, "asprintf");
703914ddf8SEdward Tomasz Napierala 
713914ddf8SEdward Tomasz Napierala 	log_debugx("unmounting %s using %s", sb->f_mntonname, fsid_str);
723914ddf8SEdward Tomasz Napierala 
733914ddf8SEdward Tomasz Napierala 	flags = MNT_BYFSID;
743914ddf8SEdward Tomasz Napierala 	if (force)
753914ddf8SEdward Tomasz Napierala 		flags |= MNT_FORCE;
763914ddf8SEdward Tomasz Napierala 	error = unmount(fsid_str, flags);
773914ddf8SEdward Tomasz Napierala 	free(fsid_str);
783914ddf8SEdward Tomasz Napierala 	if (error != 0)
793914ddf8SEdward Tomasz Napierala 		log_warn("cannot unmount %s", sb->f_mntonname);
8088e531f3SRobert Wing 	else
8188e531f3SRobert Wing 		rpc_umntall();
823914ddf8SEdward Tomasz Napierala 
833914ddf8SEdward Tomasz Napierala 	return (error);
843914ddf8SEdward Tomasz Napierala }
853914ddf8SEdward Tomasz Napierala 
863914ddf8SEdward Tomasz Napierala static const struct statfs *
find_statfs(const struct statfs * mntbuf,int nitems,const char * mountpoint)873914ddf8SEdward Tomasz Napierala find_statfs(const struct statfs *mntbuf, int nitems, const char *mountpoint)
883914ddf8SEdward Tomasz Napierala {
893914ddf8SEdward Tomasz Napierala 	int i;
903914ddf8SEdward Tomasz Napierala 
913914ddf8SEdward Tomasz Napierala 	for (i = 0; i < nitems; i++) {
923914ddf8SEdward Tomasz Napierala 		if (strcmp(mntbuf[i].f_mntonname, mountpoint) == 0)
933914ddf8SEdward Tomasz Napierala 			return (mntbuf + i);
943914ddf8SEdward Tomasz Napierala 	}
953914ddf8SEdward Tomasz Napierala 
963914ddf8SEdward Tomasz Napierala 	return (NULL);
973914ddf8SEdward Tomasz Napierala }
983914ddf8SEdward Tomasz Napierala 
993914ddf8SEdward Tomasz Napierala static void
mount_autofs(const char * from,const char * fspath,const char * options,const char * prefix)1003914ddf8SEdward Tomasz Napierala mount_autofs(const char *from, const char *fspath, const char *options,
1013914ddf8SEdward Tomasz Napierala     const char *prefix)
1023914ddf8SEdward Tomasz Napierala {
1033914ddf8SEdward Tomasz Napierala 	struct iovec *iov = NULL;
1043914ddf8SEdward Tomasz Napierala 	char errmsg[255];
1053914ddf8SEdward Tomasz Napierala 	int error, iovlen = 0;
1063914ddf8SEdward Tomasz Napierala 
1073914ddf8SEdward Tomasz Napierala 	create_directory(fspath);
1083914ddf8SEdward Tomasz Napierala 
1093914ddf8SEdward Tomasz Napierala 	log_debugx("mounting %s on %s, prefix \"%s\", options \"%s\"",
1103914ddf8SEdward Tomasz Napierala 	    from, fspath, prefix, options);
1113914ddf8SEdward Tomasz Napierala 	memset(errmsg, 0, sizeof(errmsg));
1123914ddf8SEdward Tomasz Napierala 
1133914ddf8SEdward Tomasz Napierala 	build_iovec(&iov, &iovlen, "fstype",
1143914ddf8SEdward Tomasz Napierala 	    __DECONST(void *, "autofs"), (size_t)-1);
1153914ddf8SEdward Tomasz Napierala 	build_iovec(&iov, &iovlen, "fspath",
1163914ddf8SEdward Tomasz Napierala 	    __DECONST(void *, fspath), (size_t)-1);
1173914ddf8SEdward Tomasz Napierala 	build_iovec(&iov, &iovlen, "from",
1183914ddf8SEdward Tomasz Napierala 	    __DECONST(void *, from), (size_t)-1);
1193914ddf8SEdward Tomasz Napierala 	build_iovec(&iov, &iovlen, "errmsg",
1203914ddf8SEdward Tomasz Napierala 	    errmsg, sizeof(errmsg));
1213914ddf8SEdward Tomasz Napierala 
1223914ddf8SEdward Tomasz Napierala 	/*
1233914ddf8SEdward Tomasz Napierala 	 * Append the options and mountpoint defined in auto_master(5);
1243914ddf8SEdward Tomasz Napierala 	 * this way automountd(8) does not need to parse it.
1253914ddf8SEdward Tomasz Napierala 	 */
1263914ddf8SEdward Tomasz Napierala 	build_iovec(&iov, &iovlen, "master_options",
1273914ddf8SEdward Tomasz Napierala 	    __DECONST(void *, options), (size_t)-1);
1283914ddf8SEdward Tomasz Napierala 	build_iovec(&iov, &iovlen, "master_prefix",
1293914ddf8SEdward Tomasz Napierala 	    __DECONST(void *, prefix), (size_t)-1);
1303914ddf8SEdward Tomasz Napierala 
1313914ddf8SEdward Tomasz Napierala 	error = nmount(iov, iovlen, 0);
1323914ddf8SEdward Tomasz Napierala 	if (error != 0) {
1333914ddf8SEdward Tomasz Napierala 		if (*errmsg != '\0') {
1343914ddf8SEdward Tomasz Napierala 			log_err(1, "cannot mount %s on %s: %s",
1353914ddf8SEdward Tomasz Napierala 			    from, fspath, errmsg);
1363914ddf8SEdward Tomasz Napierala 		} else {
1373914ddf8SEdward Tomasz Napierala 			log_err(1, "cannot mount %s on %s", from, fspath);
1383914ddf8SEdward Tomasz Napierala 		}
1393914ddf8SEdward Tomasz Napierala 	}
1403914ddf8SEdward Tomasz Napierala }
1413914ddf8SEdward Tomasz Napierala 
1423914ddf8SEdward Tomasz Napierala static void
mount_if_not_already(const struct node * n,const char * map,const char * options,const char * prefix,const struct statfs * mntbuf,int nitems)14361d75c32SEdward Tomasz Napierala mount_if_not_already(const struct node *n, const char *map, const char *options,
14461d75c32SEdward Tomasz Napierala     const char *prefix, const struct statfs *mntbuf, int nitems)
1453914ddf8SEdward Tomasz Napierala {
1463914ddf8SEdward Tomasz Napierala 	const struct statfs *sb;
1473914ddf8SEdward Tomasz Napierala 	char *mountpoint;
1483914ddf8SEdward Tomasz Napierala 	char *from;
1493914ddf8SEdward Tomasz Napierala 	int ret;
1503914ddf8SEdward Tomasz Napierala 
1513914ddf8SEdward Tomasz Napierala 	ret = asprintf(&from, "map %s", map);
1523914ddf8SEdward Tomasz Napierala 	if (ret < 0)
1533914ddf8SEdward Tomasz Napierala 		log_err(1, "asprintf");
1543914ddf8SEdward Tomasz Napierala 
1553914ddf8SEdward Tomasz Napierala 	mountpoint = node_path(n);
1563914ddf8SEdward Tomasz Napierala 	sb = find_statfs(mntbuf, nitems, mountpoint);
1573914ddf8SEdward Tomasz Napierala 	if (sb != NULL) {
1583914ddf8SEdward Tomasz Napierala 		if (strcmp(sb->f_fstypename, "autofs") != 0) {
1593914ddf8SEdward Tomasz Napierala 			log_debugx("unknown filesystem mounted "
1603914ddf8SEdward Tomasz Napierala 			    "on %s; mounting", mountpoint);
1613914ddf8SEdward Tomasz Napierala 			/*
1623914ddf8SEdward Tomasz Napierala 			 * XXX: Compare options and 'from',
1633914ddf8SEdward Tomasz Napierala 			 *	and update the mount if necessary.
1643914ddf8SEdward Tomasz Napierala 			 */
1653914ddf8SEdward Tomasz Napierala 		} else {
1663914ddf8SEdward Tomasz Napierala 			log_debugx("autofs already mounted "
1673914ddf8SEdward Tomasz Napierala 			    "on %s", mountpoint);
1683914ddf8SEdward Tomasz Napierala 			free(from);
1693914ddf8SEdward Tomasz Napierala 			free(mountpoint);
1703914ddf8SEdward Tomasz Napierala 			return;
1713914ddf8SEdward Tomasz Napierala 		}
1723914ddf8SEdward Tomasz Napierala 	} else {
1733914ddf8SEdward Tomasz Napierala 		log_debugx("nothing mounted on %s; mounting",
1743914ddf8SEdward Tomasz Napierala 		    mountpoint);
1753914ddf8SEdward Tomasz Napierala 	}
1763914ddf8SEdward Tomasz Napierala 
17761d75c32SEdward Tomasz Napierala 	mount_autofs(from, mountpoint, options, prefix);
1783914ddf8SEdward Tomasz Napierala 	free(from);
1793914ddf8SEdward Tomasz Napierala 	free(mountpoint);
1803914ddf8SEdward Tomasz Napierala }
1813914ddf8SEdward Tomasz Napierala 
1823914ddf8SEdward Tomasz Napierala static void
mount_unmount(struct node * root)1833914ddf8SEdward Tomasz Napierala mount_unmount(struct node *root)
1843914ddf8SEdward Tomasz Napierala {
1853914ddf8SEdward Tomasz Napierala 	struct statfs *mntbuf;
18661d75c32SEdward Tomasz Napierala 	struct node *n, *n2;
1873914ddf8SEdward Tomasz Napierala 	int i, nitems;
1883914ddf8SEdward Tomasz Napierala 
1893914ddf8SEdward Tomasz Napierala 	nitems = getmntinfo(&mntbuf, MNT_WAIT);
1903914ddf8SEdward Tomasz Napierala 	if (nitems <= 0)
1913914ddf8SEdward Tomasz Napierala 		log_err(1, "getmntinfo");
1923914ddf8SEdward Tomasz Napierala 
1933914ddf8SEdward Tomasz Napierala 	log_debugx("unmounting stale autofs mounts");
1943914ddf8SEdward Tomasz Napierala 
1953914ddf8SEdward Tomasz Napierala 	for (i = 0; i < nitems; i++) {
1963914ddf8SEdward Tomasz Napierala 		if (strcmp(mntbuf[i].f_fstypename, "autofs") != 0) {
1973914ddf8SEdward Tomasz Napierala 			log_debugx("skipping %s, filesystem type is not autofs",
1983914ddf8SEdward Tomasz Napierala 			    mntbuf[i].f_mntonname);
1993914ddf8SEdward Tomasz Napierala 			continue;
2003914ddf8SEdward Tomasz Napierala 		}
2013914ddf8SEdward Tomasz Napierala 
2023914ddf8SEdward Tomasz Napierala 		n = node_find(root, mntbuf[i].f_mntonname);
2033914ddf8SEdward Tomasz Napierala 		if (n != NULL) {
2043914ddf8SEdward Tomasz Napierala 			log_debugx("leaving autofs mounted on %s",
2053914ddf8SEdward Tomasz Napierala 			    mntbuf[i].f_mntonname);
2063914ddf8SEdward Tomasz Napierala 			continue;
2073914ddf8SEdward Tomasz Napierala 		}
2083914ddf8SEdward Tomasz Napierala 
2093914ddf8SEdward Tomasz Napierala 		log_debugx("autofs mounted on %s not found "
2103914ddf8SEdward Tomasz Napierala 		    "in new configuration; unmounting", mntbuf[i].f_mntonname);
2113914ddf8SEdward Tomasz Napierala 		unmount_by_statfs(&(mntbuf[i]), false);
2123914ddf8SEdward Tomasz Napierala 	}
2133914ddf8SEdward Tomasz Napierala 
2143914ddf8SEdward Tomasz Napierala 	log_debugx("mounting new autofs mounts");
2153914ddf8SEdward Tomasz Napierala 
2163914ddf8SEdward Tomasz Napierala 	TAILQ_FOREACH(n, &root->n_children, n_next) {
2173914ddf8SEdward Tomasz Napierala 		if (!node_is_direct_map(n)) {
21861d75c32SEdward Tomasz Napierala 			mount_if_not_already(n, n->n_map, n->n_options,
21961d75c32SEdward Tomasz Napierala 			    n->n_key, mntbuf, nitems);
2203914ddf8SEdward Tomasz Napierala 			continue;
2213914ddf8SEdward Tomasz Napierala 		}
2223914ddf8SEdward Tomasz Napierala 
2233914ddf8SEdward Tomasz Napierala 		TAILQ_FOREACH(n2, &n->n_children, n_next) {
22461d75c32SEdward Tomasz Napierala 			mount_if_not_already(n2, n->n_map, n->n_options,
22561d75c32SEdward Tomasz Napierala 			    "/", mntbuf, nitems);
2263914ddf8SEdward Tomasz Napierala 		}
2273914ddf8SEdward Tomasz Napierala 	}
2283914ddf8SEdward Tomasz Napierala }
2293914ddf8SEdward Tomasz Napierala 
2303914ddf8SEdward Tomasz Napierala static void
flush_autofs(const char * fspath,const fsid_t * fsid)231*56c44bd9SKonstantin Belousov flush_autofs(const char *fspath, const fsid_t *fsid)
232e3d5f1feSEdward Tomasz Napierala {
233e3d5f1feSEdward Tomasz Napierala 	struct iovec *iov = NULL;
234e3d5f1feSEdward Tomasz Napierala 	char errmsg[255];
235e3d5f1feSEdward Tomasz Napierala 	int error, iovlen = 0;
236e3d5f1feSEdward Tomasz Napierala 
237e3d5f1feSEdward Tomasz Napierala 	log_debugx("flushing %s", fspath);
238e3d5f1feSEdward Tomasz Napierala 	memset(errmsg, 0, sizeof(errmsg));
239e3d5f1feSEdward Tomasz Napierala 
240e3d5f1feSEdward Tomasz Napierala 	build_iovec(&iov, &iovlen, "fstype",
241e3d5f1feSEdward Tomasz Napierala 	    __DECONST(void *, "autofs"), (size_t)-1);
242e3d5f1feSEdward Tomasz Napierala 	build_iovec(&iov, &iovlen, "fspath",
243e3d5f1feSEdward Tomasz Napierala 	    __DECONST(void *, fspath), (size_t)-1);
244*56c44bd9SKonstantin Belousov 	build_iovec(&iov, &iovlen, "fsid",
245*56c44bd9SKonstantin Belousov 	    __DECONST(void *, fsid), sizeof(*fsid));
246e3d5f1feSEdward Tomasz Napierala 	build_iovec(&iov, &iovlen, "errmsg",
247e3d5f1feSEdward Tomasz Napierala 	    errmsg, sizeof(errmsg));
248e3d5f1feSEdward Tomasz Napierala 
249e3d5f1feSEdward Tomasz Napierala 	error = nmount(iov, iovlen, MNT_UPDATE);
250e3d5f1feSEdward Tomasz Napierala 	if (error != 0) {
251e3d5f1feSEdward Tomasz Napierala 		if (*errmsg != '\0') {
252e3d5f1feSEdward Tomasz Napierala 			log_err(1, "cannot flush %s: %s",
253e3d5f1feSEdward Tomasz Napierala 			    fspath, errmsg);
254e3d5f1feSEdward Tomasz Napierala 		} else {
255e3d5f1feSEdward Tomasz Napierala 			log_err(1, "cannot flush %s", fspath);
256e3d5f1feSEdward Tomasz Napierala 		}
257e3d5f1feSEdward Tomasz Napierala 	}
258e3d5f1feSEdward Tomasz Napierala }
259e3d5f1feSEdward Tomasz Napierala 
260e3d5f1feSEdward Tomasz Napierala static void
flush_caches(void)261e3d5f1feSEdward Tomasz Napierala flush_caches(void)
262e3d5f1feSEdward Tomasz Napierala {
263e3d5f1feSEdward Tomasz Napierala 	struct statfs *mntbuf;
26421b8e363SAndrew Gierth 	struct statfs statbuf;
265e3d5f1feSEdward Tomasz Napierala 	int i, nitems;
266e3d5f1feSEdward Tomasz Napierala 
267e3d5f1feSEdward Tomasz Napierala 	nitems = getmntinfo(&mntbuf, MNT_WAIT);
268e3d5f1feSEdward Tomasz Napierala 	if (nitems <= 0)
269e3d5f1feSEdward Tomasz Napierala 		log_err(1, "getmntinfo");
270e3d5f1feSEdward Tomasz Napierala 
271e3d5f1feSEdward Tomasz Napierala 	log_debugx("flushing autofs caches");
272e3d5f1feSEdward Tomasz Napierala 
273e3d5f1feSEdward Tomasz Napierala 	for (i = 0; i < nitems; i++) {
274e3d5f1feSEdward Tomasz Napierala 		if (strcmp(mntbuf[i].f_fstypename, "autofs") != 0) {
275e3d5f1feSEdward Tomasz Napierala 			log_debugx("skipping %s, filesystem type is not autofs",
276e3d5f1feSEdward Tomasz Napierala 			    mntbuf[i].f_mntonname);
277e3d5f1feSEdward Tomasz Napierala 			continue;
278e3d5f1feSEdward Tomasz Napierala 		}
27921b8e363SAndrew Gierth 		/*
28021b8e363SAndrew Gierth 		 * A direct map mountpoint may have been mounted over, in
28121b8e363SAndrew Gierth 		 * which case we can't MNT_UPDATE it. There's an obvious race
28221b8e363SAndrew Gierth 		 * condition remaining here, but that has to be fixed in the
28321b8e363SAndrew Gierth 		 * kernel.
28421b8e363SAndrew Gierth 		 */
28521b8e363SAndrew Gierth 		if (statfs(mntbuf[i].f_mntonname, &statbuf) != 0) {
28621b8e363SAndrew Gierth 			log_err(1, "cannot statfs %s", mntbuf[i].f_mntonname);
28721b8e363SAndrew Gierth 			continue;
28821b8e363SAndrew Gierth 		}
28921b8e363SAndrew Gierth 		if (strcmp(statbuf.f_fstypename, "autofs") != 0) {
29021b8e363SAndrew Gierth 			log_debugx("skipping %s, filesystem type is not autofs",
29121b8e363SAndrew Gierth 			    mntbuf[i].f_mntonname);
29221b8e363SAndrew Gierth 			continue;
29321b8e363SAndrew Gierth 		}
294e3d5f1feSEdward Tomasz Napierala 
295*56c44bd9SKonstantin Belousov 		flush_autofs(mntbuf[i].f_mntonname, &statbuf.f_fsid);
296e3d5f1feSEdward Tomasz Napierala 	}
297e3d5f1feSEdward Tomasz Napierala }
298e3d5f1feSEdward Tomasz Napierala 
299e3d5f1feSEdward Tomasz Napierala static void
unmount_automounted(bool force)3003914ddf8SEdward Tomasz Napierala unmount_automounted(bool force)
3013914ddf8SEdward Tomasz Napierala {
3023914ddf8SEdward Tomasz Napierala 	struct statfs *mntbuf;
3033914ddf8SEdward Tomasz Napierala 	int i, nitems;
3043914ddf8SEdward Tomasz Napierala 
3053914ddf8SEdward Tomasz Napierala 	nitems = getmntinfo(&mntbuf, MNT_WAIT);
3063914ddf8SEdward Tomasz Napierala 	if (nitems <= 0)
3073914ddf8SEdward Tomasz Napierala 		log_err(1, "getmntinfo");
3083914ddf8SEdward Tomasz Napierala 
3093914ddf8SEdward Tomasz Napierala 	log_debugx("unmounting automounted filesystems");
3103914ddf8SEdward Tomasz Napierala 
3113914ddf8SEdward Tomasz Napierala 	for (i = 0; i < nitems; i++) {
3123914ddf8SEdward Tomasz Napierala 		if (strcmp(mntbuf[i].f_fstypename, "autofs") == 0) {
3133914ddf8SEdward Tomasz Napierala 			log_debugx("skipping %s, filesystem type is autofs",
3143914ddf8SEdward Tomasz Napierala 			    mntbuf[i].f_mntonname);
3153914ddf8SEdward Tomasz Napierala 			continue;
3163914ddf8SEdward Tomasz Napierala 		}
3173914ddf8SEdward Tomasz Napierala 
3183914ddf8SEdward Tomasz Napierala 		if ((mntbuf[i].f_flags & MNT_AUTOMOUNTED) == 0) {
3193914ddf8SEdward Tomasz Napierala 			log_debugx("skipping %s, not automounted",
3203914ddf8SEdward Tomasz Napierala 			    mntbuf[i].f_mntonname);
3213914ddf8SEdward Tomasz Napierala 			continue;
3223914ddf8SEdward Tomasz Napierala 		}
3233914ddf8SEdward Tomasz Napierala 
3243914ddf8SEdward Tomasz Napierala 		unmount_by_statfs(&(mntbuf[i]), force);
3253914ddf8SEdward Tomasz Napierala 	}
3263914ddf8SEdward Tomasz Napierala }
3273914ddf8SEdward Tomasz Napierala 
3283914ddf8SEdward Tomasz Napierala static void
usage_automount(void)3293914ddf8SEdward Tomasz Napierala usage_automount(void)
3303914ddf8SEdward Tomasz Napierala {
3313914ddf8SEdward Tomasz Napierala 
332e3d5f1feSEdward Tomasz Napierala 	fprintf(stderr, "usage: automount [-D name=value][-o opts][-Lcfuv]\n");
3333914ddf8SEdward Tomasz Napierala 	exit(1);
3343914ddf8SEdward Tomasz Napierala }
3353914ddf8SEdward Tomasz Napierala 
3363914ddf8SEdward Tomasz Napierala int
main_automount(int argc,char ** argv)3373914ddf8SEdward Tomasz Napierala main_automount(int argc, char **argv)
3383914ddf8SEdward Tomasz Napierala {
3393914ddf8SEdward Tomasz Napierala 	struct node *root;
3403914ddf8SEdward Tomasz Napierala 	int ch, debug = 0, show_maps = 0;
3413914ddf8SEdward Tomasz Napierala 	char *options = NULL;
342e3d5f1feSEdward Tomasz Napierala 	bool do_unmount = false, force_unmount = false, flush = false;
3433914ddf8SEdward Tomasz Napierala 
3443914ddf8SEdward Tomasz Napierala 	/*
3453914ddf8SEdward Tomasz Napierala 	 * Note that in automount(8), the only purpose of variable
3463914ddf8SEdward Tomasz Napierala 	 * handling is to aid in debugging maps (automount -L).
3473914ddf8SEdward Tomasz Napierala 	 */
3483914ddf8SEdward Tomasz Napierala 	defined_init();
3493914ddf8SEdward Tomasz Napierala 
350e3d5f1feSEdward Tomasz Napierala 	while ((ch = getopt(argc, argv, "D:Lfco:uv")) != -1) {
3513914ddf8SEdward Tomasz Napierala 		switch (ch) {
3523914ddf8SEdward Tomasz Napierala 		case 'D':
3533914ddf8SEdward Tomasz Napierala 			defined_parse_and_add(optarg);
3543914ddf8SEdward Tomasz Napierala 			break;
3553914ddf8SEdward Tomasz Napierala 		case 'L':
3563914ddf8SEdward Tomasz Napierala 			show_maps++;
3573914ddf8SEdward Tomasz Napierala 			break;
358e3d5f1feSEdward Tomasz Napierala 		case 'c':
359e3d5f1feSEdward Tomasz Napierala 			flush = true;
360e3d5f1feSEdward Tomasz Napierala 			break;
3613914ddf8SEdward Tomasz Napierala 		case 'f':
3623914ddf8SEdward Tomasz Napierala 			force_unmount = true;
3633914ddf8SEdward Tomasz Napierala 			break;
3643914ddf8SEdward Tomasz Napierala 		case 'o':
3656d8e60c3SEdward Tomasz Napierala 			options = concat(options, ',', optarg);
3663914ddf8SEdward Tomasz Napierala 			break;
3673914ddf8SEdward Tomasz Napierala 		case 'u':
3683914ddf8SEdward Tomasz Napierala 			do_unmount = true;
3693914ddf8SEdward Tomasz Napierala 			break;
3703914ddf8SEdward Tomasz Napierala 		case 'v':
3713914ddf8SEdward Tomasz Napierala 			debug++;
3723914ddf8SEdward Tomasz Napierala 			break;
3733914ddf8SEdward Tomasz Napierala 		case '?':
3743914ddf8SEdward Tomasz Napierala 		default:
3753914ddf8SEdward Tomasz Napierala 			usage_automount();
3763914ddf8SEdward Tomasz Napierala 		}
3773914ddf8SEdward Tomasz Napierala 	}
3783914ddf8SEdward Tomasz Napierala 	argc -= optind;
3793914ddf8SEdward Tomasz Napierala 	if (argc != 0)
3803914ddf8SEdward Tomasz Napierala 		usage_automount();
3813914ddf8SEdward Tomasz Napierala 
3823914ddf8SEdward Tomasz Napierala 	if (force_unmount && !do_unmount)
3833914ddf8SEdward Tomasz Napierala 		usage_automount();
3843914ddf8SEdward Tomasz Napierala 
3853914ddf8SEdward Tomasz Napierala 	log_init(debug);
3863914ddf8SEdward Tomasz Napierala 
387e3d5f1feSEdward Tomasz Napierala 	if (flush) {
388e3d5f1feSEdward Tomasz Napierala 		flush_caches();
389e3d5f1feSEdward Tomasz Napierala 		return (0);
390e3d5f1feSEdward Tomasz Napierala 	}
391e3d5f1feSEdward Tomasz Napierala 
3923914ddf8SEdward Tomasz Napierala 	if (do_unmount) {
3933914ddf8SEdward Tomasz Napierala 		unmount_automounted(force_unmount);
3943914ddf8SEdward Tomasz Napierala 		return (0);
3953914ddf8SEdward Tomasz Napierala 	}
3963914ddf8SEdward Tomasz Napierala 
3973914ddf8SEdward Tomasz Napierala 	root = node_new_root();
3983914ddf8SEdward Tomasz Napierala 	parse_master(root, AUTO_MASTER_PATH);
3993914ddf8SEdward Tomasz Napierala 
4003914ddf8SEdward Tomasz Napierala 	if (show_maps) {
4013914ddf8SEdward Tomasz Napierala 		if (show_maps > 1) {
4023914ddf8SEdward Tomasz Napierala 			node_expand_indirect_maps(root);
4033914ddf8SEdward Tomasz Napierala 			node_expand_ampersand(root, NULL);
4043914ddf8SEdward Tomasz Napierala 		}
4053914ddf8SEdward Tomasz Napierala 		node_expand_defined(root);
4068ee4f5efSEdward Tomasz Napierala 		node_print(root, options);
4073914ddf8SEdward Tomasz Napierala 		return (0);
4083914ddf8SEdward Tomasz Napierala 	}
4093914ddf8SEdward Tomasz Napierala 
4103914ddf8SEdward Tomasz Napierala 	mount_unmount(root);
4113914ddf8SEdward Tomasz Napierala 
4123914ddf8SEdward Tomasz Napierala 	return (0);
4133914ddf8SEdward Tomasz Napierala }
414