diff options
Diffstat (limited to 'gl/mountlist.c')
-rw-r--r-- | gl/mountlist.c | 889 |
1 files changed, 889 insertions, 0 deletions
diff --git a/gl/mountlist.c b/gl/mountlist.c new file mode 100644 index 00000000..bb01f91e --- /dev/null +++ b/gl/mountlist.c | |||
@@ -0,0 +1,889 @@ | |||
1 | /* mountlist.c -- return a list of mounted file systems | ||
2 | |||
3 | Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, | ||
4 | 2004, 2005, 2006 Free Software Foundation, Inc. | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2, or (at your option) | ||
9 | any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software Foundation, | ||
18 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
19 | |||
20 | #include <config.h> | ||
21 | |||
22 | #include "mountlist.h" | ||
23 | |||
24 | #include <limits.h> | ||
25 | #include <stdio.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <string.h> | ||
28 | |||
29 | #include "xalloc.h" | ||
30 | |||
31 | #ifndef strstr | ||
32 | char *strstr (); | ||
33 | #endif | ||
34 | |||
35 | #include <errno.h> | ||
36 | |||
37 | #include <fcntl.h> | ||
38 | |||
39 | #include <unistd.h> | ||
40 | |||
41 | #if HAVE_SYS_PARAM_H | ||
42 | # include <sys/param.h> | ||
43 | #endif | ||
44 | |||
45 | #if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */ | ||
46 | # if HAVE_SYS_UCRED_H | ||
47 | # include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS, | ||
48 | NGROUPS is used as an array dimension in ucred.h */ | ||
49 | # include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */ | ||
50 | # endif | ||
51 | # if HAVE_SYS_MOUNT_H | ||
52 | # include <sys/mount.h> | ||
53 | # endif | ||
54 | # if HAVE_SYS_FS_TYPES_H | ||
55 | # include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */ | ||
56 | # endif | ||
57 | # if HAVE_STRUCT_FSSTAT_F_FSTYPENAME | ||
58 | # define FS_TYPE(Ent) ((Ent).f_fstypename) | ||
59 | # else | ||
60 | # define FS_TYPE(Ent) mnt_names[(Ent).f_type] | ||
61 | # endif | ||
62 | #endif /* MOUNTED_GETFSSTAT */ | ||
63 | |||
64 | #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ | ||
65 | # include <mntent.h> | ||
66 | # if !defined MOUNTED | ||
67 | # if defined _PATH_MOUNTED /* GNU libc */ | ||
68 | # define MOUNTED _PATH_MOUNTED | ||
69 | # endif | ||
70 | # if defined MNT_MNTTAB /* HP-UX. */ | ||
71 | # define MOUNTED MNT_MNTTAB | ||
72 | # endif | ||
73 | # if defined MNTTABNAME /* Dynix. */ | ||
74 | # define MOUNTED MNTTABNAME | ||
75 | # endif | ||
76 | # endif | ||
77 | #endif | ||
78 | |||
79 | #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ | ||
80 | # include <sys/mount.h> | ||
81 | #endif | ||
82 | |||
83 | #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ | ||
84 | # include <sys/statvfs.h> | ||
85 | #endif | ||
86 | |||
87 | #ifdef MOUNTED_GETMNT /* Ultrix. */ | ||
88 | # include <sys/mount.h> | ||
89 | # include <sys/fs_types.h> | ||
90 | #endif | ||
91 | |||
92 | #ifdef MOUNTED_FS_STAT_DEV /* BeOS. */ | ||
93 | # include <fs_info.h> | ||
94 | # include <dirent.h> | ||
95 | #endif | ||
96 | |||
97 | #ifdef MOUNTED_FREAD /* SVR2. */ | ||
98 | # include <mnttab.h> | ||
99 | #endif | ||
100 | |||
101 | #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */ | ||
102 | # include <mnttab.h> | ||
103 | # include <sys/fstyp.h> | ||
104 | # include <sys/statfs.h> | ||
105 | #endif | ||
106 | |||
107 | #ifdef MOUNTED_LISTMNTENT | ||
108 | # include <mntent.h> | ||
109 | #endif | ||
110 | |||
111 | #ifdef MOUNTED_GETMNTENT2 /* SVR4. */ | ||
112 | # include <sys/mnttab.h> | ||
113 | #endif | ||
114 | |||
115 | #ifdef MOUNTED_VMOUNT /* AIX. */ | ||
116 | # include <fshelp.h> | ||
117 | # include <sys/vfs.h> | ||
118 | #endif | ||
119 | |||
120 | #ifdef DOLPHIN | ||
121 | /* So special that it's not worth putting this in autoconf. */ | ||
122 | # undef MOUNTED_FREAD_FSTYP | ||
123 | # define MOUNTED_GETMNTTBL | ||
124 | #endif | ||
125 | |||
126 | #if HAVE_SYS_MNTENT_H | ||
127 | /* This is to get MNTOPT_IGNORE on e.g. SVR4. */ | ||
128 | # include <sys/mntent.h> | ||
129 | #endif | ||
130 | |||
131 | #undef MNT_IGNORE | ||
132 | #if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT | ||
133 | # define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE) | ||
134 | #else | ||
135 | # define MNT_IGNORE(M) 0 | ||
136 | #endif | ||
137 | |||
138 | #if USE_UNLOCKED_IO | ||
139 | # include "unlocked-io.h" | ||
140 | #endif | ||
141 | |||
142 | #ifndef SIZE_MAX | ||
143 | # define SIZE_MAX ((size_t) -1) | ||
144 | #endif | ||
145 | |||
146 | /* The results of open() in this file are not used with fchdir, | ||
147 | therefore save some unnecessary work in fchdir.c. */ | ||
148 | #undef open | ||
149 | #undef close | ||
150 | |||
151 | /* The results of opendir() in this file are not used with dirfd and fchdir, | ||
152 | therefore save some unnecessary work in fchdir.c. */ | ||
153 | #undef opendir | ||
154 | #undef closedir | ||
155 | |||
156 | #ifndef ME_DUMMY | ||
157 | # define ME_DUMMY(Fs_name, Fs_type) \ | ||
158 | (strcmp (Fs_type, "autofs") == 0 \ | ||
159 | || strcmp (Fs_type, "none") == 0 \ | ||
160 | || strcmp (Fs_type, "proc") == 0 \ | ||
161 | || strcmp (Fs_type, "subfs") == 0 \ | ||
162 | /* for NetBSD 3.0 */ \ | ||
163 | || strcmp (Fs_type, "kernfs") == 0 \ | ||
164 | /* for Irix 6.5 */ \ | ||
165 | || strcmp (Fs_type, "ignore") == 0) | ||
166 | #endif | ||
167 | |||
168 | #ifndef ME_REMOTE | ||
169 | /* A file system is `remote' if its Fs_name contains a `:' | ||
170 | or if (it is of type (smbfs or cifs) and its Fs_name starts with `//'). */ | ||
171 | # define ME_REMOTE(Fs_name, Fs_type) \ | ||
172 | (strchr (Fs_name, ':') != NULL \ | ||
173 | || ((Fs_name)[0] == '/' \ | ||
174 | && (Fs_name)[1] == '/' \ | ||
175 | && (strcmp (Fs_type, "smbfs") == 0 \ | ||
176 | || strcmp (Fs_type, "cifs") == 0))) | ||
177 | #endif | ||
178 | |||
179 | #if MOUNTED_GETMNTINFO | ||
180 | |||
181 | # if ! HAVE_STRUCT_STATFS_F_FSTYPENAME | ||
182 | static char * | ||
183 | fstype_to_string (short int t) | ||
184 | { | ||
185 | switch (t) | ||
186 | { | ||
187 | # ifdef MOUNT_PC | ||
188 | case MOUNT_PC: | ||
189 | return "pc"; | ||
190 | # endif | ||
191 | # ifdef MOUNT_MFS | ||
192 | case MOUNT_MFS: | ||
193 | return "mfs"; | ||
194 | # endif | ||
195 | # ifdef MOUNT_LO | ||
196 | case MOUNT_LO: | ||
197 | return "lo"; | ||
198 | # endif | ||
199 | # ifdef MOUNT_TFS | ||
200 | case MOUNT_TFS: | ||
201 | return "tfs"; | ||
202 | # endif | ||
203 | # ifdef MOUNT_TMP | ||
204 | case MOUNT_TMP: | ||
205 | return "tmp"; | ||
206 | # endif | ||
207 | # ifdef MOUNT_UFS | ||
208 | case MOUNT_UFS: | ||
209 | return "ufs" ; | ||
210 | # endif | ||
211 | # ifdef MOUNT_NFS | ||
212 | case MOUNT_NFS: | ||
213 | return "nfs" ; | ||
214 | # endif | ||
215 | # ifdef MOUNT_MSDOS | ||
216 | case MOUNT_MSDOS: | ||
217 | return "msdos" ; | ||
218 | # endif | ||
219 | # ifdef MOUNT_LFS | ||
220 | case MOUNT_LFS: | ||
221 | return "lfs" ; | ||
222 | # endif | ||
223 | # ifdef MOUNT_LOFS | ||
224 | case MOUNT_LOFS: | ||
225 | return "lofs" ; | ||
226 | # endif | ||
227 | # ifdef MOUNT_FDESC | ||
228 | case MOUNT_FDESC: | ||
229 | return "fdesc" ; | ||
230 | # endif | ||
231 | # ifdef MOUNT_PORTAL | ||
232 | case MOUNT_PORTAL: | ||
233 | return "portal" ; | ||
234 | # endif | ||
235 | # ifdef MOUNT_NULL | ||
236 | case MOUNT_NULL: | ||
237 | return "null" ; | ||
238 | # endif | ||
239 | # ifdef MOUNT_UMAP | ||
240 | case MOUNT_UMAP: | ||
241 | return "umap" ; | ||
242 | # endif | ||
243 | # ifdef MOUNT_KERNFS | ||
244 | case MOUNT_KERNFS: | ||
245 | return "kernfs" ; | ||
246 | # endif | ||
247 | # ifdef MOUNT_PROCFS | ||
248 | case MOUNT_PROCFS: | ||
249 | return "procfs" ; | ||
250 | # endif | ||
251 | # ifdef MOUNT_AFS | ||
252 | case MOUNT_AFS: | ||
253 | return "afs" ; | ||
254 | # endif | ||
255 | # ifdef MOUNT_CD9660 | ||
256 | case MOUNT_CD9660: | ||
257 | return "cd9660" ; | ||
258 | # endif | ||
259 | # ifdef MOUNT_UNION | ||
260 | case MOUNT_UNION: | ||
261 | return "union" ; | ||
262 | # endif | ||
263 | # ifdef MOUNT_DEVFS | ||
264 | case MOUNT_DEVFS: | ||
265 | return "devfs" ; | ||
266 | # endif | ||
267 | # ifdef MOUNT_EXT2FS | ||
268 | case MOUNT_EXT2FS: | ||
269 | return "ext2fs" ; | ||
270 | # endif | ||
271 | default: | ||
272 | return "?"; | ||
273 | } | ||
274 | } | ||
275 | # endif | ||
276 | |||
277 | static char * | ||
278 | fsp_to_string (const struct statfs *fsp) | ||
279 | { | ||
280 | # if HAVE_STRUCT_STATFS_F_FSTYPENAME | ||
281 | return (char *) (fsp->f_fstypename); | ||
282 | # else | ||
283 | return fstype_to_string (fsp->f_type); | ||
284 | # endif | ||
285 | } | ||
286 | |||
287 | #endif /* MOUNTED_GETMNTINFO */ | ||
288 | |||
289 | #ifdef MOUNTED_VMOUNT /* AIX. */ | ||
290 | static char * | ||
291 | fstype_to_string (int t) | ||
292 | { | ||
293 | struct vfs_ent *e; | ||
294 | |||
295 | e = getvfsbytype (t); | ||
296 | if (!e || !e->vfsent_name) | ||
297 | return "none"; | ||
298 | else | ||
299 | return e->vfsent_name; | ||
300 | } | ||
301 | #endif /* MOUNTED_VMOUNT */ | ||
302 | |||
303 | |||
304 | #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2 | ||
305 | |||
306 | /* Return the device number from MOUNT_OPTIONS, if possible. | ||
307 | Otherwise return (dev_t) -1. */ | ||
308 | |||
309 | static dev_t | ||
310 | dev_from_mount_options (char const *mount_options) | ||
311 | { | ||
312 | /* GNU/Linux allows file system implementations to define their own | ||
313 | meaning for "dev=" mount options, so don't trust the meaning | ||
314 | here. */ | ||
315 | # ifndef __linux__ | ||
316 | |||
317 | static char const dev_pattern[] = ",dev="; | ||
318 | char const *devopt = strstr (mount_options, dev_pattern); | ||
319 | |||
320 | if (devopt) | ||
321 | { | ||
322 | char const *optval = devopt + sizeof dev_pattern - 1; | ||
323 | char *optvalend; | ||
324 | unsigned long int dev; | ||
325 | errno = 0; | ||
326 | dev = strtoul (optval, &optvalend, 16); | ||
327 | if (optval != optvalend | ||
328 | && (*optvalend == '\0' || *optvalend == ',') | ||
329 | && ! (dev == ULONG_MAX && errno == ERANGE) | ||
330 | && dev == (dev_t) dev) | ||
331 | return dev; | ||
332 | } | ||
333 | |||
334 | # endif | ||
335 | |||
336 | return -1; | ||
337 | } | ||
338 | |||
339 | #endif | ||
340 | |||
341 | /* Return a list of the currently mounted file systems, or NULL on error. | ||
342 | Add each entry to the tail of the list so that they stay in order. | ||
343 | If NEED_FS_TYPE is true, ensure that the file system type fields in | ||
344 | the returned list are valid. Otherwise, they might not be. */ | ||
345 | |||
346 | struct mount_entry * | ||
347 | read_file_system_list (bool need_fs_type) | ||
348 | { | ||
349 | struct mount_entry *mount_list; | ||
350 | struct mount_entry *me; | ||
351 | struct mount_entry **mtail = &mount_list; | ||
352 | |||
353 | #ifdef MOUNTED_LISTMNTENT | ||
354 | { | ||
355 | struct tabmntent *mntlist, *p; | ||
356 | struct mntent *mnt; | ||
357 | struct mount_entry *me; | ||
358 | |||
359 | /* the third and fourth arguments could be used to filter mounts, | ||
360 | but Crays doesn't seem to have any mounts that we want to | ||
361 | remove. Specifically, automount create normal NFS mounts. | ||
362 | */ | ||
363 | |||
364 | if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0) | ||
365 | return NULL; | ||
366 | for (p = mntlist; p; p = p->next) { | ||
367 | mnt = p->ment; | ||
368 | me = xmalloc (sizeof *me); | ||
369 | me->me_devname = xstrdup (mnt->mnt_fsname); | ||
370 | me->me_mountdir = xstrdup (mnt->mnt_dir); | ||
371 | me->me_type = xstrdup (mnt->mnt_type); | ||
372 | me->me_type_malloced = 1; | ||
373 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
374 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
375 | me->me_dev = -1; | ||
376 | *mtail = me; | ||
377 | mtail = &me->me_next; | ||
378 | } | ||
379 | freemntlist (mntlist); | ||
380 | } | ||
381 | #endif | ||
382 | |||
383 | #ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ | ||
384 | { | ||
385 | struct mntent *mnt; | ||
386 | char *table = MOUNTED; | ||
387 | FILE *fp; | ||
388 | |||
389 | fp = setmntent (table, "r"); | ||
390 | if (fp == NULL) | ||
391 | return NULL; | ||
392 | |||
393 | while ((mnt = getmntent (fp))) | ||
394 | { | ||
395 | me = xmalloc (sizeof *me); | ||
396 | me->me_devname = xstrdup (mnt->mnt_fsname); | ||
397 | me->me_mountdir = xstrdup (mnt->mnt_dir); | ||
398 | me->me_type = xstrdup (mnt->mnt_type); | ||
399 | me->me_type_malloced = 1; | ||
400 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
401 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
402 | me->me_dev = dev_from_mount_options (mnt->mnt_opts); | ||
403 | |||
404 | /* Add to the linked list. */ | ||
405 | *mtail = me; | ||
406 | mtail = &me->me_next; | ||
407 | } | ||
408 | |||
409 | if (endmntent (fp) == 0) | ||
410 | goto free_then_fail; | ||
411 | } | ||
412 | #endif /* MOUNTED_GETMNTENT1. */ | ||
413 | |||
414 | #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ | ||
415 | { | ||
416 | struct statfs *fsp; | ||
417 | int entries; | ||
418 | |||
419 | entries = getmntinfo (&fsp, MNT_NOWAIT); | ||
420 | if (entries < 0) | ||
421 | return NULL; | ||
422 | for (; entries-- > 0; fsp++) | ||
423 | { | ||
424 | char *fs_type = fsp_to_string (fsp); | ||
425 | |||
426 | me = xmalloc (sizeof *me); | ||
427 | me->me_devname = xstrdup (fsp->f_mntfromname); | ||
428 | me->me_mountdir = xstrdup (fsp->f_mntonname); | ||
429 | me->me_type = fs_type; | ||
430 | me->me_type_malloced = 0; | ||
431 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
432 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
433 | me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ | ||
434 | |||
435 | /* Add to the linked list. */ | ||
436 | *mtail = me; | ||
437 | mtail = &me->me_next; | ||
438 | } | ||
439 | } | ||
440 | #endif /* MOUNTED_GETMNTINFO */ | ||
441 | |||
442 | #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ | ||
443 | { | ||
444 | struct statvfs *fsp; | ||
445 | int entries; | ||
446 | |||
447 | entries = getmntinfo (&fsp, MNT_NOWAIT); | ||
448 | if (entries < 0) | ||
449 | return NULL; | ||
450 | for (; entries-- > 0; fsp++) | ||
451 | { | ||
452 | me = xmalloc (sizeof *me); | ||
453 | me->me_devname = xstrdup (fsp->f_mntfromname); | ||
454 | me->me_mountdir = xstrdup (fsp->f_mntonname); | ||
455 | me->me_type = xstrdup (fsp->f_fstypename); | ||
456 | me->me_type_malloced = 1; | ||
457 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
458 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
459 | me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ | ||
460 | |||
461 | /* Add to the linked list. */ | ||
462 | *mtail = me; | ||
463 | mtail = &me->me_next; | ||
464 | } | ||
465 | } | ||
466 | #endif /* MOUNTED_GETMNTINFO2 */ | ||
467 | |||
468 | #ifdef MOUNTED_GETMNT /* Ultrix. */ | ||
469 | { | ||
470 | int offset = 0; | ||
471 | int val; | ||
472 | struct fs_data fsd; | ||
473 | |||
474 | while (errno = 0, | ||
475 | 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, | ||
476 | (char *) 0))) | ||
477 | { | ||
478 | me = xmalloc (sizeof *me); | ||
479 | me->me_devname = xstrdup (fsd.fd_req.devname); | ||
480 | me->me_mountdir = xstrdup (fsd.fd_req.path); | ||
481 | me->me_type = gt_names[fsd.fd_req.fstype]; | ||
482 | me->me_type_malloced = 0; | ||
483 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
484 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
485 | me->me_dev = fsd.fd_req.dev; | ||
486 | |||
487 | /* Add to the linked list. */ | ||
488 | *mtail = me; | ||
489 | mtail = &me->me_next; | ||
490 | } | ||
491 | if (val < 0) | ||
492 | goto free_then_fail; | ||
493 | } | ||
494 | #endif /* MOUNTED_GETMNT. */ | ||
495 | |||
496 | #if defined MOUNTED_FS_STAT_DEV /* BeOS */ | ||
497 | { | ||
498 | /* The next_dev() and fs_stat_dev() system calls give the list of | ||
499 | all file systems, including the information returned by statvfs() | ||
500 | (fs type, total blocks, free blocks etc.), but without the mount | ||
501 | point. But on BeOS all file systems except / are mounted in the | ||
502 | rootfs, directly under /. | ||
503 | The directory name of the mount point is often, but not always, | ||
504 | identical to the volume name of the device. | ||
505 | We therefore get the list of subdirectories of /, and the list | ||
506 | of all file systems, and match the two lists. */ | ||
507 | |||
508 | DIR *dirp; | ||
509 | struct rootdir_entry | ||
510 | { | ||
511 | char *name; | ||
512 | dev_t dev; | ||
513 | ino_t ino; | ||
514 | struct rootdir_entry *next; | ||
515 | }; | ||
516 | struct rootdir_entry *rootdir_list; | ||
517 | struct rootdir_entry **rootdir_tail; | ||
518 | int32 pos; | ||
519 | dev_t dev; | ||
520 | fs_info fi; | ||
521 | |||
522 | /* All volumes are mounted in the rootfs, directly under /. */ | ||
523 | rootdir_list = NULL; | ||
524 | rootdir_tail = &rootdir_list; | ||
525 | dirp = opendir ("/"); | ||
526 | if (dirp) | ||
527 | { | ||
528 | struct dirent *d; | ||
529 | |||
530 | while ((d = readdir (dirp)) != NULL) | ||
531 | { | ||
532 | char *name; | ||
533 | struct stat statbuf; | ||
534 | |||
535 | if (strcmp (d->d_name, "..") == 0) | ||
536 | continue; | ||
537 | |||
538 | if (strcmp (d->d_name, ".") == 0) | ||
539 | name = xstrdup ("/"); | ||
540 | else | ||
541 | { | ||
542 | name = xmalloc (1 + strlen (d->d_name) + 1); | ||
543 | name[0] = '/'; | ||
544 | strcpy (name + 1, d->d_name); | ||
545 | } | ||
546 | |||
547 | if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode)) | ||
548 | { | ||
549 | struct rootdir_entry *re = xmalloc (sizeof *re); | ||
550 | re->name = name; | ||
551 | re->dev = statbuf.st_dev; | ||
552 | re->ino = statbuf.st_ino; | ||
553 | |||
554 | /* Add to the linked list. */ | ||
555 | *rootdir_tail = re; | ||
556 | rootdir_tail = &re->next; | ||
557 | } | ||
558 | else | ||
559 | free (name); | ||
560 | } | ||
561 | closedir (dirp); | ||
562 | } | ||
563 | *rootdir_tail = NULL; | ||
564 | |||
565 | for (pos = 0; (dev = next_dev (&pos)) >= 0; ) | ||
566 | if (fs_stat_dev (dev, &fi) >= 0) | ||
567 | { | ||
568 | /* Note: fi.dev == dev. */ | ||
569 | struct rootdir_entry *re; | ||
570 | |||
571 | for (re = rootdir_list; re; re = re->next) | ||
572 | if (re->dev == fi.dev && re->ino == fi.root) | ||
573 | break; | ||
574 | |||
575 | me = xmalloc (sizeof *me); | ||
576 | me->me_devname = xstrdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name); | ||
577 | me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name); | ||
578 | me->me_type = xstrdup (fi.fsh_name); | ||
579 | me->me_type_malloced = 1; | ||
580 | me->me_dev = fi.dev; | ||
581 | me->me_dummy = 0; | ||
582 | me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0; | ||
583 | |||
584 | /* Add to the linked list. */ | ||
585 | *mtail = me; | ||
586 | mtail = &me->me_next; | ||
587 | } | ||
588 | *mtail = NULL; | ||
589 | |||
590 | while (rootdir_list != NULL) | ||
591 | { | ||
592 | struct rootdir_entry *re = rootdir_list; | ||
593 | rootdir_list = re->next; | ||
594 | free (re->name); | ||
595 | free (re); | ||
596 | } | ||
597 | } | ||
598 | #endif /* MOUNTED_FS_STAT_DEV */ | ||
599 | |||
600 | #if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */ | ||
601 | { | ||
602 | int numsys, counter; | ||
603 | size_t bufsize; | ||
604 | struct statfs *stats; | ||
605 | |||
606 | numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT); | ||
607 | if (numsys < 0) | ||
608 | return (NULL); | ||
609 | if (SIZE_MAX / sizeof *stats <= numsys) | ||
610 | xalloc_die (); | ||
611 | |||
612 | bufsize = (1 + numsys) * sizeof *stats; | ||
613 | stats = xmalloc (bufsize); | ||
614 | numsys = getfsstat (stats, bufsize, MNT_NOWAIT); | ||
615 | |||
616 | if (numsys < 0) | ||
617 | { | ||
618 | free (stats); | ||
619 | return (NULL); | ||
620 | } | ||
621 | |||
622 | for (counter = 0; counter < numsys; counter++) | ||
623 | { | ||
624 | me = xmalloc (sizeof *me); | ||
625 | me->me_devname = xstrdup (stats[counter].f_mntfromname); | ||
626 | me->me_mountdir = xstrdup (stats[counter].f_mntonname); | ||
627 | me->me_type = xstrdup (FS_TYPE (stats[counter])); | ||
628 | me->me_type_malloced = 1; | ||
629 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
630 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
631 | me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ | ||
632 | |||
633 | /* Add to the linked list. */ | ||
634 | *mtail = me; | ||
635 | mtail = &me->me_next; | ||
636 | } | ||
637 | |||
638 | free (stats); | ||
639 | } | ||
640 | #endif /* MOUNTED_GETFSSTAT */ | ||
641 | |||
642 | #if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */ | ||
643 | { | ||
644 | struct mnttab mnt; | ||
645 | char *table = "/etc/mnttab"; | ||
646 | FILE *fp; | ||
647 | |||
648 | fp = fopen (table, "r"); | ||
649 | if (fp == NULL) | ||
650 | return NULL; | ||
651 | |||
652 | while (fread (&mnt, sizeof mnt, 1, fp) > 0) | ||
653 | { | ||
654 | me = xmalloc (sizeof *me); | ||
655 | # ifdef GETFSTYP /* SVR3. */ | ||
656 | me->me_devname = xstrdup (mnt.mt_dev); | ||
657 | # else | ||
658 | me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6); | ||
659 | strcpy (me->me_devname, "/dev/"); | ||
660 | strcpy (me->me_devname + 5, mnt.mt_dev); | ||
661 | # endif | ||
662 | me->me_mountdir = xstrdup (mnt.mt_filsys); | ||
663 | me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ | ||
664 | me->me_type = ""; | ||
665 | me->me_type_malloced = 0; | ||
666 | # ifdef GETFSTYP /* SVR3. */ | ||
667 | if (need_fs_type) | ||
668 | { | ||
669 | struct statfs fsd; | ||
670 | char typebuf[FSTYPSZ]; | ||
671 | |||
672 | if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1 | ||
673 | && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) | ||
674 | { | ||
675 | me->me_type = xstrdup (typebuf); | ||
676 | me->me_type_malloced = 1; | ||
677 | } | ||
678 | } | ||
679 | # endif | ||
680 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
681 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
682 | |||
683 | /* Add to the linked list. */ | ||
684 | *mtail = me; | ||
685 | mtail = &me->me_next; | ||
686 | } | ||
687 | |||
688 | if (ferror (fp)) | ||
689 | { | ||
690 | /* The last fread() call must have failed. */ | ||
691 | int saved_errno = errno; | ||
692 | fclose (fp); | ||
693 | errno = saved_errno; | ||
694 | goto free_then_fail; | ||
695 | } | ||
696 | |||
697 | if (fclose (fp) == EOF) | ||
698 | goto free_then_fail; | ||
699 | } | ||
700 | #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */ | ||
701 | |||
702 | #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */ | ||
703 | { | ||
704 | struct mntent **mnttbl = getmnttbl (), **ent; | ||
705 | for (ent=mnttbl;*ent;ent++) | ||
706 | { | ||
707 | me = xmalloc (sizeof *me); | ||
708 | me->me_devname = xstrdup ( (*ent)->mt_resource); | ||
709 | me->me_mountdir = xstrdup ( (*ent)->mt_directory); | ||
710 | me->me_type = xstrdup ((*ent)->mt_fstype); | ||
711 | me->me_type_malloced = 1; | ||
712 | me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); | ||
713 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
714 | me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ | ||
715 | |||
716 | /* Add to the linked list. */ | ||
717 | *mtail = me; | ||
718 | mtail = &me->me_next; | ||
719 | } | ||
720 | endmnttbl (); | ||
721 | } | ||
722 | #endif | ||
723 | |||
724 | #ifdef MOUNTED_GETMNTENT2 /* SVR4. */ | ||
725 | { | ||
726 | struct mnttab mnt; | ||
727 | char *table = MNTTAB; | ||
728 | FILE *fp; | ||
729 | int ret; | ||
730 | int lockfd = -1; | ||
731 | |||
732 | # if defined F_RDLCK && defined F_SETLKW | ||
733 | /* MNTTAB_LOCK is a macro name of our own invention; it's not present in | ||
734 | e.g. Solaris 2.6. If the SVR4 folks ever define a macro | ||
735 | for this file name, we should use their macro name instead. | ||
736 | (Why not just lock MNTTAB directly? We don't know.) */ | ||
737 | # ifndef MNTTAB_LOCK | ||
738 | # define MNTTAB_LOCK "/etc/.mnttab.lock" | ||
739 | # endif | ||
740 | lockfd = open (MNTTAB_LOCK, O_RDONLY); | ||
741 | if (0 <= lockfd) | ||
742 | { | ||
743 | struct flock flock; | ||
744 | flock.l_type = F_RDLCK; | ||
745 | flock.l_whence = SEEK_SET; | ||
746 | flock.l_start = 0; | ||
747 | flock.l_len = 0; | ||
748 | while (fcntl (lockfd, F_SETLKW, &flock) == -1) | ||
749 | if (errno != EINTR) | ||
750 | { | ||
751 | int saved_errno = errno; | ||
752 | close (lockfd); | ||
753 | errno = saved_errno; | ||
754 | return NULL; | ||
755 | } | ||
756 | } | ||
757 | else if (errno != ENOENT) | ||
758 | return NULL; | ||
759 | # endif | ||
760 | |||
761 | errno = 0; | ||
762 | fp = fopen (table, "r"); | ||
763 | if (fp == NULL) | ||
764 | ret = errno; | ||
765 | else | ||
766 | { | ||
767 | while ((ret = getmntent (fp, &mnt)) == 0) | ||
768 | { | ||
769 | me = xmalloc (sizeof *me); | ||
770 | me->me_devname = xstrdup (mnt.mnt_special); | ||
771 | me->me_mountdir = xstrdup (mnt.mnt_mountp); | ||
772 | me->me_type = xstrdup (mnt.mnt_fstype); | ||
773 | me->me_type_malloced = 1; | ||
774 | me->me_dummy = MNT_IGNORE (&mnt) != 0; | ||
775 | me->me_remote = ME_REMOTE (me->me_devname, me->me_type); | ||
776 | me->me_dev = dev_from_mount_options (mnt.mnt_mntopts); | ||
777 | |||
778 | /* Add to the linked list. */ | ||
779 | *mtail = me; | ||
780 | mtail = &me->me_next; | ||
781 | } | ||
782 | |||
783 | ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1; | ||
784 | } | ||
785 | |||
786 | if (0 <= lockfd && close (lockfd) != 0) | ||
787 | ret = errno; | ||
788 | |||
789 | if (0 <= ret) | ||
790 | { | ||
791 | errno = ret; | ||
792 | goto free_then_fail; | ||
793 | } | ||
794 | } | ||
795 | #endif /* MOUNTED_GETMNTENT2. */ | ||
796 | |||
797 | #ifdef MOUNTED_VMOUNT /* AIX. */ | ||
798 | { | ||
799 | int bufsize; | ||
800 | char *entries, *thisent; | ||
801 | struct vmount *vmp; | ||
802 | int n_entries; | ||
803 | int i; | ||
804 | |||
805 | /* Ask how many bytes to allocate for the mounted file system info. */ | ||
806 | if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0) | ||
807 | return NULL; | ||
808 | entries = xmalloc (bufsize); | ||
809 | |||
810 | /* Get the list of mounted file systems. */ | ||
811 | n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); | ||
812 | if (n_entries < 0) | ||
813 | { | ||
814 | int saved_errno = errno; | ||
815 | free (entries); | ||
816 | errno = saved_errno; | ||
817 | return NULL; | ||
818 | } | ||
819 | |||
820 | for (i = 0, thisent = entries; | ||
821 | i < n_entries; | ||
822 | i++, thisent += vmp->vmt_length) | ||
823 | { | ||
824 | char *options, *ignore; | ||
825 | |||
826 | vmp = (struct vmount *) thisent; | ||
827 | me = xmalloc (sizeof *me); | ||
828 | if (vmp->vmt_flags & MNT_REMOTE) | ||
829 | { | ||
830 | char *host, *dir; | ||
831 | |||
832 | me->me_remote = 1; | ||
833 | /* Prepend the remote dirname. */ | ||
834 | host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off; | ||
835 | dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off; | ||
836 | me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2); | ||
837 | strcpy (me->me_devname, host); | ||
838 | strcat (me->me_devname, ":"); | ||
839 | strcat (me->me_devname, dir); | ||
840 | } | ||
841 | else | ||
842 | { | ||
843 | me->me_remote = 0; | ||
844 | me->me_devname = xstrdup (thisent + | ||
845 | vmp->vmt_data[VMT_OBJECT].vmt_off); | ||
846 | } | ||
847 | me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off); | ||
848 | me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype)); | ||
849 | me->me_type_malloced = 1; | ||
850 | options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off; | ||
851 | ignore = strstr (options, "ignore"); | ||
852 | me->me_dummy = (ignore | ||
853 | && (ignore == options || ignore[-1] == ',') | ||
854 | && (ignore[sizeof "ignore" - 1] == ',' | ||
855 | || ignore[sizeof "ignore" - 1] == '\0')); | ||
856 | me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */ | ||
857 | |||
858 | /* Add to the linked list. */ | ||
859 | *mtail = me; | ||
860 | mtail = &me->me_next; | ||
861 | } | ||
862 | free (entries); | ||
863 | } | ||
864 | #endif /* MOUNTED_VMOUNT. */ | ||
865 | |||
866 | *mtail = NULL; | ||
867 | return mount_list; | ||
868 | |||
869 | |||
870 | free_then_fail: | ||
871 | { | ||
872 | int saved_errno = errno; | ||
873 | *mtail = NULL; | ||
874 | |||
875 | while (mount_list) | ||
876 | { | ||
877 | me = mount_list->me_next; | ||
878 | free (mount_list->me_devname); | ||
879 | free (mount_list->me_mountdir); | ||
880 | if (mount_list->me_type_malloced) | ||
881 | free (mount_list->me_type); | ||
882 | free (mount_list); | ||
883 | mount_list = me; | ||
884 | } | ||
885 | |||
886 | errno = saved_errno; | ||
887 | return NULL; | ||
888 | } | ||
889 | } | ||