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