xref: /freebsd-src/sys/contrib/openzfs/lib/libspl/os/freebsd/mnttab.c (revision a2b560cc69eb254c92caf2027a69cadf9865d273)
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