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 *
mntopt(char ** p)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 *
hasmntopt(struct mnttab * mnt,char * opt)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
optadd(char * mntopts,size_t size,const char * opt)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
statvfs2mnttab(struct statvfs * sfs,struct mnttab * mp)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
statvfs_init(void)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
getmntany(FILE * fd,struct mnttab * mgetp,struct mnttab * mrefp)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
getmntent(FILE * fp,struct mnttab * mp)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