summaryrefslogtreecommitdiffstats
path: root/gl/mountlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/mountlist.c')
-rw-r--r--gl/mountlist.c486
1 files changed, 312 insertions, 174 deletions
diff --git a/gl/mountlist.c b/gl/mountlist.c
index 30f42861..6d384812 100644
--- a/gl/mountlist.c
+++ b/gl/mountlist.c
@@ -1,10 +1,10 @@
1/* mountlist.c -- return a list of mounted file systems 1/* mountlist.c -- return a list of mounted file systems
2 2
3 Copyright (C) 1991-1992, 1997-2013 Free Software Foundation, Inc. 3 Copyright (C) 1991-1992, 1997-2023 Free Software Foundation, Inc.
4 4
5 This program is free software: you can redistribute it and/or modify 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 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 7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version. 8 (at your option) any later version.
9 9
10 This program is distributed in the hope that it will be useful, 10 This program is distributed in the hope that it will be useful,
@@ -13,7 +13,7 @@
13 GNU General Public License for more details. 13 GNU General Public License for more details.
14 14
15 You should have received a copy of the GNU General Public License 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/>. */ 16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 17
18#include <config.h> 18#include <config.h>
19 19
@@ -37,7 +37,13 @@
37# include <sys/param.h> 37# include <sys/param.h>
38#endif 38#endif
39 39
40#if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */ 40#if MAJOR_IN_MKDEV
41# include <sys/mkdev.h>
42#elif MAJOR_IN_SYSMACROS
43# include <sys/sysmacros.h>
44#endif
45
46#if defined MOUNTED_GETFSSTAT /* OSF/1, also (obsolete) Apple Darwin 1.3 */
41# if HAVE_SYS_UCRED_H 47# if HAVE_SYS_UCRED_H
42# include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS, 48# include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
43 NGROUPS is used as an array dimension in ucred.h */ 49 NGROUPS is used as an array dimension in ucred.h */
@@ -56,102 +62,104 @@
56# endif 62# endif
57#endif /* MOUNTED_GETFSSTAT */ 63#endif /* MOUNTED_GETFSSTAT */
58 64
59#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ 65#ifdef MOUNTED_GETMNTENT1 /* glibc, HP-UX, IRIX, Cygwin, Android,
66 also (obsolete) 4.3BSD, SunOS */
60# include <mntent.h> 67# include <mntent.h>
61# if !defined MOUNTED 68# include <sys/types.h>
69# if defined __ANDROID__ /* Android */
70 /* Bionic versions from between 2014-01-09 and 2015-01-08 define MOUNTED to
71 an incorrect value; older Bionic versions don't define it at all. */
72# undef MOUNTED
73# define MOUNTED "/proc/mounts"
74# elif !defined MOUNTED
62# if defined _PATH_MOUNTED /* GNU libc */ 75# if defined _PATH_MOUNTED /* GNU libc */
63# define MOUNTED _PATH_MOUNTED 76# define MOUNTED _PATH_MOUNTED
64# endif 77# endif
65# if defined MNT_MNTTAB /* HP-UX. */ 78# if defined MNT_MNTTAB /* HP-UX. */
66# define MOUNTED MNT_MNTTAB 79# define MOUNTED MNT_MNTTAB
67# endif 80# endif
68# if defined MNTTABNAME /* Dynix. */
69# define MOUNTED MNTTABNAME
70# endif
71# endif 81# endif
72#endif 82#endif
73 83
74#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ 84#ifdef MOUNTED_GETMNTINFO /* Mac OS X, FreeBSD, OpenBSD, also (obsolete) 4.4BSD */
75# include <sys/mount.h> 85# include <sys/mount.h>
76#endif 86#endif
77 87
78#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ 88#ifdef MOUNTED_GETMNTINFO2 /* NetBSD, Minix */
79# include <sys/statvfs.h> 89# include <sys/statvfs.h>
80#endif 90#endif
81 91
82#ifdef MOUNTED_GETMNT /* Ultrix. */ 92#ifdef MOUNTED_FS_STAT_DEV /* Haiku, also (obsolete) BeOS */
83# include <sys/mount.h>
84# include <sys/fs_types.h>
85#endif
86
87#ifdef MOUNTED_FS_STAT_DEV /* BeOS. */
88# include <fs_info.h> 93# include <fs_info.h>
89# include <dirent.h> 94# include <dirent.h>
90#endif 95#endif
91 96
92#ifdef MOUNTED_FREAD /* SVR2. */ 97#ifdef MOUNTED_FREAD_FSTYP /* (obsolete) SVR3 */
93# include <mnttab.h>
94#endif
95
96#ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
97# include <mnttab.h> 98# include <mnttab.h>
98# include <sys/fstyp.h> 99# include <sys/fstyp.h>
99# include <sys/statfs.h> 100# include <sys/statfs.h>
100#endif 101#endif
101 102
102#ifdef MOUNTED_LISTMNTENT 103#ifdef MOUNTED_GETEXTMNTENT /* Solaris >= 8 */
103# include <mntent.h> 104# include <sys/mnttab.h>
104#endif 105#endif
105 106
106#ifdef MOUNTED_GETMNTENT2 /* SVR4. */ 107#ifdef MOUNTED_GETMNTENT2 /* Solaris < 8, also (obsolete) SVR4 */
107# include <sys/mnttab.h> 108# include <sys/mnttab.h>
108#endif 109#endif
109 110
110#ifdef MOUNTED_VMOUNT /* AIX. */ 111#ifdef MOUNTED_VMOUNT /* AIX */
111# include <fshelp.h> 112# include <fshelp.h>
112# include <sys/vfs.h> 113# include <sys/vfs.h>
113#endif 114#endif
114 115
115#ifdef MOUNTED_INTERIX_STATVFS /* Interix. */ 116#ifdef MOUNTED_INTERIX_STATVFS /* Interix */
116# include <sys/statvfs.h> 117# include <sys/statvfs.h>
117# include <dirent.h> 118# include <dirent.h>
118#endif 119#endif
119 120
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 121#if HAVE_SYS_MNTENT_H
127/* This is to get MNTOPT_IGNORE on e.g. SVR4. */ 122/* This is to get MNTOPT_IGNORE on e.g. SVR4. */
128# include <sys/mntent.h> 123# include <sys/mntent.h>
129#endif 124#endif
130 125
126#ifdef MOUNTED_GETMNTENT1
127# if !HAVE_SETMNTENT /* Android <= 4.4 */
128# define setmntent(fp,mode) fopen (fp, mode "e")
129# endif
130# if !HAVE_ENDMNTENT /* Android <= 4.4 */
131# define endmntent(fp) fclose (fp)
132# endif
133#endif
134
131#ifndef HAVE_HASMNTOPT 135#ifndef HAVE_HASMNTOPT
132# define hasmntopt(mnt, opt) ((char *) 0) 136# define hasmntopt(mnt, opt) ((char *) 0)
133#endif 137#endif
134 138
135#undef MNT_IGNORE 139#undef MNT_IGNORE
136#ifdef MNTOPT_IGNORE 140#ifdef MNTOPT_IGNORE
137# define MNT_IGNORE(M) hasmntopt (M, MNTOPT_IGNORE) 141# if defined __sun && defined __SVR4
142/* Solaris defines hasmntopt(struct mnttab *, char *)
143 while it is otherwise hasmntopt(struct mnttab *, const char *). */
144# define MNT_IGNORE(M) hasmntopt (M, (char *) MNTOPT_IGNORE)
145# else
146# define MNT_IGNORE(M) hasmntopt (M, MNTOPT_IGNORE)
147# endif
138#else 148#else
139# define MNT_IGNORE(M) 0 149# define MNT_IGNORE(M) 0
140#endif 150#endif
141 151
142#if USE_UNLOCKED_IO 152/* Each of the FILE streams in this file is only used in a single thread. */
143# include "unlocked-io.h" 153#include "unlocked-io.h"
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 154
151/* The results of opendir() in this file are not used with dirfd and fchdir, 155/* The results of opendir() in this file are not used with dirfd and fchdir,
152 therefore save some unnecessary work in fchdir.c. */ 156 therefore save some unnecessary work in fchdir.c. */
153#undef opendir 157#ifdef GNULIB_defined_opendir
154#undef closedir 158# undef opendir
159#endif
160#ifdef GNULIB_defined_closedir
161# undef closedir
162#endif
155 163
156#define ME_DUMMY_0(Fs_name, Fs_type) \ 164#define ME_DUMMY_0(Fs_name, Fs_type) \
157 (strcmp (Fs_type, "autofs") == 0 \ 165 (strcmp (Fs_type, "autofs") == 0 \
@@ -161,6 +169,7 @@
161 || strcmp (Fs_type, "debugfs") == 0 \ 169 || strcmp (Fs_type, "debugfs") == 0 \
162 || strcmp (Fs_type, "devpts") == 0 \ 170 || strcmp (Fs_type, "devpts") == 0 \
163 || strcmp (Fs_type, "fusectl") == 0 \ 171 || strcmp (Fs_type, "fusectl") == 0 \
172 || strcmp (Fs_type, "fuse.portal") == 0 \
164 || strcmp (Fs_type, "mqueue") == 0 \ 173 || strcmp (Fs_type, "mqueue") == 0 \
165 || strcmp (Fs_type, "rpc_pipefs") == 0 \ 174 || strcmp (Fs_type, "rpc_pipefs") == 0 \
166 || strcmp (Fs_type, "sysfs") == 0 \ 175 || strcmp (Fs_type, "sysfs") == 0 \
@@ -176,10 +185,9 @@
176 we grant an exception to any with "bind" in its list of mount options. 185 we grant an exception to any with "bind" in its list of mount options.
177 I.e., those are *not* dummy entries. */ 186 I.e., those are *not* dummy entries. */
178#ifdef MOUNTED_GETMNTENT1 187#ifdef MOUNTED_GETMNTENT1
179# define ME_DUMMY(Fs_name, Fs_type, Fs_ent) \ 188# define ME_DUMMY(Fs_name, Fs_type, Bind) \
180 (ME_DUMMY_0 (Fs_name, Fs_type) \ 189 (ME_DUMMY_0 (Fs_name, Fs_type) \
181 || (strcmp (Fs_type, "none") == 0 \ 190 || (strcmp (Fs_type, "none") == 0 && !Bind))
182 && !hasmntopt (Fs_ent, "bind")))
183#else 191#else
184# define ME_DUMMY(Fs_name, Fs_type) \ 192# define ME_DUMMY(Fs_name, Fs_type) \
185 (ME_DUMMY_0 (Fs_name, Fs_type) || strcmp (Fs_type, "none") == 0) 193 (ME_DUMMY_0 (Fs_name, Fs_type) || strcmp (Fs_type, "none") == 0)
@@ -187,11 +195,14 @@
187 195
188#ifdef __CYGWIN__ 196#ifdef __CYGWIN__
189# include <windows.h> 197# include <windows.h>
198/* Don't assume that UNICODE is not defined. */
199# undef GetDriveType
200# define GetDriveType GetDriveTypeA
190# define ME_REMOTE me_remote 201# define ME_REMOTE me_remote
191/* All cygwin mount points include ':' or start with '//'; so it 202/* All cygwin mount points include ':' or start with '//'; so it
192 requires a native Windows call to determine remote disks. */ 203 requires a native Windows call to determine remote disks. */
193static bool 204static bool
194me_remote (char const *fs_name, char const *fs_type _GL_UNUSED) 205me_remote (char const *fs_name, _GL_UNUSED char const *fs_type)
195{ 206{
196 if (fs_name[0] && fs_name[1] == ':') 207 if (fs_name[0] && fs_name[1] == ':')
197 { 208 {
@@ -212,16 +223,30 @@ me_remote (char const *fs_name, char const *fs_type _GL_UNUSED)
212 223
213#ifndef ME_REMOTE 224#ifndef ME_REMOTE
214/* A file system is "remote" if its Fs_name contains a ':' 225/* 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 '//'). */ 226 or if (it is of type (smbfs or cifs) and its Fs_name starts with '//')
227 or if it is of any other of the listed types
228 or Fs_name is equal to "-hosts" (used by autofs to mount remote fs).
229 "VM" file systems like prl_fs or vboxsf are not considered remote here. */
216# define ME_REMOTE(Fs_name, Fs_type) \ 230# define ME_REMOTE(Fs_name, Fs_type) \
217 (strchr (Fs_name, ':') != NULL \ 231 (strchr (Fs_name, ':') != NULL \
218 || ((Fs_name)[0] == '/' \ 232 || ((Fs_name)[0] == '/' \
219 && (Fs_name)[1] == '/' \ 233 && (Fs_name)[1] == '/' \
220 && (strcmp (Fs_type, "smbfs") == 0 \ 234 && (strcmp (Fs_type, "smbfs") == 0 \
221 || strcmp (Fs_type, "cifs") == 0))) 235 || strcmp (Fs_type, "smb3") == 0 \
236 || strcmp (Fs_type, "cifs") == 0)) \
237 || strcmp (Fs_type, "acfs") == 0 \
238 || strcmp (Fs_type, "afs") == 0 \
239 || strcmp (Fs_type, "coda") == 0 \
240 || strcmp (Fs_type, "auristorfs") == 0 \
241 || strcmp (Fs_type, "fhgfs") == 0 \
242 || strcmp (Fs_type, "gpfs") == 0 \
243 || strcmp (Fs_type, "ibrix") == 0 \
244 || strcmp (Fs_type, "ocfs2") == 0 \
245 || strcmp (Fs_type, "vxfs") == 0 \
246 || strcmp ("-hosts", Fs_name) == 0)
222#endif 247#endif
223 248
224#if MOUNTED_GETMNTINFO 249#if MOUNTED_GETMNTINFO /* Mac OS X, FreeBSD, OpenBSD, also (obsolete) 4.4BSD */
225 250
226# if ! HAVE_STRUCT_STATFS_F_FSTYPENAME 251# if ! HAVE_STRUCT_STATFS_F_FSTYPENAME
227static char * 252static char *
@@ -331,7 +356,7 @@ fsp_to_string (const struct statfs *fsp)
331 356
332#endif /* MOUNTED_GETMNTINFO */ 357#endif /* MOUNTED_GETMNTINFO */
333 358
334#ifdef MOUNTED_VMOUNT /* AIX. */ 359#ifdef MOUNTED_VMOUNT /* AIX */
335static char * 360static char *
336fstype_to_string (int t) 361fstype_to_string (int t)
337{ 362{
@@ -382,6 +407,46 @@ dev_from_mount_options (char const *mount_options)
382 407
383#endif 408#endif
384 409
410#if defined MOUNTED_GETMNTENT1 && (defined __linux__ || defined __ANDROID__) /* GNU/Linux, Android */
411
412/* Unescape the paths in mount tables.
413 STR is updated in place. */
414
415static void
416unescape_tab (char *str)
417{
418 size_t i, j = 0;
419 size_t len = strlen (str) + 1;
420 for (i = 0; i < len; i++)
421 {
422 if (str[i] == '\\' && (i + 4 < len)
423 && str[i + 1] >= '0' && str[i + 1] <= '3'
424 && str[i + 2] >= '0' && str[i + 2] <= '7'
425 && str[i + 3] >= '0' && str[i + 3] <= '7')
426 {
427 str[j++] = (str[i + 1] - '0') * 64 +
428 (str[i + 2] - '0') * 8 +
429 (str[i + 3] - '0');
430 i += 3;
431 }
432 else
433 str[j++] = str[i];
434 }
435}
436
437/* Find the next space in STR, terminate the string there in place,
438 and return that position. Otherwise return NULL. */
439
440static char *
441terminate_at_blank (char *str)
442{
443 char *s = strchr (str, ' ');
444 if (s)
445 *s = '\0';
446 return s;
447}
448#endif
449
385/* Return a list of the currently mounted file systems, or NULL on error. 450/* 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. 451 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 452 If NEED_FS_TYPE is true, ensure that the file system type fields in
@@ -395,69 +460,141 @@ read_file_system_list (bool need_fs_type)
395 struct mount_entry **mtail = &mount_list; 460 struct mount_entry **mtail = &mount_list;
396 (void) need_fs_type; 461 (void) need_fs_type;
397 462
398#ifdef MOUNTED_LISTMNTENT 463#ifdef MOUNTED_GETMNTENT1 /* glibc, HP-UX, IRIX, Cygwin, Android,
464 also (obsolete) 4.3BSD, SunOS */
399 { 465 {
400 struct tabmntent *mntlist, *p; 466 FILE *fp;
401 struct mntent *mnt;
402 struct mount_entry *me;
403
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.
407 */
408 467
409 if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0) 468# if defined __linux__ || defined __ANDROID__
410 return NULL; 469 /* Try parsing mountinfo first, as that make device IDs available.
411 for (p = mntlist; p; p = p->next) 470 Note we could use libmount routines to simplify this parsing a little
471 (and that code is in previous versions of this function), however
472 libmount depends on libselinux which pulls in many dependencies. */
473 char const *mountinfo = "/proc/self/mountinfo";
474 fp = fopen (mountinfo, "re");
475 if (fp != NULL)
412 { 476 {
413 mnt = p->ment; 477 char *line = NULL;
414 me = xmalloc (sizeof *me); 478 size_t buf_size = 0;
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);
421 me->me_dev = -1;
422 *mtail = me;
423 mtail = &me->me_next;
424 }
425 freemntlist (mntlist);
426 }
427#endif
428 479
429#ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ 480 while (getline (&line, &buf_size, fp) != -1)
430 { 481 {
431 struct mntent *mnt; 482 unsigned int devmaj, devmin;
432 char const *table = MOUNTED; 483 int rc, mntroot_s;
433 FILE *fp;
434 484
435 fp = setmntent (table, "r"); 485 rc = sscanf(line, "%*u " /* id - discarded */
436 if (fp == NULL) 486 "%*u " /* parent - discarded */
437 return NULL; 487 "%u:%u " /* dev major:minor */
488 "%n", /* mountroot (start) */
489 &devmaj, &devmin,
490 &mntroot_s);
438 491
439 while ((mnt = getmntent (fp))) 492 if (rc != 2 && rc != 3) /* 3 if %n included in count. */
440 { 493 continue;
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);
449 494
450 /* Add to the linked list. */ 495 /* find end of MNTROOT. */
451 *mtail = me; 496 char *mntroot = line + mntroot_s;
452 mtail = &me->me_next; 497 char *blank = terminate_at_blank (mntroot);
498 if (! blank)
499 continue;
500
501 /* find end of TARGET. */
502 char *target = blank + 1;
503 blank = terminate_at_blank (target);
504 if (! blank)
505 continue;
506
507 /* skip optional fields, terminated by " - " */
508 char *dash = strstr (blank + 1, " - ");
509 if (! dash)
510 continue;
511
512 /* advance past the " - " separator. */
513 char *fstype = dash + 3;
514 blank = terminate_at_blank (fstype);
515 if (! blank)
516 continue;
517
518 /* find end of SOURCE. */
519 char *source = blank + 1;
520 if (! terminate_at_blank (source))
521 continue;
522
523 /* manipulate the sub-strings in place. */
524 unescape_tab (source);
525 unescape_tab (target);
526 unescape_tab (mntroot);
527 unescape_tab (fstype);
528
529 me = xmalloc (sizeof *me);
530
531 me->me_devname = xstrdup (source);
532 me->me_mountdir = xstrdup (target);
533 me->me_mntroot = xstrdup (mntroot);
534 me->me_type = xstrdup (fstype);
535 me->me_type_malloced = 1;
536 me->me_dev = makedev (devmaj, devmin);
537 /* we pass "false" for the "Bind" option as that's only
538 significant when the Fs_type is "none" which will not be
539 the case when parsing "/proc/self/mountinfo", and only
540 applies for static /etc/mtab files. */
541 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, false);
542 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
543
544 /* Add to the linked list. */
545 *mtail = me;
546 mtail = &me->me_next;
547 }
548
549 free (line);
550
551 if (ferror (fp))
552 {
553 int saved_errno = errno;
554 fclose (fp);
555 errno = saved_errno;
556 goto free_then_fail;
557 }
558
559 if (fclose (fp) == EOF)
560 goto free_then_fail;
453 } 561 }
562 else /* fallback to /proc/self/mounts (/etc/mtab). */
563# endif /* __linux __ || __ANDROID__ */
564 {
565 struct mntent *mnt;
566 char const *table = MOUNTED;
454 567
455 if (endmntent (fp) == 0) 568 fp = setmntent (table, "r");
456 goto free_then_fail; 569 if (fp == NULL)
570 return NULL;
571
572 while ((mnt = getmntent (fp)))
573 {
574 bool bind = hasmntopt (mnt, "bind");
575
576 me = xmalloc (sizeof *me);
577 me->me_devname = xstrdup (mnt->mnt_fsname);
578 me->me_mountdir = xstrdup (mnt->mnt_dir);
579 me->me_mntroot = NULL;
580 me->me_type = xstrdup (mnt->mnt_type);
581 me->me_type_malloced = 1;
582 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, bind);
583 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
584 me->me_dev = dev_from_mount_options (mnt->mnt_opts);
585
586 /* Add to the linked list. */
587 *mtail = me;
588 mtail = &me->me_next;
589 }
590
591 if (endmntent (fp) == 0)
592 goto free_then_fail;
593 }
457 } 594 }
458#endif /* MOUNTED_GETMNTENT1. */ 595#endif /* MOUNTED_GETMNTENT1. */
459 596
460#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ 597#ifdef MOUNTED_GETMNTINFO /* Mac OS X, FreeBSD, OpenBSD, also (obsolete) 4.4BSD */
461 { 598 {
462 struct statfs *fsp; 599 struct statfs *fsp;
463 int entries; 600 int entries;
@@ -472,6 +609,7 @@ read_file_system_list (bool need_fs_type)
472 me = xmalloc (sizeof *me); 609 me = xmalloc (sizeof *me);
473 me->me_devname = xstrdup (fsp->f_mntfromname); 610 me->me_devname = xstrdup (fsp->f_mntfromname);
474 me->me_mountdir = xstrdup (fsp->f_mntonname); 611 me->me_mountdir = xstrdup (fsp->f_mntonname);
612 me->me_mntroot = NULL;
475 me->me_type = fs_type; 613 me->me_type = fs_type;
476 me->me_type_malloced = 0; 614 me->me_type_malloced = 0;
477 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); 615 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
@@ -485,7 +623,7 @@ read_file_system_list (bool need_fs_type)
485 } 623 }
486#endif /* MOUNTED_GETMNTINFO */ 624#endif /* MOUNTED_GETMNTINFO */
487 625
488#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ 626#ifdef MOUNTED_GETMNTINFO2 /* NetBSD, Minix */
489 { 627 {
490 struct statvfs *fsp; 628 struct statvfs *fsp;
491 int entries; 629 int entries;
@@ -498,6 +636,7 @@ read_file_system_list (bool need_fs_type)
498 me = xmalloc (sizeof *me); 636 me = xmalloc (sizeof *me);
499 me->me_devname = xstrdup (fsp->f_mntfromname); 637 me->me_devname = xstrdup (fsp->f_mntfromname);
500 me->me_mountdir = xstrdup (fsp->f_mntonname); 638 me->me_mountdir = xstrdup (fsp->f_mntonname);
639 me->me_mntroot = NULL;
501 me->me_type = xstrdup (fsp->f_fstypename); 640 me->me_type = xstrdup (fsp->f_fstypename);
502 me->me_type_malloced = 1; 641 me->me_type_malloced = 1;
503 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); 642 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
@@ -511,35 +650,7 @@ read_file_system_list (bool need_fs_type)
511 } 650 }
512#endif /* MOUNTED_GETMNTINFO2 */ 651#endif /* MOUNTED_GETMNTINFO2 */
513 652
514#ifdef MOUNTED_GETMNT /* Ultrix. */ 653#if defined MOUNTED_FS_STAT_DEV /* Haiku, also (obsolete) BeOS */
515 {
516 int offset = 0;
517 int val;
518 struct fs_data fsd;
519
520 while (errno = 0,
521 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
522 (char *) 0)))
523 {
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;
532
533 /* Add to the linked list. */
534 *mtail = me;
535 mtail = &me->me_next;
536 }
537 if (val < 0)
538 goto free_then_fail;
539 }
540#endif /* MOUNTED_GETMNT. */
541
542#if defined MOUNTED_FS_STAT_DEV /* BeOS */
543 { 654 {
544 /* The next_dev() and fs_stat_dev() system calls give the list of 655 /* The next_dev() and fs_stat_dev() system calls give the list of
545 all file systems, including the information returned by statvfs() 656 all file systems, including the information returned by statvfs()
@@ -622,6 +733,7 @@ read_file_system_list (bool need_fs_type)
622 me->me_devname = xstrdup (fi.device_name[0] != '\0' 733 me->me_devname = xstrdup (fi.device_name[0] != '\0'
623 ? fi.device_name : fi.fsh_name); 734 ? fi.device_name : fi.fsh_name);
624 me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name); 735 me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name);
736 me->me_mntroot = NULL;
625 me->me_type = xstrdup (fi.fsh_name); 737 me->me_type = xstrdup (fi.fsh_name);
626 me->me_type_malloced = 1; 738 me->me_type_malloced = 1;
627 me->me_dev = fi.dev; 739 me->me_dev = fi.dev;
@@ -644,7 +756,7 @@ read_file_system_list (bool need_fs_type)
644 } 756 }
645#endif /* MOUNTED_FS_STAT_DEV */ 757#endif /* MOUNTED_FS_STAT_DEV */
646 758
647#if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */ 759#if defined MOUNTED_GETFSSTAT /* OSF/1, also (obsolete) Apple Darwin 1.3 */
648 { 760 {
649 int numsys, counter; 761 int numsys, counter;
650 size_t bufsize; 762 size_t bufsize;
@@ -671,6 +783,7 @@ read_file_system_list (bool need_fs_type)
671 me = xmalloc (sizeof *me); 783 me = xmalloc (sizeof *me);
672 me->me_devname = xstrdup (stats[counter].f_mntfromname); 784 me->me_devname = xstrdup (stats[counter].f_mntfromname);
673 me->me_mountdir = xstrdup (stats[counter].f_mntonname); 785 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
786 me->me_mntroot = NULL;
674 me->me_type = xstrdup (FS_TYPE (stats[counter])); 787 me->me_type = xstrdup (FS_TYPE (stats[counter]));
675 me->me_type_malloced = 1; 788 me->me_type_malloced = 1;
676 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); 789 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
@@ -686,31 +799,25 @@ read_file_system_list (bool need_fs_type)
686 } 799 }
687#endif /* MOUNTED_GETFSSTAT */ 800#endif /* MOUNTED_GETFSSTAT */
688 801
689#if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */ 802#if defined MOUNTED_FREAD_FSTYP /* (obsolete) SVR3 */
690 { 803 {
691 struct mnttab mnt; 804 struct mnttab mnt;
692 char *table = "/etc/mnttab"; 805 char *table = "/etc/mnttab";
693 FILE *fp; 806 FILE *fp;
694 807
695 fp = fopen (table, "r"); 808 fp = fopen (table, "re");
696 if (fp == NULL) 809 if (fp == NULL)
697 return NULL; 810 return NULL;
698 811
699 while (fread (&mnt, sizeof mnt, 1, fp) > 0) 812 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
700 { 813 {
701 me = xmalloc (sizeof *me); 814 me = xmalloc (sizeof *me);
702# ifdef GETFSTYP /* SVR3. */
703 me->me_devname = xstrdup (mnt.mt_dev); 815 me->me_devname = xstrdup (mnt.mt_dev);
704# else
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);
708# endif
709 me->me_mountdir = xstrdup (mnt.mt_filsys); 816 me->me_mountdir = xstrdup (mnt.mt_filsys);
817 me->me_mntroot = NULL;
710 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ 818 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
711 me->me_type = ""; 819 me->me_type = "";
712 me->me_type_malloced = 0; 820 me->me_type_malloced = 0;
713# ifdef GETFSTYP /* SVR3. */
714 if (need_fs_type) 821 if (need_fs_type)
715 { 822 {
716 struct statfs fsd; 823 struct statfs fsd;
@@ -723,7 +830,6 @@ read_file_system_list (bool need_fs_type)
723 me->me_type_malloced = 1; 830 me->me_type_malloced = 1;
724 } 831 }
725 } 832 }
726# endif
727 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); 833 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
728 me->me_remote = ME_REMOTE (me->me_devname, me->me_type); 834 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
729 835
@@ -744,34 +850,57 @@ read_file_system_list (bool need_fs_type)
744 if (fclose (fp) == EOF) 850 if (fclose (fp) == EOF)
745 goto free_then_fail; 851 goto free_then_fail;
746 } 852 }
747#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */ 853#endif /* MOUNTED_FREAD_FSTYP. */
748 854
749#ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */ 855#ifdef MOUNTED_GETEXTMNTENT /* Solaris >= 8 */
750 { 856 {
751 struct mntent **mnttbl = getmnttbl (), **ent; 857 struct extmnttab mnt;
752 for (ent = mnttbl; *ent; ent++) 858 const char *table = MNTTAB;
859 FILE *fp;
860 int ret;
861
862 /* No locking is needed, because the contents of /etc/mnttab is generated
863 by the kernel. */
864
865 errno = 0;
866 fp = fopen (table, "re");
867 if (fp == NULL)
868 ret = errno;
869 else
753 { 870 {
754 me = xmalloc (sizeof *me); 871 while ((ret = getextmntent (fp, &mnt, 1)) == 0)
755 me->me_devname = xstrdup ((*ent)->mt_resource); 872 {
756 me->me_mountdir = xstrdup ((*ent)->mt_directory); 873 me = xmalloc (sizeof *me);
757 me->me_type = xstrdup ((*ent)->mt_fstype); 874 me->me_devname = xstrdup (mnt.mnt_special);
758 me->me_type_malloced = 1; 875 me->me_mountdir = xstrdup (mnt.mnt_mountp);
759 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); 876 me->me_mntroot = NULL;
760 me->me_remote = ME_REMOTE (me->me_devname, me->me_type); 877 me->me_type = xstrdup (mnt.mnt_fstype);
761 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ 878 me->me_type_malloced = 1;
879 me->me_dummy = MNT_IGNORE (&mnt) != 0;
880 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
881 me->me_dev = makedev (mnt.mnt_major, mnt.mnt_minor);
762 882
763 /* Add to the linked list. */ 883 /* Add to the linked list. */
764 *mtail = me; 884 *mtail = me;
765 mtail = &me->me_next; 885 mtail = &me->me_next;
886 }
887
888 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
889 /* Here ret = -1 means success, ret >= 0 means failure. */
890 }
891
892 if (0 <= ret)
893 {
894 errno = ret;
895 goto free_then_fail;
766 } 896 }
767 endmnttbl ();
768 } 897 }
769#endif 898#endif /* MOUNTED_GETEXTMNTENT */
770 899
771#ifdef MOUNTED_GETMNTENT2 /* SVR4. */ 900#ifdef MOUNTED_GETMNTENT2 /* Solaris < 8, also (obsolete) SVR4 */
772 { 901 {
773 struct mnttab mnt; 902 struct mnttab mnt;
774 char *table = MNTTAB; 903 const char *table = MNTTAB;
775 FILE *fp; 904 FILE *fp;
776 int ret; 905 int ret;
777 int lockfd = -1; 906 int lockfd = -1;
@@ -784,7 +913,7 @@ read_file_system_list (bool need_fs_type)
784# ifndef MNTTAB_LOCK 913# ifndef MNTTAB_LOCK
785# define MNTTAB_LOCK "/etc/.mnttab.lock" 914# define MNTTAB_LOCK "/etc/.mnttab.lock"
786# endif 915# endif
787 lockfd = open (MNTTAB_LOCK, O_RDONLY); 916 lockfd = open (MNTTAB_LOCK, O_RDONLY | O_CLOEXEC);
788 if (0 <= lockfd) 917 if (0 <= lockfd)
789 { 918 {
790 struct flock flock; 919 struct flock flock;
@@ -806,7 +935,7 @@ read_file_system_list (bool need_fs_type)
806# endif 935# endif
807 936
808 errno = 0; 937 errno = 0;
809 fp = fopen (table, "r"); 938 fp = fopen (table, "re");
810 if (fp == NULL) 939 if (fp == NULL)
811 ret = errno; 940 ret = errno;
812 else 941 else
@@ -816,6 +945,7 @@ read_file_system_list (bool need_fs_type)
816 me = xmalloc (sizeof *me); 945 me = xmalloc (sizeof *me);
817 me->me_devname = xstrdup (mnt.mnt_special); 946 me->me_devname = xstrdup (mnt.mnt_special);
818 me->me_mountdir = xstrdup (mnt.mnt_mountp); 947 me->me_mountdir = xstrdup (mnt.mnt_mountp);
948 me->me_mntroot = NULL;
819 me->me_type = xstrdup (mnt.mnt_fstype); 949 me->me_type = xstrdup (mnt.mnt_fstype);
820 me->me_type_malloced = 1; 950 me->me_type_malloced = 1;
821 me->me_dummy = MNT_IGNORE (&mnt) != 0; 951 me->me_dummy = MNT_IGNORE (&mnt) != 0;
@@ -828,6 +958,7 @@ read_file_system_list (bool need_fs_type)
828 } 958 }
829 959
830 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1; 960 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
961 /* Here ret = -1 means success, ret >= 0 means failure. */
831 } 962 }
832 963
833 if (0 <= lockfd && close (lockfd) != 0) 964 if (0 <= lockfd && close (lockfd) != 0)
@@ -841,26 +972,26 @@ read_file_system_list (bool need_fs_type)
841 } 972 }
842#endif /* MOUNTED_GETMNTENT2. */ 973#endif /* MOUNTED_GETMNTENT2. */
843 974
844#ifdef MOUNTED_VMOUNT /* AIX. */ 975#ifdef MOUNTED_VMOUNT /* AIX */
845 { 976 {
846 int bufsize; 977 int bufsize;
847 char *entries, *thisent; 978 void *entries;
979 char *thisent;
848 struct vmount *vmp; 980 struct vmount *vmp;
849 int n_entries; 981 int n_entries;
850 int i; 982 int i;
851 983
852 /* Ask how many bytes to allocate for the mounted file system info. */ 984 /* Ask how many bytes to allocate for the mounted file system info. */
853 if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0) 985 entries = &bufsize;
986 if (mntctl (MCTL_QUERY, sizeof bufsize, entries) != 0)
854 return NULL; 987 return NULL;
855 entries = xmalloc (bufsize); 988 entries = xmalloc (bufsize);
856 989
857 /* Get the list of mounted file systems. */ 990 /* Get the list of mounted file systems. */
858 n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); 991 n_entries = mntctl (MCTL_QUERY, bufsize, entries);
859 if (n_entries < 0) 992 if (n_entries < 0)
860 { 993 {
861 int saved_errno = errno;
862 free (entries); 994 free (entries);
863 errno = saved_errno;
864 return NULL; 995 return NULL;
865 } 996 }
866 997
@@ -892,6 +1023,7 @@ read_file_system_list (bool need_fs_type)
892 vmp->vmt_data[VMT_OBJECT].vmt_off); 1023 vmp->vmt_data[VMT_OBJECT].vmt_off);
893 } 1024 }
894 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off); 1025 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
1026 me->me_mntroot = NULL;
895 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype)); 1027 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
896 me->me_type_malloced = 1; 1028 me->me_type_malloced = 1;
897 options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off; 1029 options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
@@ -910,7 +1042,7 @@ read_file_system_list (bool need_fs_type)
910 } 1042 }
911#endif /* MOUNTED_VMOUNT. */ 1043#endif /* MOUNTED_VMOUNT. */
912 1044
913#ifdef MOUNTED_INTERIX_STATVFS 1045#ifdef MOUNTED_INTERIX_STATVFS /* Interix */
914 { 1046 {
915 DIR *dirp = opendir ("/dev/fs"); 1047 DIR *dirp = opendir ("/dev/fs");
916 char node[9 + NAME_MAX]; 1048 char node[9 + NAME_MAX];
@@ -924,6 +1056,8 @@ read_file_system_list (bool need_fs_type)
924 struct dirent entry; 1056 struct dirent entry;
925 struct dirent *result; 1057 struct dirent *result;
926 1058
1059 /* FIXME: readdir_r is planned to be withdrawn from POSIX and
1060 marked obsolescent in glibc. Use readdir instead. */
927 if (readdir_r (dirp, &entry, &result) || result == NULL) 1061 if (readdir_r (dirp, &entry, &result) || result == NULL)
928 break; 1062 break;
929 1063
@@ -935,6 +1069,7 @@ read_file_system_list (bool need_fs_type)
935 me = xmalloc (sizeof *me); 1069 me = xmalloc (sizeof *me);
936 me->me_devname = xstrdup (dev.f_mntfromname); 1070 me->me_devname = xstrdup (dev.f_mntfromname);
937 me->me_mountdir = xstrdup (dev.f_mntonname); 1071 me->me_mountdir = xstrdup (dev.f_mntonname);
1072 me->me_mntroot = NULL;
938 me->me_type = xstrdup (dev.f_fstypename); 1073 me->me_type = xstrdup (dev.f_fstypename);
939 me->me_type_malloced = 1; 1074 me->me_type_malloced = 1;
940 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); 1075 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
@@ -946,6 +1081,7 @@ read_file_system_list (bool need_fs_type)
946 mtail = &me->me_next; 1081 mtail = &me->me_next;
947 } 1082 }
948 } 1083 }
1084 closedir (dirp);
949 } 1085 }
950#endif /* MOUNTED_INTERIX_STATVFS */ 1086#endif /* MOUNTED_INTERIX_STATVFS */
951 1087
@@ -953,7 +1089,7 @@ read_file_system_list (bool need_fs_type)
953 return mount_list; 1089 return mount_list;
954 1090
955 1091
956 free_then_fail: 1092 free_then_fail: _GL_UNUSED_LABEL;
957 { 1093 {
958 int saved_errno = errno; 1094 int saved_errno = errno;
959 *mtail = NULL; 1095 *mtail = NULL;
@@ -972,10 +1108,12 @@ read_file_system_list (bool need_fs_type)
972 1108
973/* Free a mount entry as returned from read_file_system_list (). */ 1109/* Free a mount entry as returned from read_file_system_list (). */
974 1110
975void free_mount_entry (struct mount_entry *me) 1111void
1112free_mount_entry (struct mount_entry *me)
976{ 1113{
977 free (me->me_devname); 1114 free (me->me_devname);
978 free (me->me_mountdir); 1115 free (me->me_mountdir);
1116 free (me->me_mntroot);
979 if (me->me_type_malloced) 1117 if (me->me_type_malloced)
980 free (me->me_type); 1118 free (me->me_type);
981 free (me); 1119 free (me);