This source file includes following definitions.
- me_remote
- fstype_to_string
- fsp_to_string
- fstype_to_string
- dev_from_mount_options
- unescape_tab
- terminate_at_blank
- read_file_system_list
- free_mount_entry
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <config.h>
19
20 #include "mountlist.h"
21
22 #include <limits.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdint.h>
27
28 #include "xalloc.h"
29
30 #include <errno.h>
31
32 #include <fcntl.h>
33
34 #include <unistd.h>
35
36 #if HAVE_SYS_PARAM_H
37 # include <sys/param.h>
38 #endif
39
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
47 # if HAVE_SYS_UCRED_H
48 # include <grp.h>
49
50 # include <sys/ucred.h>
51 # endif
52 # if HAVE_SYS_MOUNT_H
53 # include <sys/mount.h>
54 # endif
55 # if HAVE_SYS_FS_TYPES_H
56 # include <sys/fs_types.h>
57 # endif
58 # if HAVE_STRUCT_FSSTAT_F_FSTYPENAME
59 # define FS_TYPE(Ent) ((Ent).f_fstypename)
60 # else
61 # define FS_TYPE(Ent) mnt_names[(Ent).f_type]
62 # endif
63 #endif
64
65 #ifdef MOUNTED_GETMNTENT1
66
67 # include <mntent.h>
68 # include <sys/types.h>
69 # if defined __ANDROID__
70
71
72 # undef MOUNTED
73 # define MOUNTED "/proc/mounts"
74 # elif !defined MOUNTED
75 # if defined _PATH_MOUNTED
76 # define MOUNTED _PATH_MOUNTED
77 # endif
78 # if defined MNT_MNTTAB
79 # define MOUNTED MNT_MNTTAB
80 # endif
81 # endif
82 #endif
83
84 #ifdef MOUNTED_GETMNTINFO
85 # include <sys/mount.h>
86 #endif
87
88 #ifdef MOUNTED_GETMNTINFO2
89 # include <sys/statvfs.h>
90 #endif
91
92 #ifdef MOUNTED_FS_STAT_DEV
93 # include <fs_info.h>
94 # include <dirent.h>
95 #endif
96
97 #ifdef MOUNTED_FREAD_FSTYP
98 # include <mnttab.h>
99 # include <sys/fstyp.h>
100 # include <sys/statfs.h>
101 #endif
102
103 #ifdef MOUNTED_GETEXTMNTENT
104 # include <sys/mnttab.h>
105 #endif
106
107 #ifdef MOUNTED_GETMNTENT2
108 # include <sys/mnttab.h>
109 #endif
110
111 #ifdef MOUNTED_VMOUNT
112 # include <fshelp.h>
113 # include <sys/vfs.h>
114 #endif
115
116 #ifdef MOUNTED_INTERIX_STATVFS
117 # include <sys/statvfs.h>
118 # include <dirent.h>
119 #endif
120
121 #if HAVE_SYS_MNTENT_H
122
123 # include <sys/mntent.h>
124 #endif
125
126 #ifdef MOUNTED_GETMNTENT1
127 # if !HAVE_SETMNTENT
128 # define setmntent(fp,mode) fopen (fp, mode "e")
129 # endif
130 # if !HAVE_ENDMNTENT
131 # define endmntent(fp) fclose (fp)
132 # endif
133 #endif
134
135 #ifndef HAVE_HASMNTOPT
136 # define hasmntopt(mnt, opt) ((char *) 0)
137 #endif
138
139 #undef MNT_IGNORE
140 #ifdef MNTOPT_IGNORE
141 # if defined __sun && defined __SVR4
142
143
144 # define MNT_IGNORE(M) hasmntopt (M, (char *) MNTOPT_IGNORE)
145 # else
146 # define MNT_IGNORE(M) hasmntopt (M, MNTOPT_IGNORE)
147 # endif
148 #else
149 # define MNT_IGNORE(M) 0
150 #endif
151
152
153 #include "unlocked-io.h"
154
155
156
157 #ifdef GNULIB_defined_opendir
158 # undef opendir
159 #endif
160 #ifdef GNULIB_defined_closedir
161 # undef closedir
162 #endif
163
164 #define ME_DUMMY_0(Fs_name, Fs_type) \
165 (strcmp (Fs_type, "autofs") == 0 \
166 || strcmp (Fs_type, "proc") == 0 \
167 || strcmp (Fs_type, "subfs") == 0 \
168 \
169 || strcmp (Fs_type, "debugfs") == 0 \
170 || strcmp (Fs_type, "devpts") == 0 \
171 || strcmp (Fs_type, "fusectl") == 0 \
172 || strcmp (Fs_type, "fuse.portal") == 0 \
173 || strcmp (Fs_type, "mqueue") == 0 \
174 || strcmp (Fs_type, "rpc_pipefs") == 0 \
175 || strcmp (Fs_type, "sysfs") == 0 \
176 \
177 || strcmp (Fs_type, "devfs") == 0 \
178 \
179 || strcmp (Fs_type, "kernfs") == 0 \
180 \
181 || strcmp (Fs_type, "ignore") == 0)
182
183
184
185
186
187 #ifdef MOUNTED_GETMNTENT1
188 # define ME_DUMMY(Fs_name, Fs_type, Bind) \
189 (ME_DUMMY_0 (Fs_name, Fs_type) \
190 || (strcmp (Fs_type, "none") == 0 && !Bind))
191 #else
192 # define ME_DUMMY(Fs_name, Fs_type) \
193 (ME_DUMMY_0 (Fs_name, Fs_type) || strcmp (Fs_type, "none") == 0)
194 #endif
195
196 #ifdef __CYGWIN__
197 # include <windows.h>
198
199 # undef GetDriveType
200 # define GetDriveType GetDriveTypeA
201 # define ME_REMOTE me_remote
202
203
204 static bool
205 me_remote (char const *fs_name, _GL_UNUSED char const *fs_type)
206 {
207 if (fs_name[0] && fs_name[1] == ':')
208 {
209 char drive[4];
210 sprintf (drive, "%c:\\", fs_name[0]);
211 switch (GetDriveType (drive))
212 {
213 case DRIVE_REMOVABLE:
214 case DRIVE_FIXED:
215 case DRIVE_CDROM:
216 case DRIVE_RAMDISK:
217 return false;
218 }
219 }
220 return true;
221 }
222 #endif
223
224 #ifndef ME_REMOTE
225
226
227
228
229
230 # define ME_REMOTE(Fs_name, Fs_type) \
231 (strchr (Fs_name, ':') != NULL \
232 || ((Fs_name)[0] == '/' \
233 && (Fs_name)[1] == '/' \
234 && (strcmp (Fs_type, "smbfs") == 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)
247 #endif
248
249 #if MOUNTED_GETMNTINFO
250
251 # if ! HAVE_STRUCT_STATFS_F_FSTYPENAME
252 static char *
253 fstype_to_string (short int t)
254 {
255 switch (t)
256 {
257 # ifdef MOUNT_PC
258 case MOUNT_PC:
259 return "pc";
260 # endif
261 # ifdef MOUNT_MFS
262 case MOUNT_MFS:
263 return "mfs";
264 # endif
265 # ifdef MOUNT_LO
266 case MOUNT_LO:
267 return "lo";
268 # endif
269 # ifdef MOUNT_TFS
270 case MOUNT_TFS:
271 return "tfs";
272 # endif
273 # ifdef MOUNT_TMP
274 case MOUNT_TMP:
275 return "tmp";
276 # endif
277 # ifdef MOUNT_UFS
278 case MOUNT_UFS:
279 return "ufs" ;
280 # endif
281 # ifdef MOUNT_NFS
282 case MOUNT_NFS:
283 return "nfs" ;
284 # endif
285 # ifdef MOUNT_MSDOS
286 case MOUNT_MSDOS:
287 return "msdos" ;
288 # endif
289 # ifdef MOUNT_LFS
290 case MOUNT_LFS:
291 return "lfs" ;
292 # endif
293 # ifdef MOUNT_LOFS
294 case MOUNT_LOFS:
295 return "lofs" ;
296 # endif
297 # ifdef MOUNT_FDESC
298 case MOUNT_FDESC:
299 return "fdesc" ;
300 # endif
301 # ifdef MOUNT_PORTAL
302 case MOUNT_PORTAL:
303 return "portal" ;
304 # endif
305 # ifdef MOUNT_NULL
306 case MOUNT_NULL:
307 return "null" ;
308 # endif
309 # ifdef MOUNT_UMAP
310 case MOUNT_UMAP:
311 return "umap" ;
312 # endif
313 # ifdef MOUNT_KERNFS
314 case MOUNT_KERNFS:
315 return "kernfs" ;
316 # endif
317 # ifdef MOUNT_PROCFS
318 case MOUNT_PROCFS:
319 return "procfs" ;
320 # endif
321 # ifdef MOUNT_AFS
322 case MOUNT_AFS:
323 return "afs" ;
324 # endif
325 # ifdef MOUNT_CD9660
326 case MOUNT_CD9660:
327 return "cd9660" ;
328 # endif
329 # ifdef MOUNT_UNION
330 case MOUNT_UNION:
331 return "union" ;
332 # endif
333 # ifdef MOUNT_DEVFS
334 case MOUNT_DEVFS:
335 return "devfs" ;
336 # endif
337 # ifdef MOUNT_EXT2FS
338 case MOUNT_EXT2FS:
339 return "ext2fs" ;
340 # endif
341 default:
342 return "?";
343 }
344 }
345 # endif
346
347 static char *
348 fsp_to_string (const struct statfs *fsp)
349 {
350 # if HAVE_STRUCT_STATFS_F_FSTYPENAME
351 return (char *) (fsp->f_fstypename);
352 # else
353 return fstype_to_string (fsp->f_type);
354 # endif
355 }
356
357 #endif
358
359 #ifdef MOUNTED_VMOUNT
360 static char *
361 fstype_to_string (int t)
362 {
363 struct vfs_ent *e;
364
365 e = getvfsbytype (t);
366 if (!e || !e->vfsent_name)
367 return "none";
368 else
369 return e->vfsent_name;
370 }
371 #endif
372
373
374 #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
375
376
377
378 static dev_t
379 dev_from_mount_options (char const *mount_options)
380 {
381
382
383
384 # ifndef __linux__
385
386 static char const dev_pattern[] = ",dev=";
387 char const *devopt = strstr (mount_options, dev_pattern);
388
389 if (devopt)
390 {
391 char const *optval = devopt + sizeof dev_pattern - 1;
392 char *optvalend;
393 unsigned long int dev;
394 errno = 0;
395 dev = strtoul (optval, &optvalend, 16);
396 if (optval != optvalend
397 && (*optvalend == '\0' || *optvalend == ',')
398 && ! (dev == ULONG_MAX && errno == ERANGE)
399 && dev == (dev_t) dev)
400 return dev;
401 }
402
403 # endif
404 (void) mount_options;
405 return -1;
406 }
407
408 #endif
409
410 #if defined MOUNTED_GETMNTENT1 && (defined __linux__ || defined __ANDROID__)
411
412
413
414
415 static void
416 unescape_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
438
439
440 static char *
441 terminate_at_blank (char *str)
442 {
443 char *s = strchr (str, ' ');
444 if (s)
445 *s = '\0';
446 return s;
447 }
448 #endif
449
450
451
452
453
454
455 struct mount_entry *
456 read_file_system_list (bool need_fs_type)
457 {
458 struct mount_entry *mount_list;
459 struct mount_entry *me;
460 struct mount_entry **mtail = &mount_list;
461 (void) need_fs_type;
462
463 #ifdef MOUNTED_GETMNTENT1
464
465 {
466 FILE *fp;
467
468 # if defined __linux__ || defined __ANDROID__
469
470
471
472
473 char const *mountinfo = "/proc/self/mountinfo";
474 fp = fopen (mountinfo, "re");
475 if (fp != NULL)
476 {
477 char *line = NULL;
478 size_t buf_size = 0;
479
480 while (getline (&line, &buf_size, fp) != -1)
481 {
482 unsigned int devmaj, devmin;
483 int rc, mntroot_s;
484
485 rc = sscanf(line, "%*u "
486 "%*u "
487 "%u:%u "
488 "%n",
489 &devmaj, &devmin,
490 &mntroot_s);
491
492 if (rc != 2 && rc != 3)
493 continue;
494
495
496 char *mntroot = line + mntroot_s;
497 char *blank = terminate_at_blank (mntroot);
498 if (! blank)
499 continue;
500
501
502 char *target = blank + 1;
503 blank = terminate_at_blank (target);
504 if (! blank)
505 continue;
506
507
508 char *dash = strstr (blank + 1, " - ");
509 if (! dash)
510 continue;
511
512
513 char *fstype = dash + 3;
514 blank = terminate_at_blank (fstype);
515 if (! blank)
516 continue;
517
518
519 char *source = blank + 1;
520 if (! terminate_at_blank (source))
521 continue;
522
523
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
538
539
540
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
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;
561 }
562 else
563 # endif
564 {
565 struct mntent *mnt;
566 char const *table = MOUNTED;
567
568 fp = setmntent (table, "r");
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
587 *mtail = me;
588 mtail = &me->me_next;
589 }
590
591 if (endmntent (fp) == 0)
592 goto free_then_fail;
593 }
594 }
595 #endif
596
597 #ifdef MOUNTED_GETMNTINFO
598 {
599 struct statfs *fsp;
600 int entries;
601
602 entries = getmntinfo (&fsp, MNT_NOWAIT);
603 if (entries < 0)
604 return NULL;
605 for (; entries-- > 0; fsp++)
606 {
607 char *fs_type = fsp_to_string (fsp);
608
609 me = xmalloc (sizeof *me);
610 me->me_devname = xstrdup (fsp->f_mntfromname);
611 me->me_mountdir = xstrdup (fsp->f_mntonname);
612 me->me_mntroot = NULL;
613 me->me_type = fs_type;
614 me->me_type_malloced = 0;
615 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
616 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
617 me->me_dev = (dev_t) -1;
618
619
620 *mtail = me;
621 mtail = &me->me_next;
622 }
623 }
624 #endif
625
626 #ifdef MOUNTED_GETMNTINFO2
627 {
628 struct statvfs *fsp;
629 int entries;
630
631 entries = getmntinfo (&fsp, MNT_NOWAIT);
632 if (entries < 0)
633 return NULL;
634 for (; entries-- > 0; fsp++)
635 {
636 me = xmalloc (sizeof *me);
637 me->me_devname = xstrdup (fsp->f_mntfromname);
638 me->me_mountdir = xstrdup (fsp->f_mntonname);
639 me->me_mntroot = NULL;
640 me->me_type = xstrdup (fsp->f_fstypename);
641 me->me_type_malloced = 1;
642 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
643 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
644 me->me_dev = (dev_t) -1;
645
646
647 *mtail = me;
648 mtail = &me->me_next;
649 }
650 }
651 #endif
652
653 #if defined MOUNTED_FS_STAT_DEV
654 {
655
656
657
658
659
660
661
662
663
664
665 DIR *dirp;
666 struct rootdir_entry
667 {
668 char *name;
669 dev_t dev;
670 ino_t ino;
671 struct rootdir_entry *next;
672 };
673 struct rootdir_entry *rootdir_list;
674 struct rootdir_entry **rootdir_tail;
675 int32 pos;
676 dev_t dev;
677 fs_info fi;
678
679
680 rootdir_list = NULL;
681 rootdir_tail = &rootdir_list;
682 dirp = opendir ("/");
683 if (dirp)
684 {
685 struct dirent *d;
686
687 while ((d = readdir (dirp)) != NULL)
688 {
689 char *name;
690 struct stat statbuf;
691
692 if (strcmp (d->d_name, "..") == 0)
693 continue;
694
695 if (strcmp (d->d_name, ".") == 0)
696 name = xstrdup ("/");
697 else
698 {
699 name = xmalloc (1 + strlen (d->d_name) + 1);
700 name[0] = '/';
701 strcpy (name + 1, d->d_name);
702 }
703
704 if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
705 {
706 struct rootdir_entry *re = xmalloc (sizeof *re);
707 re->name = name;
708 re->dev = statbuf.st_dev;
709 re->ino = statbuf.st_ino;
710
711
712 *rootdir_tail = re;
713 rootdir_tail = &re->next;
714 }
715 else
716 free (name);
717 }
718 closedir (dirp);
719 }
720 *rootdir_tail = NULL;
721
722 for (pos = 0; (dev = next_dev (&pos)) >= 0; )
723 if (fs_stat_dev (dev, &fi) >= 0)
724 {
725
726 struct rootdir_entry *re;
727
728 for (re = rootdir_list; re; re = re->next)
729 if (re->dev == fi.dev && re->ino == fi.root)
730 break;
731
732 me = xmalloc (sizeof *me);
733 me->me_devname = xstrdup (fi.device_name[0] != '\0'
734 ? fi.device_name : fi.fsh_name);
735 me->me_mountdir = xstrdup (re != NULL ? re->name : fi.fsh_name);
736 me->me_mntroot = NULL;
737 me->me_type = xstrdup (fi.fsh_name);
738 me->me_type_malloced = 1;
739 me->me_dev = fi.dev;
740 me->me_dummy = 0;
741 me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
742
743
744 *mtail = me;
745 mtail = &me->me_next;
746 }
747 *mtail = NULL;
748
749 while (rootdir_list != NULL)
750 {
751 struct rootdir_entry *re = rootdir_list;
752 rootdir_list = re->next;
753 free (re->name);
754 free (re);
755 }
756 }
757 #endif
758
759 #if defined MOUNTED_GETFSSTAT
760 {
761 int numsys, counter;
762 size_t bufsize;
763 struct statfs *stats;
764
765 numsys = getfsstat (NULL, 0L, MNT_NOWAIT);
766 if (numsys < 0)
767 return NULL;
768 if (SIZE_MAX / sizeof *stats <= numsys)
769 xalloc_die ();
770
771 bufsize = (1 + numsys) * sizeof *stats;
772 stats = xmalloc (bufsize);
773 numsys = getfsstat (stats, bufsize, MNT_NOWAIT);
774
775 if (numsys < 0)
776 {
777 free (stats);
778 return NULL;
779 }
780
781 for (counter = 0; counter < numsys; counter++)
782 {
783 me = xmalloc (sizeof *me);
784 me->me_devname = xstrdup (stats[counter].f_mntfromname);
785 me->me_mountdir = xstrdup (stats[counter].f_mntonname);
786 me->me_mntroot = NULL;
787 me->me_type = xstrdup (FS_TYPE (stats[counter]));
788 me->me_type_malloced = 1;
789 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
790 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
791 me->me_dev = (dev_t) -1;
792
793
794 *mtail = me;
795 mtail = &me->me_next;
796 }
797
798 free (stats);
799 }
800 #endif
801
802 #if defined MOUNTED_FREAD_FSTYP
803 {
804 struct mnttab mnt;
805 char *table = "/etc/mnttab";
806 FILE *fp;
807
808 fp = fopen (table, "re");
809 if (fp == NULL)
810 return NULL;
811
812 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
813 {
814 me = xmalloc (sizeof *me);
815 me->me_devname = xstrdup (mnt.mt_dev);
816 me->me_mountdir = xstrdup (mnt.mt_filsys);
817 me->me_mntroot = NULL;
818 me->me_dev = (dev_t) -1;
819 me->me_type = "";
820 me->me_type_malloced = 0;
821 if (need_fs_type)
822 {
823 struct statfs fsd;
824 char typebuf[FSTYPSZ];
825
826 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
827 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
828 {
829 me->me_type = xstrdup (typebuf);
830 me->me_type_malloced = 1;
831 }
832 }
833 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
834 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
835
836
837 *mtail = me;
838 mtail = &me->me_next;
839 }
840
841 if (ferror (fp))
842 {
843
844 int saved_errno = errno;
845 fclose (fp);
846 errno = saved_errno;
847 goto free_then_fail;
848 }
849
850 if (fclose (fp) == EOF)
851 goto free_then_fail;
852 }
853 #endif
854
855 #ifdef MOUNTED_GETEXTMNTENT
856 {
857 struct extmnttab mnt;
858 const char *table = MNTTAB;
859 FILE *fp;
860 int ret;
861
862
863
864
865 errno = 0;
866 fp = fopen (table, "re");
867 if (fp == NULL)
868 ret = errno;
869 else
870 {
871 while ((ret = getextmntent (fp, &mnt, 1)) == 0)
872 {
873 me = xmalloc (sizeof *me);
874 me->me_devname = xstrdup (mnt.mnt_special);
875 me->me_mountdir = xstrdup (mnt.mnt_mountp);
876 me->me_mntroot = NULL;
877 me->me_type = xstrdup (mnt.mnt_fstype);
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);
882
883
884 *mtail = me;
885 mtail = &me->me_next;
886 }
887
888 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
889
890 }
891
892 if (0 <= ret)
893 {
894 errno = ret;
895 goto free_then_fail;
896 }
897 }
898 #endif
899
900 #ifdef MOUNTED_GETMNTENT2
901 {
902 struct mnttab mnt;
903 const char *table = MNTTAB;
904 FILE *fp;
905 int ret;
906 int lockfd = -1;
907
908 # if defined F_RDLCK && defined F_SETLKW
909
910
911
912
913 # ifndef MNTTAB_LOCK
914 # define MNTTAB_LOCK "/etc/.mnttab.lock"
915 # endif
916 lockfd = open (MNTTAB_LOCK, O_RDONLY | O_CLOEXEC);
917 if (0 <= lockfd)
918 {
919 struct flock flock;
920 flock.l_type = F_RDLCK;
921 flock.l_whence = SEEK_SET;
922 flock.l_start = 0;
923 flock.l_len = 0;
924 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
925 if (errno != EINTR)
926 {
927 int saved_errno = errno;
928 close (lockfd);
929 errno = saved_errno;
930 return NULL;
931 }
932 }
933 else if (errno != ENOENT)
934 return NULL;
935 # endif
936
937 errno = 0;
938 fp = fopen (table, "re");
939 if (fp == NULL)
940 ret = errno;
941 else
942 {
943 while ((ret = getmntent (fp, &mnt)) == 0)
944 {
945 me = xmalloc (sizeof *me);
946 me->me_devname = xstrdup (mnt.mnt_special);
947 me->me_mountdir = xstrdup (mnt.mnt_mountp);
948 me->me_mntroot = NULL;
949 me->me_type = xstrdup (mnt.mnt_fstype);
950 me->me_type_malloced = 1;
951 me->me_dummy = MNT_IGNORE (&mnt) != 0;
952 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
953 me->me_dev = dev_from_mount_options (mnt.mnt_mntopts);
954
955
956 *mtail = me;
957 mtail = &me->me_next;
958 }
959
960 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
961
962 }
963
964 if (0 <= lockfd && close (lockfd) != 0)
965 ret = errno;
966
967 if (0 <= ret)
968 {
969 errno = ret;
970 goto free_then_fail;
971 }
972 }
973 #endif
974
975 #ifdef MOUNTED_VMOUNT
976 {
977 int bufsize;
978 void *entries;
979 char *thisent;
980 struct vmount *vmp;
981 int n_entries;
982 int i;
983
984
985 entries = &bufsize;
986 if (mntctl (MCTL_QUERY, sizeof bufsize, entries) != 0)
987 return NULL;
988 entries = xmalloc (bufsize);
989
990
991 n_entries = mntctl (MCTL_QUERY, bufsize, entries);
992 if (n_entries < 0)
993 {
994 free (entries);
995 return NULL;
996 }
997
998 for (i = 0, thisent = entries;
999 i < n_entries;
1000 i++, thisent += vmp->vmt_length)
1001 {
1002 char *options, *ignore;
1003
1004 vmp = (struct vmount *) thisent;
1005 me = xmalloc (sizeof *me);
1006 if (vmp->vmt_flags & MNT_REMOTE)
1007 {
1008 char *host, *dir;
1009
1010 me->me_remote = 1;
1011
1012 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
1013 dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
1014 me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2);
1015 strcpy (me->me_devname, host);
1016 strcat (me->me_devname, ":");
1017 strcat (me->me_devname, dir);
1018 }
1019 else
1020 {
1021 me->me_remote = 0;
1022 me->me_devname = xstrdup (thisent +
1023 vmp->vmt_data[VMT_OBJECT].vmt_off);
1024 }
1025 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
1026 me->me_mntroot = NULL;
1027 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
1028 me->me_type_malloced = 1;
1029 options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
1030 ignore = strstr (options, "ignore");
1031 me->me_dummy = (ignore
1032 && (ignore == options || ignore[-1] == ',')
1033 && (ignore[sizeof "ignore" - 1] == ','
1034 || ignore[sizeof "ignore" - 1] == '\0'));
1035 me->me_dev = (dev_t) -1;
1036
1037
1038 *mtail = me;
1039 mtail = &me->me_next;
1040 }
1041 free (entries);
1042 }
1043 #endif
1044
1045 #ifdef MOUNTED_INTERIX_STATVFS
1046 {
1047 DIR *dirp = opendir ("/dev/fs");
1048 char node[9 + NAME_MAX];
1049
1050 if (!dirp)
1051 goto free_then_fail;
1052
1053 while (1)
1054 {
1055 struct statvfs dev;
1056 struct dirent entry;
1057 struct dirent *result;
1058
1059
1060
1061 if (readdir_r (dirp, &entry, &result) || result == NULL)
1062 break;
1063
1064 strcpy (node, "/dev/fs/");
1065 strcat (node, entry.d_name);
1066
1067 if (statvfs (node, &dev) == 0)
1068 {
1069 me = xmalloc (sizeof *me);
1070 me->me_devname = xstrdup (dev.f_mntfromname);
1071 me->me_mountdir = xstrdup (dev.f_mntonname);
1072 me->me_mntroot = NULL;
1073 me->me_type = xstrdup (dev.f_fstypename);
1074 me->me_type_malloced = 1;
1075 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
1076 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
1077 me->me_dev = (dev_t) -1;
1078
1079
1080 *mtail = me;
1081 mtail = &me->me_next;
1082 }
1083 }
1084 closedir (dirp);
1085 }
1086 #endif
1087
1088 *mtail = NULL;
1089 return mount_list;
1090
1091
1092 free_then_fail: _GL_UNUSED_LABEL;
1093 {
1094 int saved_errno = errno;
1095 *mtail = NULL;
1096
1097 while (mount_list)
1098 {
1099 me = mount_list->me_next;
1100 free_mount_entry (mount_list);
1101 mount_list = me;
1102 }
1103
1104 errno = saved_errno;
1105 return NULL;
1106 }
1107 }
1108
1109
1110
1111 void
1112 free_mount_entry (struct mount_entry *me)
1113 {
1114 free (me->me_devname);
1115 free (me->me_mountdir);
1116 free (me->me_mntroot);
1117 if (me->me_type_malloced)
1118 free (me->me_type);
1119 free (me);
1120 }