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