1 /*	$OpenBSD: fstab.c,v 1.22 2016/03/17 23:48:42 mmcc Exp $ */
2 /*
3  * Copyright (c) 1980, 1988, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/types.h>
32 #include <sys/uio.h>
33 #include <sys/stat.h>
34 
35 #include <errno.h>
36 #include <limits.h>
37 #include <fstab.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 
43 static FILE *_fs_fp;
44 static struct fstab _fs_fstab;
45 
46 static int fstabscan(void);
47 
48 static int
fstabscan(void)49 fstabscan(void)
50 {
51 	char *cp;
52 #define	MAXLINELENGTH	1024
53 	static char line[MAXLINELENGTH];
54 	char subline[MAXLINELENGTH];
55 	const char *errstr;
56 	char *last;
57 	int typexx;
58 
59 	for (;;) {
60 		if (!(cp = fgets(line, sizeof(line), _fs_fp)))
61 			return(0);
62 /* OLD_STYLE_FSTAB */
63 		if (!strpbrk(cp, " \t")) {
64 			_fs_fstab.fs_spec = strtok_r(cp, ":\n", &last);
65 			if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
66 				continue;
67 			_fs_fstab.fs_file = strtok_r(NULL, ":\n", &last);
68 			_fs_fstab.fs_type = strtok_r(NULL, ":\n", &last);
69 			if (_fs_fstab.fs_type) {
70 				if (!strcmp(_fs_fstab.fs_type, FSTAB_XX))
71 					continue;
72 				_fs_fstab.fs_mntops = _fs_fstab.fs_type;
73 				_fs_fstab.fs_vfstype =
74 				    strcmp(_fs_fstab.fs_type, FSTAB_SW) ?
75 				    "ufs" : "swap";
76 				if ((cp = strtok_r(NULL, ":\n", &last))) {
77 					_fs_fstab.fs_freq = strtonum(cp, 0,
78 					    INT_MAX, &errstr);
79 					if (errstr)
80 						goto bad;
81 					if ((cp = strtok_r(NULL,
82 					    ":\n", &last))) {
83 						_fs_fstab.fs_passno =
84 						    strtonum(cp, 0, INT_MAX,
85 						    &errstr);
86 						if (errstr)
87 							goto bad;
88 						return(1);
89 					}
90 				}
91 			}
92 			goto bad;
93 		}
94 /* OLD_STYLE_FSTAB */
95 		_fs_fstab.fs_spec = strtok_r(cp, " \t\n", &last);
96 		if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
97 			continue;
98 		_fs_fstab.fs_file = strtok_r(NULL, " \t\n", &last);
99 		_fs_fstab.fs_vfstype = strtok_r(NULL, " \t\n", &last);
100 		_fs_fstab.fs_mntops = strtok_r(NULL, " \t\n", &last);
101 		if (_fs_fstab.fs_mntops == NULL)
102 			goto bad;
103 		_fs_fstab.fs_freq = 0;
104 		_fs_fstab.fs_passno = 0;
105 		if ((cp = strtok_r(NULL, " \t\n", &last)) != NULL) {
106 			_fs_fstab.fs_freq = strtonum(cp, 0, INT_MAX, &errstr);
107 			if (errstr)
108 				goto bad;
109 			if ((cp = strtok_r(NULL, " \t\n", &last)) != NULL) {
110 				_fs_fstab.fs_passno = strtonum(cp, 0, INT_MAX,
111 				    &errstr);
112 				if (errstr)
113 					goto bad;
114 			}
115 		}
116 		strlcpy(subline, _fs_fstab.fs_mntops, sizeof subline);
117 		for (typexx = 0, cp = strtok_r(subline, ",", &last); cp;
118 		     cp = strtok_r(NULL, ",", &last)) {
119 			if (strlen(cp) != 2)
120 				continue;
121 			if (!strcmp(cp, FSTAB_RW)) {
122 				_fs_fstab.fs_type = FSTAB_RW;
123 				break;
124 			}
125 			if (!strcmp(cp, FSTAB_RQ)) {
126 				_fs_fstab.fs_type = FSTAB_RQ;
127 				break;
128 			}
129 			if (!strcmp(cp, FSTAB_RO)) {
130 				_fs_fstab.fs_type = FSTAB_RO;
131 				break;
132 			}
133 			if (!strcmp(cp, FSTAB_SW)) {
134 				_fs_fstab.fs_type = FSTAB_SW;
135 				break;
136 			}
137 			if (!strcmp(cp, FSTAB_XX)) {
138 				_fs_fstab.fs_type = FSTAB_XX;
139 				typexx++;
140 				break;
141 			}
142 		}
143 		if (typexx)
144 			continue;
145 		if (cp != NULL)
146 			return(1);
147 
148 bad:		/* We silently ignore all bogus lines */
149 		;
150 	}
151 }
152 
153 struct fstab *
getfsent(void)154 getfsent(void)
155 {
156 	if ((!_fs_fp && !setfsent()) || !fstabscan())
157 		return(NULL);
158 	return(&_fs_fstab);
159 }
160 
161 struct fstab *
getfsspec(const char * name)162 getfsspec(const char *name)
163 {
164 	if (setfsent())
165 		while (fstabscan())
166 			if (!strcmp(_fs_fstab.fs_spec, name))
167 				return(&_fs_fstab);
168 	return(NULL);
169 }
170 
171 struct fstab *
getfsfile(const char * name)172 getfsfile(const char *name)
173 {
174 	if (setfsent())
175 		while (fstabscan())
176 			if (!strcmp(_fs_fstab.fs_file, name))
177 				return(&_fs_fstab);
178 	return(NULL);
179 }
180 
181 int
setfsent(void)182 setfsent(void)
183 {
184 	struct stat sbuf;
185 
186 	if (_fs_fp) {
187 		rewind(_fs_fp);
188 		return(1);
189 	}
190 
191 	if (stat(_PATH_FSTAB, &sbuf) != 0)
192 		goto fail;
193 	if ((sbuf.st_size == 0) || ((sbuf.st_mode & S_IFMT) != S_IFREG)) {
194 		errno = EFTYPE;
195 		goto fail;
196 	}
197 
198 	if ((_fs_fp = fopen(_PATH_FSTAB, "re")))
199 		return(1);
200 
201 fail:
202 	return(0);
203 }
204 DEF_WEAK(setfsent);
205 
206 void
endfsent(void)207 endfsent(void)
208 {
209 	if (_fs_fp) {
210 		(void)fclose(_fs_fp);
211 		_fs_fp = NULL;
212 	}
213 }
214