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