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