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