Fix gcc uninitialized warning in FreeBSD zio_crypt.c
[zfs.git] / lib / libspl / os / freebsd / mnttab.c
blob26a4cd992cfb6af37c65591ea10a2cf90ea08e3a
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/param.h>
33 #include <sys/mount.h>
34 #include <sys/mntent.h>
35 #include <sys/mnttab.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <pthread.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
44 static char *
45 mntopt(char **p)
47 char *cp = *p;
48 char *retstr;
50 while (*cp && isspace(*cp))
51 cp++;
53 retstr = cp;
54 while (*cp && *cp != ',')
55 cp++;
57 if (*cp) {
58 *cp = '\0';
59 cp++;
62 *p = cp;
63 return (retstr);
66 char *
67 hasmntopt(struct mnttab *mnt, const char *opt)
69 char tmpopts[MNT_LINE_MAX];
70 char *f, *opts = tmpopts;
72 if (mnt->mnt_mntopts == NULL)
73 return (NULL);
74 (void) strlcpy(opts, mnt->mnt_mntopts, MNT_LINE_MAX);
75 f = mntopt(&opts);
76 for (; *f; f = mntopt(&opts)) {
77 if (strncmp(opt, f, strlen(opt)) == 0)
78 return (f - tmpopts + mnt->mnt_mntopts);
80 return (NULL);
83 static void
84 optadd(char *mntopts, size_t size, const char *opt)
87 if (mntopts[0] != '\0')
88 strlcat(mntopts, ",", size);
89 strlcat(mntopts, opt, size);
92 static __thread char gfstypename[MFSNAMELEN];
93 static __thread char gmntfromname[MNAMELEN];
94 static __thread char gmntonname[MNAMELEN];
95 static __thread char gmntopts[MNTMAXSTR];
97 void
98 statfs2mnttab(struct statfs *sfs, struct mnttab *mp)
100 long flags;
102 strlcpy(gfstypename, sfs->f_fstypename, sizeof (gfstypename));
103 mp->mnt_fstype = gfstypename;
105 strlcpy(gmntfromname, sfs->f_mntfromname, sizeof (gmntfromname));
106 mp->mnt_special = gmntfromname;
108 strlcpy(gmntonname, sfs->f_mntonname, sizeof (gmntonname));
109 mp->mnt_mountp = gmntonname;
111 flags = sfs->f_flags;
112 gmntopts[0] = '\0';
113 #define OPTADD(opt) optadd(gmntopts, sizeof (gmntopts), (opt))
114 if (flags & MNT_RDONLY)
115 OPTADD(MNTOPT_RO);
116 else
117 OPTADD(MNTOPT_RW);
118 if (flags & MNT_NOSUID)
119 OPTADD(MNTOPT_NOSETUID);
120 else
121 OPTADD(MNTOPT_SETUID);
122 if (flags & MNT_UPDATE)
123 OPTADD(MNTOPT_REMOUNT);
124 if (flags & MNT_NOATIME)
125 OPTADD(MNTOPT_NOATIME);
126 else
127 OPTADD(MNTOPT_ATIME);
128 OPTADD(MNTOPT_NOXATTR);
129 if (flags & MNT_NOEXEC)
130 OPTADD(MNTOPT_NOEXEC);
131 else
132 OPTADD(MNTOPT_EXEC);
133 #undef OPTADD
134 mp->mnt_mntopts = gmntopts;
137 static pthread_rwlock_t gsfs_lock = PTHREAD_RWLOCK_INITIALIZER;
138 static struct statfs *gsfs = NULL;
139 static int allfs = 0;
141 static int
142 statfs_init(void)
144 struct statfs *sfs;
145 int error;
147 (void) pthread_rwlock_wrlock(&gsfs_lock);
149 if (gsfs != NULL) {
150 free(gsfs);
151 gsfs = NULL;
153 allfs = getfsstat(NULL, 0, MNT_NOWAIT);
154 if (allfs == -1)
155 goto fail;
156 gsfs = malloc(sizeof (gsfs[0]) * allfs * 2);
157 if (gsfs == NULL)
158 goto fail;
159 allfs = getfsstat(gsfs, (long)(sizeof (gsfs[0]) * allfs * 2),
160 MNT_NOWAIT);
161 if (allfs == -1)
162 goto fail;
163 sfs = realloc(gsfs, allfs * sizeof (gsfs[0]));
164 if (sfs != NULL)
165 gsfs = sfs;
166 (void) pthread_rwlock_unlock(&gsfs_lock);
167 return (0);
168 fail:
169 error = errno;
170 if (gsfs != NULL)
171 free(gsfs);
172 gsfs = NULL;
173 allfs = 0;
174 (void) pthread_rwlock_unlock(&gsfs_lock);
175 return (error);
179 getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp)
181 int i, error;
183 error = statfs_init();
184 if (error != 0)
185 return (error);
187 (void) pthread_rwlock_rdlock(&gsfs_lock);
189 for (i = 0; i < allfs; i++) {
190 if (mrefp->mnt_special != NULL &&
191 strcmp(mrefp->mnt_special, gsfs[i].f_mntfromname) != 0) {
192 continue;
194 if (mrefp->mnt_mountp != NULL &&
195 strcmp(mrefp->mnt_mountp, gsfs[i].f_mntonname) != 0) {
196 continue;
198 if (mrefp->mnt_fstype != NULL &&
199 strcmp(mrefp->mnt_fstype, gsfs[i].f_fstypename) != 0) {
200 continue;
202 statfs2mnttab(&gsfs[i], mgetp);
203 (void) pthread_rwlock_unlock(&gsfs_lock);
204 return (0);
206 (void) pthread_rwlock_unlock(&gsfs_lock);
207 return (-1);
211 getmntent(FILE *fp, struct mnttab *mp)
213 int error, nfs;
215 nfs = (int)lseek(fileno(fp), 0, SEEK_CUR);
216 if (nfs == -1)
217 return (errno);
218 /* If nfs is 0, we want to refresh out cache. */
219 if (nfs == 0 || gsfs == NULL) {
220 error = statfs_init();
221 if (error != 0)
222 return (error);
224 (void) pthread_rwlock_rdlock(&gsfs_lock);
225 if (nfs >= allfs) {
226 (void) pthread_rwlock_unlock(&gsfs_lock);
227 return (-1);
229 statfs2mnttab(&gsfs[nfs], mp);
230 (void) pthread_rwlock_unlock(&gsfs_lock);
231 if (lseek(fileno(fp), 1, SEEK_CUR) == -1)
232 return (errno);
233 return (0);