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 #ifdef HAVE_INFOMOUNT_LIST
347 static GSList *mc_mount_list = NULL;
348 #endif
349
350
351
352
353 #ifdef STAT_STATVFS
354
355
356
357
358 static int
359 statvfs_works (void)
360 {
361 #if ! (defined __linux__ && (defined __GLIBC__ || defined __UCLIBC__))
362 return 1;
363 #else
364 static int statvfs_works_cache = -1;
365 struct utsname name;
366
367 if (statvfs_works_cache < 0)
368 statvfs_works_cache = (uname (&name) == 0 && 0 <= str_verscmp (name.release, "2.6.36"));
369 return statvfs_works_cache;
370 #endif
371 }
372 #endif
373
374
375
376 #ifdef HAVE_INFOMOUNT_LIST
377 static void
378 free_mount_entry (struct mount_entry *me)
379 {
380 if (me == NULL)
381 return;
382 g_free (me->me_devname);
383 g_free (me->me_mountdir);
384 g_free (me->me_mntroot);
385 if (me->me_type_malloced)
386 g_free (me->me_type);
387 g_free (me);
388 }
389
390
391
392 #ifdef MOUNTED_GETMNTINFO
393
394 #ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME
395 static char *
396 fstype_to_string (short int t)
397 {
398 switch (t)
399 {
400 #ifdef MOUNT_PC
401
402 case MOUNT_PC:
403 return "pc";
404 #endif
405 #ifdef MOUNT_MFS
406
407 case MOUNT_MFS:
408 return "mfs";
409 #endif
410 #ifdef MOUNT_LO
411
412 case MOUNT_LO:
413 return "lo";
414 #endif
415 #ifdef MOUNT_TFS
416
417 case MOUNT_TFS:
418 return "tfs";
419 #endif
420 #ifdef MOUNT_TMP
421
422 case MOUNT_TMP:
423 return "tmp";
424 #endif
425 #ifdef MOUNT_UFS
426
427 case MOUNT_UFS:
428 return "ufs";
429 #endif
430 #ifdef MOUNT_NFS
431
432 case MOUNT_NFS:
433 return "nfs";
434 #endif
435 #ifdef MOUNT_MSDOS
436
437 case MOUNT_MSDOS:
438 return "msdos";
439 #endif
440 #ifdef MOUNT_LFS
441
442 case MOUNT_LFS:
443 return "lfs";
444 #endif
445 #ifdef MOUNT_LOFS
446
447 case MOUNT_LOFS:
448 return "lofs";
449 #endif
450 #ifdef MOUNT_FDESC
451
452 case MOUNT_FDESC:
453 return "fdesc";
454 #endif
455 #ifdef MOUNT_PORTAL
456
457 case MOUNT_PORTAL:
458 return "portal";
459 #endif
460 #ifdef MOUNT_NULL
461
462 case MOUNT_NULL:
463 return "null";
464 #endif
465 #ifdef MOUNT_UMAP
466
467 case MOUNT_UMAP:
468 return "umap";
469 #endif
470 #ifdef MOUNT_KERNFS
471
472 case MOUNT_KERNFS:
473 return "kernfs";
474 #endif
475 #ifdef MOUNT_PROCFS
476
477 case MOUNT_PROCFS:
478 return "procfs";
479 #endif
480 #ifdef MOUNT_AFS
481
482 case MOUNT_AFS:
483 return "afs";
484 #endif
485 #ifdef MOUNT_CD9660
486
487 case MOUNT_CD9660:
488 return "cd9660";
489 #endif
490 #ifdef MOUNT_UNION
491
492 case MOUNT_UNION:
493 return "union";
494 #endif
495 #ifdef MOUNT_DEVFS
496
497 case MOUNT_DEVFS:
498 return "devfs";
499 #endif
500 #ifdef MOUNT_EXT2FS
501
502 case MOUNT_EXT2FS:
503 return "ext2fs";
504 #endif
505 default:
506 return "?";
507 }
508 }
509 #endif
510
511
512
513 static char *
514 fsp_to_string (const struct statfs *fsp)
515 {
516 #ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME
517 return (char *) (fsp->f_fstypename);
518 #else
519 return fstype_to_string (fsp->f_type);
520 #endif
521 }
522 #endif
523
524
525
526 #ifdef MOUNTED_VMOUNT
527 static char *
528 fstype_to_string (int t)
529 {
530 struct vfs_ent *e;
531
532 e = getvfsbytype (t);
533 if (!e || !e->vfsent_name)
534 return "none";
535 else
536 return e->vfsent_name;
537 }
538 #endif
539
540
541
542 #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
543
544
545
546
547
548
549 static dev_t
550 dev_from_mount_options (char const *mount_options)
551 {
552
553
554
555 #ifndef __linux__
556 static char const dev_pattern[] = ",dev=";
557 char const *devopt = strstr (mount_options, dev_pattern);
558
559 if (devopt)
560 {
561 char const *optval = devopt + sizeof (dev_pattern) - 1;
562 char *optvalend;
563 unsigned long int dev;
564 errno = 0;
565 dev = strtoul (optval, &optvalend, 16);
566 if (optval != optvalend
567 && (*optvalend == '\0' || *optvalend == ',')
568 && !(dev == ULONG_MAX && errno == ERANGE) && dev == (dev_t) dev)
569 return dev;
570 }
571 #endif
572
573 (void) mount_options;
574 return -1;
575 }
576
577 #endif
578
579
580
581 #if defined MOUNTED_GETMNTENT1 && (defined __linux__ || defined __ANDROID__)
582
583
584
585 static void
586 unescape_tab (char *str)
587 {
588 size_t i, j = 0;
589 size_t len;
590
591 len = strlen (str) + 1;
592
593 for (i = 0; i < len; i++)
594 {
595 if (str[i] == '\\' && (i + 4 < len)
596 && str[i + 1] >= '0' && str[i + 1] <= '3'
597 && str[i + 2] >= '0' && str[i + 2] <= '7' && str[i + 3] >= '0' && str[i + 3] <= '7')
598 {
599 str[j++] = (str[i + 1] - '0') * 64 + (str[i + 2] - '0') * 8 + (str[i + 3] - '0');
600 i += 3;
601 }
602 else
603 str[j++] = str[i];
604 }
605 }
606 #endif
607
608
609
610
611
612
613 static GSList *
614 read_file_system_list (void)
615 {
616 GSList *mount_list = NULL;
617 struct mount_entry *me;
618
619 #ifdef MOUNTED_GETMNTENT1
620
621 {
622 FILE *fp;
623
624 #if defined __linux__ || defined __ANDROID__
625
626
627
628
629 char const *mountinfo = "/proc/self/mountinfo";
630
631 fp = fopen (mountinfo, "r");
632 if (fp != NULL)
633 {
634 char *line = NULL;
635 size_t buf_size = 0;
636
637 while (getline (&line, &buf_size, fp) != -1)
638 {
639 unsigned int devmaj, devmin;
640 int target_s, target_e, type_s, type_e;
641 int source_s, source_e, mntroot_s, mntroot_e;
642 char test;
643 char *dash;
644 int rc;
645
646 rc = sscanf (line, "%*u "
647 "%*u "
648 "%u:%u "
649 "%n%*s%n "
650 "%n%*s%n"
651 "%c",
652 &devmaj, &devmin, &mntroot_s, &mntroot_e, &target_s, &target_e, &test);
653
654 if (rc != 3 && rc != 7)
655 continue;
656
657
658 dash = strstr (line + target_e, " - ");
659 if (dash == NULL)
660 continue;
661
662 rc = sscanf (dash, " - "
663 "%n%*s%n "
664 "%n%*s%n "
665 "%c",
666 &type_s, &type_e, &source_s, &source_e, &test);
667 if (rc != 1 && rc != 5)
668 continue;
669
670
671 line[mntroot_e] = '\0';
672 line[target_e] = '\0';
673 dash[type_e] = '\0';
674 dash[source_e] = '\0';
675 unescape_tab (dash + source_s);
676 unescape_tab (line + target_s);
677 unescape_tab (line + mntroot_s);
678
679 me = g_malloc (sizeof *me);
680
681 me->me_devname = g_strdup (dash + source_s);
682 me->me_mountdir = g_strdup (line + target_s);
683 me->me_mntroot = g_strdup (line + mntroot_s);
684 me->me_type = g_strdup (dash + type_s);
685 me->me_type_malloced = 1;
686 me->me_dev = makedev (devmaj, devmin);
687
688
689
690
691 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, FALSE);
692 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
693
694 mount_list = g_slist_prepend (mount_list, me);
695 }
696
697 free (line);
698
699 if (ferror (fp) != 0)
700 {
701 int saved_errno = errno;
702
703 fclose (fp);
704 errno = saved_errno;
705 goto free_then_fail;
706 }
707
708 if (fclose (fp) == EOF)
709 goto free_then_fail;
710 }
711 else
712 #endif
713 {
714 struct mntent *mnt;
715 const char *table = MOUNTED;
716
717 fp = setmntent (table, "r");
718 if (fp == NULL)
719 return NULL;
720
721 while ((mnt = getmntent (fp)) != NULL)
722 {
723 gboolean bind;
724
725 bind = hasmntopt (mnt, "bind") != NULL;
726
727 me = g_malloc (sizeof (*me));
728 me->me_devname = g_strdup (mnt->mnt_fsname);
729 me->me_mountdir = g_strdup (mnt->mnt_dir);
730 me->me_mntroot = NULL;
731 me->me_type = g_strdup (mnt->mnt_type);
732 me->me_type_malloced = 1;
733 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, bind);
734 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
735 me->me_dev = dev_from_mount_options (mnt->mnt_opts);
736
737 mount_list = g_slist_prepend (mount_list, me);
738 }
739
740 if (endmntent (fp) == 0)
741 goto free_then_fail;
742 }
743 }
744 #endif
745
746 #ifdef MOUNTED_GETMNTINFO
747 {
748 struct statfs *fsp;
749 int entries;
750
751 entries = getmntinfo (&fsp, MNT_NOWAIT);
752 if (entries < 0)
753 return NULL;
754 for (; entries-- > 0; fsp++)
755 {
756 char *fs_type = fsp_to_string (fsp);
757
758 me = g_malloc (sizeof (*me));
759 me->me_devname = g_strdup (fsp->f_mntfromname);
760 me->me_mountdir = g_strdup (fsp->f_mntonname);
761 me->me_mntroot = NULL;
762 me->me_type = fs_type;
763 me->me_type_malloced = 0;
764 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
765 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
766 me->me_dev = (dev_t) (-1);
767
768 mount_list = g_slist_prepend (mount_list, me);
769 }
770 }
771 #endif
772
773 #ifdef MOUNTED_GETMNTINFO2
774 {
775 struct statvfs *fsp;
776 int entries;
777
778 entries = getmntinfo (&fsp, MNT_NOWAIT);
779 if (entries < 0)
780 return NULL;
781 for (; entries-- > 0; fsp++)
782 {
783 me = g_malloc (sizeof (*me));
784 me->me_devname = g_strdup (fsp->f_mntfromname);
785 me->me_mountdir = g_strdup (fsp->f_mntonname);
786 me->me_mntroot = NULL;
787 me->me_type = g_strdup (fsp->f_fstypename);
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 mount_list = g_slist_prepend (mount_list, me);
794 }
795 }
796 #endif
797
798 #if defined MOUNTED_FS_STAT_DEV
799 {
800
801
802
803
804
805
806
807
808
809
810 DIR *dirp;
811 struct rootdir_entry
812 {
813 char *name;
814 dev_t dev;
815 ino_t ino;
816 struct rootdir_entry *next;
817 };
818 struct rootdir_entry *rootdir_list;
819 struct rootdir_entry **rootdir_tail;
820 int32 pos;
821 dev_t dev;
822 fs_info fi;
823
824
825 rootdir_list = NULL;
826 rootdir_tail = &rootdir_list;
827 dirp = opendir (PATH_SEP_STR);
828 if (dirp)
829 {
830 struct dirent *d;
831
832 while ((d = readdir (dirp)) != NULL)
833 {
834 char *name;
835 struct stat statbuf;
836
837 if (DIR_IS_DOT (d->d_name))
838 continue;
839
840 if (DIR_IS_DOTDOT (d->d_name))
841 name = g_strdup (PATH_SEP_STR);
842 else
843 name = g_strconcat (PATH_SEP_STR, d->d_name, (char *) NULL);
844
845 if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
846 {
847 struct rootdir_entry *re = g_malloc (sizeof (*re));
848 re->name = name;
849 re->dev = statbuf.st_dev;
850 re->ino = statbuf.st_ino;
851
852
853 *rootdir_tail = re;
854 rootdir_tail = &re->next;
855 }
856 else
857 g_free (name);
858 }
859 closedir (dirp);
860 }
861 *rootdir_tail = NULL;
862
863 for (pos = 0; (dev = next_dev (&pos)) >= 0;)
864 if (fs_stat_dev (dev, &fi) >= 0)
865 {
866
867 struct rootdir_entry *re;
868
869 for (re = rootdir_list; re; re = re->next)
870 if (re->dev == fi.dev && re->ino == fi.root)
871 break;
872
873 me = g_malloc (sizeof (*me));
874 me->me_devname =
875 g_strdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
876 me->me_mountdir = g_strdup (re != NULL ? re->name : fi.fsh_name);
877 me->me_mntroot = NULL;
878 me->me_type = g_strdup (fi.fsh_name);
879 me->me_type_malloced = 1;
880 me->me_dev = fi.dev;
881 me->me_dummy = 0;
882 me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
883
884 mount_list = g_slist_prepend (mount_list, me);
885 }
886
887 while (rootdir_list != NULL)
888 {
889 struct rootdir_entry *re = rootdir_list;
890
891 rootdir_list = re->next;
892 g_free (re->name);
893 g_free (re);
894 }
895 }
896 #endif
897
898 #ifdef MOUNTED_GETFSSTAT
899 {
900 int numsys, counter;
901 size_t bufsize;
902 struct statfs *stats;
903
904 numsys = getfsstat (NULL, 0L, MNT_NOWAIT);
905 if (numsys < 0)
906 return NULL;
907 if (SIZE_MAX / sizeof (*stats) <= numsys)
908 {
909 fprintf (stderr, "%s\n", _("Memory exhausted!"));
910 exit (EXIT_FAILURE);
911 }
912
913 bufsize = (1 + numsys) * sizeof (*stats);
914 stats = g_malloc (bufsize);
915 numsys = getfsstat (stats, bufsize, MNT_NOWAIT);
916
917 if (numsys < 0)
918 {
919 g_free (stats);
920 return NULL;
921 }
922
923 for (counter = 0; counter < numsys; counter++)
924 {
925 me = g_malloc (sizeof (*me));
926 me->me_devname = g_strdup (stats[counter].f_mntfromname);
927 me->me_mountdir = g_strdup (stats[counter].f_mntonname);
928 me->me_mntroot = NULL;
929 me->me_type = g_strdup (FS_TYPE (stats[counter]));
930 me->me_type_malloced = 1;
931 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
932 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
933 me->me_dev = (dev_t) (-1);
934
935 mount_list = g_slist_prepend (mount_list, me);
936 }
937
938 g_free (stats);
939 }
940 #endif
941
942 #if defined MOUNTED_FREAD_FSTYP
943 {
944 struct mnttab mnt;
945 char *table = "/etc/mnttab";
946 FILE *fp;
947
948 fp = fopen (table, "r");
949 if (fp == NULL)
950 return NULL;
951
952 while (fread (&mnt, sizeof (mnt), 1, fp) > 0)
953 {
954 me = g_malloc (sizeof (*me));
955 me->me_devname = g_strdup (mnt.mt_dev);
956 me->me_mountdir = g_strdup (mnt.mt_filsys);
957 me->me_mntroot = NULL;
958 me->me_dev = (dev_t) (-1);
959 me->me_type = "";
960 me->me_type_malloced = 0;
961 {
962 struct statfs fsd;
963 char typebuf[FSTYPSZ];
964
965 if (statfs (me->me_mountdir, &fsd, sizeof (fsd), 0) != -1
966 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
967 {
968 me->me_type = g_strdup (typebuf);
969 me->me_type_malloced = 1;
970 }
971 }
972 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
973 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
974
975 mount_list = g_slist_prepend (mount_list, me);
976 }
977
978 if (ferror (fp))
979 {
980
981 int saved_errno = errno;
982
983 fclose (fp);
984 errno = saved_errno;
985 goto free_then_fail;
986 }
987
988 if (fclose (fp) == EOF)
989 goto free_then_fail;
990 }
991 #endif
992
993 #ifdef MOUNTED_GETEXTMNTENT
994 {
995 struct extmnttab mnt;
996 const char *table = MNTTAB;
997 FILE *fp;
998 int ret;
999
1000
1001
1002 errno = 0;
1003 fp = fopen (table, "r");
1004 if (fp == NULL)
1005 ret = errno;
1006 else
1007 {
1008 while ((ret = getextmntent (fp, &mnt, 1)) == 0)
1009 {
1010 me = g_malloc (sizeof *me);
1011 me->me_devname = g_strdup (mnt.mnt_special);
1012 me->me_mountdir = g_strdup (mnt.mnt_mountp);
1013 me->me_mntroot = NULL;
1014 me->me_type = g_strdup (mnt.mnt_fstype);
1015 me->me_type_malloced = 1;
1016 me->me_dummy = MNT_IGNORE (&mnt) != 0;
1017 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
1018 me->me_dev = makedev (mnt.mnt_major, mnt.mnt_minor);
1019
1020 mount_list = g_slist_prepend (mount_list, me);
1021 }
1022
1023 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
1024
1025 }
1026
1027 if (ret >= 0)
1028 {
1029 errno = ret;
1030 goto free_then_fail;
1031 }
1032 }
1033 #endif
1034
1035 #ifdef MOUNTED_GETMNTENT2
1036 {
1037 struct mnttab mnt;
1038 const char *table = MNTTAB;
1039 FILE *fp;
1040 int ret;
1041 int lockfd = -1;
1042
1043 #if defined F_RDLCK && defined F_SETLKW
1044
1045
1046
1047
1048 #ifndef MNTTAB_LOCK
1049 #define MNTTAB_LOCK "/etc/.mnttab.lock"
1050 #endif
1051 lockfd = open (MNTTAB_LOCK, O_RDONLY);
1052 if (lockfd >= 0)
1053 {
1054 struct flock flock;
1055
1056 flock.l_type = F_RDLCK;
1057 flock.l_whence = SEEK_SET;
1058 flock.l_start = 0;
1059 flock.l_len = 0;
1060 while (fcntl (lockfd, F_SETLKW, &flock) == -1)
1061 if (errno != EINTR)
1062 {
1063 int saved_errno = errno;
1064 close (lockfd);
1065 errno = saved_errno;
1066 return NULL;
1067 }
1068 }
1069 else if (errno != ENOENT)
1070 return NULL;
1071 #endif
1072
1073 errno = 0;
1074 fp = fopen (table, "r");
1075 if (fp == NULL)
1076 ret = errno;
1077 else
1078 {
1079 while ((ret = getmntent (fp, &mnt)) == 0)
1080 {
1081 me = g_malloc (sizeof (*me));
1082 me->me_devname = g_strdup (mnt.mnt_special);
1083 me->me_mountdir = g_strdup (mnt.mnt_mountp);
1084 me->me_mntroot = NULL;
1085 me->me_type = g_strdup (mnt.mnt_fstype);
1086 me->me_type_malloced = 1;
1087 me->me_dummy = MNT_IGNORE (&mnt) != 0;
1088 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
1089 me->me_dev = dev_from_mount_options (mnt.mnt_mntopts);
1090
1091 mount_list = g_slist_prepend (mount_list, me);
1092 }
1093
1094 ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
1095
1096 }
1097
1098 if (lockfd >= 0 && close (lockfd) != 0)
1099 ret = errno;
1100
1101 if (ret >= 0)
1102 {
1103 errno = ret;
1104 goto free_then_fail;
1105 }
1106 }
1107 #endif
1108
1109 #ifdef MOUNTED_VMOUNT
1110 {
1111 int bufsize;
1112 void *entries;
1113 char *thisent;
1114 struct vmount *vmp;
1115 int n_entries;
1116 int i;
1117
1118
1119 entries = &bufsize;
1120 if (mntctl (MCTL_QUERY, sizeof (bufsize), entries) != 0)
1121 return NULL;
1122 entries = g_malloc (bufsize);
1123
1124
1125 n_entries = mntctl (MCTL_QUERY, bufsize, entries);
1126 if (n_entries < 0)
1127 {
1128 int saved_errno = errno;
1129
1130 g_free (entries);
1131 errno = saved_errno;
1132 return NULL;
1133 }
1134
1135 for (i = 0, thisent = entries; i < n_entries; i++, thisent += vmp->vmt_length)
1136 {
1137 char *options, *ignore;
1138
1139 vmp = (struct vmount *) thisent;
1140 me = g_malloc (sizeof (*me));
1141 if (vmp->vmt_flags & MNT_REMOTE)
1142 {
1143 char *host, *dir;
1144
1145 me->me_remote = 1;
1146
1147 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
1148 dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
1149 me->me_devname = g_strconcat (host, ":", dir, (char *) NULL);
1150 }
1151 else
1152 {
1153 me->me_remote = 0;
1154 me->me_devname = g_strdup (thisent + vmp->vmt_data[VMT_OBJECT].vmt_off);
1155 }
1156 me->me_mountdir = g_strdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
1157 me->me_mntroot = NULL;
1158 me->me_type = g_strdup (fstype_to_string (vmp->vmt_gfstype));
1159 me->me_type_malloced = 1;
1160 options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
1161 ignore = strstr (options, "ignore");
1162 me->me_dummy = (ignore
1163 && (ignore == options || ignore[-1] == ',')
1164 && (ignore[sizeof ("ignore") - 1] == ','
1165 || ignore[sizeof ("ignore") - 1] == '\0'));
1166 me->me_dev = (dev_t) (-1);
1167
1168 mount_list = g_slist_prepend (mount_list, me);
1169 }
1170 g_free (entries);
1171 }
1172 #endif
1173
1174 #ifdef MOUNTED_INTERIX_STATVFS
1175 {
1176 DIR *dirp = opendir ("/dev/fs");
1177 char node[9 + NAME_MAX];
1178
1179 if (!dirp)
1180 goto free_then_fail;
1181
1182 while (1)
1183 {
1184 struct statvfs dev;
1185 struct dirent entry;
1186 struct dirent *result;
1187
1188 if (readdir_r (dirp, &entry, &result) || result == NULL)
1189 break;
1190
1191 strcpy (node, "/dev/fs/");
1192 strcat (node, entry.d_name);
1193
1194 if (statvfs (node, &dev) == 0)
1195 {
1196 me = g_malloc (sizeof *me);
1197 me->me_devname = g_strdup (dev.f_mntfromname);
1198 me->me_mountdir = g_strdup (dev.f_mntonname);
1199 me->me_mntroot = NULL;
1200 me->me_type = g_strdup (dev.f_fstypename);
1201 me->me_type_malloced = 1;
1202 me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
1203 me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
1204 me->me_dev = (dev_t) (-1);
1205
1206 mount_list = g_slist_prepend (mount_list, me);
1207 }
1208 }
1209 closedir (dirp);
1210 }
1211 #endif
1212
1213 return g_slist_reverse (mount_list);
1214
1215 free_then_fail:
1216 {
1217 int saved_errno = errno;
1218
1219 g_slist_free_full (mount_list, (GDestroyNotify) free_mount_entry);
1220
1221 errno = saved_errno;
1222 return NULL;
1223 }
1224 }
1225 #endif
1226
1227
1228
1229 #ifdef HAVE_INFOMOUNT_QNX
1230
1231
1232
1233
1234
1235
1236
1237 static GSList *
1238 read_file_system_list (void)
1239 {
1240 struct _disk_entry de;
1241 struct statfs fs;
1242 int i, fd;
1243 char *tp, dev[_POSIX_NAME_MAX], dir[_POSIX_PATH_MAX];
1244 struct mount_entry *me = NULL;
1245 static GSList *list = NULL;
1246
1247 if (list != NULL)
1248 {
1249 me = (struct mount_entry *) list->data;
1250
1251 g_free (me->me_devname);
1252 g_free (me->me_mountdir);
1253 g_free (me->me_mntroot);
1254 g_free (me->me_type);
1255 }
1256 else
1257 {
1258 me = (struct mount_entry *) g_malloc (sizeof (struct mount_entry));
1259 list = g_slist_prepend (list, me);
1260 }
1261
1262 if (!getcwd (dir, _POSIX_PATH_MAX))
1263 return (NULL);
1264
1265 fd = open (dir, O_RDONLY);
1266 if (fd == -1)
1267 return (NULL);
1268
1269 i = disk_get_entry (fd, &de);
1270
1271 close (fd);
1272
1273 if (i == -1)
1274 return (NULL);
1275
1276 switch (de.disk_type)
1277 {
1278 case _UNMOUNTED:
1279 tp = "unmounted";
1280 break;
1281 case _FLOPPY:
1282 tp = "Floppy";
1283 break;
1284 case _HARD:
1285 tp = "Hard";
1286 break;
1287 case _RAMDISK:
1288 tp = "Ram";
1289 break;
1290 case _REMOVABLE:
1291 tp = "Removable";
1292 break;
1293 case _TAPE:
1294 tp = "Tape";
1295 break;
1296 case _CDROM:
1297 tp = "CDROM";
1298 break;
1299 default:
1300 tp = "unknown";
1301 }
1302
1303 if (fsys_get_mount_dev (dir, &dev) == -1)
1304 return (NULL);
1305
1306 if (fsys_get_mount_pt (dev, &dir) == -1)
1307 return (NULL);
1308
1309 me->me_devname = g_strdup (dev);
1310 me->me_mountdir = g_strdup (dir);
1311 me->me_mntroot = NULL;
1312 me->me_type = g_strdup (tp);
1313 me->me_dev = de.disk_type;
1314
1315 #ifdef DEBUG
1316 fprintf (stderr,
1317 "disk_get_entry():\n\tdisk_type=%d (%s)\n\tdriver_name='%-*.*s'\n\tdisk_drv=%d\n",
1318 de.disk_type, tp, _DRIVER_NAME_LEN, _DRIVER_NAME_LEN, de.driver_name, de.disk_drv);
1319 fprintf (stderr, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev);
1320 fprintf (stderr, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir);
1321 #endif
1322
1323 return (list);
1324 }
1325 #endif
1326
1327
1328
1329 #ifdef HAVE_INFOMOUNT
1330
1331
1332
1333
1334
1335
1336
1337 static int
1338 get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
1339 {
1340 #ifdef STAT_STATVFS
1341
1342 if (statvfs_works ())
1343 {
1344 struct statvfs vfsd;
1345
1346 if (statvfs (file, &vfsd) < 0)
1347 return -1;
1348
1349
1350 fsp->fsu_blocksize = (vfsd.f_frsize
1351 ? PROPAGATE_ALL_ONES (vfsd.f_frsize)
1352 : PROPAGATE_ALL_ONES (vfsd.f_bsize));
1353
1354 fsp->fsu_blocks = PROPAGATE_ALL_ONES (vfsd.f_blocks);
1355 fsp->fsu_bfree = PROPAGATE_ALL_ONES (vfsd.f_bfree);
1356 fsp->fsu_bavail = PROPAGATE_TOP_BIT (vfsd.f_bavail);
1357 fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (vfsd.f_bavail) != 0;
1358 fsp->fsu_files = PROPAGATE_ALL_ONES (vfsd.f_files);
1359 fsp->fsu_ffree = PROPAGATE_ALL_ONES (vfsd.f_ffree);
1360 }
1361 else
1362 #endif
1363
1364 {
1365 #if defined STAT_STATVFS64
1366
1367 struct statvfs64 fsd;
1368
1369 if (statvfs64 (file, &fsd) < 0)
1370 return -1;
1371
1372
1373
1374 fsp->fsu_blocksize = fsd.f_frsize
1375 ? PROPAGATE_ALL_ONES (fsd.f_frsize)
1376 : PROPAGATE_ALL_ONES (fsd.f_bsize);
1377
1378
1379 #elif defined STAT_STATFS3_OSF1
1380
1381 struct statfs fsd;
1382
1383 if (statfs (file, &fsd, sizeof (struct statfs)) != 0)
1384 return -1;
1385
1386 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
1387
1388 #elif defined STAT_STATFS2_FRSIZE
1389
1390 struct statfs fsd;
1391
1392 if (statfs (file, &fsd) < 0)
1393 return -1;
1394
1395 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_frsize);
1396
1397 #elif defined STAT_STATFS2_BSIZE
1398
1399
1400
1401 struct statfs fsd;
1402
1403 if (statfs (file, &fsd) < 0)
1404 return -1;
1405
1406 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
1407
1408 #ifdef STATFS_TRUNCATES_BLOCK_COUNTS
1409
1410
1411
1412
1413
1414
1415 if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0)
1416 {
1417 fsd.f_blocks = fsd.f_spare[0];
1418 fsd.f_bfree = fsd.f_spare[1];
1419 fsd.f_bavail = fsd.f_spare[2];
1420 }
1421 #endif
1422
1423 #elif defined STAT_STATFS2_FSIZE
1424
1425 struct statfs fsd;
1426
1427 if (statfs (file, &fsd) < 0)
1428 return -1;
1429
1430 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
1431
1432 #elif defined STAT_STATFS4
1433
1434 struct statfs fsd;
1435
1436 if (statfs (file, &fsd, sizeof (fsd), 0) < 0)
1437 return -1;
1438
1439
1440
1441
1442 fsp->fsu_blocksize = 512;
1443 #endif
1444
1445 #if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1 \
1446 || defined STAT_STATFS2_FRSIZE || defined STAT_STATFS2_BSIZE \
1447 || defined STAT_STATFS2_FSIZE || defined STAT_STATFS4)
1448
1449 fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);
1450 fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree);
1451 fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail);
1452 fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0;
1453 fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files);
1454 fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree);
1455
1456 #endif
1457 }
1458
1459 (void) disk;
1460
1461 return 0;
1462 }
1463 #endif
1464
1465
1466
1467
1468
1469 void
1470 free_my_statfs (void)
1471 {
1472 #ifdef HAVE_INFOMOUNT_LIST
1473 g_clear_slist (&mc_mount_list, (GDestroyNotify) free_mount_entry);
1474 #endif
1475 }
1476
1477
1478
1479 void
1480 init_my_statfs (void)
1481 {
1482 #ifdef HAVE_INFOMOUNT_LIST
1483 free_my_statfs ();
1484 mc_mount_list = read_file_system_list ();
1485 #endif
1486 }
1487
1488
1489
1490 void
1491 my_statfs (struct my_statfs *myfs_stats, const char *path)
1492 {
1493 #ifdef HAVE_INFOMOUNT_LIST
1494 size_t len = 0;
1495 struct mount_entry *entry = NULL;
1496 GSList *temp;
1497 struct fs_usage fs_use;
1498
1499 for (temp = mc_mount_list; temp != NULL; temp = g_slist_next (temp))
1500 {
1501 struct mount_entry *me;
1502 size_t i;
1503
1504 me = (struct mount_entry *) temp->data;
1505 i = strlen (me->me_mountdir);
1506 if (i > len && (strncmp (path, me->me_mountdir, i) == 0) &&
1507 (entry == NULL || IS_PATH_SEP (path[i]) || path[i] == '\0'))
1508 {
1509 len = i;
1510 entry = me;
1511 }
1512 }
1513
1514 if (entry != NULL)
1515 {
1516 memset (&fs_use, 0, sizeof (fs_use));
1517 get_fs_usage (entry->me_mountdir, NULL, &fs_use);
1518
1519 myfs_stats->type = entry->me_dev;
1520 myfs_stats->typename = entry->me_type;
1521 myfs_stats->mpoint = entry->me_mountdir;
1522 myfs_stats->mroot = entry->me_mntroot;
1523 myfs_stats->device = entry->me_devname;
1524 myfs_stats->avail =
1525 ((uintmax_t) (getuid ()? fs_use.fsu_bavail : fs_use.fsu_bfree) *
1526 fs_use.fsu_blocksize) >> 10;
1527 myfs_stats->total = ((uintmax_t) fs_use.fsu_blocks * fs_use.fsu_blocksize) >> 10;
1528 myfs_stats->nfree = (uintmax_t) fs_use.fsu_ffree;
1529 myfs_stats->nodes = (uintmax_t) fs_use.fsu_files;
1530 }
1531 else
1532 #endif
1533
1534 #ifdef HAVE_INFOMOUNT_QNX
1535
1536
1537
1538
1539
1540 struct mount_entry *entry;
1541 struct fs_usage fs_use;
1542
1543 entry = read_file_system_list ();
1544 if (entry != NULL)
1545 {
1546 get_fs_usage (entry->me_mountdir, NULL, &fs_use);
1547
1548 myfs_stats->type = entry->me_dev;
1549 myfs_stats->typename = entry->me_type;
1550 myfs_stats->mpoint = entry->me_mountdir;
1551 myfs_stats->mroot = entry->me_mntroot;
1552 myfs_stats->device = entry->me_devname;
1553
1554 myfs_stats->avail = ((uintmax_t) fs_use.fsu_bfree * fs_use.fsu_blocksize) >> 10;
1555 myfs_stats->total = ((uintmax_t) fs_use.fsu_blocks * fs_use.fsu_blocksize) >> 10;
1556 myfs_stats->nfree = (uintmax_t) fs_use.fsu_ffree;
1557 myfs_stats->nodes = (uintmax_t) fs_use.fsu_files;
1558 }
1559 else
1560 #endif
1561 {
1562 myfs_stats->type = 0;
1563 myfs_stats->mpoint = "unknown";
1564 myfs_stats->device = "unknown";
1565 myfs_stats->avail = 0;
1566 myfs_stats->total = 0;
1567 myfs_stats->nfree = 0;
1568 myfs_stats->nodes = 0;
1569 }
1570 }
1571
1572