Libinfo-173.1.tar.gz
[apple/libinfo.git] / gen.subproj / fstab.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved
26 *
27 * Copyright (c) 1980, 1988, 1993
28 * The Regents of the University of California. All rights reserved.
29 *
30 * The NEXTSTEP Software License Agreement specifies the terms
31 * and conditions for redistribution.
32 *
33 * @(#)fstab.c 8.1 (Berkeley) 6/4/93
34 */
35
36
37 #include <errno.h>
38 #include <fstab.h>
39 #include <paths.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <dirent.h>
45 #include <sys/param.h>
46 #include <sys/stat.h>
47 #include <sys/mount.h>
48
49 static FILE *_fs_fp = NULL;
50 static struct fstab _fs_fstab;
51 static struct fstab _root_fstab;
52 static char _root_fstype[MFSNAMELEN];
53 static int firstTime = 1;
54 static int returnedRoot = 0;
55 static void error __P((int));
56 static int fstabscan __P((void));
57 static const char *slash = "/";
58 static const char *remountedroot = "/root";
59
60 /* We don't want to depend on fstab for the root filesystem entry,
61 ** since that can change when disks are added or removed from the system.
62 ** So, we stat "/" and find the _PATH_DEV entry that matches. The devname()
63 ** function can be used as a shortcut if _PATH_DEVDB exists. This returns a
64 ** string like "sd1a", so we need to prepend _PATH_DEV to it.
65 */
66
67 static char *getDevPath(dev_t target_dev) {
68 static char *dev = NULL;
69 char *name;
70
71 if (dev == NULL) {
72 dev = malloc(MAXPATHLEN);
73 if (dev == NULL)
74 return NULL;
75 }
76
77 strcpy(dev, _PATH_DEV);
78
79 /* The root device in fstab should always be a block special device */
80 name = devname(target_dev, S_IFBLK);
81 if (name == NULL) {
82 /* No _PATH_DEVDB. We have to search for it the slow way */
83 DIR *dirp;
84 struct dirent *ent;
85 dirp = opendir(_PATH_DEV);
86 if (dirp == NULL) {
87 perror("opendir");
88 return NULL;
89 }
90 while ((ent = readdir(dirp)) != NULL) {
91 /* Look for a block special device */
92 if (ent->d_type == DT_BLK) {
93 struct stat devst;
94 strcat(dev, ent->d_name);
95 if (stat(dev, &devst) >= 0) {
96 if (devst.st_rdev == target_dev) {
97 return dev;
98 }
99 }
100 }
101 /* set dev to _PATH_DEV and try again */
102 dev[sizeof(_PATH_DEV) - 1] = '\0';
103 }
104 } else {
105 /* We found the _PATH_DEVDB entry */
106 strcat(dev, name);
107 return dev;
108 }
109 return NULL;
110 }
111
112 static int initrootentry(struct fstab *rootentry)
113 {
114 char *rootpath = (char *)slash;
115 struct stat rootstat;
116 struct statfs rootfsinfo;
117
118 if (stat(rootpath, &rootstat) < 0) {
119 perror("stat");
120 return -1;
121 };
122 if (statfs(rootpath, &rootfsinfo) < 0) {
123 perror("statfs");
124 return -1;
125 };
126
127 /* Check to make sure we're not looking at a synthetic root: */
128 if (strcmp(rootfsinfo.f_fstypename, "synthfs") == 0) {
129 rootpath = (char *)remountedroot;
130 if (stat(rootpath, &rootstat) < 0) {
131 perror("stat");
132 return -1;
133 };
134 if (statfs(rootpath, &rootfsinfo) < 0) {
135 perror("statfs");
136 return -1;
137 };
138 };
139
140 /* Copy the type name before returning a pointer a pointer to it */
141 strncpy(_root_fstype, rootfsinfo.f_fstypename, MFSNAMELEN);
142
143 rootentry->fs_spec = getDevPath(rootstat.st_dev);
144 rootentry->fs_file = rootpath;
145 rootentry->fs_vfstype = _root_fstype;
146 rootentry->fs_mntops = FSTAB_RW;
147 rootentry->fs_type = FSTAB_RW;
148 rootentry->fs_freq = 0;
149 rootentry->fs_passno = 1;
150
151 return 0;
152 }
153
154 static int fstabscan()
155 {
156 register char *cp;
157 #define MAXLINELENGTH 1024
158 static char *line = NULL;
159 char subline[MAXLINELENGTH];
160 int typexx;
161
162 if (!returnedRoot) {
163 returnedRoot = 1;
164 if (firstTime) {
165 firstTime = 0;
166 if (initrootentry(&_root_fstab) != 0) {
167 return 0;
168 };
169 }
170 _fs_fstab = _root_fstab;
171 return 1;
172 }
173 if (!_fs_fp) {
174 return(0);
175 }
176
177 if (line == NULL) {
178 line = malloc(MAXLINELENGTH);
179 if (line == NULL)
180 return 0;
181 }
182
183 for (;;) {
184 if (!(cp = fgets(line, MAXLINELENGTH, _fs_fp)))
185 return(0);
186 /* OLD_STYLE_FSTAB */
187 if (!strpbrk(cp, " \t")) {
188 _fs_fstab.fs_spec = strtok(cp, ":\n");
189 #if defined(__APPLE__)
190 if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
191 continue;
192 #endif
193 _fs_fstab.fs_file = strtok((char *)NULL, ":\n");
194 /* Only list the root filesystem once */
195 if (!_fs_fstab.fs_file || !(strcmp(_fs_fstab.fs_file, "/"))) {
196 continue;
197 }
198 _fs_fstab.fs_type = strtok((char *)NULL, ":\n");
199 if (_fs_fstab.fs_type) {
200 if (!strcmp(_fs_fstab.fs_type, FSTAB_XX))
201 continue;
202 _fs_fstab.fs_mntops = _fs_fstab.fs_type;
203 _fs_fstab.fs_vfstype =
204 strcmp(_fs_fstab.fs_type, FSTAB_SW) ?
205 "ufs" : "swap";
206 if ((cp = strtok((char *)NULL, ":\n"))) {
207 _fs_fstab.fs_freq = atoi(cp);
208 if ((cp = strtok((char *)NULL, ":\n"))) {
209 _fs_fstab.fs_passno = atoi(cp);
210 return(1);
211 }
212 }
213 }
214 goto bad;
215 }
216 /* OLD_STYLE_FSTAB */
217 _fs_fstab.fs_spec = strtok(cp, " \t\n");
218 if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
219 continue;
220 _fs_fstab.fs_file = strtok((char *)NULL, " \t\n");
221 /* Only list the root filesystem once */
222 if (!(strcmp(_fs_fstab.fs_file, "/"))) {
223 continue;
224 }
225 _fs_fstab.fs_vfstype = strtok((char *)NULL, " \t\n");
226 _fs_fstab.fs_mntops = strtok((char *)NULL, " \t\n");
227 if (_fs_fstab.fs_mntops == NULL)
228 goto bad;
229 _fs_fstab.fs_freq = 0;
230 _fs_fstab.fs_passno = 0;
231 if ((cp = strtok((char *)NULL, " \t\n")) != NULL) {
232 _fs_fstab.fs_freq = atoi(cp);
233 if ((cp = strtok((char *)NULL, " \t\n")) != NULL)
234 _fs_fstab.fs_passno = atoi(cp);
235 }
236 strcpy(subline, _fs_fstab.fs_mntops);
237 for (typexx = 0, cp = strtok(subline, ","); cp;
238 cp = strtok((char *)NULL, ",")) {
239 if (strlen(cp) != 2)
240 continue;
241 if (!strcmp(cp, FSTAB_RW)) {
242 _fs_fstab.fs_type = FSTAB_RW;
243 break;
244 }
245 if (!strcmp(cp, FSTAB_RQ)) {
246 _fs_fstab.fs_type = FSTAB_RQ;
247 break;
248 }
249 if (!strcmp(cp, FSTAB_RO)) {
250 _fs_fstab.fs_type = FSTAB_RO;
251 break;
252 }
253 if (!strcmp(cp, FSTAB_SW)) {
254 _fs_fstab.fs_type = FSTAB_SW;
255 break;
256 }
257 if (!strcmp(cp, FSTAB_XX)) {
258 _fs_fstab.fs_type = FSTAB_XX;
259 typexx++;
260 break;
261 }
262 }
263 if (typexx)
264 continue;
265 if (cp != NULL)
266 return(1);
267
268 bad: /* no way to distinguish between EOF and syntax error */
269 error(EFTYPE);
270 }
271 /* NOTREACHED */
272 }
273
274 struct fstab *
275 getfsent()
276 {
277 if (!returnedRoot) {
278 setfsent();
279 }
280 if (!fstabscan()) {
281 return((struct fstab *)NULL);
282 }
283 return(&_fs_fstab);
284 }
285
286 struct fstab *
287 getfsspec(name)
288 register const char *name;
289 {
290 if (setfsent())
291 while (fstabscan())
292 if (!strcmp(_fs_fstab.fs_spec, name))
293 return(&_fs_fstab);
294 return((struct fstab *)NULL);
295 }
296
297 struct fstab *
298 getfsfile(name)
299 register const char *name;
300 {
301 if (setfsent())
302 while (fstabscan())
303 if (!strcmp(_fs_fstab.fs_file, name))
304 return(&_fs_fstab);
305 return((struct fstab *)NULL);
306 }
307
308 int
309 setfsent()
310 {
311 returnedRoot = 0;
312 if (_fs_fp) {
313 rewind(_fs_fp);
314 } else {
315 _fs_fp = fopen(_PATH_FSTAB, "r");
316 }
317 return(1);
318 }
319
320 void
321 endfsent()
322 {
323 returnedRoot = 0;
324 if (_fs_fp) {
325 (void)fclose(_fs_fp);
326 _fs_fp = NULL;
327 }
328 }
329
330 static void error(err)
331 int err;
332 {
333 char *p;
334
335 (void)write(STDERR_FILENO, "fstab: ", 7);
336 (void)write(STDERR_FILENO, _PATH_FSTAB, sizeof(_PATH_FSTAB) - 1);
337 (void)write(STDERR_FILENO, ": ", 1);
338 p = strerror(err);
339 (void)write(STDERR_FILENO, p, strlen(p));
340 (void)write(STDERR_FILENO, "\n", 1);
341 }