1168404Spjd/*- 2168404Spjd * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3168404Spjd * All rights reserved. 4168404Spjd * 5168404Spjd * Redistribution and use in source and binary forms, with or without 6168404Spjd * modification, are permitted provided that the following conditions 7168404Spjd * are met: 8168404Spjd * 1. Redistributions of source code must retain the above copyright 9168404Spjd * notice, this list of conditions and the following disclaimer. 10168404Spjd * 2. Redistributions in binary form must reproduce the above copyright 11168404Spjd * notice, this list of conditions and the following disclaimer in the 12168404Spjd * documentation and/or other materials provided with the distribution. 13168404Spjd * 14168404Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15168404Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16168404Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17168404Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18168404Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19168404Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20168404Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21168404Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22168404Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23168404Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24168404Spjd * SUCH DAMAGE. 25168404Spjd */ 26168404Spjd 27168404Spjd/* 28168404Spjd * This file implements Solaris compatible getmntany() and hasmntopt() 29168404Spjd * functions. 30168404Spjd */ 31168404Spjd 32168404Spjd#include <sys/cdefs.h> 33168404Spjd__FBSDID("$FreeBSD$"); 34168404Spjd 35168404Spjd#include <sys/param.h> 36168404Spjd#include <sys/mount.h> 37168404Spjd#include <sys/mntent.h> 38168404Spjd#include <sys/mnttab.h> 39209962Smm 40209962Smm#include <ctype.h> 41209962Smm#include <errno.h> 42168404Spjd#include <stdio.h> 43185029Spjd#include <stdlib.h> 44185029Spjd#include <string.h> 45168404Spjd 46168404Spjdstatic char * 47168404Spjdmntopt(char **p) 48168404Spjd{ 49168404Spjd char *cp = *p; 50168404Spjd char *retstr; 51168404Spjd 52168404Spjd while (*cp && isspace(*cp)) 53168404Spjd cp++; 54168404Spjd 55168404Spjd retstr = cp; 56168404Spjd while (*cp && *cp != ',') 57168404Spjd cp++; 58168404Spjd 59168404Spjd if (*cp) { 60168404Spjd *cp = '\0'; 61168404Spjd cp++; 62168404Spjd } 63168404Spjd 64168404Spjd *p = cp; 65168404Spjd return (retstr); 66168404Spjd} 67168404Spjd 68168404Spjdchar * 69168404Spjdhasmntopt(struct mnttab *mnt, char *opt) 70168404Spjd{ 71168404Spjd char tmpopts[MNT_LINE_MAX]; 72168404Spjd char *f, *opts = tmpopts; 73168404Spjd 74168404Spjd if (mnt->mnt_mntopts == NULL) 75168404Spjd return (NULL); 76168404Spjd (void) strcpy(opts, mnt->mnt_mntopts); 77168404Spjd f = mntopt(&opts); 78168404Spjd for (; *f; f = mntopt(&opts)) { 79168404Spjd if (strncmp(opt, f, strlen(opt)) == 0) 80168404Spjd return (f - tmpopts + mnt->mnt_mntopts); 81168404Spjd } 82168404Spjd return (NULL); 83168404Spjd} 84168404Spjd 85168404Spjdstatic void 86168404Spjdoptadd(char *mntopts, size_t size, const char *opt) 87168404Spjd{ 88168404Spjd 89168404Spjd if (mntopts[0] != '\0') 90168404Spjd strlcat(mntopts, ",", size); 91168404Spjd strlcat(mntopts, opt, size); 92168404Spjd} 93168404Spjd 94209962Smmvoid 95209962Smmstatfs2mnttab(struct statfs *sfs, struct mnttab *mp) 96168404Spjd{ 97168404Spjd static char mntopts[MNTMAXSTR]; 98209962Smm long flags; 99168404Spjd 100168404Spjd mntopts[0] = '\0'; 101168404Spjd 102209962Smm flags = sfs->f_flags; 103209962Smm#define OPTADD(opt) optadd(mntopts, sizeof(mntopts), (opt)) 104209962Smm if (flags & MNT_RDONLY) 105209962Smm OPTADD(MNTOPT_RO); 106209962Smm else 107209962Smm OPTADD(MNTOPT_RW); 108209962Smm if (flags & MNT_NOSUID) 109209962Smm OPTADD(MNTOPT_NOSUID); 110209962Smm else 111209962Smm OPTADD(MNTOPT_SETUID); 112209962Smm if (flags & MNT_UPDATE) 113209962Smm OPTADD(MNTOPT_REMOUNT); 114209962Smm if (flags & MNT_NOATIME) 115209962Smm OPTADD(MNTOPT_NOATIME); 116209962Smm else 117209962Smm OPTADD(MNTOPT_ATIME); 118209962Smm OPTADD(MNTOPT_NOXATTR); 119209962Smm if (flags & MNT_NOEXEC) 120209962Smm OPTADD(MNTOPT_NOEXEC); 121209962Smm else 122209962Smm OPTADD(MNTOPT_EXEC); 123209962Smm#undef OPTADD 124209962Smm mp->mnt_special = sfs->f_mntfromname; 125209962Smm mp->mnt_mountp = sfs->f_mntonname; 126209962Smm mp->mnt_fstype = sfs->f_fstypename; 127209962Smm mp->mnt_mntopts = mntopts; 128209962Smm} 129209962Smm 130209962Smmstatic struct statfs *gsfs = NULL; 131209962Smmstatic int allfs = 0; 132209962Smm 133209962Smmstatic int 134209962Smmstatfs_init(void) 135209962Smm{ 136209962Smm struct statfs *sfs; 137209962Smm int error; 138209962Smm 139209962Smm if (gsfs != NULL) { 140209962Smm free(gsfs); 141209962Smm gsfs = NULL; 142168404Spjd } 143209962Smm allfs = getfsstat(NULL, 0, MNT_WAIT); 144209962Smm if (allfs == -1) 145209962Smm goto fail; 146209962Smm gsfs = malloc(sizeof(gsfs[0]) * allfs * 2); 147209962Smm if (gsfs == NULL) 148209962Smm goto fail; 149209962Smm allfs = getfsstat(gsfs, (long)(sizeof(gsfs[0]) * allfs * 2), 150209962Smm MNT_WAIT); 151209962Smm if (allfs == -1) 152209962Smm goto fail; 153209962Smm sfs = realloc(gsfs, allfs * sizeof(gsfs[0])); 154209962Smm if (sfs != NULL) 155209962Smm gsfs = sfs; 156209962Smm return (0); 157209962Smmfail: 158209962Smm error = errno; 159209962Smm if (gsfs != NULL) 160209962Smm free(gsfs); 161209962Smm gsfs = NULL; 162209962Smm allfs = 0; 163209962Smm return (error); 164209962Smm} 165209962Smm 166209962Smmint 167209962Smmgetmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp) 168209962Smm{ 169209962Smm struct statfs *sfs; 170209962Smm int i, error; 171209962Smm 172209962Smm error = statfs_init(); 173209962Smm if (error != 0) 174209962Smm return (error); 175209962Smm 176209962Smm for (i = 0; i < allfs; i++) { 177168404Spjd if (mrefp->mnt_special != NULL && 178209962Smm strcmp(mrefp->mnt_special, gsfs[i].f_mntfromname) != 0) { 179168404Spjd continue; 180168404Spjd } 181168404Spjd if (mrefp->mnt_mountp != NULL && 182209962Smm strcmp(mrefp->mnt_mountp, gsfs[i].f_mntonname) != 0) { 183168404Spjd continue; 184168404Spjd } 185168404Spjd if (mrefp->mnt_fstype != NULL && 186209962Smm strcmp(mrefp->mnt_fstype, gsfs[i].f_fstypename) != 0) { 187168404Spjd continue; 188168404Spjd } 189209962Smm statfs2mnttab(&gsfs[i], mgetp); 190168404Spjd return (0); 191168404Spjd } 192168404Spjd return (-1); 193168404Spjd} 194209962Smm 195209962Smmint 196209962Smmgetmntent(FILE *fp, struct mnttab *mp) 197209962Smm{ 198209962Smm struct statfs *sfs; 199209962Smm int error, nfs; 200209962Smm 201209962Smm nfs = (int)lseek(fileno(fp), 0, SEEK_CUR); 202209962Smm if (nfs == -1) 203209962Smm return (errno); 204209962Smm /* If nfs is 0, we want to refresh out cache. */ 205209962Smm if (nfs == 0 || gsfs == NULL) { 206209962Smm error = statfs_init(); 207209962Smm if (error != 0) 208209962Smm return (error); 209209962Smm } 210209962Smm if (nfs >= allfs) 211209962Smm return (-1); 212209962Smm statfs2mnttab(&gsfs[nfs], mp); 213209962Smm if (lseek(fileno(fp), 1, SEEK_CUR) == -1) 214209962Smm return (errno); 215209962Smm return (0); 216209962Smm} 217