summaryrefslogtreecommitdiffstats
path: root/gl/mountlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/mountlist.c')
-rw-r--r--gl/mountlist.c889
1 files changed, 889 insertions, 0 deletions
diff --git a/gl/mountlist.c b/gl/mountlist.c
new file mode 100644
index 0000000..bb01f91
--- /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
32char *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
182static char *
183fstype_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
277static char *
278fsp_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. */
290static char *
291fstype_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
309static dev_t
310dev_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
346struct mount_entry *
347read_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}