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