From c94bd717ba865a97f38bd16273c080678d5fdafa Mon Sep 17 00:00:00 2001 From: dillon Date: Sun, 21 Nov 1999 08:06:00 +0000 Subject: Add rpc.umntall utility, to be used by startup and shutdown scripts to replace (broken) umntall signal code previously in mountd. Submitted by: Martin Blapp --- usr.sbin/Makefile | 1 + usr.sbin/rpc.umntall/Makefile | 8 + usr.sbin/rpc.umntall/mounttab.c | 221 +++++++++++++++++++++++++++ usr.sbin/rpc.umntall/mounttab.h | 45 ++++++ usr.sbin/rpc.umntall/rpc.umntall.8 | 111 ++++++++++++++ usr.sbin/rpc.umntall/rpc.umntall.c | 295 +++++++++++++++++++++++++++++++++++++ 6 files changed, 681 insertions(+) create mode 100644 usr.sbin/rpc.umntall/Makefile create mode 100644 usr.sbin/rpc.umntall/mounttab.c create mode 100644 usr.sbin/rpc.umntall/mounttab.h create mode 100644 usr.sbin/rpc.umntall/rpc.umntall.8 create mode 100644 usr.sbin/rpc.umntall/rpc.umntall.c (limited to 'usr.sbin') diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index e8da33e..98de11d 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -73,6 +73,7 @@ SUBDIR= IPXrouted \ rmt \ rpc.lockd \ rpc.statd \ + rpc.umntall \ rpc.yppasswdd \ rpc.ypupdated \ rpc.ypxfrd \ diff --git a/usr.sbin/rpc.umntall/Makefile b/usr.sbin/rpc.umntall/Makefile new file mode 100644 index 0000000..207bfc9 --- /dev/null +++ b/usr.sbin/rpc.umntall/Makefile @@ -0,0 +1,8 @@ +# @(#)Makefile 8.4 (Berkeley) 6/22/95 +# $FreeBSD$ + +PROG= rpc.umntall +SRCS= rpc.umntall.c mounttab.c +MAN8= rpc.umntall.8 + +.include diff --git a/usr.sbin/rpc.umntall/mounttab.c b/usr.sbin/rpc.umntall/mounttab.c new file mode 100644 index 0000000..7ebd6e5 --- /dev/null +++ b/usr.sbin/rpc.umntall/mounttab.c @@ -0,0 +1,221 @@ +/* + * 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. + * + */ + +#ifndef lint +static const char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "mounttab.h" + +int verbose; +struct mtablist *mtabhead; + +/* + * 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; + time_t *now; + + now = NULL; + if ((mtabfile = fopen(PATH_MOUNTTAB, "a")) == NULL) + return (0); + else { + fprintf(mtabfile, "%ld\t%s\t%s\n", time(now), hostp, dirp); + fclose(mtabfile); + return (1); + } +} + +/* + * Read mounttab line for line and return struct mtablist. + */ +int +read_mtab(struct mtablist *mtabp) { + struct mtablist **mtabpp; + char *hostp, *dirp, *cp; + char str[STRSIZ]; + char *timep; + time_t time; + 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); + } + } + time = 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 == ' ' || *timep == '\n') { + badline(timep); + continue; + } + hostp = strsep(&cp, " \t\n"); + if (hostp == NULL || *hostp == ' ' || *hostp == '\n') { + badline(hostp); + continue; + } + dirp = strsep(&cp, " \t\n"); + if (dirp == NULL || *dirp == ' ' || *dirp == '\n') { + badline(dirp); + continue; + } + time = strtoul(timep, (char **)NULL, 10); + if (errno == ERANGE) { + badline(timep); + continue; + } + if ((mtabp = malloc(sizeof (struct mtablist))) == NULL) { + syslog(LOG_ERR, "malloc"); + fclose(mtabfile); + return (0); + } + mtabp->mtab_time = time; + memmove(mtabp->mtab_host, hostp, RPCMNT_NAMELEN); + mtabp->mtab_host[RPCMNT_NAMELEN - 1] = '\0'; + memmove(mtabp->mtab_dirp, dirp, RPCMNT_PATHLEN); + mtabp->mtab_dirp[RPCMNT_PATHLEN - 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() { + struct mtablist *mtabp; + 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 != NULL && + strlen(mtabp->mtab_host) > 0) { + fprintf(mtabfile, "%ld\t%s\t%s\n", mtabp->mtab_time, + 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) { + struct mtablist *mtabp; + char *host; + + host = strdup(hostp); + for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { + if (mtabp->mtab_host != NULL && + strcmp(mtabp->mtab_host, host) == 0) { + if (dirp == NULL) { + if (verbose) { + warnx("entries deleted for " + "host %s", host); + } + bzero(mtabp->mtab_host, RPCMNT_NAMELEN); + } else { + if (strcmp(mtabp->mtab_dirp, dirp) == 0) { + if (verbose) { + warnx("entry deleted for " + "%s:%s", host, dirp); + } + bzero(mtabp->mtab_host, RPCMNT_NAMELEN); + } + } + } + } + free(host); +} + +/* + * Free struct mtablist mtab. + */ +void +free_mtab() { + struct mtablist *mtabp; + struct mtablist *mtab_next; + + for (mtabp = mtabhead; mtabp != NULL; mtabp = mtab_next) { + mtab_next = mtabp->mtab_next; + free(mtabp); + mtabp = mtab_next; + } +} + +/* + * Print bad lines to syslog. + */ +void +badline(char *bad) { + + syslog(LOG_ERR, "skipped bad line in mounttab with entry %s", bad); +} diff --git a/usr.sbin/rpc.umntall/mounttab.h b/usr.sbin/rpc.umntall/mounttab.h new file mode 100644 index 0000000..21d789a --- /dev/null +++ b/usr.sbin/rpc.umntall/mounttab.h @@ -0,0 +1,45 @@ +/* + * 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. + * + * $FreeBSD$ + */ + +#define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+100) +#define PATH_MOUNTTAB "/var/db/mounttab" + +/* Structure for /var/db/mounttab */ +struct mtablist { + time_t mtab_time; + char mtab_host[RPCMNT_NAMELEN]; + char mtab_dirp[RPCMNT_PATHLEN]; + struct mtablist *mtab_next; +}; + +int add_mtab(char *, char *); +void badline (char *); +void clean_mtab (char *, char *); +int read_mtab (struct mtablist *); +int write_mtab (void); +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 0000000..2fafe30 --- /dev/null +++ b/usr.sbin/rpc.umntall/rpc.umntall.8 @@ -0,0 +1,111 @@ +.\" +.\" 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. +.\" +.\" $FreeBSD$ +.\" +.Dd November 17, 1999 +.Dt RPC.UMNTALL 8 +.Os +.Sh NAME +.Nm rpc.umntall +.Nd Notify NFS servers about unmounted NFS filesystems +.Sh SYNOPSIS +.Nm rpc.umntall +.Op Fl e Ar expire +.Op Fl h Ar host +.Op Fl k +.Op Fl p Ar remotepath +.Op Fl v +.Sh DESCRIPTION +.Nm +is as command as proposed in the +.Tn NFS +RPC specification; see +.%T "NFS Version 3 Protocol Specification", +RFC 1813, Appendix I. 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 +command +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 +command +cares about all remaining entries in this table which result from crashes +or unproper shutdowns. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl e Ar expire +All entries which are not actually mounted or older than +.Ar expire +(seconds) are removed from /var/db/mounttab. This may be the case +for DNS changes or long out of service periods. Default expire time +is 172800 seconds (2 days). +.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 filesystems. Compare the NFS filesystems 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 filesystems, so calling +RPC UMNTALL isn't 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-filesystems +.El +.Sh HISTORY +The +.Nm +command first appeared in +.Fx 4.0 . +.El +.Sh SEE ALSO +.Xr mountd 8 , +.Xr umount 8 , +.Xr mount_nfs 8 +.Sh AUTHORS +.An Martin Blapp Aq 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 0000000..9d1dbec --- /dev/null +++ b/usr.sbin/rpc.umntall/rpc.umntall.c @@ -0,0 +1,295 @@ +/* + * 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. + * + */ + +#ifndef lint +static const char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#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 *); + +struct mtablist *mtabhead; + +int +main(int argc, char **argv) { + int ch, keep, success, pathlen; + time_t expire, *now; + char *host, *path; + struct mtablist *mtab; + + mtab = NULL; + now = NULL; + expire = 0; + host = path = '\0'; + success = keep = verbose = 0; + while ((ch = getopt(argc, argv, "h:kp:ve:")) != -1) + switch (ch) { + case 'h': + host = optarg; + break; + case 'e': + expire = (time_t)optarg; + break; + case 'k': + keep = 1; + break; + case 'p': + path = optarg; + break; + case 'v': + verbose = 1; + break; + case '?': + usage(); + default: + } + argc -= optind; + argv += optind; + + /* Ignore SIGINT and SIGQUIT during shutdown */ + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + + /* Default expiretime is two days */ + if (expire == 0) + expire = 172800; + /* + * Read PATH_MOUNTTAB and check each entry + * and do finally the unmounts. + */ + if (host == NULL && path == NULL) { + if (!read_mtab(mtab)) { + if (verbose) + warnx("nothing to do, remove %s", + PATH_MOUNTTAB); + } + for (mtab = mtabhead; mtab != NULL; mtab = mtab->mtab_next) { + if (*mtab->mtab_host != '\0' && + (do_umntall(mtab->mtab_host) || + mtab->mtab_time <= (time(now) - expire))) { + if (keep && is_mounted(mtab->mtab_host, + mtab->mtab_dirp)) { + if (verbose) { + warnx("skipping entry %s:%s", + mtab->mtab_host, + mtab->mtab_dirp); + } + } else + clean_mtab(mtab->mtab_host, NULL); + } + } + /* Only do a RPC UMNTALL for this specific host */ + } else if (host != NULL && path == NULL) { + if (!do_umntall(host)) + exit(1); + else + success = 1; + /* Someone forgot to enter a hostname */ + } else if (host == NULL && path != NULL) + usage(); + /* Only do a RPC UMOUNT for this specific mount */ + else { + for (pathlen = strlen(path); + pathlen > 1 && path[pathlen - 1] == '/'; pathlen--) + path[pathlen - 1] = '\0'; + if (!do_umount(host, path)) + exit(1); + else + success = 1; + } + /* Write and unlink PATH_MOUNTTAB if necessary */ + if (success) { + if (verbose) + warnx("UMOUNT RPC successfully sent to %s", host); + if (read_mtab(mtab)) { + mtab = mtabhead; + clean_mtab(host, path); + } + } + if (!write_mtab()) { + free_mtab(); + exit(1); + } + free_mtab(); + exit(0); +} + +/* + * Send a RPC_MNT UMNTALL request to hostname. + */ +int +do_umntall(char *hostname) { + enum clnt_stat clnt_stat; + struct hostent *hp; + struct sockaddr_in saddr; + struct timeval pertry, try; + int so; + CLIENT *clp; + + if ((hp = gethostbyname(hostname)) == NULL) { + warnx("gethostbyname(%s) failed", hostname); + return (0); + } + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = 0; + memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length, + sizeof(saddr.sin_addr))); + pertry.tv_sec = 3; + pertry.tv_usec = 0; + so = RPC_ANYSOCK; + if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, + pertry, &so)) == NULL) { + clnt_pcreateerror("Cannot send MNT PRC"); + return (0); + } + clp->cl_auth = authunix_create_default(); + try.tv_sec = 3; + try.tv_usec = 0; + clnt_stat = clnt_call(clp, RPCMNT_UMNTALL, xdr_void, (caddr_t)0, + xdr_void, (caddr_t)0, try); + if (clnt_stat != RPC_SUCCESS) { + clnt_perror(clp, "Bad MNT RPC"); + return (0); + } else + return (1); +} + +/* + * Send a RPC_MNT UMOUNT request for dirp to hostname. + */ +int +do_umount(char *hostname, char *dirp) { + enum clnt_stat clnt_stat; + struct hostent *hp; + struct sockaddr_in saddr; + struct timeval pertry, try; + CLIENT *clp; + int so; + + if ((hp = gethostbyname(hostname)) == NULL) { + warnx("gethostbyname(%s) failed", hostname); + return (0); + } + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = 0; + memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length, + sizeof(saddr.sin_addr))); + pertry.tv_sec = 3; + pertry.tv_usec = 0; + so = RPC_ANYSOCK; + if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, + pertry, &so)) == NULL) { + clnt_pcreateerror("Cannot send MNT PRC"); + return (0); + } + clp->cl_auth = authunix_create_default(); + try.tv_sec = 3; + try.tv_usec = 0; + clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, dirp, + xdr_void, (caddr_t)0, try); + if (clnt_stat != RPC_SUCCESS) { + clnt_perror(clp, "Bad MNT RPC"); + return (0); + } + return (1); +} + +/* + * 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, hostlen, dirlen; + int mntsize, i; + + hostlen = strlen(hostname); + dirlen = strlen(dirp); + if ((hostlen + dirlen) >= MNAMELEN) + return (0); + memmove(name, hostname, hostlen); + name[hostlen] = ':'; + memmove(name + hostlen + 1, dirp, dirlen); + name[hostlen + dirlen + 1] = '\0'; + 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, RPCMNT_PATHLEN)); +} + +static void +usage() { + + (void)fprintf(stderr, "%s\n", + "usage: rpc.umntall [-h host] [-k] [-p path] [-t expire] [-v]"); + exit(1); +} -- cgit v1.1