diff options
Diffstat (limited to 'usr.sbin/rpc.umntall')
| -rw-r--r-- | usr.sbin/rpc.umntall/Makefile | 9 | ||||
| -rw-r--r-- | usr.sbin/rpc.umntall/Makefile.depend | 17 | ||||
| -rw-r--r-- | usr.sbin/rpc.umntall/mounttab.c | 230 | ||||
| -rw-r--r-- | usr.sbin/rpc.umntall/mounttab.h | 46 | ||||
| -rw-r--r-- | usr.sbin/rpc.umntall/rpc.umntall.8 | 124 | ||||
| -rw-r--r-- | usr.sbin/rpc.umntall/rpc.umntall.c | 264 | 
6 files changed, 690 insertions, 0 deletions
| diff --git a/usr.sbin/rpc.umntall/Makefile b/usr.sbin/rpc.umntall/Makefile new file mode 100644 index 000000000000..d9143020bc0c --- /dev/null +++ b/usr.sbin/rpc.umntall/Makefile @@ -0,0 +1,9 @@ +PACKAGE=	nfs + +PROG=	rpc.umntall +MAN=	rpc.umntall.8 +SRCS=	rpc.umntall.c mounttab.c + +WARNS?= 3 + +.include <bsd.prog.mk> diff --git a/usr.sbin/rpc.umntall/Makefile.depend b/usr.sbin/rpc.umntall/Makefile.depend new file mode 100644 index 000000000000..a2d89550fa2b --- /dev/null +++ b/usr.sbin/rpc.umntall/Makefile.depend @@ -0,0 +1,17 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ +	include \ +	include/rpc \ +	include/rpcsvc \ +	include/xlocale \ +	lib/${CSU_DIR} \ +	lib/libc \ +	lib/libcompiler_rt \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/rpc.umntall/mounttab.c b/usr.sbin/rpc.umntall/mounttab.c new file mode 100644 index 000000000000..0043d4302e59 --- /dev/null +++ b/usr.sbin/rpc.umntall/mounttab.c @@ -0,0 +1,230 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1999 Martin Blapp + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +#include <sys/syslog.h> + +#include <rpc/rpc.h> +#include <rpcsvc/mount.h> + +#include <err.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "mounttab.h" + +struct mtablist *mtabhead; + +static void badline(const char *field, const char *bad); + +/* + * Add an entry to PATH_MOUNTTAB for each mounted NFS filesystem, + * so the client can notify the NFS server even after reboot. + */ +int +add_mtab(char *hostp, char *dirp) +{ +	FILE *mtabfile; + +	if ((mtabfile = fopen(PATH_MOUNTTAB, "a")) == NULL) +		return (0); +	else { +		fprintf(mtabfile, "%ld\t%s\t%s\n", +		    (long)time(NULL), hostp, dirp); +		fclose(mtabfile); +		return (1); +	} +} + +/* + * Read mounttab line for line and return struct mtablist. + */ +int +read_mtab(void) +{ +	struct mtablist **mtabpp, *mtabp; +	char *hostp, *dirp, *cp; +	char str[STRSIZ]; +	char *timep, *endp; +	time_t actiontime; +	u_long ultmp; +	FILE *mtabfile; + +	if ((mtabfile = fopen(PATH_MOUNTTAB, "r")) == NULL) { +		if (errno == ENOENT) +			return (0); +		else { +			syslog(LOG_ERR, "can't open %s", PATH_MOUNTTAB); +			return (0); +		} +	} +	actiontime = 0; +	mtabpp = &mtabhead; +	while (fgets(str, STRSIZ, mtabfile) != NULL) { +		cp = str; +		errno = 0; +		if (*cp == '#' || *cp == ' ' || *cp == '\n') +			continue; +		timep = strsep(&cp, " \t\n"); +		if (timep == NULL || *timep == '\0') { +			badline("time", timep); +			continue; +		} +		hostp = strsep(&cp, " \t\n"); +		if (hostp == NULL || *hostp == '\0') { +			badline("host", hostp); +			continue; +		} +		dirp = strsep(&cp, " \t\n"); +		if (dirp == NULL || *dirp == '\0') { +			badline("dir", dirp); +			continue; +		} +		ultmp = strtoul(timep, &endp, 10); +		if (ultmp == ULONG_MAX || *endp != '\0') { +			badline("time", timep); +			continue; +		} +		actiontime = ultmp; +		if ((mtabp = malloc(sizeof (struct mtablist))) == NULL) { +			syslog(LOG_ERR, "malloc"); +			fclose(mtabfile); +			return (0); +		} +		mtabp->mtab_time = actiontime; +		memmove(mtabp->mtab_host, hostp, MNTNAMLEN); +		mtabp->mtab_host[MNTNAMLEN - 1] = '\0'; +		memmove(mtabp->mtab_dirp, dirp, MNTPATHLEN); +		mtabp->mtab_dirp[MNTPATHLEN - 1] = '\0'; +		mtabp->mtab_next = (struct mtablist *)NULL; +		*mtabpp = mtabp; +		mtabpp = &mtabp->mtab_next; +	} +	fclose(mtabfile); +	return (1); +} + +/* + * Rewrite PATH_MOUNTTAB from scratch and skip bad entries. + * Unlink PATH_MOUNTAB if no entry is left. + */ +int +write_mtab(int verbose) +{ +	struct mtablist *mtabp, *mp; +	FILE *mtabfile; +	int line; + +	if ((mtabfile = fopen(PATH_MOUNTTAB, "w")) == NULL) { +		syslog(LOG_ERR, "can't write to %s", PATH_MOUNTTAB); +			return (0); +	} +	line = 0; +	for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { +		if (mtabp->mtab_host[0] == '\0') +			continue; +		/* Skip if a later (hence more recent) entry is identical. */ +		for (mp = mtabp->mtab_next; mp != NULL; mp = mp->mtab_next) +			if (strcmp(mtabp->mtab_host, mp->mtab_host) == 0 && +			    strcmp(mtabp->mtab_dirp, mp->mtab_dirp) == 0) +				break; +		if (mp != NULL) +			continue; + +		fprintf(mtabfile, "%ld\t%s\t%s\n", +		    (long)mtabp->mtab_time, mtabp->mtab_host, +		    mtabp->mtab_dirp); +		if (verbose) +			warnx("write mounttab entry %s:%s", +			    mtabp->mtab_host, mtabp->mtab_dirp); +		line++; +	} +	fclose(mtabfile); +	if (line == 0) { +		if (unlink(PATH_MOUNTTAB) == -1) { +			syslog(LOG_ERR, "can't remove %s", PATH_MOUNTTAB); +			return (0); +		} +	} +	return (1); +} + +/* + * Mark the entries as clean where RPC calls have been done successfully. + */ +void +clean_mtab(char *hostp, char *dirp, int verbose) +{ +	struct mtablist *mtabp; +	char *host; + +	/* Copy hostp in case it points to an entry that we are zeroing out. */ +	host = strdup(hostp); +	for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { +		if (strcmp(mtabp->mtab_host, host) != 0) +			continue; +		if (dirp != NULL && strcmp(mtabp->mtab_dirp, dirp) != 0) +			continue; + +		if (verbose) +			warnx("delete mounttab entry%s %s:%s", +			    (dirp == NULL) ? " by host" : "", +			    mtabp->mtab_host, mtabp->mtab_dirp); +		bzero(mtabp->mtab_host, MNTNAMLEN); +	} +	free(host); +} + +/* + * Free struct mtablist mtab. + */ +void +free_mtab(void) +{ +	struct mtablist *mtabp; + +	while ((mtabp = mtabhead) != NULL) { +		mtabhead = mtabhead->mtab_next; +		free(mtabp); +	} +} + +/* + * Print bad lines to syslog. + */ +static void +badline(const char *field, const char *bad) +{ +	syslog(LOG_ERR, "bad mounttab %s field '%s'", field, +	    (bad == NULL) ? "<null>" : bad); +} diff --git a/usr.sbin/rpc.umntall/mounttab.h b/usr.sbin/rpc.umntall/mounttab.h new file mode 100644 index 000000000000..e576978ba7bd --- /dev/null +++ b/usr.sbin/rpc.umntall/mounttab.h @@ -0,0 +1,46 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1999 Martin Blapp + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define STRSIZ  (MNTNAMLEN+MNTPATHLEN+100) +#define PATH_MOUNTTAB	"/var/db/mounttab" + +/* Structure for /var/db/mounttab */ +struct mtablist { +	time_t	mtab_time; +	char	mtab_host[MNTNAMLEN]; +	char	mtab_dirp[MNTPATHLEN]; +	struct mtablist *mtab_next; +}; + +extern struct mtablist *mtabhead; + +int	add_mtab(char *, char *); +void	clean_mtab(char *, char *, int); +int	read_mtab(void); +int	write_mtab(int); +void	free_mtab(void); diff --git a/usr.sbin/rpc.umntall/rpc.umntall.8 b/usr.sbin/rpc.umntall/rpc.umntall.8 new file mode 100644 index 000000000000..73b4e9094e3f --- /dev/null +++ b/usr.sbin/rpc.umntall/rpc.umntall.8 @@ -0,0 +1,124 @@ +.\" +.\" Copyright (c) 1999 Martin Blapp +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd November 17, 1999 +.Dt RPC.UMNTALL 8 +.Os +.Sh NAME +.Nm rpc.umntall +.Nd notify NFS servers about unmounted NFS file systems +.Sh SYNOPSIS +.Nm +.Op Fl e Ar expire +.Op Fl h Ar host +.Op Fl k +.Op Fl p Ar remotepath +.Op Fl v +.Sh DESCRIPTION +The +.Nm +utility is proposed in the +.Tn NFS +RPC specification; see +.Rs +.%T "NFS Version 3 Protocol Specification" +.%O "RFC 1813, Appendix I" +.Re +It uses remote procedure calls to remove mount entries from +.Pa /var/db/mountdtab +on the remote NFS server. +It is called automatically +without any parameters during startup and shutdown of +the system. +This ensures that +.Xr showmount 8 +does not display old and expired entries. +The +.Nm +utility +is only needed on client side, where +.Xr mount_nfs 8 +adds a mount entry with the current date to +.Pa /var/db/mounttab , +and +.Xr umount 8 +removes the entry again. +The +.Nm +utility +cares about all remaining entries in this table which result from crashes +or unproper shutdowns. +.Pp +The options are as follows: +.Bl -tag -width indentxxx +.It Fl e Ar expire +All entries which are not actually mounted or older than +.Ar expire +(seconds) are removed from +.Pa /var/db/mounttab . +This may be the case +for DNS changes or long out of service periods. +Default expire time +is 86400 seconds (one day). +.It Fl h Ar host +Only remove the specific hostname. +Send a UMNTALL RPC to the NFS server. +.It Fl k +Keep entries for existing NFS file systems. +Compare the NFS file systems from +the mounttab against the kernel mountlist and do not send the RPC to +existing mount entries. +Useful during startup of the system. +It may be +possible that there are already mounted NFS file systems, so calling +RPC UMOUNT is not a good idea. +This is the case if the user has rebooted +to 'single user mode' and starts up the system again. +.It Fl p Ar path +Only remove the specific mount-path. +Send a UMOUNT RPC to the NFS server. +This option implies the +.Fl host +option. +.It Fl v +Verbose, additional information is printed for each processed mounttab +entry. +.El +.Sh FILES +.Bl -tag -width /var/db/mounttab -compact +.It Pa /var/db/mounttab +mounted nfs-file systems +.El +.Sh SEE ALSO +.Xr mount_nfs 8 , +.Xr mountd 8 , +.Xr umount 8 +.Sh HISTORY +The +.Nm +utility first appeared in +.Fx 4.0 . +.Sh AUTHORS +.An Martin Blapp Aq Mt mb@imp.ch diff --git a/usr.sbin/rpc.umntall/rpc.umntall.c b/usr.sbin/rpc.umntall/rpc.umntall.c new file mode 100644 index 000000000000..b5f0413c0857 --- /dev/null +++ b/usr.sbin/rpc.umntall/rpc.umntall.c @@ -0,0 +1,264 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1999 Martin Blapp + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/param.h> +#include <sys/ucred.h> +#include <sys/mount.h> + +#include <rpc/rpc.h> +#include <rpcsvc/mount.h> + +#include <err.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "mounttab.h" + +int verbose; + +static int do_umount (char *, char *); +static int do_umntall (char *); +static int is_mounted (char *, char *); +static void usage (void); +int	xdr_dir (XDR *, char *); + +int +main(int argc, char **argv) { +	int ch, keep, success, pathlen; +	time_t expire, now; +	char *host, *path; +	struct mtablist *mtab; + +	expire = 0; +	host = path = NULL; +	success = keep = verbose = 0; +	while ((ch = getopt(argc, argv, "h:kp:ve:")) != -1) +		switch (ch) { +		case 'h': +			host = optarg; +			break; +		case 'e': +			expire = atoi(optarg); +			break; +		case 'k': +			keep = 1; +			break; +		case 'p': +			path = optarg; +			break; +		case 'v': +			verbose = 1; +			break; +		case '?': +			usage(); +		default: +			break; +		} +	argc -= optind; +	argv += optind; + +	/* Default expiretime is one day */ +	if (expire == 0) +		expire = 86400; +	time(&now); + +	/* Read PATH_MOUNTTAB. */ +	if (!read_mtab()) { +		if (verbose) +			warnx("no mounttab entries (%s does not exist)", +			    PATH_MOUNTTAB); +		mtabhead = NULL; +	} + +	if (host == NULL && path == NULL) { +		/* Check each entry and do any necessary unmount RPCs. */ +		for (mtab = mtabhead; mtab != NULL; mtab = mtab->mtab_next) { +			if (*mtab->mtab_host == '\0') +				continue; +			if (mtab->mtab_time + expire < now) { +				/* Clear expired entry. */ +				if (verbose) +					warnx("remove expired entry %s:%s", +					    mtab->mtab_host, mtab->mtab_dirp); +				bzero(mtab->mtab_host, +				    sizeof(mtab->mtab_host)); +				continue; +			} +			if (keep && is_mounted(mtab->mtab_host, +			    mtab->mtab_dirp)) { +				if (verbose) +					warnx("skip entry %s:%s", +					    mtab->mtab_host, mtab->mtab_dirp); +				continue; +			} +			if (do_umount(mtab->mtab_host, mtab->mtab_dirp)) { +				if (verbose) +					warnx("umount RPC for %s:%s succeeded", +					    mtab->mtab_host, mtab->mtab_dirp); +				/* Remove all entries for this host + path. */ +				clean_mtab(mtab->mtab_host, mtab->mtab_dirp, +				    verbose); +			} +		} +		success = 1; +	} else { +		if (host == NULL && path != NULL) +			/* Missing hostname. */ +			usage(); +		if (path == NULL) { +			/* Do a RPC UMNTALL for this specific host */ +			success = do_umntall(host); +			if (verbose && success) +				warnx("umntall RPC for %s succeeded", host); +		} else { +			/* Do a RPC UMNTALL for this specific mount */ +			for (pathlen = strlen(path); +			    pathlen > 1 && path[pathlen - 1] == '/'; pathlen--) +				path[pathlen - 1] = '\0'; +			success = do_umount(host, path); +			if (verbose && success) +				warnx("umount RPC for %s:%s succeeded", host, +				    path); +		} +		/* If successful, remove any corresponding mounttab entries. */ +		if (success) +			clean_mtab(host, path, verbose); +	} +	/* Write and unlink PATH_MOUNTTAB if necessary */ +	if (success) +		success = write_mtab(verbose); +	free_mtab(); +	exit (success ? 0 : 1); +} + +/* + * Send a RPC_MNT UMNTALL request to hostname. + * XXX This works for all mountd implementations, + * but produces a RPC IOERR on non FreeBSD systems. + */ +int +do_umntall(char *hostname) { +	enum clnt_stat clnt_stat; +	struct timeval try; +	CLIENT *clp; + +	try.tv_sec = 3; +	try.tv_usec = 0; +	clp = clnt_create_timed(hostname, MOUNTPROG, MOUNTVERS, "udp", +	    &try); +	if (clp == NULL) { +		warnx("%s: %s", hostname, clnt_spcreateerror("MOUNTPROG")); +		return (0); +	} +	clp->cl_auth = authunix_create_default(); +	clnt_stat = clnt_call(clp, MOUNTPROC_UMNTALL, +	    (xdrproc_t)xdr_void, (caddr_t)0, +	    (xdrproc_t)xdr_void, (caddr_t)0, try); +	if (clnt_stat != RPC_SUCCESS) +		warnx("%s: %s", hostname, clnt_sperror(clp, "MOUNTPROC_UMNTALL")); +	auth_destroy(clp->cl_auth); +	clnt_destroy(clp); +	return (clnt_stat == RPC_SUCCESS); +} + +/* + * Send a RPC_MNT UMOUNT request for dirp to hostname. + */ +int +do_umount(char *hostname, char *dirp) { +	enum clnt_stat clnt_stat; +	struct timeval try; +	CLIENT *clp; + +	try.tv_sec = 3; +	try.tv_usec = 0; +	clp = clnt_create_timed(hostname, MOUNTPROG, MOUNTVERS, "udp", +	    &try); +	if (clp  == NULL) { +		warnx("%s: %s", hostname, clnt_spcreateerror("MOUNTPROG")); +		return (0); +	} +	clp->cl_auth = authsys_create_default(); +	clnt_stat = clnt_call(clp, MOUNTPROC_UMNT, (xdrproc_t)xdr_dir, dirp, +	    (xdrproc_t)xdr_void, (caddr_t)0, try); +	if (clnt_stat != RPC_SUCCESS) +		warnx("%s: %s", hostname, clnt_sperror(clp, "MOUNTPROC_UMNT")); +	auth_destroy(clp->cl_auth); +	clnt_destroy(clp); +	return (clnt_stat == RPC_SUCCESS); +} + +/* + * Check if the entry is still/already mounted. + */ +int +is_mounted(char *hostname, char *dirp) { +	struct statfs *mntbuf; +	char name[MNAMELEN + 1]; +	size_t bufsize; +	int mntsize, i; + +	if (strlen(hostname) + strlen(dirp) >= MNAMELEN) +		return (0); +	snprintf(name, sizeof(name), "%s:%s", hostname, dirp); +	mntsize = getfsstat(NULL, 0, MNT_NOWAIT); +	if (mntsize <= 0) +		return (0); +	bufsize = (mntsize + 1) * sizeof(struct statfs); +	if ((mntbuf = malloc(bufsize)) == NULL) +		err(1, "malloc"); +	mntsize = getfsstat(mntbuf, (long)bufsize, MNT_NOWAIT); +	for (i = mntsize - 1; i >= 0; i--) { +		if (strcmp(mntbuf[i].f_mntfromname, name) == 0) { +			free(mntbuf); +			return (1); +		} +	} +	free(mntbuf); +	return (0); +} + +/* + * xdr routines for mount rpc's + */ +int +xdr_dir(XDR *xdrsp, char *dirp) { +	return (xdr_string(xdrsp, &dirp, MNTPATHLEN)); +} + +static void +usage(void) +{ +	(void)fprintf(stderr, "%s\n", +	    "usage: rpc.umntall [-kv] [-e expire] [-h host] [-p path]"); +	exit(1); +} | 
