Libinfo-78.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;
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 fstabscan __P((void));
57 static char *getRootDev(void);
58 static const char *slash = "/";
59 static const char *remountedroot = "/root";
60
61 /* We don't want to depend on fstab for the root filesystem entry,
62 ** since that can change when disks are added or removed from the system.
63 ** So, we stat "/" and find the _PATH_DEV entry that matches. The devname()
64 ** function can be used as a shortcut if _PATH_DEVDB exists. This returns a
65 ** string like "sd1a", so we need to prepend _PATH_DEV to it.
66 */
67
68 static char *getDevPath(dev_t target_dev) {
69 static char dev[MAXPATHLEN];
70 char *name;
71
72 strcpy(dev, _PATH_DEV);
73
74 /* The root device in fstab should always be a block special device */
75 name = devname(target_dev, S_IFBLK);
76 if (name == NULL) {
77 /* No _PATH_DEVDB. We have to search for it the slow way */
78 DIR *dirp;
79 struct dirent *ent;
80 dirp = opendir(_PATH_DEV);
81 if (dirp == NULL) {
82 perror("opendir");
83 return NULL;
84 }
85 while ((ent = readdir(dirp)) != NULL) {
86 /* Look for a block special device */
87 if (ent->d_type == DT_BLK) {
88 struct stat devst;
89 strcat(dev, ent->d_name);
90 if (stat(dev, &devst) >= 0) {
91 if (devst.st_rdev == target_dev) {
92 return dev;
93 }
94 }
95 }
96 /* set dev to _PATH_DEV and try again */
97 dev[sizeof(_PATH_DEV) - 1] = '\0';
98 }
99 } else {
100 /* We found the _PATH_DEVDB entry */
101 strcat(dev, name);
102 return dev;
103 }
104 return NULL;
105 }
106
107 static int initrootentry(struct fstab *rootentry)
108 {
109 char *rootpath = slash;
110 struct stat rootstat;
111 struct statfs rootfsinfo;
112 char *rootdevname;
113
114 if (stat(rootpath, &rootstat) < 0) {
115 perror("stat");
116 return -1;
117 };
118 if (statfs(rootpath, &rootfsinfo) < 0) {
119 perror("statfs");
120 return -1;
121 };
122
123 /* Check to make sure we're not looking at a synthetic root: */
124 if (strcmp(rootfsinfo.f_fstypename, "synthfs") == 0) {
125 rootpath = remountedroot;
126 if (stat(rootpath, &rootstat) < 0) {
127 perror("stat");
128 return -1;
129 };
130 if (statfs(rootpath, &rootfsinfo) < 0) {
131 perror("statfs");
132 return -1;
133 };
134 };
135
136 /* Copy the type name before returning a pointer a pointer to it */
137 strncpy(_root_fstype, rootfsinfo.f_fstypename, MFSNAMELEN);
138
139 rootentry->fs_spec = getDevPath(rootstat.st_dev);
140 rootentry->fs_file = rootpath;
141 rootentry->fs_vfstype = _root_fstype;
142 rootentry->fs_mntops = FSTAB_RW;
143 rootentry->fs_type = FSTAB_RW;
144 rootentry->fs_freq = 0;
145 rootentry->fs_passno = 1;
146
147 return 0;
148 }
149
150 static int fstabscan()
151 {
152 register char *cp;
153 #define MAXLINELENGTH 1024
154 static char line[MAXLINELENGTH];
155 char subline[MAXLINELENGTH];
156 int typexx;
157
158 if (!returnedRoot) {
159 returnedRoot = 1;
160 if (firstTime) {
161 firstTime = 0;
162 if (initrootentry(&_root_fstab) != 0) {
163 return 0;
164 };
165 }
166 _fs_fstab = _root_fstab;
167 return 1;
168 }
169 if (!_fs_fp) {
170 return(0);
171 }
172 for (;;) {
173 if (!(cp = fgets(line, sizeof(line), _fs_fp)))
174 return(0);
175 /* OLD_STYLE_FSTAB */
176 if (!strpbrk(cp, " \t")) {
177 _fs_fstab.fs_spec = strtok(cp, ":\n");
178 #if defined(__APPLE__)
179 if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
180 continue;
181 #endif
182 _fs_fstab.fs_file = strtok((char *)NULL, ":\n");
183 /* Only list the root filesystem once */
184 if (!(strcmp(_fs_fstab.fs_file, "/"))) {
185 continue;
186 }
187 _fs_fstab.fs_type = strtok((char *)NULL, ":\n");
188 if (_fs_fstab.fs_type) {
189 if (!strcmp(_fs_fstab.fs_type, FSTAB_XX))
190 continue;
191 _fs_fstab.fs_mntops = _fs_fstab.fs_type;
192 _fs_fstab.fs_vfstype =
193 strcmp(_fs_fstab.fs_type, FSTAB_SW) ?
194 "ufs" : "swap";
195 if ((cp = strtok((char *)NULL, ":\n"))) {
196 _fs_fstab.fs_freq = atoi(cp);
197 if ((cp = strtok((char *)NULL, ":\n"))) {
198 _fs_fstab.fs_passno = atoi(cp);
199 return(1);
200 }
201 }
202 }
203 goto bad;
204 }
205 /* OLD_STYLE_FSTAB */
206 _fs_fstab.fs_spec = strtok(cp, " \t\n");
207 if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
208 continue;
209 _fs_fstab.fs_file = strtok((char *)NULL, " \t\n");
210 /* Only list the root filesystem once */
211 if (!(strcmp(_fs_fstab.fs_file, "/"))) {
212 continue;
213 }
214 _fs_fstab.fs_vfstype = strtok((char *)NULL, " \t\n");
215 _fs_fstab.fs_mntops = strtok((char *)NULL, " \t\n");
216 if (_fs_fstab.fs_mntops == NULL)
217 goto bad;
218 _fs_fstab.fs_freq = 0;
219 _fs_fstab.fs_passno = 0;
220 if ((cp = strtok((char *)NULL, " \t\n")) != NULL) {
221 _fs_fstab.fs_freq = atoi(cp);
222 if ((cp = strtok((char *)NULL, " \t\n")) != NULL)
223 _fs_fstab.fs_passno = atoi(cp);
224 }
225 strcpy(subline, _fs_fstab.fs_mntops);
226 for (typexx = 0, cp = strtok(subline, ","); cp;
227 cp = strtok((char *)NULL, ",")) {
228 if (strlen(cp) != 2)
229 continue;
230 if (!strcmp(cp, FSTAB_RW)) {
231 _fs_fstab.fs_type = FSTAB_RW;
232 break;
233 }
234 if (!strcmp(cp, FSTAB_RQ)) {
235 _fs_fstab.fs_type = FSTAB_RQ;
236 break;
237 }
238 if (!strcmp(cp, FSTAB_RO)) {
239 _fs_fstab.fs_type = FSTAB_RO;
240 break;
241 }
242 if (!strcmp(cp, FSTAB_SW)) {
243 _fs_fstab.fs_type = FSTAB_SW;
244 break;
245 }
246 if (!strcmp(cp, FSTAB_XX)) {
247 _fs_fstab.fs_type = FSTAB_XX;
248 typexx++;
249 break;
250 }
251 }
252 if (typexx)
253 continue;
254 if (cp != NULL)
255 return(1);
256
257 bad: /* no way to distinguish between EOF and syntax error */
258 error(EFTYPE);
259 }
260 /* NOTREACHED */
261 }
262
263 struct fstab *
264 getfsent()
265 {
266 if (!returnedRoot) {
267 setfsent();
268 }
269 if (!fstabscan()) {
270 return((struct fstab *)NULL);
271 }
272 return(&_fs_fstab);
273 }
274
275 struct fstab *
276 getfsspec(name)
277 register const char *name;
278 {
279 if (setfsent())
280 while (fstabscan())
281 if (!strcmp(_fs_fstab.fs_spec, name))
282 return(&_fs_fstab);
283 return((struct fstab *)NULL);
284 }
285
286 struct fstab *
287 getfsfile(name)
288 register const char *name;
289 {
290 if (setfsent())
291 while (fstabscan())
292 if (!strcmp(_fs_fstab.fs_file, name))
293 return(&_fs_fstab);
294 return((struct fstab *)NULL);
295 }
296
297 int
298 setfsent()
299 {
300 returnedRoot = 0;
301 if (_fs_fp) {
302 rewind(_fs_fp);
303 } else {
304 _fs_fp = fopen(_PATH_FSTAB, "r");
305 }
306 return(1);
307 }
308
309 void
310 endfsent()
311 {
312 returnedRoot = 0;
313 if (_fs_fp) {
314 (void)fclose(_fs_fp);
315 _fs_fp = NULL;
316 }
317 }
318
319 static void error(err)
320 int err;
321 {
322 char *p;
323
324 (void)write(STDERR_FILENO, "fstab: ", 7);
325 (void)write(STDERR_FILENO, _PATH_FSTAB, sizeof(_PATH_FSTAB) - 1);
326 (void)write(STDERR_FILENO, ": ", 1);
327 p = strerror(err);
328 (void)write(STDERR_FILENO, p, strlen(p));
329 (void)write(STDERR_FILENO, "\n", 1);
330 }