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