11558Srgrimes/*- 21558Srgrimes * Copyright (c) 1980, 1989, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 4. Neither the name of the University nor the names of its contributors 141558Srgrimes * may be used to endorse or promote products derived from this software 151558Srgrimes * without specific prior written permission. 161558Srgrimes * 171558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271558Srgrimes * SUCH DAMAGE. 281558Srgrimes */ 291558Srgrimes 301558Srgrimes#ifndef lint 3138041Scharnierstatic const char copyright[] = 321558Srgrimes"@(#) Copyright (c) 1980, 1989, 1993\n\ 331558Srgrimes The Regents of the University of California. All rights reserved.\n"; 341558Srgrimes#endif /* not lint */ 351558Srgrimes 361558Srgrimes#ifndef lint 3738041Scharnier#if 0 3826683Sbdestatic char sccsid[] = "@(#)umount.c 8.8 (Berkeley) 5/8/95"; 3938041Scharnier#endif 4038041Scharnierstatic const char rcsid[] = 4150476Speter "$FreeBSD$"; 421558Srgrimes#endif /* not lint */ 431558Srgrimes 441558Srgrimes#include <sys/param.h> 451558Srgrimes#include <sys/mount.h> 4674462Salfred#include <sys/socket.h> 47117794Siedowse#include <sys/stat.h> 481558Srgrimes 491558Srgrimes#include <netdb.h> 501558Srgrimes#include <rpc/rpc.h> 51194880Sdfr#include <rpcsvc/mount.h> 521558Srgrimes 53117742Siedowse#include <ctype.h> 541558Srgrimes#include <err.h> 55117132Siedowse#include <errno.h> 561558Srgrimes#include <fstab.h> 571558Srgrimes#include <stdio.h> 581558Srgrimes#include <stdlib.h> 591558Srgrimes#include <string.h> 601558Srgrimes#include <unistd.h> 611558Srgrimes 6253550Sdillon#include "mounttab.h" 6353550Sdillon 64117794Siedowsetypedef enum { FIND, REMOVE, CHECKUNIQUE } dowhat; 651558Srgrimes 66227081Sedstatic struct addrinfo *nfshost_ai = NULL; 67227081Sedstatic int fflag, vflag; 68227081Sedstatic char *nfshost; 691558Srgrimes 70117720Siedowsestruct statfs *checkmntlist(char *); 7152340Sgreenint checkvfsname (const char *, char **); 72117794Siedowsestruct statfs *getmntentry(const char *fromname, const char *onname, 73117794Siedowse fsid_t *fsid, dowhat what); 7452340Sgreenchar **makevfslist (const char *); 7552340Sgreensize_t mntinfo (struct statfs **); 7674462Salfredint namematch (struct addrinfo *); 77117794Siedowseint parsehexfsid(const char *hex, fsid_t *fsid); 78201135Sdelphijint sacmp (void *, void *); 7952340Sgreenint umountall (char **); 8074462Salfredint checkname (char *, char **); 81117794Siedowseint umountfs(struct statfs *sfs); 8252340Sgreenvoid usage (void); 8352340Sgreenint xdr_dir (XDR *, char *); 8452340Sgreen 851558Srgrimesint 8652340Sgreenmain(int argc, char *argv[]) 871558Srgrimes{ 8874462Salfred int all, errs, ch, mntsize, error; 89117712Siedowse char **typelist = NULL; 90117712Siedowse struct statfs *mntbuf, *sfs; 9174462Salfred struct addrinfo hints; 921558Srgrimes 9352440Sgreen all = errs = 0; 94113220Smdodd while ((ch = getopt(argc, argv, "AaF:fh:t:v")) != -1) 951558Srgrimes switch (ch) { 9626683Sbde case 'A': 9726683Sbde all = 2; 9826683Sbde break; 991558Srgrimes case 'a': 1001558Srgrimes all = 1; 1011558Srgrimes break; 102113220Smdodd case 'F': 103113220Smdodd setfstab(optarg); 104113220Smdodd break; 1051558Srgrimes case 'f': 1061558Srgrimes fflag = MNT_FORCE; 1071558Srgrimes break; 10826683Sbde case 'h': /* -h implies -A. */ 10926683Sbde all = 2; 1101558Srgrimes nfshost = optarg; 1111558Srgrimes break; 1121558Srgrimes case 't': 11326683Sbde if (typelist != NULL) 11452340Sgreen err(1, "only one -t option may be specified"); 11526683Sbde typelist = makevfslist(optarg); 1161558Srgrimes break; 1171558Srgrimes case 'v': 1181558Srgrimes vflag = 1; 1191558Srgrimes break; 1201558Srgrimes default: 1211558Srgrimes usage(); 1221558Srgrimes /* NOTREACHED */ 1231558Srgrimes } 1241558Srgrimes argc -= optind; 1251558Srgrimes argv += optind; 1261558Srgrimes 127222466Srmacklem /* Start disks transferring immediately. */ 128222466Srmacklem if ((fflag & MNT_FORCE) == 0) 129222466Srmacklem sync(); 130222466Srmacklem 13138041Scharnier if ((argc == 0 && !all) || (argc != 0 && all)) 1321558Srgrimes usage(); 1331558Srgrimes 1341558Srgrimes /* -h implies "-t nfs" if no -t flag. */ 1351558Srgrimes if ((nfshost != NULL) && (typelist == NULL)) 13626683Sbde typelist = makevfslist("nfs"); 1378871Srgrimes 13874462Salfred if (nfshost != NULL) { 13974462Salfred memset(&hints, 0, sizeof hints); 14074462Salfred error = getaddrinfo(nfshost, NULL, &hints, &nfshost_ai); 14184868Siedowse if (error) 14284868Siedowse errx(1, "%s: %s", nfshost, gai_strerror(error)); 14374462Salfred } 14474462Salfred 14526683Sbde switch (all) { 14626683Sbde case 2: 14752340Sgreen if ((mntsize = mntinfo(&mntbuf)) <= 0) 14826683Sbde break; 14952340Sgreen /* 15052340Sgreen * We unmount the nfs-mounts in the reverse order 15152340Sgreen * that they were mounted. 15252340Sgreen */ 15352340Sgreen for (errs = 0, mntsize--; mntsize > 0; mntsize--) { 154117712Siedowse sfs = &mntbuf[mntsize]; 155117712Siedowse if (checkvfsname(sfs->f_fstypename, typelist)) 15626683Sbde continue; 157224040Smckusick if (strcmp(sfs->f_mntonname, "/dev") == 0) 158224040Smckusick continue; 159117794Siedowse if (umountfs(sfs) != 0) 16026683Sbde errs = 1; 16126683Sbde } 16252340Sgreen free(mntbuf); 16326683Sbde break; 16426683Sbde case 1: 1651558Srgrimes if (setfsent() == 0) 166113220Smdodd err(1, "%s", getfstab()); 16726683Sbde errs = umountall(typelist); 16826683Sbde break; 16926683Sbde case 0: 1701558Srgrimes for (errs = 0; *argv != NULL; ++argv) 17174462Salfred if (checkname(*argv, typelist) != 0) 17226683Sbde errs = 1; 17326683Sbde break; 17426683Sbde } 1751558Srgrimes exit(errs); 1761558Srgrimes} 1771558Srgrimes 1781558Srgrimesint 17952340Sgreenumountall(char **typelist) 1801558Srgrimes{ 181101651Smux struct xvfsconf vfc; 1821558Srgrimes struct fstab *fs; 18338041Scharnier int rval; 1841558Srgrimes char *cp; 18552374Sgreen static int firstcall = 1; 1861558Srgrimes 18752622Sgreen if ((fs = getfsent()) != NULL) 18852374Sgreen firstcall = 0; 18952622Sgreen else if (firstcall) 19052622Sgreen errx(1, "fstab reading failure"); 19152622Sgreen else 19252622Sgreen return (0); 19352340Sgreen do { 1941558Srgrimes /* Ignore the root. */ 1951558Srgrimes if (strcmp(fs->fs_file, "/") == 0) 1961558Srgrimes continue; 1971558Srgrimes /* 1981558Srgrimes * !!! 1991558Srgrimes * Historic practice: ignore unknown FSTAB_* fields. 2001558Srgrimes */ 2011558Srgrimes if (strcmp(fs->fs_type, FSTAB_RW) && 2021558Srgrimes strcmp(fs->fs_type, FSTAB_RO) && 2031558Srgrimes strcmp(fs->fs_type, FSTAB_RQ)) 2041558Srgrimes continue; 205102231Strhodes /* Ignore unknown file system types. */ 20665525Sdes if (getvfsbyname(fs->fs_vfstype, &vfc) == -1) 2071558Srgrimes continue; 20826683Sbde if (checkvfsname(fs->fs_vfstype, typelist)) 2091558Srgrimes continue; 2101558Srgrimes 2118871Srgrimes /* 212102231Strhodes * We want to unmount the file systems in the reverse order 2131558Srgrimes * that they were mounted. So, we save off the file name 2141558Srgrimes * in some allocated memory, and then call recursively. 2151558Srgrimes */ 2161558Srgrimes if ((cp = malloc((size_t)strlen(fs->fs_file) + 1)) == NULL) 21752340Sgreen err(1, "malloc failed"); 2181558Srgrimes (void)strcpy(cp, fs->fs_file); 21926683Sbde rval = umountall(typelist); 22074462Salfred rval = checkname(cp, typelist) || rval; 22152374Sgreen free(cp); 22252374Sgreen return (rval); 22352340Sgreen } while ((fs = getfsent()) != NULL); 2241558Srgrimes return (0); 2251558Srgrimes} 2261558Srgrimes 22774462Salfred/* 228117794Siedowse * Do magic checks on mountpoint/device/fsid, and then call unmount(2). 22974462Salfred */ 2301558Srgrimesint 231201135Sdelphijcheckname(char *mntname, char **typelist) 2321558Srgrimes{ 233117794Siedowse char buf[MAXPATHLEN]; 234117794Siedowse struct statfs sfsbuf; 235117794Siedowse struct stat sb; 236117712Siedowse struct statfs *sfs; 237117794Siedowse char *delimp; 238117794Siedowse dev_t dev; 239117794Siedowse int len; 2401558Srgrimes 24152340Sgreen /* 24252340Sgreen * 1. Check if the name exists in the mounttable. 24352340Sgreen */ 244201135Sdelphij sfs = checkmntlist(mntname); 24552340Sgreen /* 24652340Sgreen * 2. Remove trailing slashes if there are any. After that 24752340Sgreen * we look up the name in the mounttable again. 24852340Sgreen */ 249117132Siedowse if (sfs == NULL) { 250201135Sdelphij len = strlen(mntname); 251201135Sdelphij while (len > 1 && mntname[len - 1] == '/') 252201135Sdelphij mntname[--len] = '\0'; 253201135Sdelphij sfs = checkmntlist(mntname); 254117794Siedowse } 255117794Siedowse /* 256117794Siedowse * 3. Check if the deprecated NFS syntax with an '@' has been used 257117794Siedowse * and translate it to the ':' syntax. Look up the name in the 258117794Siedowse * mount table again. 259117794Siedowse */ 260201135Sdelphij if (sfs == NULL && (delimp = strrchr(mntname, '@')) != NULL) { 261201135Sdelphij snprintf(buf, sizeof(buf), "%s:%.*s", delimp + 1, 262201135Sdelphij (int)(delimp - mntname), mntname); 263117794Siedowse len = strlen(buf); 264121692Siedowse while (len > 1 && buf[len - 1] == '/') 265117794Siedowse buf[--len] = '\0'; 266117794Siedowse sfs = checkmntlist(buf); 267117794Siedowse } 268117794Siedowse /* 269117794Siedowse * 4. Resort to a statfs(2) call. This is the last check so that 270117794Siedowse * hung NFS filesystems for example can be unmounted without 271117794Siedowse * potentially blocking forever in statfs() as long as the 272117794Siedowse * filesystem is specified unambiguously. This covers all the 273117794Siedowse * hard cases such as symlinks and mismatches between the 274117794Siedowse * mount list and reality. 275117794Siedowse * We also do this if an ambiguous mount point was specified. 276117794Siedowse */ 277201135Sdelphij if (sfs == NULL || (getmntentry(NULL, mntname, NULL, FIND) != NULL && 278201135Sdelphij getmntentry(NULL, mntname, NULL, CHECKUNIQUE) == NULL)) { 279201135Sdelphij if (statfs(mntname, &sfsbuf) != 0) { 280201135Sdelphij warn("%s: statfs", mntname); 281201135Sdelphij } else if (stat(mntname, &sb) != 0) { 282201135Sdelphij warn("%s: stat", mntname); 283117794Siedowse } else if (S_ISDIR(sb.st_mode)) { 284201135Sdelphij /* Check that `mntname' is the root directory. */ 285117794Siedowse dev = sb.st_dev; 286201135Sdelphij snprintf(buf, sizeof(buf), "%s/..", mntname); 287117794Siedowse if (stat(buf, &sb) != 0) { 288117794Siedowse warn("%s: stat", buf); 289117794Siedowse } else if (sb.st_dev == dev) { 290117794Siedowse warnx("%s: not a file system root directory", 291201135Sdelphij mntname); 292117794Siedowse return (1); 293117794Siedowse } else 294117794Siedowse sfs = &sfsbuf; 2951558Srgrimes } 296117794Siedowse } 297117794Siedowse if (sfs == NULL) { 298201135Sdelphij warnx("%s: unknown file system", mntname); 299117794Siedowse return (1); 300117794Siedowse } 301117720Siedowse if (checkvfsname(sfs->f_fstypename, typelist)) 30226683Sbde return (1); 303117794Siedowse return (umountfs(sfs)); 30474462Salfred} 30574462Salfred 30674462Salfred/* 30774462Salfred * NFS stuff and unmount(2) call 30874462Salfred */ 30974462Salfredint 310117794Siedowseumountfs(struct statfs *sfs) 31174462Salfred{ 312117132Siedowse char fsidbuf[64]; 31374462Salfred enum clnt_stat clnt_stat; 31474462Salfred struct timeval try; 31574462Salfred struct addrinfo *ai, hints; 31674462Salfred int do_rpc; 31774462Salfred CLIENT *clp; 31874462Salfred char *nfsdirname, *orignfsdirname; 31974462Salfred char *hostp, *delimp; 32074462Salfred 32174462Salfred ai = NULL; 32280118Siedowse do_rpc = 0; 32380118Siedowse hostp = NULL; 32474462Salfred nfsdirname = delimp = orignfsdirname = NULL; 32574462Salfred memset(&hints, 0, sizeof hints); 32674462Salfred 327117794Siedowse if (strcmp(sfs->f_fstypename, "nfs") == 0) { 328117794Siedowse if ((nfsdirname = strdup(sfs->f_mntfromname)) == NULL) 32974462Salfred err(1, "strdup"); 33074462Salfred orignfsdirname = nfsdirname; 331203490Sume if (*nfsdirname == '[' && 332203490Sume (delimp = strchr(nfsdirname + 1, ']')) != NULL && 333203490Sume *(delimp + 1) == ':') { 334203490Sume hostp = nfsdirname + 1; 335203490Sume nfsdirname = delimp + 2; 336203490Sume } else if ((delimp = strrchr(nfsdirname, ':')) != NULL) { 337203490Sume hostp = nfsdirname; 338203490Sume nfsdirname = delimp + 1; 339203490Sume } 340203490Sume if (hostp != NULL) { 34174462Salfred *delimp = '\0'; 34274462Salfred getaddrinfo(hostp, NULL, &hints, &ai); 34374462Salfred if (ai == NULL) { 34474462Salfred warnx("can't get net id for host"); 34574462Salfred } 34674462Salfred } 34780118Siedowse 34880118Siedowse /* 34980118Siedowse * Check if we have to start the rpc-call later. 35080118Siedowse * If there are still identical nfs-names mounted, 35180118Siedowse * we skip the rpc-call. Obviously this has to 35280118Siedowse * happen before unmount(2), but it should happen 35380118Siedowse * after the previous namecheck. 35480118Siedowse * A non-NULL return means that this is the last 35580118Siedowse * mount from mntfromname that is still mounted. 35680118Siedowse */ 357117794Siedowse if (getmntentry(sfs->f_mntfromname, NULL, NULL, 358117794Siedowse CHECKUNIQUE) != NULL) 35980118Siedowse do_rpc = 1; 36074462Salfred } 36174462Salfred 362243082Seadler if (!namematch(ai)) { 363243082Seadler free(orignfsdirname); 36426683Sbde return (1); 365243082Seadler } 366117794Siedowse /* First try to unmount using the file system ID. */ 367117794Siedowse snprintf(fsidbuf, sizeof(fsidbuf), "FSID:%d:%d", sfs->f_fsid.val[0], 368117794Siedowse sfs->f_fsid.val[1]); 369117794Siedowse if (unmount(fsidbuf, fflag | MNT_BYFSID) != 0) { 370122804Siedowse /* XXX, non-root users get a zero fsid, so don't warn. */ 371122804Siedowse if (errno != ENOENT || sfs->f_fsid.val[0] != 0 || 372122804Siedowse sfs->f_fsid.val[1] != 0) 373122804Siedowse warn("unmount of %s failed", sfs->f_mntonname); 374243082Seadler if (errno != ENOENT) { 375243082Seadler free(orignfsdirname); 376117794Siedowse return (1); 377243082Seadler } 378123160Siedowse /* Compatibility for old kernels. */ 379123160Siedowse if (sfs->f_fsid.val[0] != 0 || sfs->f_fsid.val[1] != 0) 380123160Siedowse warnx("retrying using path instead of file system ID"); 381117794Siedowse if (unmount(sfs->f_mntonname, fflag) != 0) { 382117794Siedowse warn("unmount of %s failed", sfs->f_mntonname); 383243082Seadler free(orignfsdirname); 384117794Siedowse return (1); 385117132Siedowse } 386117132Siedowse } 387117794Siedowse /* Mark this this file system as unmounted. */ 388117794Siedowse getmntentry(NULL, NULL, &sfs->f_fsid, REMOVE); 38952340Sgreen if (vflag) 390117794Siedowse (void)printf("%s: unmount from %s\n", sfs->f_mntfromname, 391117794Siedowse sfs->f_mntonname); 39252340Sgreen /* 39352340Sgreen * Report to mountd-server which nfsname 39452340Sgreen * has been unmounted. 39552340Sgreen */ 39674462Salfred if (ai != NULL && !(fflag & MNT_FORCE) && do_rpc) { 397270258Speter clp = clnt_create(hostp, MOUNTPROG, MOUNTVERS3, "udp"); 39874462Salfred if (clp == NULL) { 39980118Siedowse warnx("%s: %s", hostp, 400194880Sdfr clnt_spcreateerror("MOUNTPROG")); 401243082Seadler free(orignfsdirname); 4021558Srgrimes return (1); 4031558Srgrimes } 40474462Salfred clp->cl_auth = authsys_create_default(); 4051558Srgrimes try.tv_sec = 20; 4061558Srgrimes try.tv_usec = 0; 407194880Sdfr clnt_stat = clnt_call(clp, MOUNTPROC_UMNT, (xdrproc_t)xdr_dir, 408113216Smdodd nfsdirname, (xdrproc_t)xdr_void, (caddr_t)0, try); 4091558Srgrimes if (clnt_stat != RPC_SUCCESS) { 41080118Siedowse warnx("%s: %s", hostp, 41180118Siedowse clnt_sperror(clp, "RPCMNT_UMOUNT")); 412243082Seadler free(orignfsdirname); 4131558Srgrimes return (1); 4141558Srgrimes } 41553550Sdillon /* 41653550Sdillon * Remove the unmounted entry from /var/db/mounttab. 41753550Sdillon */ 41880146Siedowse if (read_mtab()) { 41980146Siedowse clean_mtab(hostp, nfsdirname, vflag); 42080146Siedowse if(!write_mtab(vflag)) 42180118Siedowse warnx("cannot remove mounttab entry %s:%s", 42253550Sdillon hostp, nfsdirname); 42353550Sdillon free_mtab(); 42453550Sdillon } 4251558Srgrimes auth_destroy(clp->cl_auth); 4261558Srgrimes clnt_destroy(clp); 4271558Srgrimes } 428243082Seadler free(orignfsdirname); 4291558Srgrimes return (0); 4301558Srgrimes} 4311558Srgrimes 432117132Siedowsestruct statfs * 433117794Siedowsegetmntentry(const char *fromname, const char *onname, fsid_t *fsid, dowhat what) 4341558Srgrimes{ 43526683Sbde static struct statfs *mntbuf; 43652340Sgreen static size_t mntsize = 0; 43752340Sgreen static char *mntcheck = NULL; 438117794Siedowse struct statfs *sfs, *foundsfs; 43952340Sgreen int i, count; 4401558Srgrimes 44152340Sgreen if (mntsize <= 0) { 44252340Sgreen if ((mntsize = mntinfo(&mntbuf)) <= 0) 44352340Sgreen return (NULL); 4441558Srgrimes } 44552340Sgreen if (mntcheck == NULL) { 446117794Siedowse if ((mntcheck = calloc(mntsize + 1, sizeof(int))) == NULL) 44752340Sgreen err(1, "calloc"); 44852340Sgreen } 44952340Sgreen /* 450102231Strhodes * We want to get the file systems in the reverse order 451117794Siedowse * that they were mounted. Unmounted file systems are marked 452117794Siedowse * in a table called 'mntcheck'. 45352340Sgreen */ 454117794Siedowse count = 0; 455117794Siedowse foundsfs = NULL; 456117794Siedowse for (i = mntsize - 1; i >= 0; i--) { 457117794Siedowse if (mntcheck[i]) 458117794Siedowse continue; 459117794Siedowse sfs = &mntbuf[i]; 460117794Siedowse if (fromname != NULL && strcmp(sfs->f_mntfromname, 461117794Siedowse fromname) != 0) 462117794Siedowse continue; 463117794Siedowse if (onname != NULL && strcmp(sfs->f_mntonname, onname) != 0) 464117794Siedowse continue; 465117794Siedowse if (fsid != NULL && bcmp(&sfs->f_fsid, fsid, 466117794Siedowse sizeof(*fsid)) != 0) 467117794Siedowse continue; 468117132Siedowse 469117794Siedowse switch (what) { 470117794Siedowse case CHECKUNIQUE: 471117794Siedowse foundsfs = sfs; 472117794Siedowse count++; 473117794Siedowse continue; 474117794Siedowse case REMOVE: 475117794Siedowse mntcheck[i] = 1; 476117794Siedowse break; 477117794Siedowse default: 478117794Siedowse break; 4791558Srgrimes } 480117794Siedowse return (sfs); 4811558Srgrimes } 482117794Siedowse 483117794Siedowse if (what == CHECKUNIQUE && count == 1) 484117794Siedowse return (foundsfs); 485117794Siedowse return (NULL); 4861558Srgrimes} 4871558Srgrimes 4881558Srgrimesint 489201135Sdelphijsacmp(void *sa1, void *sa2) 4901558Srgrimes{ 49174462Salfred void *p1, *p2; 49274462Salfred int len; 4931558Srgrimes 494201135Sdelphij if (((struct sockaddr *)sa1)->sa_family != 495201135Sdelphij ((struct sockaddr *)sa2)->sa_family) 4961558Srgrimes return (1); 4971558Srgrimes 498201135Sdelphij switch (((struct sockaddr *)sa1)->sa_family) { 49974462Salfred case AF_INET: 50074462Salfred p1 = &((struct sockaddr_in *)sa1)->sin_addr; 50174462Salfred p2 = &((struct sockaddr_in *)sa2)->sin_addr; 50274462Salfred len = 4; 50374462Salfred break; 50474462Salfred case AF_INET6: 50574462Salfred p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr; 50674462Salfred p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr; 50774462Salfred len = 16; 50874462Salfred if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != 50974462Salfred ((struct sockaddr_in6 *)sa2)->sin6_scope_id) 51074462Salfred return (1); 51174462Salfred break; 51274462Salfred default: 5131558Srgrimes return (1); 51474462Salfred } 5151558Srgrimes 51674462Salfred return memcmp(p1, p2, len); 51774462Salfred} 51874462Salfred 51974462Salfredint 52074462Salfrednamematch(struct addrinfo *ai) 52174462Salfred{ 52274462Salfred struct addrinfo *aip; 52374462Salfred 52474462Salfred if (nfshost == NULL || nfshost_ai == NULL) 52574462Salfred return (1); 52674462Salfred 52774462Salfred while (ai != NULL) { 52874462Salfred aip = nfshost_ai; 52974462Salfred while (aip != NULL) { 53074462Salfred if (sacmp(ai->ai_addr, aip->ai_addr) == 0) 5311558Srgrimes return (1); 53274462Salfred aip = aip->ai_next; 5331558Srgrimes } 53474462Salfred ai = ai->ai_next; 5351558Srgrimes } 53674462Salfred 5371558Srgrimes return (0); 5381558Srgrimes} 5391558Srgrimes 540117132Siedowsestruct statfs * 541201135Sdelphijcheckmntlist(char *mntname) 54252340Sgreen{ 543117132Siedowse struct statfs *sfs; 544117794Siedowse fsid_t fsid; 54552340Sgreen 546117794Siedowse sfs = NULL; 547201135Sdelphij if (parsehexfsid(mntname, &fsid) == 0) 548117794Siedowse sfs = getmntentry(NULL, NULL, &fsid, FIND); 549117132Siedowse if (sfs == NULL) 550201135Sdelphij sfs = getmntentry(NULL, mntname, NULL, FIND); 551117742Siedowse if (sfs == NULL) 552201135Sdelphij sfs = getmntentry(mntname, NULL, NULL, FIND); 553117132Siedowse return (sfs); 55452340Sgreen} 55552340Sgreen 55652340Sgreensize_t 55752340Sgreenmntinfo(struct statfs **mntbuf) 55852340Sgreen{ 55952340Sgreen static struct statfs *origbuf; 56052340Sgreen size_t bufsize; 56152340Sgreen int mntsize; 56252340Sgreen 56353550Sdillon mntsize = getfsstat(NULL, 0, MNT_NOWAIT); 56452340Sgreen if (mntsize <= 0) 56552340Sgreen return (0); 56652340Sgreen bufsize = (mntsize + 1) * sizeof(struct statfs); 56752340Sgreen if ((origbuf = malloc(bufsize)) == NULL) 56852340Sgreen err(1, "malloc"); 56952340Sgreen mntsize = getfsstat(origbuf, (long)bufsize, MNT_NOWAIT); 57052340Sgreen *mntbuf = origbuf; 57152340Sgreen return (mntsize); 57252340Sgreen} 57352340Sgreen 574117794Siedowse/* 575123160Siedowse * Convert a hexadecimal filesystem ID to an fsid_t. 576117794Siedowse * Returns 0 on success. 577117794Siedowse */ 578117794Siedowseint 579117794Siedowseparsehexfsid(const char *hex, fsid_t *fsid) 58052340Sgreen{ 581117794Siedowse char hexbuf[3]; 582117794Siedowse int i; 583117794Siedowse 584117794Siedowse if (strlen(hex) != sizeof(*fsid) * 2) 585117794Siedowse return (-1); 586117794Siedowse hexbuf[2] = '\0'; 587121692Siedowse for (i = 0; i < (int)sizeof(*fsid); i++) { 588117794Siedowse hexbuf[0] = hex[i * 2]; 589117794Siedowse hexbuf[1] = hex[i * 2 + 1]; 590117794Siedowse if (!isxdigit(hexbuf[0]) || !isxdigit(hexbuf[1])) 591117794Siedowse return (-1); 592117794Siedowse ((u_char *)fsid)[i] = strtol(hexbuf, NULL, 16); 59352340Sgreen } 594117794Siedowse return (0); 59552340Sgreen} 59652340Sgreen 5971558Srgrimes/* 5981558Srgrimes * xdr routines for mount rpc's 5991558Srgrimes */ 6001558Srgrimesint 60152340Sgreenxdr_dir(XDR *xdrsp, char *dirp) 6021558Srgrimes{ 60352340Sgreen 604194880Sdfr return (xdr_string(xdrsp, &dirp, MNTPATHLEN)); 6051558Srgrimes} 6061558Srgrimes 6071558Srgrimesvoid 608201252Sedusage(void) 6091558Srgrimes{ 61052340Sgreen 61126742Scharnier (void)fprintf(stderr, "%s\n%s\n", 612219955Sru "usage: umount [-fv] special ... | node ... | fsid ...", 613141611Sru " umount -a | -A [-F fstab] [-fv] [-h host] [-t type]"); 6141558Srgrimes exit(1); 6151558Srgrimes} 616