1*eda14cbcSMatt Macy /* 2*eda14cbcSMatt Macy * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3*eda14cbcSMatt Macy * All rights reserved. 4*eda14cbcSMatt Macy * 5*eda14cbcSMatt Macy * Redistribution and use in source and binary forms, with or without 6*eda14cbcSMatt Macy * modification, are permitted provided that the following conditions 7*eda14cbcSMatt Macy * are met: 8*eda14cbcSMatt Macy * 1. Redistributions of source code must retain the above copyright 9*eda14cbcSMatt Macy * notice, this list of conditions and the following disclaimer. 10*eda14cbcSMatt Macy * 2. Redistributions in binary form must reproduce the above copyright 11*eda14cbcSMatt Macy * notice, this list of conditions and the following disclaimer in the 12*eda14cbcSMatt Macy * documentation and/or other materials provided with the distribution. 13*eda14cbcSMatt Macy * 14*eda14cbcSMatt Macy * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15*eda14cbcSMatt Macy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*eda14cbcSMatt Macy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*eda14cbcSMatt Macy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18*eda14cbcSMatt Macy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*eda14cbcSMatt Macy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*eda14cbcSMatt Macy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*eda14cbcSMatt Macy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*eda14cbcSMatt Macy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*eda14cbcSMatt Macy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*eda14cbcSMatt Macy * SUCH DAMAGE. 25*eda14cbcSMatt Macy */ 26*eda14cbcSMatt Macy 27*eda14cbcSMatt Macy /* 28*eda14cbcSMatt Macy * This file implements Solaris compatible getmntany() and hasmntopt() 29*eda14cbcSMatt Macy * functions. 30*eda14cbcSMatt Macy */ 31*eda14cbcSMatt Macy 32*eda14cbcSMatt Macy #include <sys/cdefs.h> 33*eda14cbcSMatt Macy __FBSDID("$FreeBSD$"); 34*eda14cbcSMatt Macy 35*eda14cbcSMatt Macy #include <sys/param.h> 36*eda14cbcSMatt Macy #include <sys/mount.h> 37*eda14cbcSMatt Macy #include <sys/mntent.h> 38*eda14cbcSMatt Macy #include <sys/mnttab.h> 39*eda14cbcSMatt Macy 40*eda14cbcSMatt Macy #include <ctype.h> 41*eda14cbcSMatt Macy #include <errno.h> 42*eda14cbcSMatt Macy #include <stdio.h> 43*eda14cbcSMatt Macy #include <stdlib.h> 44*eda14cbcSMatt Macy #include <string.h> 45*eda14cbcSMatt Macy 46*eda14cbcSMatt Macy static char * 47*eda14cbcSMatt Macy mntopt(char **p) 48*eda14cbcSMatt Macy { 49*eda14cbcSMatt Macy char *cp = *p; 50*eda14cbcSMatt Macy char *retstr; 51*eda14cbcSMatt Macy 52*eda14cbcSMatt Macy while (*cp && isspace(*cp)) 53*eda14cbcSMatt Macy cp++; 54*eda14cbcSMatt Macy 55*eda14cbcSMatt Macy retstr = cp; 56*eda14cbcSMatt Macy while (*cp && *cp != ',') 57*eda14cbcSMatt Macy cp++; 58*eda14cbcSMatt Macy 59*eda14cbcSMatt Macy if (*cp) { 60*eda14cbcSMatt Macy *cp = '\0'; 61*eda14cbcSMatt Macy cp++; 62*eda14cbcSMatt Macy } 63*eda14cbcSMatt Macy 64*eda14cbcSMatt Macy *p = cp; 65*eda14cbcSMatt Macy return (retstr); 66*eda14cbcSMatt Macy } 67*eda14cbcSMatt Macy 68*eda14cbcSMatt Macy char * 69*eda14cbcSMatt Macy hasmntopt(struct mnttab *mnt, char *opt) 70*eda14cbcSMatt Macy { 71*eda14cbcSMatt Macy char tmpopts[MNT_LINE_MAX]; 72*eda14cbcSMatt Macy char *f, *opts = tmpopts; 73*eda14cbcSMatt Macy 74*eda14cbcSMatt Macy if (mnt->mnt_mntopts == NULL) 75*eda14cbcSMatt Macy return (NULL); 76*eda14cbcSMatt Macy (void) strcpy(opts, mnt->mnt_mntopts); 77*eda14cbcSMatt Macy f = mntopt(&opts); 78*eda14cbcSMatt Macy for (; *f; f = mntopt(&opts)) { 79*eda14cbcSMatt Macy if (strncmp(opt, f, strlen(opt)) == 0) 80*eda14cbcSMatt Macy return (f - tmpopts + mnt->mnt_mntopts); 81*eda14cbcSMatt Macy } 82*eda14cbcSMatt Macy return (NULL); 83*eda14cbcSMatt Macy } 84*eda14cbcSMatt Macy 85*eda14cbcSMatt Macy static void 86*eda14cbcSMatt Macy optadd(char *mntopts, size_t size, const char *opt) 87*eda14cbcSMatt Macy { 88*eda14cbcSMatt Macy 89*eda14cbcSMatt Macy if (mntopts[0] != '\0') 90*eda14cbcSMatt Macy strlcat(mntopts, ",", size); 91*eda14cbcSMatt Macy strlcat(mntopts, opt, size); 92*eda14cbcSMatt Macy } 93*eda14cbcSMatt Macy 94*eda14cbcSMatt Macy void 95*eda14cbcSMatt Macy statfs2mnttab(struct statfs *sfs, struct mnttab *mp) 96*eda14cbcSMatt Macy { 97*eda14cbcSMatt Macy static char mntopts[MNTMAXSTR]; 98*eda14cbcSMatt Macy long flags; 99*eda14cbcSMatt Macy 100*eda14cbcSMatt Macy mntopts[0] = '\0'; 101*eda14cbcSMatt Macy 102*eda14cbcSMatt Macy flags = sfs->f_flags; 103*eda14cbcSMatt Macy #define OPTADD(opt) optadd(mntopts, sizeof (mntopts), (opt)) 104*eda14cbcSMatt Macy if (flags & MNT_RDONLY) 105*eda14cbcSMatt Macy OPTADD(MNTOPT_RO); 106*eda14cbcSMatt Macy else 107*eda14cbcSMatt Macy OPTADD(MNTOPT_RW); 108*eda14cbcSMatt Macy if (flags & MNT_NOSUID) 109*eda14cbcSMatt Macy OPTADD(MNTOPT_NOSETUID); 110*eda14cbcSMatt Macy else 111*eda14cbcSMatt Macy OPTADD(MNTOPT_SETUID); 112*eda14cbcSMatt Macy if (flags & MNT_UPDATE) 113*eda14cbcSMatt Macy OPTADD(MNTOPT_REMOUNT); 114*eda14cbcSMatt Macy if (flags & MNT_NOATIME) 115*eda14cbcSMatt Macy OPTADD(MNTOPT_NOATIME); 116*eda14cbcSMatt Macy else 117*eda14cbcSMatt Macy OPTADD(MNTOPT_ATIME); 118*eda14cbcSMatt Macy OPTADD(MNTOPT_NOXATTR); 119*eda14cbcSMatt Macy if (flags & MNT_NOEXEC) 120*eda14cbcSMatt Macy OPTADD(MNTOPT_NOEXEC); 121*eda14cbcSMatt Macy else 122*eda14cbcSMatt Macy OPTADD(MNTOPT_EXEC); 123*eda14cbcSMatt Macy #undef OPTADD 124*eda14cbcSMatt Macy mp->mnt_special = strdup(sfs->f_mntfromname); 125*eda14cbcSMatt Macy mp->mnt_mountp = strdup(sfs->f_mntonname); 126*eda14cbcSMatt Macy mp->mnt_fstype = strdup(sfs->f_fstypename); 127*eda14cbcSMatt Macy mp->mnt_mntopts = strdup(mntopts); 128*eda14cbcSMatt Macy } 129*eda14cbcSMatt Macy 130*eda14cbcSMatt Macy static struct statfs *gsfs = NULL; 131*eda14cbcSMatt Macy static int allfs = 0; 132*eda14cbcSMatt Macy 133*eda14cbcSMatt Macy static int 134*eda14cbcSMatt Macy statfs_init(void) 135*eda14cbcSMatt Macy { 136*eda14cbcSMatt Macy struct statfs *sfs; 137*eda14cbcSMatt Macy int error; 138*eda14cbcSMatt Macy 139*eda14cbcSMatt Macy if (gsfs != NULL) { 140*eda14cbcSMatt Macy free(gsfs); 141*eda14cbcSMatt Macy gsfs = NULL; 142*eda14cbcSMatt Macy } 143*eda14cbcSMatt Macy allfs = getfsstat(NULL, 0, MNT_WAIT); 144*eda14cbcSMatt Macy if (allfs == -1) 145*eda14cbcSMatt Macy goto fail; 146*eda14cbcSMatt Macy gsfs = malloc(sizeof (gsfs[0]) * allfs * 2); 147*eda14cbcSMatt Macy if (gsfs == NULL) 148*eda14cbcSMatt Macy goto fail; 149*eda14cbcSMatt Macy allfs = getfsstat(gsfs, (long)(sizeof (gsfs[0]) * allfs * 2), 150*eda14cbcSMatt Macy MNT_WAIT); 151*eda14cbcSMatt Macy if (allfs == -1) 152*eda14cbcSMatt Macy goto fail; 153*eda14cbcSMatt Macy sfs = realloc(gsfs, allfs * sizeof (gsfs[0])); 154*eda14cbcSMatt Macy if (sfs != NULL) 155*eda14cbcSMatt Macy gsfs = sfs; 156*eda14cbcSMatt Macy return (0); 157*eda14cbcSMatt Macy fail: 158*eda14cbcSMatt Macy error = errno; 159*eda14cbcSMatt Macy if (gsfs != NULL) 160*eda14cbcSMatt Macy free(gsfs); 161*eda14cbcSMatt Macy gsfs = NULL; 162*eda14cbcSMatt Macy allfs = 0; 163*eda14cbcSMatt Macy return (error); 164*eda14cbcSMatt Macy } 165*eda14cbcSMatt Macy 166*eda14cbcSMatt Macy int 167*eda14cbcSMatt Macy getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp) 168*eda14cbcSMatt Macy { 169*eda14cbcSMatt Macy // struct statfs *sfs; 170*eda14cbcSMatt Macy int i, error; 171*eda14cbcSMatt Macy 172*eda14cbcSMatt Macy error = statfs_init(); 173*eda14cbcSMatt Macy if (error != 0) 174*eda14cbcSMatt Macy return (error); 175*eda14cbcSMatt Macy 176*eda14cbcSMatt Macy for (i = 0; i < allfs; i++) { 177*eda14cbcSMatt Macy if (mrefp->mnt_special != NULL && 178*eda14cbcSMatt Macy strcmp(mrefp->mnt_special, gsfs[i].f_mntfromname) != 0) { 179*eda14cbcSMatt Macy continue; 180*eda14cbcSMatt Macy } 181*eda14cbcSMatt Macy if (mrefp->mnt_mountp != NULL && 182*eda14cbcSMatt Macy strcmp(mrefp->mnt_mountp, gsfs[i].f_mntonname) != 0) { 183*eda14cbcSMatt Macy continue; 184*eda14cbcSMatt Macy } 185*eda14cbcSMatt Macy if (mrefp->mnt_fstype != NULL && 186*eda14cbcSMatt Macy strcmp(mrefp->mnt_fstype, gsfs[i].f_fstypename) != 0) { 187*eda14cbcSMatt Macy continue; 188*eda14cbcSMatt Macy } 189*eda14cbcSMatt Macy statfs2mnttab(&gsfs[i], mgetp); 190*eda14cbcSMatt Macy return (0); 191*eda14cbcSMatt Macy } 192*eda14cbcSMatt Macy return (-1); 193*eda14cbcSMatt Macy } 194*eda14cbcSMatt Macy 195*eda14cbcSMatt Macy int 196*eda14cbcSMatt Macy getmntent(FILE *fp, struct mnttab *mp) 197*eda14cbcSMatt Macy { 198*eda14cbcSMatt Macy // struct statfs *sfs; 199*eda14cbcSMatt Macy int error, nfs; 200*eda14cbcSMatt Macy 201*eda14cbcSMatt Macy nfs = (int)lseek(fileno(fp), 0, SEEK_CUR); 202*eda14cbcSMatt Macy if (nfs == -1) 203*eda14cbcSMatt Macy return (errno); 204*eda14cbcSMatt Macy /* If nfs is 0, we want to refresh out cache. */ 205*eda14cbcSMatt Macy if (nfs == 0 || gsfs == NULL) { 206*eda14cbcSMatt Macy error = statfs_init(); 207*eda14cbcSMatt Macy if (error != 0) 208*eda14cbcSMatt Macy return (error); 209*eda14cbcSMatt Macy } 210*eda14cbcSMatt Macy if (nfs >= allfs) 211*eda14cbcSMatt Macy return (-1); 212*eda14cbcSMatt Macy statfs2mnttab(&gsfs[nfs], mp); 213*eda14cbcSMatt Macy if (lseek(fileno(fp), 1, SEEK_CUR) == -1) 214*eda14cbcSMatt Macy return (errno); 215*eda14cbcSMatt Macy return (0); 216*eda14cbcSMatt Macy } 217