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
43static FILE *_fs_fp;
44static struct fstab _fs_fstab;
45
46static int fstabscan(void);
47
48static int
49fstabscan(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
148bad:		/* We silently ignore all bogus lines */
149		;
150	}
151}
152
153struct fstab *
154getfsent(void)
155{
156	if ((!_fs_fp && !setfsent()) || !fstabscan())
157		return(NULL);
158	return(&_fs_fstab);
159}
160
161struct fstab *
162getfsspec(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
171struct fstab *
172getfsfile(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
181int
182setfsent(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
201fail:
202	return(0);
203}
204DEF_WEAK(setfsent);
205
206void
207endfsent(void)
208{
209	if (_fs_fp) {
210		(void)fclose(_fs_fp);
211		_fs_fp = NULL;
212	}
213}
214