xref: /freebsd-src/usr.sbin/autofs/autounmountd.c (revision 4d65a7c6951cea0333f1a0c1b32c38489cdfa6c5)
13914ddf8SEdward Tomasz Napierala /*-
2*4d846d26SWarner 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/event.h>
343914ddf8SEdward Tomasz Napierala #include <sys/mount.h>
353914ddf8SEdward Tomasz Napierala #include <sys/time.h>
363914ddf8SEdward Tomasz Napierala #include <assert.h>
373914ddf8SEdward Tomasz Napierala #include <errno.h>
38592d6e85SEdward Tomasz Napierala #include <libutil.h>
393914ddf8SEdward Tomasz Napierala #include <stdbool.h>
403914ddf8SEdward Tomasz Napierala #include <stdint.h>
413914ddf8SEdward Tomasz Napierala #include <stdio.h>
423914ddf8SEdward Tomasz Napierala #include <stdlib.h>
433914ddf8SEdward Tomasz Napierala #include <string.h>
443914ddf8SEdward Tomasz Napierala #include <unistd.h>
453914ddf8SEdward Tomasz Napierala 
463914ddf8SEdward Tomasz Napierala #include "common.h"
473914ddf8SEdward Tomasz Napierala 
483914ddf8SEdward Tomasz Napierala #define AUTOUNMOUNTD_PIDFILE	"/var/run/autounmountd.pid"
493914ddf8SEdward Tomasz Napierala 
503914ddf8SEdward Tomasz Napierala struct automounted_fs {
513914ddf8SEdward Tomasz Napierala 	TAILQ_ENTRY(automounted_fs)	af_next;
523914ddf8SEdward Tomasz Napierala 	time_t				af_mount_time;
533914ddf8SEdward Tomasz Napierala 	bool				af_mark;
543914ddf8SEdward Tomasz Napierala 	fsid_t				af_fsid;
553914ddf8SEdward Tomasz Napierala 	char				af_mountpoint[MNAMELEN];
563914ddf8SEdward Tomasz Napierala };
573914ddf8SEdward Tomasz Napierala 
583914ddf8SEdward Tomasz Napierala static TAILQ_HEAD(, automounted_fs)	automounted;
593914ddf8SEdward Tomasz Napierala 
603914ddf8SEdward Tomasz Napierala static struct automounted_fs *
automounted_find(fsid_t fsid)613914ddf8SEdward Tomasz Napierala automounted_find(fsid_t fsid)
623914ddf8SEdward Tomasz Napierala {
633914ddf8SEdward Tomasz Napierala 	struct automounted_fs *af;
643914ddf8SEdward Tomasz Napierala 
653914ddf8SEdward Tomasz Napierala 	TAILQ_FOREACH(af, &automounted, af_next) {
66245bfd34SRyan Moeller 		if (fsidcmp(&af->af_fsid, &fsid) == 0)
673914ddf8SEdward Tomasz Napierala 			return (af);
683914ddf8SEdward Tomasz Napierala 	}
693914ddf8SEdward Tomasz Napierala 
703914ddf8SEdward Tomasz Napierala 	return (NULL);
713914ddf8SEdward Tomasz Napierala }
723914ddf8SEdward Tomasz Napierala 
733914ddf8SEdward Tomasz Napierala static struct automounted_fs *
automounted_add(fsid_t fsid,const char * mountpoint)743914ddf8SEdward Tomasz Napierala automounted_add(fsid_t fsid, const char *mountpoint)
753914ddf8SEdward Tomasz Napierala {
763914ddf8SEdward Tomasz Napierala 	struct automounted_fs *af;
773914ddf8SEdward Tomasz Napierala 
7827525377SEdward Tomasz Napierala 	af = calloc(1, sizeof(*af));
793914ddf8SEdward Tomasz Napierala 	if (af == NULL)
803914ddf8SEdward Tomasz Napierala 		log_err(1, "calloc");
813914ddf8SEdward Tomasz Napierala 	af->af_mount_time = time(NULL);
823914ddf8SEdward Tomasz Napierala 	af->af_fsid = fsid;
833914ddf8SEdward Tomasz Napierala 	strlcpy(af->af_mountpoint, mountpoint, sizeof(af->af_mountpoint));
843914ddf8SEdward Tomasz Napierala 
853914ddf8SEdward Tomasz Napierala 	TAILQ_INSERT_TAIL(&automounted, af, af_next);
863914ddf8SEdward Tomasz Napierala 
873914ddf8SEdward Tomasz Napierala 	return (af);
883914ddf8SEdward Tomasz Napierala }
893914ddf8SEdward Tomasz Napierala 
903914ddf8SEdward Tomasz Napierala static void
automounted_remove(struct automounted_fs * af)913914ddf8SEdward Tomasz Napierala automounted_remove(struct automounted_fs *af)
923914ddf8SEdward Tomasz Napierala {
933914ddf8SEdward Tomasz Napierala 
943914ddf8SEdward Tomasz Napierala 	TAILQ_REMOVE(&automounted, af, af_next);
953914ddf8SEdward Tomasz Napierala 	free(af);
963914ddf8SEdward Tomasz Napierala }
973914ddf8SEdward Tomasz Napierala 
983914ddf8SEdward Tomasz Napierala static void
refresh_automounted(void)993914ddf8SEdward Tomasz Napierala refresh_automounted(void)
1003914ddf8SEdward Tomasz Napierala {
1013914ddf8SEdward Tomasz Napierala 	struct automounted_fs *af, *tmpaf;
1023914ddf8SEdward Tomasz Napierala 	struct statfs *mntbuf;
1033914ddf8SEdward Tomasz Napierala 	int i, nitems;
1043914ddf8SEdward Tomasz Napierala 
1053914ddf8SEdward Tomasz Napierala 	nitems = getmntinfo(&mntbuf, MNT_WAIT);
1063914ddf8SEdward Tomasz Napierala 	if (nitems <= 0)
1073914ddf8SEdward Tomasz Napierala 		log_err(1, "getmntinfo");
1083914ddf8SEdward Tomasz Napierala 
1093914ddf8SEdward Tomasz Napierala 	log_debugx("refreshing list of automounted filesystems");
1103914ddf8SEdward Tomasz Napierala 
1113914ddf8SEdward Tomasz Napierala 	TAILQ_FOREACH(af, &automounted, af_next)
1123914ddf8SEdward Tomasz Napierala 		af->af_mark = false;
1133914ddf8SEdward Tomasz Napierala 
1143914ddf8SEdward Tomasz Napierala 	for (i = 0; i < nitems; i++) {
1153914ddf8SEdward Tomasz Napierala 		if (strcmp(mntbuf[i].f_fstypename, "autofs") == 0) {
1163914ddf8SEdward Tomasz Napierala 			log_debugx("skipping %s, filesystem type is autofs",
1173914ddf8SEdward Tomasz Napierala 			    mntbuf[i].f_mntonname);
1183914ddf8SEdward Tomasz Napierala 			continue;
1193914ddf8SEdward Tomasz Napierala 		}
1203914ddf8SEdward Tomasz Napierala 
1213914ddf8SEdward Tomasz Napierala 		if ((mntbuf[i].f_flags & MNT_AUTOMOUNTED) == 0) {
1223914ddf8SEdward Tomasz Napierala 			log_debugx("skipping %s, not automounted",
1233914ddf8SEdward Tomasz Napierala 			    mntbuf[i].f_mntonname);
1243914ddf8SEdward Tomasz Napierala 			continue;
1253914ddf8SEdward Tomasz Napierala 		}
1263914ddf8SEdward Tomasz Napierala 
1273914ddf8SEdward Tomasz Napierala 		af = automounted_find(mntbuf[i].f_fsid);
1283914ddf8SEdward Tomasz Napierala 		if (af == NULL) {
1293914ddf8SEdward Tomasz Napierala 			log_debugx("new automounted filesystem found on %s "
1303914ddf8SEdward Tomasz Napierala 			    "(FSID:%d:%d)", mntbuf[i].f_mntonname,
1313914ddf8SEdward Tomasz Napierala 			    mntbuf[i].f_fsid.val[0], mntbuf[i].f_fsid.val[1]);
1323914ddf8SEdward Tomasz Napierala 			af = automounted_add(mntbuf[i].f_fsid,
1333914ddf8SEdward Tomasz Napierala 			    mntbuf[i].f_mntonname);
1343914ddf8SEdward Tomasz Napierala 		} else {
1353914ddf8SEdward Tomasz Napierala 			log_debugx("already known automounted filesystem "
1363914ddf8SEdward Tomasz Napierala 			    "found on %s (FSID:%d:%d)", mntbuf[i].f_mntonname,
1373914ddf8SEdward Tomasz Napierala 			    mntbuf[i].f_fsid.val[0], mntbuf[i].f_fsid.val[1]);
1383914ddf8SEdward Tomasz Napierala 		}
1393914ddf8SEdward Tomasz Napierala 		af->af_mark = true;
1403914ddf8SEdward Tomasz Napierala 	}
1413914ddf8SEdward Tomasz Napierala 
1423914ddf8SEdward Tomasz Napierala 	TAILQ_FOREACH_SAFE(af, &automounted, af_next, tmpaf) {
1433914ddf8SEdward Tomasz Napierala 		if (af->af_mark)
1443914ddf8SEdward Tomasz Napierala 			continue;
1453914ddf8SEdward Tomasz Napierala 		log_debugx("lost filesystem mounted on %s (FSID:%d:%d)",
1463914ddf8SEdward Tomasz Napierala 		    af->af_mountpoint, af->af_fsid.val[0], af->af_fsid.val[1]);
1473914ddf8SEdward Tomasz Napierala 		automounted_remove(af);
1483914ddf8SEdward Tomasz Napierala 	}
1493914ddf8SEdward Tomasz Napierala }
1503914ddf8SEdward Tomasz Napierala 
1513914ddf8SEdward Tomasz Napierala static int
unmount_by_fsid(const fsid_t fsid,const char * mountpoint)1523914ddf8SEdward Tomasz Napierala unmount_by_fsid(const fsid_t fsid, const char *mountpoint)
1533914ddf8SEdward Tomasz Napierala {
1543914ddf8SEdward Tomasz Napierala 	char *fsid_str;
1553914ddf8SEdward Tomasz Napierala 	int error, ret;
1563914ddf8SEdward Tomasz Napierala 
1573914ddf8SEdward Tomasz Napierala 	ret = asprintf(&fsid_str, "FSID:%d:%d", fsid.val[0], fsid.val[1]);
1583914ddf8SEdward Tomasz Napierala 	if (ret < 0)
1593914ddf8SEdward Tomasz Napierala 		log_err(1, "asprintf");
1603914ddf8SEdward Tomasz Napierala 
161debc480eSEdward Tomasz Napierala 	error = unmount(fsid_str, MNT_NONBUSY | MNT_BYFSID);
1623914ddf8SEdward Tomasz Napierala 	if (error != 0) {
1633914ddf8SEdward Tomasz Napierala 		if (errno == EBUSY) {
1643914ddf8SEdward Tomasz Napierala 			log_debugx("cannot unmount %s (%s): %s",
1653914ddf8SEdward Tomasz Napierala 			    mountpoint, fsid_str, strerror(errno));
1663914ddf8SEdward Tomasz Napierala 		} else {
1673914ddf8SEdward Tomasz Napierala 			log_warn("cannot unmount %s (%s)",
1683914ddf8SEdward Tomasz Napierala 			    mountpoint, fsid_str);
1693914ddf8SEdward Tomasz Napierala 		}
17088e531f3SRobert Wing 	} else
17188e531f3SRobert Wing 		rpc_umntall();
1723914ddf8SEdward Tomasz Napierala 
1733914ddf8SEdward Tomasz Napierala 	free(fsid_str);
1743914ddf8SEdward Tomasz Napierala 
1753914ddf8SEdward Tomasz Napierala 	return (error);
1763914ddf8SEdward Tomasz Napierala }
1773914ddf8SEdward Tomasz Napierala 
178ca05fff0SJustin Hibbits static time_t
expire_automounted(time_t expiration_time)179ca05fff0SJustin Hibbits expire_automounted(time_t expiration_time)
1803914ddf8SEdward Tomasz Napierala {
1813914ddf8SEdward Tomasz Napierala 	struct automounted_fs *af, *tmpaf;
1823914ddf8SEdward Tomasz Napierala 	time_t now;
183ca05fff0SJustin Hibbits 	time_t mounted_for, mounted_max = -1;
1843914ddf8SEdward Tomasz Napierala 	int error;
1853914ddf8SEdward Tomasz Napierala 
1863914ddf8SEdward Tomasz Napierala 	now = time(NULL);
1873914ddf8SEdward Tomasz Napierala 
1883914ddf8SEdward Tomasz Napierala 	log_debugx("expiring automounted filesystems");
1893914ddf8SEdward Tomasz Napierala 
1903914ddf8SEdward Tomasz Napierala 	TAILQ_FOREACH_SAFE(af, &automounted, af_next, tmpaf) {
1913914ddf8SEdward Tomasz Napierala 		mounted_for = difftime(now, af->af_mount_time);
1923914ddf8SEdward Tomasz Napierala 
1933914ddf8SEdward Tomasz Napierala 		if (mounted_for < expiration_time) {
1943914ddf8SEdward Tomasz Napierala 			log_debugx("skipping %s (FSID:%d:%d), mounted "
1953447ea90SJustin Hibbits 			    "for %jd  seconds", af->af_mountpoint,
1963914ddf8SEdward Tomasz Napierala 			    af->af_fsid.val[0], af->af_fsid.val[1],
1973447ea90SJustin Hibbits 			    (intmax_t)mounted_for);
1983914ddf8SEdward Tomasz Napierala 
1993914ddf8SEdward Tomasz Napierala 			if (mounted_for > mounted_max)
2003914ddf8SEdward Tomasz Napierala 				mounted_max = mounted_for;
2013914ddf8SEdward Tomasz Napierala 
2023914ddf8SEdward Tomasz Napierala 			continue;
2033914ddf8SEdward Tomasz Napierala 		}
2043914ddf8SEdward Tomasz Napierala 
2053914ddf8SEdward Tomasz Napierala 		log_debugx("filesystem mounted on %s (FSID:%d:%d), "
206ca05fff0SJustin Hibbits 		    "was mounted for %ld seconds; unmounting",
2073914ddf8SEdward Tomasz Napierala 		    af->af_mountpoint, af->af_fsid.val[0], af->af_fsid.val[1],
208ca05fff0SJustin Hibbits 		    (long)mounted_for);
2093914ddf8SEdward Tomasz Napierala 		error = unmount_by_fsid(af->af_fsid, af->af_mountpoint);
2103914ddf8SEdward Tomasz Napierala 		if (error != 0) {
2113914ddf8SEdward Tomasz Napierala 			if (mounted_for > mounted_max)
2123914ddf8SEdward Tomasz Napierala 				mounted_max = mounted_for;
2133914ddf8SEdward Tomasz Napierala 		}
2143914ddf8SEdward Tomasz Napierala 	}
2153914ddf8SEdward Tomasz Napierala 
2163914ddf8SEdward Tomasz Napierala 	return (mounted_max);
2173914ddf8SEdward Tomasz Napierala }
2183914ddf8SEdward Tomasz Napierala 
2193914ddf8SEdward Tomasz Napierala static void
usage_autounmountd(void)2203914ddf8SEdward Tomasz Napierala usage_autounmountd(void)
2213914ddf8SEdward Tomasz Napierala {
2223914ddf8SEdward Tomasz Napierala 
2233914ddf8SEdward Tomasz Napierala 	fprintf(stderr, "usage: autounmountd [-r time][-t time][-dv]\n");
2243914ddf8SEdward Tomasz Napierala 	exit(1);
2253914ddf8SEdward Tomasz Napierala }
2263914ddf8SEdward Tomasz Napierala 
2273914ddf8SEdward Tomasz Napierala static void
do_wait(int kq,time_t sleep_time)228ca05fff0SJustin Hibbits do_wait(int kq, time_t sleep_time)
2293914ddf8SEdward Tomasz Napierala {
2303914ddf8SEdward Tomasz Napierala 	struct timespec timeout;
2313914ddf8SEdward Tomasz Napierala 	struct kevent unused;
23221cee0c5SEdward Tomasz Napierala 	int nevents;
2333914ddf8SEdward Tomasz Napierala 
234ca05fff0SJustin Hibbits 	if (sleep_time != -1) {
235ca05fff0SJustin Hibbits 		assert(sleep_time > 0);
2363914ddf8SEdward Tomasz Napierala 		timeout.tv_sec = sleep_time;
2373914ddf8SEdward Tomasz Napierala 		timeout.tv_nsec = 0;
2383914ddf8SEdward Tomasz Napierala 
239ca05fff0SJustin Hibbits 		log_debugx("waiting for filesystem event for %ld seconds",
240ca05fff0SJustin Hibbits 		    (long)sleep_time);
24121cee0c5SEdward Tomasz Napierala 		nevents = kevent(kq, NULL, 0, &unused, 1, &timeout);
24221cee0c5SEdward Tomasz Napierala 	} else {
24321cee0c5SEdward Tomasz Napierala 		log_debugx("waiting for filesystem event");
24421cee0c5SEdward Tomasz Napierala 		nevents = kevent(kq, NULL, 0, &unused, 1, NULL);
24521cee0c5SEdward Tomasz Napierala 	}
2468379360aSEdward Tomasz Napierala 	if (nevents < 0) {
2478379360aSEdward Tomasz Napierala 		if (errno == EINTR)
2488379360aSEdward Tomasz Napierala 			return;
2493914ddf8SEdward Tomasz Napierala 		log_err(1, "kevent");
2508379360aSEdward Tomasz Napierala 	}
2513914ddf8SEdward Tomasz Napierala 
25221cee0c5SEdward Tomasz Napierala 	if (nevents == 0) {
2533914ddf8SEdward Tomasz Napierala 		log_debugx("timeout reached");
254ca05fff0SJustin Hibbits 		assert(sleep_time > 0);
25521cee0c5SEdward Tomasz Napierala 	} else {
2563914ddf8SEdward Tomasz Napierala 		log_debugx("got filesystem event");
2573914ddf8SEdward Tomasz Napierala 	}
25821cee0c5SEdward Tomasz Napierala }
2593914ddf8SEdward Tomasz Napierala 
2603914ddf8SEdward Tomasz Napierala int
main_autounmountd(int argc,char ** argv)2613914ddf8SEdward Tomasz Napierala main_autounmountd(int argc, char **argv)
2623914ddf8SEdward Tomasz Napierala {
2633914ddf8SEdward Tomasz Napierala 	struct kevent event;
2643914ddf8SEdward Tomasz Napierala 	struct pidfh *pidfh;
2653914ddf8SEdward Tomasz Napierala 	pid_t otherpid;
2663914ddf8SEdward Tomasz Napierala 	const char *pidfile_path = AUTOUNMOUNTD_PIDFILE;
2673914ddf8SEdward Tomasz Napierala 	int ch, debug = 0, error, kq;
268ca05fff0SJustin Hibbits 	time_t expiration_time = 600, retry_time = 600, mounted_max, sleep_time;
2693914ddf8SEdward Tomasz Napierala 	bool dont_daemonize = false;
2703914ddf8SEdward Tomasz Napierala 
2713914ddf8SEdward Tomasz Napierala 	while ((ch = getopt(argc, argv, "dr:t:v")) != -1) {
2723914ddf8SEdward Tomasz Napierala 		switch (ch) {
2733914ddf8SEdward Tomasz Napierala 		case 'd':
2743914ddf8SEdward Tomasz Napierala 			dont_daemonize = true;
2753914ddf8SEdward Tomasz Napierala 			debug++;
2763914ddf8SEdward Tomasz Napierala 			break;
2773914ddf8SEdward Tomasz Napierala 		case 'r':
2783914ddf8SEdward Tomasz Napierala 			retry_time = atoi(optarg);
2793914ddf8SEdward Tomasz Napierala 			break;
2803914ddf8SEdward Tomasz Napierala 		case 't':
2813914ddf8SEdward Tomasz Napierala 			expiration_time = atoi(optarg);
2823914ddf8SEdward Tomasz Napierala 			break;
2833914ddf8SEdward Tomasz Napierala 		case 'v':
2843914ddf8SEdward Tomasz Napierala 			debug++;
2853914ddf8SEdward Tomasz Napierala 			break;
2863914ddf8SEdward Tomasz Napierala 		case '?':
2873914ddf8SEdward Tomasz Napierala 		default:
2883914ddf8SEdward Tomasz Napierala 			usage_autounmountd();
2893914ddf8SEdward Tomasz Napierala 		}
2903914ddf8SEdward Tomasz Napierala 	}
2913914ddf8SEdward Tomasz Napierala 	argc -= optind;
2923914ddf8SEdward Tomasz Napierala 	if (argc != 0)
2933914ddf8SEdward Tomasz Napierala 		usage_autounmountd();
2943914ddf8SEdward Tomasz Napierala 
2953914ddf8SEdward Tomasz Napierala 	if (retry_time <= 0)
2963914ddf8SEdward Tomasz Napierala 		log_errx(1, "retry time must be greater than zero");
2973914ddf8SEdward Tomasz Napierala 	if (expiration_time <= 0)
2983914ddf8SEdward Tomasz Napierala 		log_errx(1, "expiration time must be greater than zero");
2993914ddf8SEdward Tomasz Napierala 
3003914ddf8SEdward Tomasz Napierala 	log_init(debug);
3013914ddf8SEdward Tomasz Napierala 
3023914ddf8SEdward Tomasz Napierala 	pidfh = pidfile_open(pidfile_path, 0600, &otherpid);
3033914ddf8SEdward Tomasz Napierala 	if (pidfh == NULL) {
3043914ddf8SEdward Tomasz Napierala 		if (errno == EEXIST) {
3053914ddf8SEdward Tomasz Napierala 			log_errx(1, "daemon already running, pid: %jd.",
3063914ddf8SEdward Tomasz Napierala 			    (intmax_t)otherpid);
3073914ddf8SEdward Tomasz Napierala 		}
3083914ddf8SEdward Tomasz Napierala 		log_err(1, "cannot open or create pidfile \"%s\"",
3093914ddf8SEdward Tomasz Napierala 		    pidfile_path);
3103914ddf8SEdward Tomasz Napierala 	}
3113914ddf8SEdward Tomasz Napierala 
3123914ddf8SEdward Tomasz Napierala 	if (dont_daemonize == false) {
3133914ddf8SEdward Tomasz Napierala 		if (daemon(0, 0) == -1) {
3143914ddf8SEdward Tomasz Napierala 			log_warn("cannot daemonize");
3153914ddf8SEdward Tomasz Napierala 			pidfile_remove(pidfh);
3163914ddf8SEdward Tomasz Napierala 			exit(1);
3173914ddf8SEdward Tomasz Napierala 		}
3183914ddf8SEdward Tomasz Napierala 	}
3193914ddf8SEdward Tomasz Napierala 
3203914ddf8SEdward Tomasz Napierala 	pidfile_write(pidfh);
3213914ddf8SEdward Tomasz Napierala 
3223914ddf8SEdward Tomasz Napierala 	TAILQ_INIT(&automounted);
3233914ddf8SEdward Tomasz Napierala 
3243914ddf8SEdward Tomasz Napierala 	kq = kqueue();
3253914ddf8SEdward Tomasz Napierala 	if (kq < 0)
3263914ddf8SEdward Tomasz Napierala 		log_err(1, "kqueue");
3273914ddf8SEdward Tomasz Napierala 
328ce22a792SRobert Wing 	EV_SET(&event, 0, EVFILT_FS, EV_ADD | EV_CLEAR, VQ_MOUNT | VQ_UNMOUNT, 0, NULL);
3293914ddf8SEdward Tomasz Napierala 	error = kevent(kq, &event, 1, NULL, 0, NULL);
3303914ddf8SEdward Tomasz Napierala 	if (error < 0)
3313914ddf8SEdward Tomasz Napierala 		log_err(1, "kevent");
3323914ddf8SEdward Tomasz Napierala 
3333914ddf8SEdward Tomasz Napierala 	for (;;) {
3343914ddf8SEdward Tomasz Napierala 		refresh_automounted();
3353914ddf8SEdward Tomasz Napierala 		mounted_max = expire_automounted(expiration_time);
336ca05fff0SJustin Hibbits 		if (mounted_max == -1) {
33721cee0c5SEdward Tomasz Napierala 			sleep_time = mounted_max;
33821cee0c5SEdward Tomasz Napierala 			log_debugx("no filesystems to expire");
33921cee0c5SEdward Tomasz Napierala 		} else if (mounted_max < expiration_time) {
3403914ddf8SEdward Tomasz Napierala 			sleep_time = difftime(expiration_time, mounted_max);
341ca05fff0SJustin Hibbits 			log_debugx("some filesystems expire in %ld  seconds",
342ca05fff0SJustin Hibbits 			    (long)sleep_time);
3433914ddf8SEdward Tomasz Napierala 		} else {
3443914ddf8SEdward Tomasz Napierala 			sleep_time = retry_time;
3453914ddf8SEdward Tomasz Napierala 			log_debugx("some expired filesystems remain mounted, "
346ca05fff0SJustin Hibbits 			    "will retry in %ld  seconds", (long)sleep_time);
3473914ddf8SEdward Tomasz Napierala 		}
3483914ddf8SEdward Tomasz Napierala 
3493914ddf8SEdward Tomasz Napierala 		do_wait(kq, sleep_time);
3503914ddf8SEdward Tomasz Napierala 	}
3513914ddf8SEdward Tomasz Napierala 
3523914ddf8SEdward Tomasz Napierala 	return (0);
3533914ddf8SEdward Tomasz Napierala }
354