xref: /netbsd/external/cddl/osnet/lib/libzfs/mnttab.c (revision cc17ee2e)
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