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