rpc.umntall.c revision 56038
153494Sdillon/* 253494Sdillon * Copyright (c) 1999 Martin Blapp 353494Sdillon * All rights reserved. 453494Sdillon * 553494Sdillon * Redistribution and use in source and binary forms, with or without 653494Sdillon * modification, are permitted provided that the following conditions 753494Sdillon * are met: 853494Sdillon * 1. Redistributions of source code must retain the above copyright 953494Sdillon * notice, this list of conditions and the following disclaimer. 1053494Sdillon * 2. Redistributions in binary form must reproduce the above copyright 1153494Sdillon * notice, this list of conditions and the following disclaimer in the 1253494Sdillon * documentation and/or other materials provided with the distribution. 1353494Sdillon * 1453494Sdillon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1553494Sdillon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1653494Sdillon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1753494Sdillon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1853494Sdillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1953494Sdillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2053494Sdillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2153494Sdillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2253494Sdillon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2353494Sdillon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2453494Sdillon * SUCH DAMAGE. 2553494Sdillon * 2653494Sdillon */ 2753494Sdillon 2853494Sdillon#ifndef lint 2953494Sdillonstatic const char rcsid[] = 3053494Sdillon "$FreeBSD: head/usr.sbin/rpc.umntall/rpc.umntall.c 56038 2000-01-15 14:28:14Z green $"; 3153494Sdillon#endif /* not lint */ 3253494Sdillon 3353494Sdillon#include <sys/param.h> 3453494Sdillon#include <sys/ucred.h> 3553494Sdillon#include <sys/mount.h> 3653494Sdillon 3753494Sdillon#include <rpc/rpc.h> 3853494Sdillon#include <nfs/rpcv2.h> 3953494Sdillon 4053494Sdillon#include <err.h> 4153494Sdillon#include <netdb.h> 4253494Sdillon#include <stdio.h> 4353494Sdillon#include <stdlib.h> 4453494Sdillon#include <string.h> 4553494Sdillon#include <unistd.h> 4653494Sdillon 4753494Sdillon#include "mounttab.h" 4853494Sdillon 4953494Sdillonint verbose; 5053494Sdillon 5153494Sdillonstatic int do_umount (char *, char *); 5253494Sdillonstatic int do_umntall (char *); 5353494Sdillonstatic int is_mounted (char *, char *); 5453494Sdillonstatic void usage (void); 5553494Sdillonint xdr_dir (XDR *, char *); 5653494Sdillon 5753494Sdillonstruct mtablist *mtabhead; 5853494Sdillon 5953494Sdillonint 6053494Sdillonmain(int argc, char **argv) { 6153494Sdillon int ch, keep, success, pathlen; 6253494Sdillon time_t expire, *now; 6353494Sdillon char *host, *path; 6453494Sdillon struct mtablist *mtab; 6553494Sdillon 6653494Sdillon mtab = NULL; 6753494Sdillon now = NULL; 6853494Sdillon expire = 0; 6953494Sdillon host = path = '\0'; 7053494Sdillon success = keep = verbose = 0; 7153494Sdillon while ((ch = getopt(argc, argv, "h:kp:ve:")) != -1) 7253494Sdillon switch (ch) { 7353494Sdillon case 'h': 7453494Sdillon host = optarg; 7553494Sdillon break; 7653494Sdillon case 'e': 7753494Sdillon expire = (time_t)optarg; 7853494Sdillon break; 7953494Sdillon case 'k': 8053494Sdillon keep = 1; 8153494Sdillon break; 8253494Sdillon case 'p': 8353494Sdillon path = optarg; 8453494Sdillon break; 8553494Sdillon case 'v': 8653494Sdillon verbose = 1; 8753494Sdillon break; 8853494Sdillon case '?': 8953494Sdillon usage(); 9053494Sdillon default: 9153494Sdillon } 9253494Sdillon argc -= optind; 9353494Sdillon argv += optind; 9453494Sdillon 9553494Sdillon /* Ignore SIGINT and SIGQUIT during shutdown */ 9653494Sdillon signal(SIGINT, SIG_IGN); 9753494Sdillon signal(SIGQUIT, SIG_IGN); 9853494Sdillon 9956038Sgreen /* Default expiretime is one day */ 10053494Sdillon if (expire == 0) 10156038Sgreen expire = 86400; 10253494Sdillon /* 10353494Sdillon * Read PATH_MOUNTTAB and check each entry 10453494Sdillon * and do finally the unmounts. 10553494Sdillon */ 10653494Sdillon if (host == NULL && path == NULL) { 10753494Sdillon if (!read_mtab(mtab)) { 10853494Sdillon if (verbose) 10956038Sgreen warnx("nothing to do, %s does not exist", 11053494Sdillon PATH_MOUNTTAB); 11153494Sdillon } 11253494Sdillon for (mtab = mtabhead; mtab != NULL; mtab = mtab->mtab_next) { 11354341Sgrog if (*mtab->mtab_host != '\0' || 11454341Sgrog mtab->mtab_time <= (time(now) - expire)) { 11553494Sdillon if (keep && is_mounted(mtab->mtab_host, 11653494Sdillon mtab->mtab_dirp)) { 11753494Sdillon if (verbose) { 11856038Sgreen warnx("skip entry %s:%s", 11953494Sdillon mtab->mtab_host, 12053494Sdillon mtab->mtab_dirp); 12153494Sdillon } 12254341Sgrog } else if (do_umount(mtab->mtab_host, 12356038Sgreen mtab->mtab_dirp) || 12456038Sgreen mtab->mtab_time <= (time(now) - expire)) { 12554341Sgrog clean_mtab(mtab->mtab_host, 12654341Sgrog mtab->mtab_dirp); 12754341Sgrog } 12853494Sdillon } 12953494Sdillon } 13053494Sdillon /* Only do a RPC UMNTALL for this specific host */ 13153494Sdillon } else if (host != NULL && path == NULL) { 13253494Sdillon if (!do_umntall(host)) 13353494Sdillon exit(1); 13453494Sdillon else 13553494Sdillon success = 1; 13653494Sdillon /* Someone forgot to enter a hostname */ 13753494Sdillon } else if (host == NULL && path != NULL) 13853494Sdillon usage(); 13953494Sdillon /* Only do a RPC UMOUNT for this specific mount */ 14053494Sdillon else { 14153494Sdillon for (pathlen = strlen(path); 14253494Sdillon pathlen > 1 && path[pathlen - 1] == '/'; pathlen--) 14353494Sdillon path[pathlen - 1] = '\0'; 14453494Sdillon if (!do_umount(host, path)) 14553494Sdillon exit(1); 14653494Sdillon else 14753494Sdillon success = 1; 14853494Sdillon } 14953494Sdillon /* Write and unlink PATH_MOUNTTAB if necessary */ 15053494Sdillon if (success) { 15153494Sdillon if (verbose) 15253494Sdillon warnx("UMOUNT RPC successfully sent to %s", host); 15353494Sdillon if (read_mtab(mtab)) { 15453494Sdillon mtab = mtabhead; 15553494Sdillon clean_mtab(host, path); 15653494Sdillon } 15753494Sdillon } 15853494Sdillon if (!write_mtab()) { 15953494Sdillon free_mtab(); 16053494Sdillon exit(1); 16153494Sdillon } 16253494Sdillon free_mtab(); 16353494Sdillon exit(0); 16453494Sdillon} 16553494Sdillon 16653494Sdillon/* 16753494Sdillon * Send a RPC_MNT UMNTALL request to hostname. 16854341Sgrog * XXX This works for all mountd implementations, 16954341Sgrog * but produces a RPC IOERR on non FreeBSD systems. 17053494Sdillon */ 17153494Sdillonint 17253494Sdillondo_umntall(char *hostname) { 17353494Sdillon enum clnt_stat clnt_stat; 17453494Sdillon struct hostent *hp; 17553494Sdillon struct sockaddr_in saddr; 17653494Sdillon struct timeval pertry, try; 17753494Sdillon int so; 17853494Sdillon CLIENT *clp; 17953494Sdillon 18053494Sdillon if ((hp = gethostbyname(hostname)) == NULL) { 18153494Sdillon warnx("gethostbyname(%s) failed", hostname); 18253494Sdillon return (0); 18353494Sdillon } 18453494Sdillon memset(&saddr, 0, sizeof(saddr)); 18553494Sdillon saddr.sin_family = AF_INET; 18653494Sdillon saddr.sin_port = 0; 18753494Sdillon memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length, 18853494Sdillon sizeof(saddr.sin_addr))); 18953494Sdillon pertry.tv_sec = 3; 19053494Sdillon pertry.tv_usec = 0; 19153494Sdillon so = RPC_ANYSOCK; 19253494Sdillon if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, 19353494Sdillon pertry, &so)) == NULL) { 19453494Sdillon clnt_pcreateerror("Cannot send MNT PRC"); 19553494Sdillon return (0); 19653494Sdillon } 19753494Sdillon clp->cl_auth = authunix_create_default(); 19853494Sdillon try.tv_sec = 3; 19953494Sdillon try.tv_usec = 0; 20053494Sdillon clnt_stat = clnt_call(clp, RPCMNT_UMNTALL, xdr_void, (caddr_t)0, 20153494Sdillon xdr_void, (caddr_t)0, try); 20253494Sdillon if (clnt_stat != RPC_SUCCESS) { 20353494Sdillon clnt_perror(clp, "Bad MNT RPC"); 20453494Sdillon return (0); 20553494Sdillon } else 20653494Sdillon return (1); 20753494Sdillon} 20853494Sdillon 20953494Sdillon/* 21053494Sdillon * Send a RPC_MNT UMOUNT request for dirp to hostname. 21153494Sdillon */ 21253494Sdillonint 21353494Sdillondo_umount(char *hostname, char *dirp) { 21453494Sdillon enum clnt_stat clnt_stat; 21553494Sdillon struct hostent *hp; 21653494Sdillon struct sockaddr_in saddr; 21753494Sdillon struct timeval pertry, try; 21853494Sdillon CLIENT *clp; 21953494Sdillon int so; 22053494Sdillon 22153494Sdillon if ((hp = gethostbyname(hostname)) == NULL) { 22253494Sdillon warnx("gethostbyname(%s) failed", hostname); 22353494Sdillon return (0); 22453494Sdillon } 22553494Sdillon memset(&saddr, 0, sizeof(saddr)); 22653494Sdillon saddr.sin_family = AF_INET; 22753494Sdillon saddr.sin_port = 0; 22853494Sdillon memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length, 22953494Sdillon sizeof(saddr.sin_addr))); 23053494Sdillon pertry.tv_sec = 3; 23153494Sdillon pertry.tv_usec = 0; 23253494Sdillon so = RPC_ANYSOCK; 23353494Sdillon if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, 23453494Sdillon pertry, &so)) == NULL) { 23553494Sdillon clnt_pcreateerror("Cannot send MNT PRC"); 23653494Sdillon return (0); 23753494Sdillon } 23853494Sdillon clp->cl_auth = authunix_create_default(); 23953494Sdillon try.tv_sec = 3; 24053494Sdillon try.tv_usec = 0; 24153494Sdillon clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, dirp, 24253494Sdillon xdr_void, (caddr_t)0, try); 24353494Sdillon if (clnt_stat != RPC_SUCCESS) { 24453494Sdillon clnt_perror(clp, "Bad MNT RPC"); 24553494Sdillon return (0); 24653494Sdillon } 24753494Sdillon return (1); 24853494Sdillon} 24953494Sdillon 25053494Sdillon/* 25153494Sdillon * Check if the entry is still/already mounted. 25253494Sdillon */ 25353494Sdillonint 25453494Sdillonis_mounted(char *hostname, char *dirp) { 25553494Sdillon struct statfs *mntbuf; 25653494Sdillon char name[MNAMELEN + 1]; 25753494Sdillon size_t bufsize, hostlen, dirlen; 25853494Sdillon int mntsize, i; 25953494Sdillon 26053494Sdillon hostlen = strlen(hostname); 26153494Sdillon dirlen = strlen(dirp); 26253494Sdillon if ((hostlen + dirlen) >= MNAMELEN) 26353494Sdillon return (0); 26453494Sdillon memmove(name, hostname, hostlen); 26553494Sdillon name[hostlen] = ':'; 26653494Sdillon memmove(name + hostlen + 1, dirp, dirlen); 26753494Sdillon name[hostlen + dirlen + 1] = '\0'; 26853494Sdillon mntsize = getfsstat(NULL, 0, MNT_NOWAIT); 26953494Sdillon if (mntsize <= 0) 27053494Sdillon return (0); 27153494Sdillon bufsize = (mntsize + 1) * sizeof(struct statfs); 27253494Sdillon if ((mntbuf = malloc(bufsize)) == NULL) 27353494Sdillon err(1, "malloc"); 27453494Sdillon mntsize = getfsstat(mntbuf, (long)bufsize, MNT_NOWAIT); 27553494Sdillon for (i = mntsize - 1; i >= 0; i--) { 27653494Sdillon if (strcmp(mntbuf[i].f_mntfromname, name) == 0) { 27753494Sdillon free(mntbuf); 27853494Sdillon return (1); 27953494Sdillon } 28053494Sdillon } 28153494Sdillon free(mntbuf); 28253494Sdillon return (0); 28353494Sdillon} 28453494Sdillon 28553494Sdillon/* 28653494Sdillon * xdr routines for mount rpc's 28753494Sdillon */ 28853494Sdillonint 28953494Sdillonxdr_dir(XDR *xdrsp, char *dirp) { 29053494Sdillon 29153494Sdillon return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 29253494Sdillon} 29353494Sdillon 29453494Sdillonstatic void 29553494Sdillonusage() { 29653494Sdillon 29753494Sdillon (void)fprintf(stderr, "%s\n", 29853494Sdillon "usage: rpc.umntall [-h host] [-k] [-p path] [-t expire] [-v]"); 29953494Sdillon exit(1); 30053494Sdillon} 301