[Companion] clang / linux compilation fix
[opentx.git] / companion / src / storage / mountlist.cpp
blob341e00100b5d384c0c8aaca5e73c5267b3f8c0d8
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 /* mountlist.c -- return a list of mounted file systems
23 Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
24 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
26 This program is free software; you can redistribute it and/or modify
27 it under the terms of the GNU General Public License as published by
28 the Free Software Foundation; either version 2, or (at your option)
29 any later version.
31 This program is distributed in the hope that it will be useful,
32 but WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 GNU General Public License for more details.
36 You should have received a copy of the GNU General Public License
37 along with this program; if not, see <http://www.gnu.org/licenses/>.
40 // This file is not used on some platforms, so don't do anything for them
41 #if(!(defined(WIN32) || !defined __GNUC__)&&(!defined(__amigaos4__))&&(!defined(__AROS__))&&(!defined(__MORPHOS__))&&(!defined(__amigaos__)))
43 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) // MacOS X is POSIX compliant
44 #define MOUNTED_GETMNTINFO
45 #if defined(__APPLE__)
46 #include <sys/types.h>
47 #endif
48 #if defined(__OpenBSD__)
49 #define HAVE_STRUCT_STATFS_F_FSTYPENAME 1
50 #include <sys/param.h> /* types.h needs this */
51 #include <sys/types.h>
52 #endif
53 #elif defined(__NetBSD__)
54 #define MOUNTED_GETMNTINFO2
55 #elif defined(__BEOS__) || defined(__HAIKU__)
56 #define MOUNTED_FS_STAT_DEV
57 #elif defined(__TRU64__)
58 #define MOUNTED_GETFSSTAT 1
59 #define HAVE_SYS_MOUNT_H 1
60 #include <sys/types.h>
61 #else
62 #define MOUNTED_GETMNTENT1
63 #endif
65 #include "mountlist.h"
67 #include <limits.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
72 #include <errno.h>
74 #include <fcntl.h>
75 #include <unistd.h>
77 #if HAVE_SYS_PARAM_H
78 # include <sys/param.h>
79 #endif
81 #if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */
82 # if HAVE_SYS_UCRED_H
83 # include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
84 NGROUPS is used as an array dimension in ucred.h */
85 # include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */
86 # endif
87 # if HAVE_SYS_MOUNT_H
88 # include <sys/mount.h>
89 # endif
90 # if HAVE_SYS_FS_TYPES_H
91 # include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */
92 # endif
93 # if HAVE_STRUCT_FSSTAT_F_FSTYPENAME
94 # define FS_TYPE(Ent) ((Ent).f_fstypename)
95 # else
96 # define FS_TYPE(Ent) mnt_names[(Ent).f_type]
97 # endif
98 #endif /* MOUNTED_GETFSSTAT */
100 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
101 # include <mntent.h>
102 # if !defined MOUNTED
103 # if defined _PATH_MOUNTED /* GNU libc */
104 # define MOUNTED _PATH_MOUNTED
105 # endif
106 # if defined MNT_MNTTAB /* HP-UX. */
107 # define MOUNTED MNT_MNTTAB
108 # endif
109 # if defined MNTTABNAME /* Dynix. */
110 # define MOUNTED MNTTABNAME
111 # endif
112 # endif
113 #endif
115 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
116 # include <sys/mount.h>
117 #endif
119 #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
120 # include <sys/statvfs.h>
121 #endif
123 #ifdef MOUNTED_GETMNT /* Ultrix. */
124 # include <sys/mount.h>
125 # include <sys/fs_types.h>
126 #endif
128 #ifdef MOUNTED_FS_STAT_DEV /* BeOS. */
129 # include <fs_info.h>
130 # include <dirent.h>
131 #endif
133 #ifdef MOUNTED_FREAD /* SVR2. */
134 # include <mnttab.h>
135 #endif
137 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
138 # include <mnttab.h>
139 # include <sys/fstyp.h>
140 # include <sys/statfs.h>
141 #endif
143 #ifdef MOUNTED_LISTMNTENT
144 # include <mntent.h>
145 #endif
147 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
148 # include <sys/mnttab.h>
149 #endif
151 #ifdef MOUNTED_VMOUNT /* AIX. */
152 # include <fshelp.h>
153 # include <sys/vfs.h>
154 #endif
156 #ifdef DOLPHIN
157 /* So special that it's not worth putting this in autoconf. */
158 # undef MOUNTED_FREAD_FSTYP
159 # define MOUNTED_GETMNTTBL
160 #endif
162 #if HAVE_SYS_MNTENT_H
163 /* This is to get MNTOPT_IGNORE on e.g. SVR4. */
164 # include <sys/mntent.h>
165 #endif
167 #undef MNT_IGNORE
168 #if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT
169 # define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
170 #else
171 # define MNT_IGNORE(M) 0
172 #endif
174 #if USE_UNLOCKED_IO
175 # include "unlocked-io.h"
176 #endif
178 #ifndef SIZE_MAX
179 # define SIZE_MAX ((size_t) -1)
180 #endif
182 /* The results of open() in this file are not used with fchdir,
183 therefore save some unnecessary work in fchdir.c. */
184 #undef open
185 #undef close
187 /* The results of opendir() in this file are not used with dirfd and fchdir,
188 therefore save some unnecessary work in fchdir.c. */
189 #undef opendir
190 #undef closedir
192 // gcc2 under haiku and beos don't like these macros for some reason.
193 // As they are not used there anyways, we remove them and everyone is happy.
194 #if !defined(__HAIKU__) && !defined(__BEOS__)
195 #ifndef ME_DUMMY
196 # define ME_DUMMY(Fs_name, Fs_type) \
197 (strcmp (Fs_type, "autofs") == 0 \
198 || strcmp (Fs_type, "none") == 0 \
199 || strcmp (Fs_type, "proc") == 0 \
200 || strcmp (Fs_type, "subfs") == 0 \
201 || strcmp (Fs_type, "sysfs") == 0 \
202 || strcmp (Fs_type, "usbfs") == 0 \
203 || strcmp (Fs_type, "devpts") == 0 \
204 || strcmp (Fs_type, "tmpfs") == 0 \
205 /* for NetBSD 3.0 */ \
206 || strcmp (Fs_type, "kernfs") == 0 \
207 /* for Irix 6.5 */ \
208 || strcmp (Fs_type, "ignore") == 0 \
209 /* for MacOSX */ \
210 || strcmp (Fs_type, "devfs") == 0 \
211 || strcmp (Fs_type, "fdesc") == 0 \
212 || strcmp (Fs_type, "nfs") == 0 \
213 || strcmp (Fs_type, "volfs") == 0)
214 #endif
216 #ifndef ME_REMOTE
217 /* A file system is `remote' if its Fs_name contains a `:'
218 or if (it is of type (smbfs or cifs) and its Fs_name starts with `//'). */
219 # define ME_REMOTE(Fs_name, Fs_type) \
220 (strchr (Fs_name, ':') != NULL \
221 || ((Fs_name)[0] == '/' \
222 && (Fs_name)[1] == '/' \
223 && (strcmp (Fs_type, "smbfs") == 0 \
224 || strcmp (Fs_type, "cifs") == 0)))
225 #endif
226 #endif // HAIKU / BEOS
228 #ifdef MOUNTED_GETMNTINFO
230 # if ! HAVE_STRUCT_STATFS_F_FSTYPENAME && !defined(__clang__)
231 static const char *
232 fstype_to_string (short int t)
234 switch (t)
236 # ifdef MOUNT_PC
237 case MOUNT_PC:
238 return "pc";
239 # endif
240 # ifdef MOUNT_MFS
241 case MOUNT_MFS:
242 return "mfs";
243 # endif
244 # ifdef MOUNT_LO
245 case MOUNT_LO:
246 return "lo";
247 # endif
248 # ifdef MOUNT_TFS
249 case MOUNT_TFS:
250 return "tfs";
251 # endif
252 # ifdef MOUNT_TMP
253 case MOUNT_TMP:
254 return "tmp";
255 # endif
256 # ifdef MOUNT_UFS
257 case MOUNT_UFS:
258 return "ufs" ;
259 # endif
260 # ifdef MOUNT_NFS
261 case MOUNT_NFS:
262 return "nfs" ;
263 # endif
264 # ifdef MOUNT_MSDOS
265 case MOUNT_MSDOS:
266 return "msdos" ;
267 # endif
268 # ifdef MOUNT_LFS
269 case MOUNT_LFS:
270 return "lfs" ;
271 # endif
272 # ifdef MOUNT_LOFS
273 case MOUNT_LOFS:
274 return "lofs" ;
275 # endif
276 # ifdef MOUNT_FDESC
277 case MOUNT_FDESC:
278 return "fdesc" ;
279 # endif
280 # ifdef MOUNT_PORTAL
281 case MOUNT_PORTAL:
282 return "portal" ;
283 # endif
284 # ifdef MOUNT_NULL
285 case MOUNT_NULL:
286 return "null" ;
287 # endif
288 # ifdef MOUNT_UMAP
289 case MOUNT_UMAP:
290 return "umap" ;
291 # endif
292 # ifdef MOUNT_KERNFS
293 case MOUNT_KERNFS:
294 return "kernfs" ;
295 # endif
296 # ifdef MOUNT_PROCFS
297 case MOUNT_PROCFS:
298 return "procfs" ;
299 # endif
300 # ifdef MOUNT_AFS
301 case MOUNT_AFS:
302 return "afs" ;
303 # endif
304 # ifdef MOUNT_CD9660
305 case MOUNT_CD9660:
306 return "cd9660" ;
307 # endif
308 # ifdef MOUNT_UNION
309 case MOUNT_UNION:
310 return "union" ;
311 # endif
312 # ifdef MOUNT_DEVFS
313 case MOUNT_DEVFS:
314 return "devfs" ;
315 # endif
316 # ifdef MOUNT_EXT2FS
317 case MOUNT_EXT2FS:
318 return "ext2fs" ;
319 # endif
320 default:
321 return "?";
324 # endif
326 #if !defined(__clang__)
327 static const char *
328 fsp_to_string (const struct statfs *fsp)
330 # if HAVE_STRUCT_STATFS_F_FSTYPENAME
331 return (char *) (fsp->f_fstypename);
332 # else
333 return fstype_to_string (fsp->f_type);
334 # endif
336 #endif
338 #endif /* MOUNTED_GETMNTINFO */
340 #ifdef MOUNTED_VMOUNT /* AIX. */
341 static char *
342 fstype_to_string (int t)
344 struct vfs_ent *e;
346 e = getvfsbytype (t);
347 if (!e || !e->vfsent_name)
348 return "none";
349 else
350 return e->vfsent_name;
352 #endif /* MOUNTED_VMOUNT */
354 #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
356 /* Return the device number from MOUNT_OPTIONS, if possible.
357 Otherwise return (dev_t) -1. */
359 static dev_t
360 dev_from_mount_options (char const *mount_options)
362 /* GNU/Linux allows file system implementations to define their own
363 meaning for "dev=" mount options, so don't trust the meaning
364 here. */
365 # ifndef __linux__
366 static char const dev_pattern[] = ",dev=";
367 char const *devopt = strstr (mount_options, dev_pattern);
369 if (devopt)
371 char const *optval = devopt + sizeof dev_pattern - 1;
372 char *optvalend;
373 unsigned long int dev;
374 errno = 0;
375 dev = strtoul (optval, &optvalend, 16);
376 if (optval != optvalend
377 && (*optvalend == '\0' || *optvalend == ',')
378 && ! (dev == ULONG_MAX && errno == ERANGE)
379 && dev == (dev_t) dev)
380 return dev;
382 #else
383 (void)mount_options; // unused
384 # endif
386 return -1;
389 #endif
391 /* Return a list of the currently mounted file systems, or NULL on error.
392 Add each entry to the tail of the list so that they stay in order.
393 If NEED_FS_TYPE is true, ensure that the file system type fields in
394 the returned list are valid. Otherwise, they might not be. */
396 struct mount_entry *
397 read_file_system_list (bool need_fs_type)
399 struct mount_entry *mount_list;
400 struct mount_entry *me;
401 struct mount_entry **mtail = &mount_list;
402 (void)need_fs_type; // may be unused
404 #ifdef MOUNTED_LISTMNTENT
406 struct tabmntent *mntlist, *p;
407 struct mntent *mnt;
408 struct mount_entry *me;
410 /* the third and fourth arguments could be used to filter mounts,
411 but Crays doesn't seem to have any mounts that we want to
412 remove. Specifically, automount create normal NFS mounts.
415 if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0)
416 return NULL;
417 for (p = mntlist; p; p = p->next) {
418 mnt = p->ment;
419 me = xmalloc (sizeof *me);
420 me->me_devname = xstrdup (mnt->mnt_fsname);
421 me->me_mountdir = xstrdup (mnt->mnt_dir);
422 me->me_type = xstrdup (mnt->mnt_type);
423 me->me_type_malloced = 1;
424 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
425 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
426 me->me_dev = -1;
427 *mtail = me;
428 mtail = &me->me_next;
430 freemntlist (mntlist);
432 #endif
434 #ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
436 struct mntent *mnt;
437 const char *table = MOUNTED;
438 FILE *fp;
440 fp = setmntent (table, "r");
441 if (fp == NULL)
442 return NULL;
444 while ((mnt = getmntent (fp)))
446 me = (mount_entry *) malloc (sizeof *me);
447 me->me_devname = strdup (mnt->mnt_fsname);
448 me->me_mountdir = strdup (mnt->mnt_dir);
449 me->me_type = strdup (mnt->mnt_type);
450 me->me_type_malloced = 1;
451 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
452 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
453 me->me_dev = dev_from_mount_options (mnt->mnt_opts);
455 /* Add to the linked list. */
456 *mtail = me;
457 mtail = &me->me_next;
460 if (endmntent (fp) == 0)
461 goto free_then_fail;
463 #endif /* MOUNTED_GETMNTENT1. */
465 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
467 struct statfs *fsp;
468 int entries;
470 entries = getmntinfo (&fsp, MNT_NOWAIT);
471 if (entries < 0)
472 return NULL;
473 for (; entries-- > 0; fsp++)
475 me = (mount_entry *) malloc (sizeof *me);
476 me->me_devname = strdup (fsp->f_mntfromname);
477 me->me_mountdir = strdup (fsp->f_mntonname);
478 #if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
479 me->me_type = fsp->f_fstypename;
480 #else
481 me->me_type = fsp->fs_typename;
482 #endif
483 me->me_type_malloced = 0;
484 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
485 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
486 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
488 /* Add to the linked list. */
489 *mtail = me;
490 mtail = &me->me_next;
493 #endif /* MOUNTED_GETMNTINFO */
495 #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
497 struct statvfs *fsp;
498 int entries;
500 entries = getmntinfo (&fsp, MNT_NOWAIT);
501 if (entries < 0)
502 return NULL;
503 for (; entries-- > 0; fsp++)
505 me = malloc (sizeof *me);
506 me->me_devname = strdup (fsp->f_mntfromname);
507 me->me_mountdir = strdup (fsp->f_mntonname);
508 me->me_type = strdup (fsp->f_fstypename);
509 me->me_type_malloced = 1;
510 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
511 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
512 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
514 /* Add to the linked list. */
515 *mtail = me;
516 mtail = &me->me_next;
519 #endif /* MOUNTED_GETMNTINFO2 */
521 #ifdef MOUNTED_GETMNT /* Ultrix. */
523 int offset = 0;
524 int val;
525 struct fs_data fsd;
527 while (errno = 0,
528 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
529 (char *) 0)))
531 me = xmalloc (sizeof *me);
532 me->me_devname = xstrdup (fsd.fd_req.devname);
533 me->me_mountdir = xstrdup (fsd.fd_req.path);
534 me->me_type = gt_names[fsd.fd_req.fstype];
535 me->me_type_malloced = 0;
536 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
537 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
538 me->me_dev = fsd.fd_req.dev;
540 /* Add to the linked list. */
541 *mtail = me;
542 mtail = &me->me_next;
544 if (val < 0)
545 goto free_then_fail;
547 #endif /* MOUNTED_GETMNT. */
549 #if defined MOUNTED_FS_STAT_DEV /* BeOS */
551 /* The next_dev() and fs_stat_dev() system calls give the list of
552 all file systems, including the information returned by statvfs()
553 (fs type, total blocks, free blocks etc.), but without the mount
554 point. But on BeOS all file systems except / are mounted in the
555 rootfs, directly under /.
556 The directory name of the mount point is often, but not always,
557 identical to the volume name of the device.
558 We therefore get the list of subdirectories of /, and the list
559 of all file systems, and match the two lists. */
561 DIR *dirp;
562 struct rootdir_entry
564 char *name;
565 dev_t dev;
566 ino_t ino;
567 struct rootdir_entry *next;
569 struct rootdir_entry *rootdir_list;
570 struct rootdir_entry **rootdir_tail;
571 int32 pos;
572 dev_t dev;
573 fs_info fi;
575 /* All volumes are mounted in the rootfs, directly under /. */
576 rootdir_list = NULL;
577 rootdir_tail = &rootdir_list;
578 dirp = opendir ("/");
579 if (dirp)
581 struct dirent *d;
583 while ((d = readdir (dirp)) != NULL)
585 char *name;
586 struct stat statbuf;
588 if (strcmp (d->d_name, "..") == 0)
589 continue;
591 if (strcmp (d->d_name, ".") == 0)
592 name = strdup ("/");
593 else
595 name = malloc (1 + strlen (d->d_name) + 1);
596 name[0] = '/';
597 strcpy (name + 1, d->d_name);
600 if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
602 struct rootdir_entry *re = malloc (sizeof *re);
603 re->name = name;
604 re->dev = statbuf.st_dev;
605 re->ino = statbuf.st_ino;
607 /* Add to the linked list. */
608 *rootdir_tail = re;
609 rootdir_tail = &re->next;
611 else
612 free (name);
614 closedir (dirp);
616 *rootdir_tail = NULL;
618 for (pos = 0; (dev = next_dev (&pos)) >= 0; )
619 if (fs_stat_dev (dev, &fi) >= 0)
621 /* Note: fi.dev == dev. */
622 struct rootdir_entry *re;
624 for (re = rootdir_list; re; re = re->next)
625 if (re->dev == fi.dev && re->ino == fi.root)
626 break;
628 me = malloc (sizeof *me);
629 me->me_devname = strdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
630 me->me_mountdir = strdup (re != NULL ? re->name : fi.fsh_name);
631 me->me_type = strdup (fi.fsh_name);
632 me->me_type_malloced = 1;
633 me->me_dev = fi.dev;
634 me->me_dummy = 0;
635 me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
637 /* Add to the linked list. */
638 *mtail = me;
639 mtail = &me->me_next;
641 *mtail = NULL;
643 while (rootdir_list != NULL)
645 struct rootdir_entry *re = rootdir_list;
646 rootdir_list = re->next;
647 free (re->name);
648 free (re);
651 #endif /* MOUNTED_FS_STAT_DEV */
653 #if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
655 int numsys, counter;
656 size_t bufsize;
657 struct statfs *stats;
659 numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT);
660 if (numsys < 0)
661 return (NULL);
663 if (SIZE_MAX / sizeof *stats <= numsys)
664 xalloc_die ();*/
666 bufsize = (1 + numsys) * sizeof *stats;
667 stats = malloc (bufsize);
668 numsys = getfsstat (stats, bufsize, MNT_NOWAIT);
670 if (numsys < 0)
672 free (stats);
673 return (NULL);
676 for (counter = 0; counter < numsys; counter++)
678 me = malloc (sizeof *me);
679 me->me_devname = strdup (stats[counter].f_mntfromname);
680 me->me_mountdir = strdup (stats[counter].f_mntonname);
681 //me->me_type = strdup (FS_TYPE (stats[counter]));
682 me->me_type_malloced = 1;
683 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
684 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
685 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
687 /* Add to the linked list. */
688 *mtail = me;
689 mtail = &me->me_next;
692 free (stats);
694 #endif /* MOUNTED_GETFSSTAT */
696 #if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */
698 struct mnttab mnt;
699 char *table = "/etc/mnttab";
700 FILE *fp;
702 fp = fopen (table, "r");
703 if (fp == NULL)
704 return NULL;
706 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
708 me = xmalloc (sizeof *me);
709 # ifdef GETFSTYP /* SVR3. */
710 me->me_devname = xstrdup (mnt.mt_dev);
711 # else
712 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
713 strcpy (me->me_devname, "/dev/");
714 strcpy (me->me_devname + 5, mnt.mt_dev);
715 # endif
716 me->me_mountdir = xstrdup (mnt.mt_filsys);
717 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
718 me->me_type = "";
719 me->me_type_malloced = 0;
720 # ifdef GETFSTYP /* SVR3. */
721 if (need_fs_type)
723 struct statfs fsd;
724 char typebuf[FSTYPSZ];
726 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
727 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
729 me->me_type = xstrdup (typebuf);
730 me->me_type_malloced = 1;
733 # endif
734 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
735 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
737 /* Add to the linked list. */
738 *mtail = me;
739 mtail = &me->me_next;
742 if (ferror (fp))
744 /* The last fread() call must have failed. */
745 int saved_errno = errno;
746 fclose (fp);
747 errno = saved_errno;
748 goto free_then_fail;
751 if (fclose (fp) == EOF)
752 goto free_then_fail;
754 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
756 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */
758 struct mntent **mnttbl = getmnttbl (), **ent;
759 for (ent=mnttbl;*ent;ent++)
761 me = xmalloc (sizeof *me);
762 me->me_devname = xstrdup ( (*ent)->mt_resource);
763 me->me_mountdir = xstrdup ( (*ent)->mt_directory);
764 me->me_type = xstrdup ((*ent)->mt_fstype);
765 me->me_type_malloced = 1;
766 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
767 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
768 me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
770 /* Add to the linked list. */
771 *mtail = me;
772 mtail = &me->me_next;
774 endmnttbl ();
776 #endif
778 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
780 struct mnttab mnt;
781 char *table = MNTTAB;
782 FILE *fp;
783 int ret;
784 int lockfd = -1;
786 # if defined F_RDLCK && defined F_SETLKW
787 /* MNTTAB_LOCK is a macro name of our own invention; it's not present in
788 e.g. Solaris 2.6. If the SVR4 folks ever define a macro
789 for this file name, we should use their macro name instead.
790 (Why not just lock MNTTAB directly? We don't know.) */
791 # ifndef MNTTAB_LOCK
792 # define MNTTAB_LOCK "/etc/.mnttab.lock"
793 # endif
794 lockfd = open (MNTTAB_LOCK, O_RDONLY);
795 if (0 <= lockfd)
797 struct flock flock;
798 flock.l_type = F_RDLCK;
799 flock.l_whence = SEEK_SET;
800 flock.l_start = 0;
801 flock.l_len = 0;
802 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
803 if (errno != EINTR)
805 int saved_errno = errno;
806 close (lockfd);
807 errno = saved_errno;
808 return NULL;
811 else if (errno != ENOENT)
812 return NULL;
813 # endif
815 errno = 0;
816 fp = fopen (table, "r");
817 if (fp == NULL)
818 ret = errno;
819 else
821 while ((ret = getmntent (fp, &mnt)) == 0)
823 me = xmalloc (sizeof *me);
824 me->me_devname = xstrdup (mnt.mnt_special);
825 me->me_mountdir = xstrdup (mnt.mnt_mountp);
826 me->me_type = xstrdup (mnt.mnt_fstype);
827 me->me_type_malloced = 1;
828 me->me_dummy = MNT_IGNORE (&mnt) != 0;
829 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
830 me->me_dev = dev_from_mount_options (mnt.mnt_mntopts);
832 /* Add to the linked list. */
833 *mtail = me;
834 mtail = &me->me_next;
837 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
840 if (0 <= lockfd && close (lockfd) != 0)
841 ret = errno;
843 if (0 <= ret)
845 errno = ret;
846 goto free_then_fail;
849 #endif /* MOUNTED_GETMNTENT2. */
851 #ifdef MOUNTED_VMOUNT /* AIX. */
853 int bufsize;
854 char *entries, *thisent;
855 struct vmount *vmp;
856 int n_entries;
857 int i;
859 /* Ask how many bytes to allocate for the mounted file system info. */
860 if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0)
861 return NULL;
862 entries = xmalloc (bufsize);
864 /* Get the list of mounted file systems. */
865 n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
866 if (n_entries < 0)
868 int saved_errno = errno;
869 free (entries);
870 errno = saved_errno;
871 return NULL;
874 for (i = 0, thisent = entries;
875 i < n_entries;
876 i++, thisent += vmp->vmt_length)
878 char *options, *ignore;
880 vmp = (struct vmount *) thisent;
881 me = xmalloc (sizeof *me);
882 if (vmp->vmt_flags & MNT_REMOTE)
884 char *host, *dir;
886 me->me_remote = 1;
887 /* Prepend the remote dirname. */
888 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
889 dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
890 me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2);
891 strcpy (me->me_devname, host);
892 strcat (me->me_devname, ":");
893 strcat (me->me_devname, dir);
895 else
897 me->me_remote = 0;
898 me->me_devname = xstrdup (thisent +
899 vmp->vmt_data[VMT_OBJECT].vmt_off);
901 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
902 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
903 me->me_type_malloced = 1;
904 options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
905 ignore = strstr (options, "ignore");
906 me->me_dummy = (ignore
907 && (ignore == options || ignore[-1] == ',')
908 && (ignore[sizeof "ignore" - 1] == ','
909 || ignore[sizeof "ignore" - 1] == '\0'));
910 me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
912 /* Add to the linked list. */
913 *mtail = me;
914 mtail = &me->me_next;
916 free (entries);
918 #endif /* MOUNTED_VMOUNT. */
920 *mtail = NULL;
921 return mount_list;
923 #if defined(MOUNTED_GETMNTENT1) || defined(MOUNTED_GETMNTENT2) || defined(MOUNTED_GETMNT) || defined(MOUNTED_FREAD) || defined(MOUNTED_FREAD_FSTYP)
924 free_then_fail:
926 int saved_errno = errno;
927 *mtail = NULL;
929 while (mount_list)
931 me = mount_list->me_next;
932 free (mount_list->me_devname);
933 free (mount_list->me_mountdir);
934 if (mount_list->me_type_malloced)
935 free (mount_list->me_type);
936 free (mount_list);
937 mount_list = me;
940 errno = saved_errno;
941 return NULL;
943 #endif
946 void free_file_system_list(struct mount_entry * mount_list)
948 struct mount_entry * me;
949 while (mount_list)
951 me = mount_list->me_next;
952 free (mount_list->me_devname);
953 free (mount_list->me_mountdir);
954 if (mount_list->me_type_malloced)
955 free (mount_list->me_type);
956 free (mount_list);
957 mount_list = me;
961 #endif