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 50 char * 51 mntopt(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 72 char * 73 hasmntopt(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 89 static void 90 optadd(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 98 void 99 statvfs2mnttab(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 134 static struct statvfs *gsfs; 135 static int allfs; 136 137 static int 138 statvfs_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); 160 fail: 161 error = errno; 162 if (gsfs != NULL) 163 free(gsfs); 164 gsfs = NULL; 165 allfs = 0; 166 return (error); 167 } 168 169 int 170 getmntany(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 197 int 198 getmntent(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