1 /* mountlist.c -- return a list of mounted file systems
3 Copyright (C) 1991-1992, 1997-2013 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "mountlist.h"
37 # include <sys/param.h>
40 #if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */
42 # include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
43 NGROUPS is used as an array dimension in ucred.h */
44 # include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */
47 # include <sys/mount.h>
49 # if HAVE_SYS_FS_TYPES_H
50 # include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */
52 # if HAVE_STRUCT_FSSTAT_F_FSTYPENAME
53 # define FS_TYPE(Ent) ((Ent).f_fstypename)
55 # define FS_TYPE(Ent) mnt_names[(Ent).f_type]
57 #endif /* MOUNTED_GETFSSTAT */
59 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
62 # if defined _PATH_MOUNTED /* GNU libc */
63 # define MOUNTED _PATH_MOUNTED
65 # if defined MNT_MNTTAB /* HP-UX. */
66 # define MOUNTED MNT_MNTTAB
68 # if defined MNTTABNAME /* Dynix. */
69 # define MOUNTED MNTTABNAME
74 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
75 # include <sys/mount.h>
78 #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
79 # include <sys/statvfs.h>
82 #ifdef MOUNTED_GETMNT /* Ultrix. */
83 # include <sys/mount.h>
84 # include <sys/fs_types.h>
87 #ifdef MOUNTED_FS_STAT_DEV /* BeOS. */
92 #ifdef MOUNTED_FREAD /* SVR2. */
96 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
98 # include <sys/fstyp.h>
99 # include <sys/statfs.h>
102 #ifdef MOUNTED_LISTMNTENT
106 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
107 # include <sys/mnttab.h>
110 #ifdef MOUNTED_VMOUNT /* AIX. */
112 # include <sys/vfs.h>
115 #ifdef MOUNTED_INTERIX_STATVFS /* Interix. */
116 # include <sys/statvfs.h>
121 /* So special that it's not worth putting this in autoconf. */
122 # undef MOUNTED_FREAD_FSTYP
123 # define MOUNTED_GETMNTTBL
126 #if HAVE_SYS_MNTENT_H
127 /* This is to get MNTOPT_IGNORE on e.g. SVR4. */
128 # include <sys/mntent.h>
131 #ifndef HAVE_HASMNTOPT
132 # define hasmntopt(mnt, opt) ((char *) 0)
137 # define MNT_IGNORE(M) hasmntopt (M, MNTOPT_IGNORE)
139 # define MNT_IGNORE(M) 0
143 # include "unlocked-io.h"
146 /* The results of open() in this file are not used with fchdir,
147 therefore save some unnecessary work in fchdir.c. */
151 /* The results of opendir() in this file are not used with dirfd and fchdir,
152 therefore save some unnecessary work in fchdir.c. */
156 #define ME_DUMMY_0(Fs_name, Fs_type) \
157 (strcmp (Fs_type, "autofs") == 0 \
158 || strcmp (Fs_type, "proc") == 0 \
159 || strcmp (Fs_type, "subfs") == 0 \
160 /* for Linux 2.6/3.x */ \
161 || strcmp (Fs_type, "debugfs") == 0 \
162 || strcmp (Fs_type, "devpts") == 0 \
163 || strcmp (Fs_type, "fusectl") == 0 \
164 || strcmp (Fs_type, "mqueue") == 0 \
165 || strcmp (Fs_type, "rpc_pipefs") == 0 \
166 || strcmp (Fs_type, "sysfs") == 0 \
167 /* FreeBSD, Linux 2.4 */ \
168 || strcmp (Fs_type, "devfs") == 0 \
169 /* for NetBSD 3.0 */ \
170 || strcmp (Fs_type, "kernfs") == 0 \
172 || strcmp (Fs_type, "ignore") == 0)
174 /* Historically, we have marked as "dummy" any file system of type "none",
175 but now that programs like du need to know about bind-mounted directories,
176 we grant an exception to any with "bind" in its list of mount options.
177 I.e., those are *not* dummy entries. */
178 #ifdef MOUNTED_GETMNTENT1
179 # define ME_DUMMY(Fs_name, Fs_type, Fs_ent) \
180 (ME_DUMMY_0 (Fs_name, Fs_type) \
181 || (strcmp (Fs_type, "none") == 0 \
182 && !hasmntopt (Fs_ent, "bind")))
184 # define ME_DUMMY(Fs_name, Fs_type) \
185 (ME_DUMMY_0 (Fs_name, Fs_type) || strcmp (Fs_type, "none") == 0)
189 # include <windows.h>
190 # define ME_REMOTE me_remote
191 /* All cygwin mount points include ':' or start with '//'; so it
192 requires a native Windows call to determine remote disks. */
194 me_remote (char const *fs_name
, char const *fs_type _GL_UNUSED
)
196 if (fs_name
[0] && fs_name
[1] == ':')
199 sprintf (drive
, "%c:\\", fs_name
[0]);
200 switch (GetDriveType (drive
))
202 case DRIVE_REMOVABLE
:
214 /* A file system is "remote" if its Fs_name contains a ':'
215 or if (it is of type (smbfs or cifs) and its Fs_name starts with '//'). */
216 # define ME_REMOTE(Fs_name, Fs_type) \
217 (strchr (Fs_name, ':') != NULL \
218 || ((Fs_name)[0] == '/' \
219 && (Fs_name)[1] == '/' \
220 && (strcmp (Fs_type, "smbfs") == 0 \
221 || strcmp (Fs_type, "cifs") == 0)))
224 #if MOUNTED_GETMNTINFO
226 # if ! HAVE_STRUCT_STATFS_F_FSTYPENAME
228 fstype_to_string (short int t
)
323 fsp_to_string (const struct statfs
*fsp
)
325 # if HAVE_STRUCT_STATFS_F_FSTYPENAME
326 return (char *) (fsp
->f_fstypename
);
328 return fstype_to_string (fsp
->f_type
);
332 #endif /* MOUNTED_GETMNTINFO */
334 #ifdef MOUNTED_VMOUNT /* AIX. */
336 fstype_to_string (int t
)
340 e
= getvfsbytype (t
);
341 if (!e
|| !e
->vfsent_name
)
344 return e
->vfsent_name
;
346 #endif /* MOUNTED_VMOUNT */
349 #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
351 /* Return the device number from MOUNT_OPTIONS, if possible.
352 Otherwise return (dev_t) -1. */
354 dev_from_mount_options (char const *mount_options
)
356 /* GNU/Linux allows file system implementations to define their own
357 meaning for "dev=" mount options, so don't trust the meaning
361 static char const dev_pattern
[] = ",dev=";
362 char const *devopt
= strstr (mount_options
, dev_pattern
);
366 char const *optval
= devopt
+ sizeof dev_pattern
- 1;
368 unsigned long int dev
;
370 dev
= strtoul (optval
, &optvalend
, 16);
371 if (optval
!= optvalend
372 && (*optvalend
== '\0' || *optvalend
== ',')
373 && ! (dev
== ULONG_MAX
&& errno
== ERANGE
)
374 && dev
== (dev_t
) dev
)
379 (void) mount_options
;
385 /* Return a list of the currently mounted file systems, or NULL on error.
386 Add each entry to the tail of the list so that they stay in order.
387 If NEED_FS_TYPE is true, ensure that the file system type fields in
388 the returned list are valid. Otherwise, they might not be. */
391 read_file_system_list (bool need_fs_type
)
393 struct mount_entry
*mount_list
;
394 struct mount_entry
*me
;
395 struct mount_entry
**mtail
= &mount_list
;
398 #ifdef MOUNTED_LISTMNTENT
400 struct tabmntent
*mntlist
, *p
;
402 struct mount_entry
*me
;
404 /* the third and fourth arguments could be used to filter mounts,
405 but Crays doesn't seem to have any mounts that we want to
406 remove. Specifically, automount create normal NFS mounts.
409 if (listmntent (&mntlist
, KMTAB
, NULL
, NULL
) < 0)
411 for (p
= mntlist
; p
; p
= p
->next
)
414 me
= xmalloc (sizeof *me
);
415 me
->me_devname
= xstrdup (mnt
->mnt_fsname
);
416 me
->me_mountdir
= xstrdup (mnt
->mnt_dir
);
417 me
->me_type
= xstrdup (mnt
->mnt_type
);
418 me
->me_type_malloced
= 1;
419 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
420 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
423 mtail
= &me
->me_next
;
425 freemntlist (mntlist
);
429 #ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
432 char const *table
= MOUNTED
;
435 fp
= setmntent (table
, "r");
439 while ((mnt
= getmntent (fp
)))
441 me
= xmalloc (sizeof *me
);
442 me
->me_devname
= xstrdup (mnt
->mnt_fsname
);
443 me
->me_mountdir
= xstrdup (mnt
->mnt_dir
);
444 me
->me_type
= xstrdup (mnt
->mnt_type
);
445 me
->me_type_malloced
= 1;
446 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
, mnt
);
447 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
448 me
->me_dev
= dev_from_mount_options (mnt
->mnt_opts
);
450 /* Add to the linked list. */
452 mtail
= &me
->me_next
;
455 if (endmntent (fp
) == 0)
458 #endif /* MOUNTED_GETMNTENT1. */
460 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
465 entries
= getmntinfo (&fsp
, MNT_NOWAIT
);
468 for (; entries
-- > 0; fsp
++)
470 char *fs_type
= fsp_to_string (fsp
);
472 me
= xmalloc (sizeof *me
);
473 me
->me_devname
= xstrdup (fsp
->f_mntfromname
);
474 me
->me_mountdir
= xstrdup (fsp
->f_mntonname
);
475 me
->me_type
= fs_type
;
476 me
->me_type_malloced
= 0;
477 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
478 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
479 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
481 /* Add to the linked list. */
483 mtail
= &me
->me_next
;
486 #endif /* MOUNTED_GETMNTINFO */
488 #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
493 entries
= getmntinfo (&fsp
, MNT_NOWAIT
);
496 for (; entries
-- > 0; fsp
++)
498 me
= xmalloc (sizeof *me
);
499 me
->me_devname
= xstrdup (fsp
->f_mntfromname
);
500 me
->me_mountdir
= xstrdup (fsp
->f_mntonname
);
501 me
->me_type
= xstrdup (fsp
->f_fstypename
);
502 me
->me_type_malloced
= 1;
503 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
504 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
505 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
507 /* Add to the linked list. */
509 mtail
= &me
->me_next
;
512 #endif /* MOUNTED_GETMNTINFO2 */
514 #ifdef MOUNTED_GETMNT /* Ultrix. */
521 0 < (val
= getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
,
524 me
= xmalloc (sizeof *me
);
525 me
->me_devname
= xstrdup (fsd
.fd_req
.devname
);
526 me
->me_mountdir
= xstrdup (fsd
.fd_req
.path
);
527 me
->me_type
= gt_names
[fsd
.fd_req
.fstype
];
528 me
->me_type_malloced
= 0;
529 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
530 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
531 me
->me_dev
= fsd
.fd_req
.dev
;
533 /* Add to the linked list. */
535 mtail
= &me
->me_next
;
540 #endif /* MOUNTED_GETMNT. */
542 #if defined MOUNTED_FS_STAT_DEV /* BeOS */
544 /* The next_dev() and fs_stat_dev() system calls give the list of
545 all file systems, including the information returned by statvfs()
546 (fs type, total blocks, free blocks etc.), but without the mount
547 point. But on BeOS all file systems except / are mounted in the
548 rootfs, directly under /.
549 The directory name of the mount point is often, but not always,
550 identical to the volume name of the device.
551 We therefore get the list of subdirectories of /, and the list
552 of all file systems, and match the two lists. */
560 struct rootdir_entry
*next
;
562 struct rootdir_entry
*rootdir_list
;
563 struct rootdir_entry
**rootdir_tail
;
568 /* All volumes are mounted in the rootfs, directly under /. */
570 rootdir_tail
= &rootdir_list
;
571 dirp
= opendir ("/");
576 while ((d
= readdir (dirp
)) != NULL
)
581 if (strcmp (d
->d_name
, "..") == 0)
584 if (strcmp (d
->d_name
, ".") == 0)
585 name
= xstrdup ("/");
588 name
= xmalloc (1 + strlen (d
->d_name
) + 1);
590 strcpy (name
+ 1, d
->d_name
);
593 if (lstat (name
, &statbuf
) >= 0 && S_ISDIR (statbuf
.st_mode
))
595 struct rootdir_entry
*re
= xmalloc (sizeof *re
);
597 re
->dev
= statbuf
.st_dev
;
598 re
->ino
= statbuf
.st_ino
;
600 /* Add to the linked list. */
602 rootdir_tail
= &re
->next
;
609 *rootdir_tail
= NULL
;
611 for (pos
= 0; (dev
= next_dev (&pos
)) >= 0; )
612 if (fs_stat_dev (dev
, &fi
) >= 0)
614 /* Note: fi.dev == dev. */
615 struct rootdir_entry
*re
;
617 for (re
= rootdir_list
; re
; re
= re
->next
)
618 if (re
->dev
== fi
.dev
&& re
->ino
== fi
.root
)
621 me
= xmalloc (sizeof *me
);
622 me
->me_devname
= xstrdup (fi
.device_name
[0] != '\0'
623 ? fi
.device_name
: fi
.fsh_name
);
624 me
->me_mountdir
= xstrdup (re
!= NULL
? re
->name
: fi
.fsh_name
);
625 me
->me_type
= xstrdup (fi
.fsh_name
);
626 me
->me_type_malloced
= 1;
629 me
->me_remote
= (fi
.flags
& B_FS_IS_SHARED
) != 0;
631 /* Add to the linked list. */
633 mtail
= &me
->me_next
;
637 while (rootdir_list
!= NULL
)
639 struct rootdir_entry
*re
= rootdir_list
;
640 rootdir_list
= re
->next
;
645 #endif /* MOUNTED_FS_STAT_DEV */
647 #if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
651 struct statfs
*stats
;
653 numsys
= getfsstat (NULL
, 0L, MNT_NOWAIT
);
656 if (SIZE_MAX
/ sizeof *stats
<= numsys
)
659 bufsize
= (1 + numsys
) * sizeof *stats
;
660 stats
= xmalloc (bufsize
);
661 numsys
= getfsstat (stats
, bufsize
, MNT_NOWAIT
);
669 for (counter
= 0; counter
< numsys
; counter
++)
671 me
= xmalloc (sizeof *me
);
672 me
->me_devname
= xstrdup (stats
[counter
].f_mntfromname
);
673 me
->me_mountdir
= xstrdup (stats
[counter
].f_mntonname
);
674 me
->me_type
= xstrdup (FS_TYPE (stats
[counter
]));
675 me
->me_type_malloced
= 1;
676 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
677 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
678 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
680 /* Add to the linked list. */
682 mtail
= &me
->me_next
;
687 #endif /* MOUNTED_GETFSSTAT */
689 #if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */
692 char *table
= "/etc/mnttab";
695 fp
= fopen (table
, "r");
699 while (fread (&mnt
, sizeof mnt
, 1, fp
) > 0)
701 me
= xmalloc (sizeof *me
);
702 # ifdef GETFSTYP /* SVR3. */
703 me
->me_devname
= xstrdup (mnt
.mt_dev
);
705 me
->me_devname
= xmalloc (strlen (mnt
.mt_dev
) + 6);
706 strcpy (me
->me_devname
, "/dev/");
707 strcpy (me
->me_devname
+ 5, mnt
.mt_dev
);
709 me
->me_mountdir
= xstrdup (mnt
.mt_filsys
);
710 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
712 me
->me_type_malloced
= 0;
713 # ifdef GETFSTYP /* SVR3. */
717 char typebuf
[FSTYPSZ
];
719 if (statfs (me
->me_mountdir
, &fsd
, sizeof fsd
, 0) != -1
720 && sysfs (GETFSTYP
, fsd
.f_fstyp
, typebuf
) != -1)
722 me
->me_type
= xstrdup (typebuf
);
723 me
->me_type_malloced
= 1;
727 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
728 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
730 /* Add to the linked list. */
732 mtail
= &me
->me_next
;
737 /* The last fread() call must have failed. */
738 int saved_errno
= errno
;
744 if (fclose (fp
) == EOF
)
747 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
749 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */
751 struct mntent
**mnttbl
= getmnttbl (), **ent
;
752 for (ent
= mnttbl
; *ent
; ent
++)
754 me
= xmalloc (sizeof *me
);
755 me
->me_devname
= xstrdup ((*ent
)->mt_resource
);
756 me
->me_mountdir
= xstrdup ((*ent
)->mt_directory
);
757 me
->me_type
= xstrdup ((*ent
)->mt_fstype
);
758 me
->me_type_malloced
= 1;
759 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
760 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
761 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
763 /* Add to the linked list. */
765 mtail
= &me
->me_next
;
771 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
774 char *table
= MNTTAB
;
779 # if defined F_RDLCK && defined F_SETLKW
780 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
781 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
782 for this file name, we should use their macro name instead.
783 (Why not just lock MNTTAB directly? We don't know.) */
785 # define MNTTAB_LOCK "/etc/.mnttab.lock"
787 lockfd
= open (MNTTAB_LOCK
, O_RDONLY
);
791 flock
.l_type
= F_RDLCK
;
792 flock
.l_whence
= SEEK_SET
;
795 while (fcntl (lockfd
, F_SETLKW
, &flock
) == -1)
798 int saved_errno
= errno
;
804 else if (errno
!= ENOENT
)
809 fp
= fopen (table
, "r");
814 while ((ret
= getmntent (fp
, &mnt
)) == 0)
816 me
= xmalloc (sizeof *me
);
817 me
->me_devname
= xstrdup (mnt
.mnt_special
);
818 me
->me_mountdir
= xstrdup (mnt
.mnt_mountp
);
819 me
->me_type
= xstrdup (mnt
.mnt_fstype
);
820 me
->me_type_malloced
= 1;
821 me
->me_dummy
= MNT_IGNORE (&mnt
) != 0;
822 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
823 me
->me_dev
= dev_from_mount_options (mnt
.mnt_mntopts
);
825 /* Add to the linked list. */
827 mtail
= &me
->me_next
;
830 ret
= fclose (fp
) == EOF
? errno
: 0 < ret
? 0 : -1;
833 if (0 <= lockfd
&& close (lockfd
) != 0)
842 #endif /* MOUNTED_GETMNTENT2. */
844 #ifdef MOUNTED_VMOUNT /* AIX. */
847 char *entries
, *thisent
;
852 /* Ask how many bytes to allocate for the mounted file system info. */
853 if (mntctl (MCTL_QUERY
, sizeof bufsize
, (struct vmount
*) &bufsize
) != 0)
855 entries
= xmalloc (bufsize
);
857 /* Get the list of mounted file systems. */
858 n_entries
= mntctl (MCTL_QUERY
, bufsize
, (struct vmount
*) entries
);
861 int saved_errno
= errno
;
867 for (i
= 0, thisent
= entries
;
869 i
++, thisent
+= vmp
->vmt_length
)
871 char *options
, *ignore
;
873 vmp
= (struct vmount
*) thisent
;
874 me
= xmalloc (sizeof *me
);
875 if (vmp
->vmt_flags
& MNT_REMOTE
)
880 /* Prepend the remote dirname. */
881 host
= thisent
+ vmp
->vmt_data
[VMT_HOSTNAME
].vmt_off
;
882 dir
= thisent
+ vmp
->vmt_data
[VMT_OBJECT
].vmt_off
;
883 me
->me_devname
= xmalloc (strlen (host
) + strlen (dir
) + 2);
884 strcpy (me
->me_devname
, host
);
885 strcat (me
->me_devname
, ":");
886 strcat (me
->me_devname
, dir
);
891 me
->me_devname
= xstrdup (thisent
+
892 vmp
->vmt_data
[VMT_OBJECT
].vmt_off
);
894 me
->me_mountdir
= xstrdup (thisent
+ vmp
->vmt_data
[VMT_STUB
].vmt_off
);
895 me
->me_type
= xstrdup (fstype_to_string (vmp
->vmt_gfstype
));
896 me
->me_type_malloced
= 1;
897 options
= thisent
+ vmp
->vmt_data
[VMT_ARGS
].vmt_off
;
898 ignore
= strstr (options
, "ignore");
899 me
->me_dummy
= (ignore
900 && (ignore
== options
|| ignore
[-1] == ',')
901 && (ignore
[sizeof "ignore" - 1] == ','
902 || ignore
[sizeof "ignore" - 1] == '\0'));
903 me
->me_dev
= (dev_t
) -1; /* vmt_fsid might be the info we want. */
905 /* Add to the linked list. */
907 mtail
= &me
->me_next
;
911 #endif /* MOUNTED_VMOUNT. */
913 #ifdef MOUNTED_INTERIX_STATVFS
915 DIR *dirp
= opendir ("/dev/fs");
916 char node
[9 + NAME_MAX
];
925 struct dirent
*result
;
927 if (readdir_r (dirp
, &entry
, &result
) || result
== NULL
)
930 strcpy (node
, "/dev/fs/");
931 strcat (node
, entry
.d_name
);
933 if (statvfs (node
, &dev
) == 0)
935 me
= xmalloc (sizeof *me
);
936 me
->me_devname
= xstrdup (dev
.f_mntfromname
);
937 me
->me_mountdir
= xstrdup (dev
.f_mntonname
);
938 me
->me_type
= xstrdup (dev
.f_fstypename
);
939 me
->me_type_malloced
= 1;
940 me
->me_dummy
= ME_DUMMY (me
->me_devname
, me
->me_type
);
941 me
->me_remote
= ME_REMOTE (me
->me_devname
, me
->me_type
);
942 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
944 /* Add to the linked list. */
946 mtail
= &me
->me_next
;
950 #endif /* MOUNTED_INTERIX_STATVFS */
958 int saved_errno
= errno
;
963 me
= mount_list
->me_next
;
964 free_mount_entry (mount_list
);
973 /* Free a mount entry as returned from read_file_system_list (). */
975 void free_mount_entry (struct mount_entry
*me
)
977 free (me
->me_devname
);
978 free (me
->me_mountdir
);
979 if (me
->me_type_malloced
)