1 /* mountlist.c -- return a list of mounted filesystems
2 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 * \brief Source: list of mounted filesystems
27 #include <sys/types.h>
29 /* This header needs to be included before sys/mount.h on *BSD */
30 #ifdef HAVE_SYS_PARAM_H
31 #include <sys/param.h>
34 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
35 #include <sys/mount.h>
36 #include <sys/fs_types.h>
37 #endif /* MOUNTED_GETFSSTAT */
39 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
42 #if defined(MNT_MNTTAB) /* HP-UX. */
43 #define MOUNTED MNT_MNTTAB
45 #if defined(MNTTABNAME) /* Dynix. */
46 #define MOUNTED MNTTABNAME
51 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
52 #include <sys/mount.h>
55 #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
56 #include <sys/statvfs.h>
59 #ifdef MOUNTED_GETMNT /* Ultrix. */
60 #include <sys/mount.h>
61 #include <sys/fs_types.h>
64 #ifdef MOUNTED_FREAD /* SVR2. */
68 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
70 #include <sys/fstyp.h>
71 #include <sys/statfs.h>
74 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
75 #include <sys/mnttab.h>
78 #ifdef MOUNTED_VMOUNT /* AIX. */
83 #ifdef HAVE_SYS_STATFS_H
84 #include <sys/statfs.h>
87 #ifdef HAVE_INFOMOUNT_QNX
92 #ifdef HAVE_SYS_MOUNT_H
93 #include <sys/mount.h>
100 #ifdef HAVE_SYS_FILSYS_H
101 #include <sys/filsys.h> /* SVR2. */
104 #ifdef HAVE_DUSTAT_H /* AIX PS/2. */
105 #include <sys/dustat.h>
108 #ifdef HAVE_SYS_STATVFS_H /* SVR4. */
109 #include <sys/statvfs.h>
112 #include "lib/global.h"
113 #include "mountlist.h"
116 /* So special that it's not worth putting this in autoconf. */
117 #undef MOUNTED_FREAD_FSTYP
118 #define MOUNTED_GETMNTTBL
121 #if defined (__QNX__) && !defined(__QNXNTO__) && !defined (HAVE_INFOMOUNT_LIST)
122 # define HAVE_INFOMOUNT_QNX
125 #if defined(HAVE_INFOMOUNT_LIST) || defined(HAVE_INFOMOUNT_QNX)
126 # define HAVE_INFOMOUNT
129 /* A mount table entry. */
132 char *me_devname
; /* Device node pathname, including "/dev/". */
133 char *me_mountdir
; /* Mount point directory pathname. */
134 char *me_type
; /* "nfs", "4.2", etc. */
135 dev_t me_dev
; /* Device number of me_mountdir. */
136 struct mount_entry
*me_next
;
141 fsblkcnt_t fsu_blocks
; /* Total blocks. */
142 fsblkcnt_t fsu_bfree
; /* Free blocks available to superuser. */
143 fsblkcnt_t fsu_bavail
; /* Free blocks available to non-superuser. */
144 fsfilcnt_t fsu_files
; /* Total file nodes. */
145 fsfilcnt_t fsu_ffree
; /* Free file nodes. */
148 static int get_fs_usage (char *path
, struct fs_usage
*fsp
);
150 #ifdef HAVE_INFOMOUNT_LIST
152 static struct mount_entry
*mount_list
= NULL
;
154 static void free_mount_entry (struct mount_entry
*me
)
159 free (me
->me_devname
);
161 free (me
->me_mountdir
);
167 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
168 /* Return the value of the hexadecimal number represented by CP.
169 No prefix (like '0x') or suffix (like 'h') is expected to be
172 static int xatoi (const char *cp
)
178 if (*cp
>= 'a' && *cp
<= 'f')
179 val
= val
* 16 + *cp
- 'a' + 10;
180 else if (*cp
>= 'A' && *cp
<= 'F')
181 val
= val
* 16 + *cp
- 'A' + 10;
182 else if (*cp
>= '0' && *cp
<= '9')
183 val
= val
* 16 + *cp
- '0';
190 #endif /* MOUNTED_GETMNTENT1 */
192 #ifdef MOUNTED_GETMNTINFO
194 #ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME
195 static char *fstype_to_string (short t
)
286 #endif /* ! HAVE_STRUCT_STATFS_F_FSTYPENAME */
288 #endif /* MOUNTED_GETMNTINFO */
290 #ifdef MOUNTED_VMOUNT /* AIX. */
292 fstype_to_string (int t
)
296 e
= getvfsbytype (t
);
297 if (!e
|| !e
->vfsent_name
)
300 return e
->vfsent_name
;
302 #endif /* MOUNTED_VMOUNT */
304 /* Return a list of the currently mounted filesystems, or NULL on error.
305 Add each entry to the tail of the list so that they stay in order.
306 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
307 the returned list are valid. Otherwise, they might not be.
308 If ALL_FS is zero, do not return entries for filesystems that
309 are automounter (dummy) entries. */
311 static struct mount_entry
*
312 read_filesystem_list (int need_fs_type
, int all_fs
)
314 struct mount_entry
*mlist
;
315 struct mount_entry
*me
;
316 struct mount_entry
*mtail
;
321 /* Start the list off with a dummy entry. */
322 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
326 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
333 fp
= setmntent (MOUNTED
, "r");
337 while ((mnt
= getmntent (fp
))) {
338 if (!all_fs
&& (!strcmp (mnt
->mnt_type
, "ignore")
339 || !strcmp (mnt
->mnt_type
, "auto")))
342 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
343 me
->me_devname
= strdup (mnt
->mnt_fsname
);
344 me
->me_mountdir
= strdup (mnt
->mnt_dir
);
345 me
->me_type
= strdup (mnt
->mnt_type
);
346 devopt
= strstr (mnt
->mnt_opts
, "dev=");
348 if (devopt
[4] == '0' && (devopt
[5] == 'x' || devopt
[5] == 'X'))
349 me
->me_dev
= xatoi (devopt
+ 6);
351 me
->me_dev
= xatoi (devopt
+ 4);
353 me
->me_dev
= -1; /* Magic; means not known yet. */
356 /* Add to the linked list. */
361 if (endmntent (fp
) == 0)
365 #endif /* MOUNTED_GETMNTENT1 */
367 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
372 entries
= getmntinfo (&fsp
, MNT_NOWAIT
);
375 while (entries
-- > 0) {
376 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
377 me
->me_devname
= strdup (fsp
->f_mntfromname
);
378 me
->me_mountdir
= strdup (fsp
->f_mntonname
);
379 #ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME
380 me
->me_type
= strdup (fsp
->f_fstypename
);
382 me
->me_type
= fstype_to_string (fsp
->f_type
);
384 me
->me_dev
= -1; /* Magic; means not known yet. */
387 /* Add to the linked list. */
393 #endif /* MOUNTED_GETMNTINFO */
395 #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
400 entries
= getmntinfo (&fsp
, MNT_NOWAIT
);
403 for (; entries
-- > 0; fsp
++) {
404 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
405 me
->me_devname
= strdup (fsp
->f_mntfromname
);
406 me
->me_mountdir
= strdup (fsp
->f_mntonname
);
407 me
->me_type
= strdup (fsp
->f_fstypename
);
408 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
410 /* Add to the linked list. */
415 #endif /* MOUNTED_GETMNTINFO2 */
417 #ifdef MOUNTED_GETMNT /* Ultrix. */
423 while ((val
= getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
,
425 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
426 me
->me_devname
= strdup (fsd
.fd_req
.devname
);
427 me
->me_mountdir
= strdup (fsd
.fd_req
.path
);
428 me
->me_type
= gt_names
[fsd
.fd_req
.fstype
];
429 me
->me_dev
= fsd
.fd_req
.dev
;
432 /* Add to the linked list. */
439 #endif /* MOUNTED_GETMNT */
441 #ifdef MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
443 int numsys
, counter
, bufsize
;
444 struct statfs
*stats
;
446 numsys
= getfsstat ((struct statfs
*) 0, 0L, MNT_WAIT
);
450 bufsize
= (1 + numsys
) * sizeof (struct statfs
);
451 stats
= (struct statfs
*) malloc (bufsize
);
452 numsys
= getfsstat (stats
, bufsize
, MNT_WAIT
);
458 for (counter
= 0; counter
< numsys
; counter
++) {
459 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
460 me
->me_devname
= strdup (stats
[counter
].f_mntfromname
);
461 me
->me_mountdir
= strdup (stats
[counter
].f_mntonname
);
462 me
->me_type
= mnt_names
[stats
[counter
].f_type
];
463 me
->me_dev
= -1; /* Magic; means not known yet. */
466 /* Add to the linked list. */
473 #endif /* MOUNTED_GETFSSTAT */
475 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
478 char *table
= "/etc/mnttab";
481 fp
= fopen (table
, "r");
485 while (fread (&mnt
, sizeof mnt
, 1, fp
) > 0) {
486 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
487 #ifdef GETFSTYP /* SVR3. */
488 me
->me_devname
= strdup (mnt
.mt_dev
);
490 me
->me_devname
= malloc (strlen (mnt
.mt_dev
) + 6);
491 strcpy (me
->me_devname
, "/dev/");
492 strcpy (me
->me_devname
+ 5, mnt
.mt_dev
);
494 me
->me_mountdir
= strdup (mnt
.mt_filsys
);
495 me
->me_dev
= -1; /* Magic; means not known yet. */
497 #ifdef GETFSTYP /* SVR3. */
500 char typebuf
[FSTYPSZ
];
502 if (statfs (me
->me_mountdir
, &fsd
, sizeof fsd
, 0) != -1
503 && sysfs (GETFSTYP
, fsd
.f_fstyp
, typebuf
) != -1)
504 me
->me_type
= strdup (typebuf
);
509 /* Add to the linked list. */
514 if (fclose (fp
) == EOF
)
517 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP */
519 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
521 struct mntent
**mnttbl
= getmnttbl (), **ent
;
522 for (ent
= mnttbl
; *ent
; ent
++) {
523 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
524 me
->me_devname
= strdup ((*ent
)->mt_resource
);
525 me
->me_mountdir
= strdup ((*ent
)->mt_directory
);
526 me
->me_type
= strdup ((*ent
)->mt_fstype
);
527 me
->me_dev
= -1; /* Magic; means not known yet. */
530 /* Add to the linked list. */
536 #endif /* MOUNTED_GETMNTTBL */
538 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
541 char *table
= MNTTAB
;
545 fp
= fopen (table
, "r");
549 while ((ret
= getmntent (fp
, &mnt
)) == 0) {
550 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
551 me
->me_devname
= strdup (mnt
.mnt_special
);
552 me
->me_mountdir
= strdup (mnt
.mnt_mountp
);
553 me
->me_type
= strdup (mnt
.mnt_fstype
);
554 me
->me_dev
= -1; /* Magic; means not known yet. */
556 /* Add to the linked list. */
563 if (fclose (fp
) == EOF
)
566 #endif /* MOUNTED_GETMNTENT2 */
568 #ifdef MOUNTED_VMOUNT /* AIX. */
571 char *entries
, *thisent
;
574 /* Ask how many bytes to allocate for the mounted filesystem info. */
575 mntctl (MCTL_QUERY
, sizeof bufsize
, (struct vmount
*) &bufsize
);
576 entries
= malloc (bufsize
);
578 /* Get the list of mounted filesystems. */
579 mntctl (MCTL_QUERY
, bufsize
, (struct vmount
*) entries
);
581 for (thisent
= entries
; thisent
< entries
+ bufsize
;
582 thisent
+= vmp
->vmt_length
) {
583 vmp
= (struct vmount
*) thisent
;
584 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
585 if (vmp
->vmt_flags
& MNT_REMOTE
) {
588 /* Prepend the remote pathname. */
589 host
= thisent
+ vmp
->vmt_data
[VMT_HOSTNAME
].vmt_off
;
590 path
= thisent
+ vmp
->vmt_data
[VMT_OBJECT
].vmt_off
;
591 me
->me_devname
= malloc (strlen (host
) + strlen (path
) + 2);
592 strcpy (me
->me_devname
, host
);
593 strcat (me
->me_devname
, ":");
594 strcat (me
->me_devname
, path
);
596 me
->me_devname
= strdup (thisent
+
597 vmp
->vmt_data
[VMT_OBJECT
].vmt_off
);
599 me
->me_mountdir
= strdup (thisent
+ vmp
->vmt_data
[VMT_STUB
].vmt_off
);
600 me
->me_type
= strdup (fstype_to_string (vmp
->vmt_gfstype
));
601 me
->me_dev
= -1; /* vmt_fsid might be the info we want. */
604 /* Add to the linked list. */
610 #endif /* MOUNTED_VMOUNT */
612 /* Free the dummy head. */
614 mlist
= mlist
->me_next
;
618 #endif /* HAVE_INFOMOUNT_LIST */
620 #ifdef HAVE_INFOMOUNT_QNX
622 ** QNX has no [gs]etmnt*(), [gs]etfs*(), or /etc/mnttab, but can do
623 ** this via the following code.
624 ** Note that, as this is based on CWD, it only fills one mount_entry
625 ** structure. See my_statfs() in utilunix.c for the "other side" of
629 static struct mount_entry
*
630 read_filesystem_list(int need_fs_type
, int all_fs
)
632 struct _disk_entry de
;
635 char *tp
, dev
[_POSIX_NAME_MAX
], dir
[_POSIX_PATH_MAX
];
637 static struct mount_entry
*me
= NULL
;
641 if (me
->me_devname
) free(me
->me_devname
);
642 if (me
->me_mountdir
) free(me
->me_mountdir
);
643 if (me
->me_type
) free(me
->me_type
);
646 me
= (struct mount_entry
*)malloc(sizeof(struct mount_entry
));
648 if (!getcwd(dir
, _POSIX_PATH_MAX
)) return (NULL
);
650 if ((fd
= open(dir
, O_RDONLY
)) == -1) return (NULL
);
652 i
= disk_get_entry(fd
, &de
);
656 if (i
== -1) return (NULL
);
658 switch (de
.disk_type
)
660 case _UNMOUNTED
: tp
= "unmounted"; break;
661 case _FLOPPY
: tp
= "Floppy"; break;
662 case _HARD
: tp
= "Hard"; break;
663 case _RAMDISK
: tp
= "Ram"; break;
664 case _REMOVABLE
: tp
= "Removable"; break;
665 case _TAPE
: tp
= "Tape"; break;
666 case _CDROM
: tp
= "CDROM"; break;
667 default: tp
= "unknown";
670 if (fsys_get_mount_dev(dir
, &dev
) == -1) return (NULL
);
672 if (fsys_get_mount_pt(dev
, &dir
) == -1) return (NULL
);
674 me
->me_devname
= strdup(dev
);
675 me
->me_mountdir
= strdup(dir
);
676 me
->me_type
= strdup(tp
);
677 me
->me_dev
= de
.disk_type
;
680 fprintf(stderr
, "disk_get_entry():\n\tdisk_type=%d (%s)\n\tdriver_name='%-*.*s'\n\tdisk_drv=%d\n",
681 de
.disk_type
, tp
, _DRIVER_NAME_LEN
, _DRIVER_NAME_LEN
, de
.driver_name
, de
.disk_drv
);
682 fprintf(stderr
, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev
);
683 fprintf(stderr
, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir
);
688 #endif /* HAVE_INFOMOUNT_QNX */
691 init_my_statfs (void)
693 #ifdef HAVE_INFOMOUNT_LIST
695 struct mount_entry
*next
= mount_list
->me_next
;
696 free_mount_entry (mount_list
);
700 mount_list
= read_filesystem_list (1, 1);
701 #endif /* HAVE_INFOMOUNT_LIST */
705 my_statfs (struct my_statfs
*myfs_stats
, const char *path
)
707 #ifdef HAVE_INFOMOUNT_LIST
709 struct mount_entry
*entry
= NULL
;
710 struct mount_entry
*temp
= mount_list
;
711 struct fs_usage fs_use
;
714 i
= strlen (temp
->me_mountdir
);
715 if (i
> len
&& (strncmp (path
, temp
->me_mountdir
, i
) == 0))
716 if (!entry
|| (path
[i
] == PATH_SEP
|| path
[i
] == 0)){
720 temp
= temp
->me_next
;
724 memset (&fs_use
, 0, sizeof (struct fs_usage
));
725 get_fs_usage (entry
->me_mountdir
, &fs_use
);
727 myfs_stats
->type
= entry
->me_dev
;
728 myfs_stats
->typename
= entry
->me_type
;
729 myfs_stats
->mpoint
= entry
->me_mountdir
;
730 myfs_stats
->device
= entry
->me_devname
;
731 myfs_stats
->avail
= getuid () ? fs_use
.fsu_bavail
/2 : fs_use
.fsu_bfree
/2;
732 myfs_stats
->total
= fs_use
.fsu_blocks
/2;
733 myfs_stats
->nfree
= fs_use
.fsu_ffree
;
734 myfs_stats
->nodes
= fs_use
.fsu_files
;
736 #endif /* HAVE_INFOMOUNT_LIST */
738 #ifdef HAVE_INFOMOUNT_QNX
740 ** This is the "other side" of the hack to read_filesystem_list() in
742 ** It's not the most efficient approach, but consumes less memory. It
743 ** also accomodates QNX's ability to mount filesystems on the fly.
745 struct mount_entry
*entry
;
746 struct fs_usage fs_use
;
748 if ((entry
= read_filesystem_list(0, 0)) != NULL
)
750 get_fs_usage(entry
->me_mountdir
, &fs_use
);
752 myfs_stats
->type
= entry
->me_dev
;
753 myfs_stats
->typename
= entry
->me_type
;
754 myfs_stats
->mpoint
= entry
->me_mountdir
;
755 myfs_stats
->device
= entry
->me_devname
;
757 myfs_stats
->avail
= fs_use
.fsu_bfree
/ 2;
758 myfs_stats
->total
= fs_use
.fsu_blocks
/ 2;
759 myfs_stats
->nfree
= fs_use
.fsu_ffree
;
760 myfs_stats
->nodes
= fs_use
.fsu_files
;
763 #endif /* HAVE_INFOMOUNT_QNX */
765 myfs_stats
->type
= 0;
766 myfs_stats
->mpoint
= "unknown";
767 myfs_stats
->device
= "unknown";
768 myfs_stats
->avail
= 0;
769 myfs_stats
->total
= 0;
770 myfs_stats
->nfree
= 0;
771 myfs_stats
->nodes
= 0;
775 #ifdef HAVE_INFOMOUNT
777 /* Return the number of TOSIZE-byte blocks used by
778 BLOCKS FROMSIZE-byte blocks, rounding away from zero.
779 TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */
782 fs_adjust_blocks (fsblkcnt_t blocks
, int fromsize
, int tosize
)
789 if (fromsize
== tosize
) /* E.g., from 512 to 512. */
791 else if (fromsize
> tosize
) /* E.g., from 2048 to 512. */
792 return blocks
* (fromsize
/ tosize
);
793 else /* E.g., from 256 to 512. */
794 return blocks
/ (tosize
/ fromsize
);
797 #if defined(_AIX) && defined(_I386)
798 /* AIX PS/2 does not supply statfs. */
799 static int aix_statfs (char *path
, struct statfs
*fsb
)
804 if (stat (path
, &stats
))
806 if (dustat (stats
.st_dev
, 0, &fsd
, sizeof (fsd
)))
809 fsb
->f_bsize
= fsd
.du_bsize
;
810 fsb
->f_blocks
= fsd
.du_fsize
- fsd
.du_isize
;
811 fsb
->f_bfree
= fsd
.du_tfree
;
812 fsb
->f_bavail
= fsd
.du_tfree
;
813 fsb
->f_files
= (fsd
.du_isize
- 2) * fsd
.du_inopb
;
814 fsb
->f_ffree
= fsd
.du_tinode
;
815 fsb
->f_fsid
.val
[0] = fsd
.du_site
;
816 fsb
->f_fsid
.val
[1] = fsd
.du_pckno
;
819 #define statfs(path,fsb) aix_statfs(path,fsb)
820 #endif /* _AIX && _I386 */
822 /* Fill in the fields of FSP with information about space usage for
823 the filesystem on which PATH resides.
824 Return 0 if successful, -1 if not. */
827 get_fs_usage (char *path
, struct fs_usage
*fsp
)
829 #ifdef STAT_STATFS3_OSF1
832 if (statfs (path
, &fsd
, sizeof (struct statfs
)) != 0)
834 #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512)
835 #endif /* STAT_STATFS3_OSF1 */
837 #ifdef STAT_STATFS2_FS_DATA /* Ultrix. */
840 if (statfs (path
, &fsd
) != 1)
842 #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), 1024, 512)
843 fsp
->fsu_blocks
= CONVERT_BLOCKS (fsd
.fd_req
.btot
);
844 fsp
->fsu_bfree
= CONVERT_BLOCKS (fsd
.fd_req
.bfree
);
845 fsp
->fsu_bavail
= CONVERT_BLOCKS (fsd
.fd_req
.bfreen
);
846 fsp
->fsu_files
= fsd
.fd_req
.gtot
;
847 fsp
->fsu_ffree
= fsd
.fd_req
.gfree
;
850 #ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX. */
853 if (statfs (path
, &fsd
) < 0)
855 #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512)
858 #ifdef STAT_STATFS2_FSIZE /* 4.4BSD. */
861 if (statfs (path
, &fsd
) < 0)
863 #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512)
866 #ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX. */
869 if (statfs (path
, &fsd
, sizeof fsd
, 0) < 0)
871 /* Empirically, the block counts on most SVR3 and SVR3-derived
872 systems seem to always be in terms of 512-byte blocks,
873 no matter what value f_bsize has. */
875 #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512)
877 #define CONVERT_BLOCKS(b) (b)
878 #ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx. */
879 #ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */
880 #define f_bavail f_bfree
886 #ifdef STAT_STATVFS /* SVR4. */
889 if (statvfs (path
, &fsd
) < 0)
891 /* f_frsize isn't guaranteed to be supported. */
892 #define CONVERT_BLOCKS(b) \
893 fs_adjust_blocks ((b), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
896 #if defined(CONVERT_BLOCKS) && !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ_FILSYS) /* !Ultrix && !SVR2. */
897 fsp
->fsu_blocks
= CONVERT_BLOCKS (fsd
.f_blocks
);
898 fsp
->fsu_bfree
= CONVERT_BLOCKS (fsd
.f_bfree
);
899 fsp
->fsu_bavail
= CONVERT_BLOCKS (fsd
.f_bavail
);
900 fsp
->fsu_files
= fsd
.f_files
;
901 fsp
->fsu_ffree
= fsd
.f_ffree
;
907 #endif /* HAVE_INFOMOUNT */