This source file includes following definitions.
- me_remote
- statvfs_works
- free_mount_entry
- fstype_to_string
- fsp_to_string
- fstype_to_string
- dev_from_mount_options
- unescape_tab
- read_file_system_list
- read_file_system_list
- get_fs_usage
- free_my_statfs
- init_my_statfs
- my_statfs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #include <config.h>
28
29 #include <limits.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdint.h>
34 #include <sys/types.h>
35
36 #include <errno.h>
37
38
39 #ifdef HAVE_SYS_PARAM_H
40 #include <sys/param.h>
41 #endif
42
43 #if defined STAT_STATVFS || defined STAT_STATVFS64
44 #include <sys/statvfs.h>
45 #else
46
47
48 #include <fcntl.h>
49 #include <unistd.h>
50 #include <sys/stat.h>
51
52 #ifdef MOUNTED_GETFSSTAT
53 #ifdef HAVE_SYS_UCRED_H
54 #include <grp.h>
55
56 #include <sys/ucred.h>
57 #endif
58 #ifdef HAVE_SYS_MOUNT_H
59 #include <sys/mount.h>
60 #endif
61 #ifdef HAVE_SYS_FS_TYPES_H
62 #include <sys/fs_types.h>
63 #endif
64 #ifdef HAVE_STRUCT_FSSTAT_F_FSTYPENAME
65 #define FS_TYPE(Ent) ((Ent).f_fstypename)
66 #else
67 #define FS_TYPE(Ent) mnt_names[(Ent).f_type]
68 #endif
69 #endif
70 #endif
71
72 #ifdef HAVE_SYS_VFS_H
73 #include <sys/vfs.h>
74 #endif
75 #ifdef HAVE_SYS_FS_S5PARAM_H
76 #include <sys/fs/s5param.h>
77 #endif
78 #ifdef HAVE_SYS_STATFS_H
79 #include <sys/statfs.h>
80 #endif
81
82 #ifdef MOUNTED_GETMNTENT1
83
84 #include <mntent.h>
85 #include <sys/types.h>
86 #if defined __ANDROID__
87
88
89 #undef MOUNTED
90 #define MOUNTED "/proc/mounts"
91 #elif !defined MOUNTED
92 #ifdef _PATH_MOUNTED
93 #define MOUNTED _PATH_MOUNTED
94 #endif
95 #ifdef MNT_MNTTAB
96 #define MOUNTED MNT_MNTTAB
97 #endif
98 #endif
99 #endif
100
101 #ifdef MOUNTED_GETMNTINFO
102 #include <sys/mount.h>
103 #endif
104
105 #ifdef MOUNTED_GETMNTINFO2
106 #include <sys/statvfs.h>
107 #endif
108
109 #ifdef MOUNTED_FS_STAT_DEV
110 #include <fs_info.h>
111 #include <dirent.h>
112 #endif
113
114 #ifdef MOUNTED_FREAD_FSTYP
115 #include <mnttab.h>
116 #include <sys/fstyp.h>
117 #include <sys/statfs.h>
118 #endif
119
120 #ifdef MOUNTED_GETEXTMNTENT
121 #include <sys/mnttab.h>
122 #endif
123
124 #ifdef MOUNTED_GETMNTENT2
125 #include <sys/mnttab.h>
126 #endif
127
128 #ifdef MOUNTED_VMOUNT
129 #include <fshelp.h>
130 #include <sys/vfs.h>
131 #endif
132
133 #ifdef MOUNTED_INTERIX_STATVFS
134 #include <sys/statvfs.h>
135 #include <dirent.h>
136 #endif
137
138 #ifdef HAVE_SYS_MNTENT_H
139
140 #include <sys/mntent.h>
141 #endif
142
143 #ifdef MOUNTED_GETMNTENT1
144 #if !HAVE_SETMNTENT
145 #define setmntent(fp,mode) fopen (fp, mode)
146 #endif
147 #if !HAVE_ENDMNTENT
148 #define endmntent(fp) fclose (fp)
149 #endif
150 #endif
151
152 #ifndef HAVE_HASMNTOPT
153 #define hasmntopt(mnt, opt) ((char *) 0)
154 #endif
155
156 #undef MNT_IGNORE
157 #ifdef MNTOPT_IGNORE
158 #if defined __sun && defined __SVR4
159
160
161 #define MNT_IGNORE(M) hasmntopt (M, (char *) MNTOPT_IGNORE)
162 #else
163 #define MNT_IGNORE(M) hasmntopt (M, MNTOPT_IGNORE)
164 #endif
165 #else
166 #define MNT_IGNORE(M) 0
167 #endif
168
169 #ifdef HAVE_INFOMOUNT_QNX
170 #include <sys/disk.h>
171 #include <sys/fsys.h>
172 #endif
173
174 #ifdef HAVE_SYS_STATVFS_H
175 #include <sys/statvfs.h>
176 #endif
177
178 #include "lib/global.h"
179 #include "lib/strutil.h"
180 #include "lib/unixcompat.h"
181 #include "mountlist.h"
182
183
184
185
186
187 #if defined (__QNX__) && !defined(__QNXNTO__) && !defined (HAVE_INFOMOUNT_LIST)
188 #define HAVE_INFOMOUNT_QNX
189 #endif
190
191 #if defined(HAVE_INFOMOUNT_LIST) || defined(HAVE_INFOMOUNT_QNX)
192 #define HAVE_INFOMOUNT
193 #endif
194
195
196
197 #undef opendir
198 #undef closedir
199
200 #define ME_DUMMY_0(Fs_name, Fs_type) \
201 (strcmp (Fs_type, "autofs") == 0 \
202 || strcmp (Fs_type, "proc") == 0 \
203 || strcmp (Fs_type, "subfs") == 0 \
204 \
205 || strcmp (Fs_type, "debugfs") == 0 \
206 || strcmp (Fs_type, "devpts") == 0 \
207 || strcmp (Fs_type, "fusectl") == 0 \
208 || strcmp (Fs_type, "fuse.portal") == 0 \
209 || strcmp (Fs_type, "mqueue") == 0 \
210 || strcmp (Fs_type, "rpc_pipefs") == 0 \
211 || strcmp (Fs_type, "sysfs") == 0 \
212 \
213 || strcmp (Fs_type, "devfs") == 0 \
214 \
215 || strcmp (Fs_type, "kernfs") == 0 \
216 \
217 || strcmp (Fs_type, "ignore") == 0)
218
219
220
221
222
223 #ifdef MOUNTED_GETMNTENT1
224 #define ME_DUMMY(Fs_name, Fs_type, Bind) \
225 (ME_DUMMY_0 (Fs_name, Fs_type) \
226 || (strcmp (Fs_type, "none") == 0 && !Bind))
227 #else
228 #define ME_DUMMY(Fs_name, Fs_type) \
229 (ME_DUMMY_0 (Fs_name, Fs_type) || strcmp (Fs_type, "none") == 0)
230 #endif
231
232 #ifdef __CYGWIN__
233 #include <windows.h>
234 #define ME_REMOTE me_remote
235
236
237 static int
238 me_remote (char const *fs_name, char const *fs_type)
239 {
240 (void) fs_type;
241
242 if (fs_name[0] && fs_name[1] == ':')
243 {
244 char drive[4];
245 sprintf (drive, "%c:\\", fs_name[0]);
246 switch (GetDriveType (drive))
247 {
248 case DRIVE_REMOVABLE:
249 case DRIVE_FIXED:
250 case DRIVE_CDROM:
251 case DRIVE_RAMDISK:
252 return 0;
253 }
254 }
255 return 1;
256 }
257 #endif
258 #ifndef ME_REMOTE
259
260
261
262
263
264 #define ME_REMOTE(Fs_name, Fs_type) \
265 (strchr (Fs_name, ':') != NULL \
266 || ((Fs_name)[0] == '/' \
267 && (Fs_name)[1] == '/' \
268 && (strcmp (Fs_type, "smbfs") == 0 \
269 || strcmp (Fs_type, "smb3") == 0 \
270 || strcmp (Fs_type, "cifs") == 0)) \
271 || strcmp (Fs_type, "acfs") == 0 \
272 || strcmp (Fs_type, "afs") == 0 \
273 || strcmp (Fs_type, "coda") == 0 \
274 || strcmp (Fs_type, "auristorfs") == 0 \
275 || strcmp (Fs_type, "fhgfs") == 0 \
276 || strcmp (Fs_type, "gpfs") == 0 \
277 || strcmp (Fs_type, "ibrix") == 0 \
278 || strcmp (Fs_type, "ocfs2") == 0 \
279 || strcmp (Fs_type, "vxfs") == 0 \
280 || strcmp ("-hosts", Fs_name) == 0)
281 #endif
282
283
284
285
286
287 #define PROPAGATE_ALL_ONES(x) \
288 ((sizeof (x) < sizeof (uintmax_t) \
289 && (~ (x) == (sizeof (x) < sizeof (int) \
290 ? - (1 << (sizeof (x) * CHAR_BIT)) \
291 : 0))) \
292 ? UINTMAX_MAX : (uintmax_t) (x))
293
294
295 #define EXTRACT_TOP_BIT(x) ((x) & ((uintmax_t) 1 << (sizeof (x) * CHAR_BIT - 1)))
296
297
298
299
300
301
302
303
304 #define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1))
305
306 #ifdef STAT_STATVFS
307 #if ! (defined __linux__ && (defined __GLIBC__ || defined __UCLIBC__))
308
309 #undef STAT_STATFS2_FRSIZE
310 #else
311 #include <sys/utsname.h>
312 #include <sys/statfs.h>
313 #define STAT_STATFS2_BSIZE 1
314 #endif
315 #endif
316
317
318
319
320 struct mount_entry
321 {
322 char *me_devname;
323 char *me_mountdir;
324 char *me_mntroot;
325
326 char *me_type;
327 dev_t me_dev;
328 unsigned int me_dummy:1;
329 unsigned int me_remote:1;
330 unsigned int me_type_malloced:1;
331 };
332
333 struct fs_usage
334 {
335 uintmax_t fsu_blocksize;
336 uintmax_t fsu_blocks;
337 uintmax_t fsu_bfree;
338 uintmax_t fsu_bavail;
339 int fsu_bavail_top_bit_set;
340 uintmax_t fsu_files;
341 uintmax_t fsu_ffree;
342 };
343
344
345
346
347
348 #ifdef HAVE_INFOMOUNT_LIST
349 static GSList *mc_mount_list = NULL;
350 #endif
351
352
353
354
355
356 #ifdef STAT_STATVFS
357
358
359
360
361 static int
362 statvfs_works (void)
363 {
364 #if ! (defined __linux__ && (defined __GLIBC__ || defined __UCLIBC__))
365 return 1;
366 #else
367 static int statvfs_works_cache = -1;
368 struct utsname name;
369
370 if (statvfs_works_cache < 0)
371 statvfs_works_cache = (uname (&name) == 0 && 0 <= str_verscmp (name.release, "2.6.36"));
372 return statvfs_works_cache;
373 #endif
374 }
375 #endif
376
377
378
379 #ifdef HAVE_INFOMOUNT_LIST
380 static void
381 free_mount_entry (struct mount_entry *me)
382 {
383 if (me == NULL)
384 return;
385 g_free (me->me_devname);
386 g_free (me->me_mountdir);
387 g_free (me->me_mntroot);
388 if (me->me_type_malloced)
389 g_free (me->me_type);
390 g_free (me);
391 }
392
393
394
395 #ifdef MOUNTED_GETMNTINFO
396
397 #ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME
398 static char *
399 fstype_to_string (short int t)
400 {
401 switch (t)
402 {
403 #ifdef MOUNT_PC
404
405 case MOUNT_PC:
406 return "pc";
407 #endif
408 #ifdef MOUNT_MFS
409
410 case MOUNT_MFS:
411 return "mfs";
412 #endif
413 #ifdef MOUNT_LO
414
415 case MOUNT_LO:
416 return "lo";
417 #endif
418 #ifdef MOUNT_TFS
419
420 case MOUNT_TFS:
421 return "tfs";
422 #endif
423 #ifdef MOUNT_TMP
424
425 case MOUNT_TMP:
426 return "tmp";
427 #endif
428 #ifdef MOUNT_UFS
429
430 case MOUNT_UFS:
431 return "ufs";
432 #endif
433 #ifdef MOUNT_NFS
434
435 case MOUNT_NFS:
436 return "nfs";
437 #endif
438 #ifdef MOUNT_MSDOS
439
440 case MOUNT_MSDOS:
441 return "msdos";
442 #endif
443 #ifdef MOUNT_LFS
444
445 case MOUNT_LFS:
446 return "lfs";
447 #endif
448 #ifdef MOUNT_LOFS
449
450 case MOUNT_LOFS:
451 return "lofs";
452 #endif
453 #ifdef MOUNT_FDESC
454
455 case MOUNT_FDESC:
456 return "fdesc";
457 #endif
458 #ifdef MOUNT_PORTAL
459
460 case MOUNT_PORTAL:
461 return "portal";
462 #endif
463 #ifdef MOUNT_NULL
464
465 case MOUNT_NULL:
466 return "null";
467 #endif
468 #ifdef MOUNT_UMAP
469
470 case MOUNT_UMAP:
471 return "umap";
472 #endif
473 #ifdef MOUNT_KERNFS
474
475 case MOUNT_KERNFS:
476 return "kernfs";
477 #endif
478 #ifdef MOUNT_PROCFS
479
480 case MOUNT_PROCFS:
481 return "procfs";
482 #endif
483 #ifdef MOUNT_AFS
484
485 case MOUNT_AFS:
486 return "afs";
487 #endif
488 #ifdef MOUNT_CD9660
489
490 case MOUNT_CD9660:
491 return "cd9660";
492 #endif
493 #ifdef MOUNT_UNION
494
495 case MOUNT_UNION:
496 return "union";
497 #endif
498 #ifdef MOUNT_DEVFS
499
500 case MOUNT_DEVFS:
501 return "devfs";
502 #endif
503 #ifdef MOUNT_EXT2FS
504
505 case MOUNT_EXT2FS:
506 return "ext2fs";
507 #endif
508 default:
509 return "?";
510 }
511 }
512 #endif
513
514
515
516 static char *
517 fsp_to_string (const struct statfs *fsp)
518 {
519 #ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME
520 return (char *) (fsp->f_fstypename);
521 #else
522 return fstype_to_string (fsp->f_type);
523 #endif
524 }
525 #endif
526
527
528
529 #ifdef MOUNTED_VMOUNT
530 static char *
531 fstype_to_string (int t)
532 {
533 struct vfs_ent *e;
534
535 e = getvfsbytype (t);
536 if (!e || !e->vfsent_name)
537 return "none";
538 else
539 return e->vfsent_name;
540 }
541 #endif
542
543
544
545 #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
546
547
548
549
550
551
552 static dev_t
553 dev_from_mount_options (char const *mount_options)
554 {
555
556
557
558 #ifndef __linux__
559 static char const dev_pattern[] = ",dev=";
560 char const *devopt = strstr (mount_options, dev_pattern);
561
562 if (devopt)
563 {
564 char const *optval = devopt + sizeof (dev_pattern) - 1;
565 char *optvalend;
566 unsigned long int dev;
567 errno = 0;
568 dev = strtoul (optval, &optvalend, 16);
569 if (optval != optvalend
570 && (*optvalend == '\0' || *optvalend == ',')
571 && !(dev == ULONG_MAX && errno == ERANGE) && dev == (dev_t) dev)
572 return dev;
573 }
574 #endif
575
576 (void) mount_options;
577 return -1;
578 }
579
580 #endif
581
582
583
584 #if defined MOUNTED_GETMNTENT1 && (defined __linux__ || defined __ANDROID__)
585
586
587
588 static void
589 unescape_tab (char *str)
590 {
591 size_t i, j = 0;
592 size_t len;
593
594 len = strlen (str) + 1;
595
596 for (i = 0; i < len; i++)
597 {
598 if (str[i] == '\\' && (i + 4 < len)
599 && str[i + 1] >= '0' && str[i + 1] <= '3'
600 && str[i + 2] >= '0' && str[i + 2] <= '7' && str[i + 3] >= '0' && str[i + 3] <= '7')
601 {
602 str[j++] = (str[i + 1] - '0') * 64 + (str[i + 2] - '0') * 8 + (str[i + 3] - '0');
603 i += 3;
604 }
605 else
606 str[j++] = str[i];
607 }
608 }
609 #endif
610
611
612
613
614
615
616 static GSList *
617 read_file_system_list (void)
618 {
619 GSList *mount_list = NULL;
620 struct mount_entry *me;
621
622 #ifdef MOUNTED_GETMNTENT1
623
624 {
625 FILE *fp;
626
627 #if defined __linux__ || defined __ANDROID__
628
629
630
631
632 char const *mountinfo = "/proc/self/mountinfo";
633
634 fp = fopen (mountinfo, "r");
635 if (fp != NULL)
636 {
637 char *line = NULL;
638 size_t buf_size = 0;
639
640 while (getline (&line, &buf_size, fp) != -1)
641 {
642 unsigned int devmaj, devmin;
643 int target_s, target_e, type_s, type_e;
644 int source_s, source_e, mntroot_s, mntroot_e;
645 char test;
646 char *dash;
647 int rc;
648
649 rc = sscanf (line, "%*u "
650 "%*u "
651 "%u:%u "
652 "%n%*s%n "
653 "%n%*s%n"
654 "%c",
655 &devmaj, &devmin, &mntroot_s, &mntroot_e, &target_s, &target_e, &test);
656
657 if (rc != 3 && rc != 7)
658 continue;
659
660
661 dash = strstr (line + target_e, " - ");
662 if (dash == NULL)
663 continue;
664
665 rc = sscanf (dash, " - "
666 "%n%*s%n "
667 "%n%*s%n "
668 "%c",
669 &type_s, &type_e, &source_s, &source_e, &test);
670 if (rc != 1 && rc != 5)
671 continue;
672
673
674 line[mntroot_e] = '\0';
675 line[target_e] = '\0';
676 dash[type_e] = '\0';
677 dash[source_e] = '\0';
678 unescape_tab (dash + source_s);
679 unescape_tab (line + target_s);
680 unescape_tab (line + mntroot_s);
681
682 me = g_malloc (sizeof *me);
683
684 me->me_devname = g_strdup (dash + source_s);
685 me->me_mountdir = g_strdup (line + target_s);
686 me->me_mntroot = g_strdup (line + mntroot_s);
687 me->me_type = g_strdup (dash + type_s);
688 me->me_type_malloced = 1;
689 me->me_dev = makedev (devmaj, devmin);
690
691
692
693
694 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, FALSE);
695 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
696
697 mount_list = g_slist_prepend (mount_list, me);
698 }
699
700 free (line);
701
702 if (ferror (fp) != 0)
703 {
704 int saved_errno = errno;
705
706 fclose (fp);
707 errno = saved_errno;
708 goto free_then_fail;
709 }
710
711 if (fclose (fp) == EOF)
712 goto free_then_fail;
713 }
714 else
715 #endif
716 {
717 struct mntent *mnt;
718 const char *table = MOUNTED;
719
720 fp = setmntent (table, "r");
721 if (fp == NULL)
722 return NULL;
723
724 while ((mnt = getmntent (fp)) != NULL)
725 {
726 gboolean bind;
727
728 bind = hasmntopt (mnt, "bind") != NULL;
729
730 me = g_malloc (sizeof (*me));
731 me->me_devname = g_strdup (mnt->mnt_fsname);
732 me->me_mountdir = g_strdup (mnt->mnt_dir);
733 me->me_mntroot = NULL;
734 me->me_type = g_strdup (mnt->mnt_type);
735 me->me_type_malloced = 1;
736 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, bind);
737 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
738 me->me_dev = dev_from_mount_options (mnt->mnt_opts);
739
740 mount_list = g_slist_prepend (mount_list, me);
741 }
742
743 if (endmntent (fp) == 0)
744 goto free_then_fail;
745 }
746 }
747 #endif
748
749 #ifdef MOUNTED_GETMNTINFO
750 {
751 struct statfs *fsp;
752 int entries;
753
754 entries = getmntinfo (&fsp, MNT_NOWAIT);
755 if (entries < 0)
756 return NULL;
757 for (; entries-- > 0; fsp++)
758 {
759 char *fs_type = fsp_to_string (fsp);
760
761 me = g_malloc (sizeof (*me));
762 me->me_devname = g_strdup (fsp->f_mntfromname);
763 me->me_mountdir = g_strdup (fsp->f_mntonname);
764 me->me_mntroot = NULL;
765 me->me_type = fs_type;
766 me->me_type_malloced = 0;
767 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
768 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
769 me->me_dev = (dev_t) (-1);
770
771 mount_list = g_slist_prepend (mount_list, me);
772 }
773 }
774 #endif
775
776 #ifdef MOUNTED_GETMNTINFO2
777 {
778 struct statvfs *fsp;
779 int entries;
780
781 entries = getmntinfo (&fsp, MNT_NOWAIT);
782 if (entries < 0)
783 return NULL;
784 for (; entries-- > 0; fsp++)
785 {
786 me = g_malloc (sizeof (*me));
787 me->me_devname = g_strdup (fsp->f_mntfromname);
788 me->me_mountdir = g_strdup (fsp->f_mntonname);
789 me->me_mntroot = NULL;
790 me->me_type = g_strdup (fsp->f_fstypename);
791 me->me_type_malloced = 1;
792 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
793 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
794 me->me_dev = (dev_t) (-1);
795
796 mount_list = g_slist_prepend (mount_list, me);
797 }
798 }
799 #endif
800
801 #if defined MOUNTED_FS_STAT_DEV
802 {
803
804
805
806
807
808
809
810
811
812
813 DIR *dirp;
814 struct rootdir_entry
815 {
816 char *name;
817 dev_t dev;
818 ino_t ino;
819 struct rootdir_entry *next;
820 };
821 struct rootdir_entry *rootdir_list;
822 struct rootdir_entry **rootdir_tail;
823 int32 pos;
824 dev_t dev;
825 fs_info fi;
826
827
828 rootdir_list = NULL;
829 rootdir_tail = &rootdir_list;
830 dirp = opendir (PATH_SEP_STR);
831 if (dirp)
832 {
833 struct dirent *d;
834
835 while ((d = readdir (dirp)) != NULL)
836 {
837 char *name;
838 struct stat statbuf;
839
840 if (DIR_IS_DOT (d->d_name))
841 continue;
842
843 if (DIR_IS_DOTDOT (d->d_name))
844 name = g_strdup (PATH_SEP_STR);
845 else
846 name = g_strconcat (PATH_SEP_STR, d->d_name, (char *) NULL);
847
848 if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
849 {
850 struct rootdir_entry *re = g_malloc (sizeof (*re));
851 re->name = name;
852 re->dev = statbuf.st_dev;
853 re->ino = statbuf.st_ino;
854
855
856 *rootdir_tail = re;
857 rootdir_tail = &re->next;
858 }
859 else
860 g_free (name);
861 }
862 closedir (dirp);
863 }
864 *rootdir_tail = NULL;
865
866 for (pos = 0; (dev = next_dev (&pos)) >= 0;)
867 if (fs_stat_dev (dev, &fi) >= 0)
868 {
869
870 struct rootdir_entry *re;
871
872 for (re = rootdir_list; re; re = re->next)
873 if (re->dev == fi.dev && re->ino == fi.root)
874 break;
875
876 me = g_malloc (sizeof (*me));
877 me->me_devname =
878 g_strdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
879 me->me_mountdir = g_strdup (re != NULL ? re->name : fi.fsh_name);
880 me->me_mntroot = NULL;
881 me->me_type = g_strdup (fi.fsh_name);
882 me->me_type_malloced = 1;
883 me->me_dev = fi.dev;
884 me->me_dummy = 0;
885 me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
886
887 mount_list = g_slist_prepend (mount_list, me);
888 }
889
890 while (rootdir_list != NULL)
891 {
892 struct rootdir_entry *re = rootdir_list;
893
894 rootdir_list = re->next;
895 g_free (re->name);
896 g_free (re);
897 }
898 }
899 #endif
900
901 #ifdef MOUNTED_GETFSSTAT
902 {
903 int numsys, counter;
904 size_t bufsize;
905 struct statfs *stats;
906
907 numsys = getfsstat (NULL, 0L, MNT_NOWAIT);
908 if (numsys < 0)
909 return NULL;
910 if (SIZE_MAX / sizeof (*stats) <= numsys)
911 {
912 fprintf (stderr, "%s\n", _("Memory exhausted!"));
913 exit (EXIT_FAILURE);
914 }
915
916 bufsize = (1 + numsys) * sizeof (*stats);
917 stats = g_malloc (bufsize);
918 numsys = getfsstat (stats, bufsize, MNT_NOWAIT);
919
920 if (numsys < 0)
921 {
922 g_free (stats);
923 return NULL;
924 }
925
926 for (counter = 0; counter < numsys; counter++)
927 {
928 me = g_malloc (sizeof (*me));
929 me->me_devname = g_strdup (stats[counter].f_mntfromname);
930 me->me_mountdir = g_strdup (stats[counter].f_mntonname);
931 me->me_mntroot = NULL;
932 me->me_type = g_strdup (FS_TYPE (stats[counter]));
933 me->me_type_malloced = 1;
934 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
935 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
936 me->me_dev = (dev_t) (-1);
937
938 mount_list = g_slist_prepend (mount_list, me);
939 }
940
941 g_free (stats);
942 }
943 #endif
944
945 #if defined MOUNTED_FREAD_FSTYP
946 {
947 struct mnttab mnt;
948 char *table = "/etc/mnttab";
949 FILE *fp;
950
951 fp = fopen (table, "r");
952 if (fp == NULL)
953 return NULL;
954
955 while (fread (&mnt, sizeof (mnt), 1, fp) > 0)
956 {
957 me = g_malloc (sizeof (*me));
958 me->me_devname = g_strdup (mnt.mt_dev);
959 me->me_mountdir = g_strdup (mnt.mt_filsys);
960 me->me_mntroot = NULL;
961 me->me_dev = (dev_t) (-1);
962 me->me_type = "";
963 me->me_type_malloced = 0;
964 {
965 struct statfs fsd;
966 char typebuf[FSTYPSZ];
967
968 if (statfs (me->me_mountdir, &fsd, sizeof (fsd), 0) != -1
969 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
970 {
971 me->me_type = g_strdup (typebuf);
972 me->me_type_malloced = 1;
973 }
974 }
975 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
976 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
977
978 mount_list = g_slist_prepend (mount_list, me);
979 }
980
981 if (ferror (fp))
982 {
983
984 int saved_errno = errno;
985
986 fclose (fp);
987 errno = saved_errno;
988 goto free_then_fail;
989 }
990
991 if (fclose (fp) == EOF)
992 goto free_then_fail;
993 }
994 #endif
995
996 #ifdef MOUNTED_GETEXTMNTENT
997 {
998 struct extmnttab mnt;
999 const char *table = MNTTAB;
1000 FILE *fp;
1001 int ret;
1002
1003
1004
1005 errno = 0;
1006 fp = fopen (table, "r");
1007 if (fp == NULL)
1008 ret = errno;
1009 else
1010 {
1011 while ((ret = getextmntent (fp, &mnt, 1)) == 0)
1012 {
1013 me = g_malloc (sizeof *me);
1014 me->me_devname = g_strdup (mnt.mnt_special);
1015 me->me_mountdir = g_strdup (mnt.mnt_mountp);
1016 me->me_mntroot = NULL;
1017 me->me_type = g_strdup (mnt.mnt_fstype);
1018 me->me_type_malloced = 1;
1019 me->me_dummy = MNT_IGNORE (&mnt) != 0;
1020 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
1021 me->me_dev = makedev (mnt.mnt_major, mnt.mnt_minor);
1022
1023 mount_list = g_slist_prepend (mount_list, me);
1024 }
1025
1026 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
1027
1028 }
1029
1030 if (ret >= 0)
1031 {
1032 errno = ret;
1033 goto free_then_fail;
1034 }
1035 }
1036 #endif
1037
1038 #ifdef MOUNTED_GETMNTENT2
1039 {
1040 struct mnttab mnt;
1041 const char *table = MNTTAB;
1042 FILE *fp;
1043 int ret;
1044 int lockfd = -1;
1045
1046 #if defined F_RDLCK && defined F_SETLKW
1047
1048
1049
1050
1051 #ifndef MNTTAB_LOCK
1052 #define MNTTAB_LOCK "/etc/.mnttab.lock"
1053 #endif
1054 lockfd = open (MNTTAB_LOCK, O_RDONLY);
1055 if (lockfd >= 0)
1056 {
1057 struct flock flock;
1058
1059 flock.l_type = F_RDLCK;
1060 flock.l_whence = SEEK_SET;
1061 flock.l_start = 0;
1062 flock.l_len = 0;
1063 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
1064 if (errno != EINTR)
1065 {
1066 int saved_errno = errno;
1067 close (lockfd);
1068 errno = saved_errno;
1069 return NULL;
1070 }
1071 }
1072 else if (errno != ENOENT)
1073 return NULL;
1074 #endif
1075
1076 errno = 0;
1077 fp = fopen (table, "r");
1078 if (fp == NULL)
1079 ret = errno;
1080 else
1081 {
1082 while ((ret = getmntent (fp, &mnt)) == 0)
1083 {
1084 me = g_malloc (sizeof (*me));
1085 me->me_devname = g_strdup (mnt.mnt_special);
1086 me->me_mountdir = g_strdup (mnt.mnt_mountp);
1087 me->me_mntroot = NULL;
1088 me->me_type = g_strdup (mnt.mnt_fstype);
1089 me->me_type_malloced = 1;
1090 me->me_dummy = MNT_IGNORE (&mnt) != 0;
1091 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
1092 me->me_dev = dev_from_mount_options (mnt.mnt_mntopts);
1093
1094 mount_list = g_slist_prepend (mount_list, me);
1095 }
1096
1097 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
1098
1099 }
1100
1101 if (lockfd >= 0 && close (lockfd) != 0)
1102 ret = errno;
1103
1104 if (ret >= 0)
1105 {
1106 errno = ret;
1107 goto free_then_fail;
1108 }
1109 }
1110 #endif
1111
1112 #ifdef MOUNTED_VMOUNT
1113 {
1114 int bufsize;
1115 void *entries;
1116 char *thisent;
1117 struct vmount *vmp;
1118 int n_entries;
1119 int i;
1120
1121
1122 entries = &bufsize;
1123 if (mntctl (MCTL_QUERY, sizeof (bufsize), entries) != 0)
1124 return NULL;
1125 entries = g_malloc (bufsize);
1126
1127
1128 n_entries = mntctl (MCTL_QUERY, bufsize, entries);
1129 if (n_entries < 0)
1130 {
1131 int saved_errno = errno;
1132
1133 g_free (entries);
1134 errno = saved_errno;
1135 return NULL;
1136 }
1137
1138 for (i = 0, thisent = entries; i < n_entries; i++, thisent += vmp->vmt_length)
1139 {
1140 char *options, *ignore;
1141
1142 vmp = (struct vmount *) thisent;
1143 me = g_malloc (sizeof (*me));
1144 if (vmp->vmt_flags & MNT_REMOTE)
1145 {
1146 char *host, *dir;
1147
1148 me->me_remote = 1;
1149
1150 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
1151 dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
1152 me->me_devname = g_strconcat (host, ":", dir, (char *) NULL);
1153 }
1154 else
1155 {
1156 me->me_remote = 0;
1157 me->me_devname = g_strdup (thisent + vmp->vmt_data[VMT_OBJECT].vmt_off);
1158 }
1159 me->me_mountdir = g_strdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
1160 me->me_mntroot = NULL;
1161 me->me_type = g_strdup (fstype_to_string (vmp->vmt_gfstype));
1162 me->me_type_malloced = 1;
1163 options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
1164 ignore = strstr (options, "ignore");
1165 me->me_dummy = (ignore
1166 && (ignore == options || ignore[-1] == ',')
1167 && (ignore[sizeof ("ignore") - 1] == ','
1168 || ignore[sizeof ("ignore") - 1] == '\0'));
1169 me->me_dev = (dev_t) (-1);
1170
1171 mount_list = g_slist_prepend (mount_list, me);
1172 }
1173 g_free (entries);
1174 }
1175 #endif
1176
1177 #ifdef MOUNTED_INTERIX_STATVFS
1178 {
1179 DIR *dirp = opendir ("/dev/fs");
1180 char node[9 + NAME_MAX];
1181
1182 if (!dirp)
1183 goto free_then_fail;
1184
1185 while (1)
1186 {
1187 struct statvfs dev;
1188 struct dirent entry;
1189 struct dirent *result;
1190
1191 if (readdir_r (dirp, &entry, &result) || result == NULL)
1192 break;
1193
1194 strcpy (node, "/dev/fs/");
1195 strcat (node, entry.d_name);
1196
1197 if (statvfs (node, &dev) == 0)
1198 {
1199 me = g_malloc (sizeof *me);
1200 me->me_devname = g_strdup (dev.f_mntfromname);
1201 me->me_mountdir = g_strdup (dev.f_mntonname);
1202 me->me_mntroot = NULL;
1203 me->me_type = g_strdup (dev.f_fstypename);
1204 me->me_type_malloced = 1;
1205 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
1206 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
1207 me->me_dev = (dev_t) (-1);
1208
1209 mount_list = g_slist_prepend (mount_list, me);
1210 }
1211 }
1212 closedir (dirp);
1213 }
1214 #endif
1215
1216 return g_slist_reverse (mount_list);
1217
1218 free_then_fail: MC_UNUSED;
1219 {
1220 int saved_errno = errno;
1221
1222 g_slist_free_full (mount_list, (GDestroyNotify) free_mount_entry);
1223
1224 errno = saved_errno;
1225 return NULL;
1226 }
1227 }
1228 #endif
1229
1230
1231
1232 #ifdef HAVE_INFOMOUNT_QNX
1233
1234
1235
1236
1237
1238
1239
1240 static GSList *
1241 read_file_system_list (void)
1242 {
1243 struct _disk_entry de;
1244 struct statfs fs;
1245 int i, fd;
1246 char *tp, dev[_POSIX_NAME_MAX], dir[_POSIX_PATH_MAX];
1247 struct mount_entry *me = NULL;
1248 static GSList *list = NULL;
1249
1250 if (list != NULL)
1251 {
1252 me = (struct mount_entry *) list->data;
1253
1254 g_free (me->me_devname);
1255 g_free (me->me_mountdir);
1256 g_free (me->me_mntroot);
1257 g_free (me->me_type);
1258 }
1259 else
1260 {
1261 me = (struct mount_entry *) g_malloc (sizeof (struct mount_entry));
1262 list = g_slist_prepend (list, me);
1263 }
1264
1265 if (!getcwd (dir, _POSIX_PATH_MAX))
1266 return (NULL);
1267
1268 fd = open (dir, O_RDONLY);
1269 if (fd == -1)
1270 return (NULL);
1271
1272 i = disk_get_entry (fd, &de);
1273
1274 close (fd);
1275
1276 if (i == -1)
1277 return (NULL);
1278
1279 switch (de.disk_type)
1280 {
1281 case _UNMOUNTED:
1282 tp = "unmounted";
1283 break;
1284 case _FLOPPY:
1285 tp = "Floppy";
1286 break;
1287 case _HARD:
1288 tp = "Hard";
1289 break;
1290 case _RAMDISK:
1291 tp = "Ram";
1292 break;
1293 case _REMOVABLE:
1294 tp = "Removable";
1295 break;
1296 case _TAPE:
1297 tp = "Tape";
1298 break;
1299 case _CDROM:
1300 tp = "CDROM";
1301 break;
1302 default:
1303 tp = "unknown";
1304 }
1305
1306 if (fsys_get_mount_dev (dir, &dev) == -1)
1307 return (NULL);
1308
1309 if (fsys_get_mount_pt (dev, &dir) == -1)
1310 return (NULL);
1311
1312 me->me_devname = g_strdup (dev);
1313 me->me_mountdir = g_strdup (dir);
1314 me->me_mntroot = NULL;
1315 me->me_type = g_strdup (tp);
1316 me->me_dev = de.disk_type;
1317
1318 #ifdef DEBUG
1319 fprintf (stderr,
1320 "disk_get_entry():\n\tdisk_type=%d (%s)\n\tdriver_name='%-*.*s'\n\tdisk_drv=%d\n",
1321 de.disk_type, tp, _DRIVER_NAME_LEN, _DRIVER_NAME_LEN, de.driver_name, de.disk_drv);
1322 fprintf (stderr, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev);
1323 fprintf (stderr, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir);
1324 #endif
1325
1326 return (list);
1327 }
1328 #endif
1329
1330
1331
1332 #ifdef HAVE_INFOMOUNT
1333
1334
1335
1336
1337
1338
1339
1340 static int
1341 get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
1342 {
1343 #ifdef STAT_STATVFS
1344
1345 if (statvfs_works ())
1346 {
1347 struct statvfs vfsd;
1348
1349 if (statvfs (file, &vfsd) < 0)
1350 return -1;
1351
1352
1353 fsp->fsu_blocksize = (vfsd.f_frsize
1354 ? PROPAGATE_ALL_ONES (vfsd.f_frsize)
1355 : PROPAGATE_ALL_ONES (vfsd.f_bsize));
1356
1357 fsp->fsu_blocks = PROPAGATE_ALL_ONES (vfsd.f_blocks);
1358 fsp->fsu_bfree = PROPAGATE_ALL_ONES (vfsd.f_bfree);
1359 fsp->fsu_bavail = PROPAGATE_TOP_BIT (vfsd.f_bavail);
1360 fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (vfsd.f_bavail) != 0;
1361 fsp->fsu_files = PROPAGATE_ALL_ONES (vfsd.f_files);
1362 fsp->fsu_ffree = PROPAGATE_ALL_ONES (vfsd.f_ffree);
1363 }
1364 else
1365 #endif
1366
1367 {
1368 #if defined STAT_STATVFS64
1369
1370 struct statvfs64 fsd;
1371
1372 if (statvfs64 (file, &fsd) < 0)
1373 return -1;
1374
1375
1376
1377 fsp->fsu_blocksize = fsd.f_frsize
1378 ? PROPAGATE_ALL_ONES (fsd.f_frsize)
1379 : PROPAGATE_ALL_ONES (fsd.f_bsize);
1380
1381
1382 #elif defined STAT_STATFS3_OSF1
1383
1384 struct statfs fsd;
1385
1386 if (statfs (file, &fsd, sizeof (struct statfs)) != 0)
1387 return -1;
1388
1389 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
1390
1391 #elif defined STAT_STATFS2_FRSIZE
1392
1393 struct statfs fsd;
1394
1395 if (statfs (file, &fsd) < 0)
1396 return -1;
1397
1398 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_frsize);
1399
1400 #elif defined STAT_STATFS2_BSIZE
1401
1402
1403
1404 struct statfs fsd;
1405
1406 if (statfs (file, &fsd) < 0)
1407 return -1;
1408
1409 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
1410
1411 #ifdef STATFS_TRUNCATES_BLOCK_COUNTS
1412
1413
1414
1415
1416
1417
1418 if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0)
1419 {
1420 fsd.f_blocks = fsd.f_spare[0];
1421 fsd.f_bfree = fsd.f_spare[1];
1422 fsd.f_bavail = fsd.f_spare[2];
1423 }
1424 #endif
1425
1426 #elif defined STAT_STATFS2_FSIZE
1427
1428 struct statfs fsd;
1429
1430 if (statfs (file, &fsd) < 0)
1431 return -1;
1432
1433 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
1434
1435 #elif defined STAT_STATFS4
1436
1437 struct statfs fsd;
1438
1439 if (statfs (file, &fsd, sizeof (fsd), 0) < 0)
1440 return -1;
1441
1442
1443
1444
1445 fsp->fsu_blocksize = 512;
1446 #endif
1447
1448 #if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1 \
1449 || defined STAT_STATFS2_FRSIZE || defined STAT_STATFS2_BSIZE \
1450 || defined STAT_STATFS2_FSIZE || defined STAT_STATFS4)
1451
1452 fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);
1453 fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree);
1454 fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail);
1455 fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0;
1456 fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files);
1457 fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree);
1458
1459 #endif
1460 }
1461
1462 (void) disk;
1463
1464 return 0;
1465 }
1466 #endif
1467
1468
1469
1470
1471
1472 void
1473 free_my_statfs (void)
1474 {
1475 #ifdef HAVE_INFOMOUNT_LIST
1476 g_clear_slist (&mc_mount_list, (GDestroyNotify) free_mount_entry);
1477 #endif
1478 }
1479
1480
1481
1482 void
1483 init_my_statfs (void)
1484 {
1485 #ifdef HAVE_INFOMOUNT_LIST
1486 free_my_statfs ();
1487 mc_mount_list = read_file_system_list ();
1488 #endif
1489 }
1490
1491
1492
1493 void
1494 my_statfs (struct my_statfs *myfs_stats, const char *path)
1495 {
1496 #ifdef HAVE_INFOMOUNT_LIST
1497 size_t len = 0;
1498 struct mount_entry *entry = NULL;
1499 GSList *temp;
1500 struct fs_usage fs_use;
1501
1502 for (temp = mc_mount_list; temp != NULL; temp = g_slist_next (temp))
1503 {
1504 struct mount_entry *me;
1505 size_t i;
1506
1507 me = (struct mount_entry *) temp->data;
1508 i = strlen (me->me_mountdir);
1509 if (i > len && (strncmp (path, me->me_mountdir, i) == 0) &&
1510 (entry == NULL || IS_PATH_SEP (path[i]) || path[i] == '\0'))
1511 {
1512 len = i;
1513 entry = me;
1514 }
1515 }
1516
1517 if (entry != NULL)
1518 {
1519 memset (&fs_use, 0, sizeof (fs_use));
1520 get_fs_usage (entry->me_mountdir, NULL, &fs_use);
1521
1522 myfs_stats->type = entry->me_dev;
1523 myfs_stats->typename = entry->me_type;
1524 myfs_stats->mpoint = entry->me_mountdir;
1525 myfs_stats->mroot = entry->me_mntroot;
1526 myfs_stats->device = entry->me_devname;
1527 myfs_stats->avail =
1528 ((uintmax_t) (getuid ()? fs_use.fsu_bavail : fs_use.fsu_bfree) *
1529 fs_use.fsu_blocksize) >> 10;
1530 myfs_stats->total = ((uintmax_t) fs_use.fsu_blocks * fs_use.fsu_blocksize) >> 10;
1531 myfs_stats->nfree = (uintmax_t) fs_use.fsu_ffree;
1532 myfs_stats->nodes = (uintmax_t) fs_use.fsu_files;
1533 }
1534 else
1535 #endif
1536
1537 #ifdef HAVE_INFOMOUNT_QNX
1538
1539
1540
1541
1542
1543 struct mount_entry *entry;
1544 struct fs_usage fs_use;
1545
1546 entry = read_file_system_list ();
1547 if (entry != NULL)
1548 {
1549 get_fs_usage (entry->me_mountdir, NULL, &fs_use);
1550
1551 myfs_stats->type = entry->me_dev;
1552 myfs_stats->typename = entry->me_type;
1553 myfs_stats->mpoint = entry->me_mountdir;
1554 myfs_stats->mroot = entry->me_mntroot;
1555 myfs_stats->device = entry->me_devname;
1556
1557 myfs_stats->avail = ((uintmax_t) fs_use.fsu_bfree * fs_use.fsu_blocksize) >> 10;
1558 myfs_stats->total = ((uintmax_t) fs_use.fsu_blocks * fs_use.fsu_blocksize) >> 10;
1559 myfs_stats->nfree = (uintmax_t) fs_use.fsu_ffree;
1560 myfs_stats->nodes = (uintmax_t) fs_use.fsu_files;
1561 }
1562 else
1563 #endif
1564 {
1565 myfs_stats->type = 0;
1566 myfs_stats->mpoint = "unknown";
1567 myfs_stats->device = "unknown";
1568 myfs_stats->avail = 0;
1569 myfs_stats->total = 0;
1570 myfs_stats->nfree = 0;
1571 myfs_stats->nodes = 0;
1572 }
1573 }
1574
1575