fstab.c revision 165903
1/*
2 * Copyright (c) 1980, 1988, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
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.
13 * 4. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char sccsid[] = "@(#)fstab.c	8.1 (Berkeley) 6/4/93";
32#endif /* LIBC_SCCS and not lint */
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/lib/libc/gen/fstab.c 165903 2007-01-09 00:28:16Z imp $");
35
36#include "namespace.h"
37#include <sys/param.h>
38#include <sys/mount.h>
39#include <sys/stat.h>
40
41#include <errno.h>
42#include <fstab.h>
43#include <paths.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48#include "un-namespace.h"
49
50static FILE *_fs_fp;
51static struct fstab _fs_fstab;
52static int LineNo = 0;
53static char *path_fstab;
54static char fstab_path[PATH_MAX];
55static int fsp_set = 0;
56
57static void error(int);
58static void fixfsfile(void);
59static int fstabscan(void);
60
61void
62setfstab(const char *file)
63{
64
65	if (file == NULL) {
66		path_fstab = _PATH_FSTAB;
67	} else {
68		strncpy(fstab_path, file, PATH_MAX);
69		fstab_path[PATH_MAX - 1] = '\0';
70		path_fstab = fstab_path;
71	}
72	fsp_set = 1;
73
74	return;
75}
76
77const char *
78getfstab (void)
79{
80
81	if (fsp_set)
82		return (path_fstab);
83	else
84		return (_PATH_FSTAB);
85}
86
87static void
88fixfsfile()
89{
90	static char buf[sizeof(_PATH_DEV) + MNAMELEN];
91	struct stat sb;
92	struct statfs sf;
93
94	if (strcmp(_fs_fstab.fs_file, "/") != 0)
95		return;
96	if (statfs("/", &sf) != 0)
97		return;
98	if (sf.f_mntfromname[0] == '/')
99		buf[0] = '\0';
100	else
101		strcpy(buf, _PATH_DEV);
102	strcat(buf, sf.f_mntfromname);
103	if (stat(buf, &sb) != 0 ||
104	    (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode)))
105		return;
106	_fs_fstab.fs_spec = buf;
107}
108
109static int
110fstabscan()
111{
112	char *cp, *p;
113#define	MAXLINELENGTH	1024
114	static char line[MAXLINELENGTH];
115	char subline[MAXLINELENGTH];
116	int typexx;
117
118	for (;;) {
119
120		if (!(p = fgets(line, sizeof(line), _fs_fp)))
121			return(0);
122/* OLD_STYLE_FSTAB */
123		++LineNo;
124		if (*line == '#' || *line == '\n')
125			continue;
126		if (!strpbrk(p, " \t")) {
127			_fs_fstab.fs_spec = strsep(&p, ":\n");
128			_fs_fstab.fs_file = strsep(&p, ":\n");
129			fixfsfile();
130			_fs_fstab.fs_type = strsep(&p, ":\n");
131			if (_fs_fstab.fs_type) {
132				if (!strcmp(_fs_fstab.fs_type, FSTAB_XX))
133					continue;
134				_fs_fstab.fs_mntops = _fs_fstab.fs_type;
135				_fs_fstab.fs_vfstype =
136				    strcmp(_fs_fstab.fs_type, FSTAB_SW) ?
137				    "ufs" : "swap";
138				if ((cp = strsep(&p, ":\n")) != NULL) {
139					_fs_fstab.fs_freq = atoi(cp);
140					if ((cp = strsep(&p, ":\n")) != NULL) {
141						_fs_fstab.fs_passno = atoi(cp);
142						return(1);
143					}
144				}
145			}
146			goto bad;
147		}
148/* OLD_STYLE_FSTAB */
149		while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
150			;
151		_fs_fstab.fs_spec = cp;
152		if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
153			continue;
154		while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
155			;
156		_fs_fstab.fs_file = cp;
157		fixfsfile();
158		while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
159			;
160		_fs_fstab.fs_vfstype = cp;
161		while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
162			;
163		_fs_fstab.fs_mntops = cp;
164		if (_fs_fstab.fs_mntops == NULL)
165			goto bad;
166		_fs_fstab.fs_freq = 0;
167		_fs_fstab.fs_passno = 0;
168		while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
169			;
170		if (cp != NULL) {
171			_fs_fstab.fs_freq = atoi(cp);
172			while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
173				;
174			if (cp != NULL)
175				_fs_fstab.fs_passno = atoi(cp);
176		}
177		strcpy(subline, _fs_fstab.fs_mntops);
178		p = subline;
179		for (typexx = 0, cp = strsep(&p, ","); cp;
180		     cp = strsep(&p, ",")) {
181			if (strlen(cp) != 2)
182				continue;
183			if (!strcmp(cp, FSTAB_RW)) {
184				_fs_fstab.fs_type = FSTAB_RW;
185				break;
186			}
187			if (!strcmp(cp, FSTAB_RQ)) {
188				_fs_fstab.fs_type = FSTAB_RQ;
189				break;
190			}
191			if (!strcmp(cp, FSTAB_RO)) {
192				_fs_fstab.fs_type = FSTAB_RO;
193				break;
194			}
195			if (!strcmp(cp, FSTAB_SW)) {
196				_fs_fstab.fs_type = FSTAB_SW;
197				break;
198			}
199			if (!strcmp(cp, FSTAB_XX)) {
200				_fs_fstab.fs_type = FSTAB_XX;
201				typexx++;
202				break;
203			}
204		}
205		if (typexx)
206			continue;
207		if (cp != NULL)
208			return(1);
209
210bad:		/* no way to distinguish between EOF and syntax error */
211		error(EFTYPE);
212	}
213	/* NOTREACHED */
214}
215
216struct fstab *
217getfsent()
218{
219	if ((!_fs_fp && !setfsent()) || !fstabscan())
220		return((struct fstab *)NULL);
221	return(&_fs_fstab);
222}
223
224struct fstab *
225getfsspec(name)
226	const char *name;
227{
228	if (setfsent())
229		while (fstabscan())
230			if (!strcmp(_fs_fstab.fs_spec, name))
231				return(&_fs_fstab);
232	return((struct fstab *)NULL);
233}
234
235struct fstab *
236getfsfile(name)
237	const char *name;
238{
239	if (setfsent())
240		while (fstabscan())
241			if (!strcmp(_fs_fstab.fs_file, name))
242				return(&_fs_fstab);
243	return((struct fstab *)NULL);
244}
245
246int
247setfsent()
248{
249	if (_fs_fp) {
250		rewind(_fs_fp);
251		LineNo = 0;
252		return(1);
253	}
254	if (fsp_set == 0) {
255		if (issetugid())
256			setfstab(NULL);
257		else
258			setfstab(getenv("PATH_FSTAB"));
259	}
260	if ((_fs_fp = fopen(path_fstab, "r")) != NULL) {
261		LineNo = 0;
262		return(1);
263	}
264	error(errno);
265	return(0);
266}
267
268void
269endfsent()
270{
271	if (_fs_fp) {
272		(void)fclose(_fs_fp);
273		_fs_fp = NULL;
274	}
275
276	fsp_set = 0;
277}
278
279static void
280error(err)
281	int err;
282{
283	char *p;
284	char num[30];
285
286	(void)_write(STDERR_FILENO, "fstab: ", 7);
287	(void)_write(STDERR_FILENO, path_fstab, strlen(path_fstab));
288	(void)_write(STDERR_FILENO, ":", 1);
289	sprintf(num, "%d: ", LineNo);
290	(void)_write(STDERR_FILENO, num, strlen(num));
291	p = strerror(err);
292	(void)_write(STDERR_FILENO, p, strlen(p));
293	(void)_write(STDERR_FILENO, "\n", 1);
294}
295