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>
113 #include "mountlist.h"
117 /* So special that it's not worth putting this in autoconf. */
118 #undef MOUNTED_FREAD_FSTYP
119 #define MOUNTED_GETMNTTBL
122 #if defined (__QNX__) && !defined(__QNXNTO__) && !defined (HAVE_INFOMOUNT_LIST)
123 # define HAVE_INFOMOUNT_QNX
126 #if defined(HAVE_INFOMOUNT_LIST) || defined(HAVE_INFOMOUNT_QNX)
127 # define HAVE_INFOMOUNT
130 /* A mount table entry. */
133 char *me_devname
; /* Device node pathname, including "/dev/". */
134 char *me_mountdir
; /* Mount point directory pathname. */
135 char *me_type
; /* "nfs", "4.2", etc. */
136 dev_t me_dev
; /* Device number of me_mountdir. */
137 struct mount_entry
*me_next
;
142 fsblkcnt_t fsu_blocks
; /* Total blocks. */
143 fsblkcnt_t fsu_bfree
; /* Free blocks available to superuser. */
144 fsblkcnt_t fsu_bavail
; /* Free blocks available to non-superuser. */
145 fsfilcnt_t fsu_files
; /* Total file nodes. */
146 fsfilcnt_t fsu_ffree
; /* Free file nodes. */
149 static int get_fs_usage (char *path
, struct fs_usage
*fsp
);
151 #ifdef HAVE_INFOMOUNT_LIST
153 static struct mount_entry
*mount_list
= NULL
;
155 static void free_mount_entry (struct mount_entry
*me
)
160 free (me
->me_devname
);
162 free (me
->me_mountdir
);
168 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
169 /* Return the value of the hexadecimal number represented by CP.
170 No prefix (like '0x') or suffix (like 'h') is expected to be
173 static int xatoi (const char *cp
)
179 if (*cp
>= 'a' && *cp
<= 'f')
180 val
= val
* 16 + *cp
- 'a' + 10;
181 else if (*cp
>= 'A' && *cp
<= 'F')
182 val
= val
* 16 + *cp
- 'A' + 10;
183 else if (*cp
>= '0' && *cp
<= '9')
184 val
= val
* 16 + *cp
- '0';
191 #endif /* MOUNTED_GETMNTENT1 */
193 #ifdef MOUNTED_GETMNTINFO
195 #ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME
196 static char *fstype_to_string (short t
)
287 #endif /* ! HAVE_STRUCT_STATFS_F_FSTYPENAME */
289 #endif /* MOUNTED_GETMNTINFO */
291 #ifdef MOUNTED_VMOUNT /* AIX. */
293 fstype_to_string (int t
)
297 e
= getvfsbytype (t
);
298 if (!e
|| !e
->vfsent_name
)
301 return e
->vfsent_name
;
303 #endif /* MOUNTED_VMOUNT */
305 /* Return a list of the currently mounted filesystems, or NULL on error.
306 Add each entry to the tail of the list so that they stay in order.
307 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
308 the returned list are valid. Otherwise, they might not be.
309 If ALL_FS is zero, do not return entries for filesystems that
310 are automounter (dummy) entries. */
312 static struct mount_entry
*
313 read_filesystem_list (int need_fs_type
, int all_fs
)
315 struct mount_entry
*mlist
;
316 struct mount_entry
*me
;
317 struct mount_entry
*mtail
;
322 /* Start the list off with a dummy entry. */
323 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
327 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
334 fp
= setmntent (MOUNTED
, "r");
338 while ((mnt
= getmntent (fp
))) {
339 if (!all_fs
&& (!strcmp (mnt
->mnt_type
, "ignore")
340 || !strcmp (mnt
->mnt_type
, "auto")))
343 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
344 me
->me_devname
= strdup (mnt
->mnt_fsname
);
345 me
->me_mountdir
= strdup (mnt
->mnt_dir
);
346 me
->me_type
= strdup (mnt
->mnt_type
);
347 devopt
= strstr (mnt
->mnt_opts
, "dev=");
349 if (devopt
[4] == '0' && (devopt
[5] == 'x' || devopt
[5] == 'X'))
350 me
->me_dev
= xatoi (devopt
+ 6);
352 me
->me_dev
= xatoi (devopt
+ 4);
354 me
->me_dev
= -1; /* Magic; means not known yet. */
357 /* Add to the linked list. */
362 if (endmntent (fp
) == 0)
366 #endif /* MOUNTED_GETMNTENT1 */
368 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
373 entries
= getmntinfo (&fsp
, MNT_NOWAIT
);
376 while (entries
-- > 0) {
377 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
378 me
->me_devname
= strdup (fsp
->f_mntfromname
);
379 me
->me_mountdir
= strdup (fsp
->f_mntonname
);
380 #ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME
381 me
->me_type
= strdup (fsp
->f_fstypename
);
383 me
->me_type
= fstype_to_string (fsp
->f_type
);
385 me
->me_dev
= -1; /* Magic; means not known yet. */
388 /* Add to the linked list. */
394 #endif /* MOUNTED_GETMNTINFO */
396 #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
401 entries
= getmntinfo (&fsp
, MNT_NOWAIT
);
404 for (; entries
-- > 0; fsp
++) {
405 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
406 me
->me_devname
= strdup (fsp
->f_mntfromname
);
407 me
->me_mountdir
= strdup (fsp
->f_mntonname
);
408 me
->me_type
= strdup (fsp
->f_fstypename
);
409 me
->me_dev
= (dev_t
) -1; /* Magic; means not known yet. */
411 /* Add to the linked list. */
416 #endif /* MOUNTED_GETMNTINFO2 */
418 #ifdef MOUNTED_GETMNT /* Ultrix. */
424 while ((val
= getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
,
426 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
427 me
->me_devname
= strdup (fsd
.fd_req
.devname
);
428 me
->me_mountdir
= strdup (fsd
.fd_req
.path
);
429 me
->me_type
= gt_names
[fsd
.fd_req
.fstype
];
430 me
->me_dev
= fsd
.fd_req
.dev
;
433 /* Add to the linked list. */
440 #endif /* MOUNTED_GETMNT */
442 #ifdef MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
444 int numsys
, counter
, bufsize
;
445 struct statfs
*stats
;
447 numsys
= getfsstat ((struct statfs
*) 0, 0L, MNT_WAIT
);
451 bufsize
= (1 + numsys
) * sizeof (struct statfs
);
452 stats
= (struct statfs
*) malloc (bufsize
);
453 numsys
= getfsstat (stats
, bufsize
, MNT_WAIT
);
459 for (counter
= 0; counter
< numsys
; counter
++) {
460 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
461 me
->me_devname
= strdup (stats
[counter
].f_mntfromname
);
462 me
->me_mountdir
= strdup (stats
[counter
].f_mntonname
);
463 me
->me_type
= mnt_names
[stats
[counter
].f_type
];
464 me
->me_dev
= -1; /* Magic; means not known yet. */
467 /* Add to the linked list. */
474 #endif /* MOUNTED_GETFSSTAT */
476 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
479 char *table
= "/etc/mnttab";
482 fp
= fopen (table
, "r");
486 while (fread (&mnt
, sizeof mnt
, 1, fp
) > 0) {
487 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
488 #ifdef GETFSTYP /* SVR3. */
489 me
->me_devname
= strdup (mnt
.mt_dev
);
491 me
->me_devname
= malloc (strlen (mnt
.mt_dev
) + 6);
492 strcpy (me
->me_devname
, "/dev/");
493 strcpy (me
->me_devname
+ 5, mnt
.mt_dev
);
495 me
->me_mountdir
= strdup (mnt
.mt_filsys
);
496 me
->me_dev
= -1; /* Magic; means not known yet. */
498 #ifdef GETFSTYP /* SVR3. */
501 char typebuf
[FSTYPSZ
];
503 if (statfs (me
->me_mountdir
, &fsd
, sizeof fsd
, 0) != -1
504 && sysfs (GETFSTYP
, fsd
.f_fstyp
, typebuf
) != -1)
505 me
->me_type
= strdup (typebuf
);
510 /* Add to the linked list. */
515 if (fclose (fp
) == EOF
)
518 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP */
520 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
522 struct mntent
**mnttbl
= getmnttbl (), **ent
;
523 for (ent
= mnttbl
; *ent
; ent
++) {
524 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
525 me
->me_devname
= strdup ((*ent
)->mt_resource
);
526 me
->me_mountdir
= strdup ((*ent
)->mt_directory
);
527 me
->me_type
= strdup ((*ent
)->mt_fstype
);
528 me
->me_dev
= -1; /* Magic; means not known yet. */
531 /* Add to the linked list. */
537 #endif /* MOUNTED_GETMNTTBL */
539 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
542 char *table
= MNTTAB
;
546 fp
= fopen (table
, "r");
550 while ((ret
= getmntent (fp
, &mnt
)) == 0) {
551 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
552 me
->me_devname
= strdup (mnt
.mnt_special
);
553 me
->me_mountdir
= strdup (mnt
.mnt_mountp
);
554 me
->me_type
= strdup (mnt
.mnt_fstype
);
555 me
->me_dev
= -1; /* Magic; means not known yet. */
557 /* Add to the linked list. */
564 if (fclose (fp
) == EOF
)
567 #endif /* MOUNTED_GETMNTENT2 */
569 #ifdef MOUNTED_VMOUNT /* AIX. */
572 char *entries
, *thisent
;
575 /* Ask how many bytes to allocate for the mounted filesystem info. */
576 mntctl (MCTL_QUERY
, sizeof bufsize
, (struct vmount
*) &bufsize
);
577 entries
= malloc (bufsize
);
579 /* Get the list of mounted filesystems. */
580 mntctl (MCTL_QUERY
, bufsize
, (struct vmount
*) entries
);
582 for (thisent
= entries
; thisent
< entries
+ bufsize
;
583 thisent
+= vmp
->vmt_length
) {
584 vmp
= (struct vmount
*) thisent
;
585 me
= (struct mount_entry
*) malloc (sizeof (struct mount_entry
));
586 if (vmp
->vmt_flags
& MNT_REMOTE
) {
589 /* Prepend the remote pathname. */
590 host
= thisent
+ vmp
->vmt_data
[VMT_HOSTNAME
].vmt_off
;
591 path
= thisent
+ vmp
->vmt_data
[VMT_OBJECT
].vmt_off
;
592 me
->me_devname
= malloc (strlen (host
) + strlen (path
) + 2);
593 strcpy (me
->me_devname
, host
);
594 strcat (me
->me_devname
, ":");
595 strcat (me
->me_devname
, path
);
597 me
->me_devname
= strdup (thisent
+
598 vmp
->vmt_data
[VMT_OBJECT
].vmt_off
);
600 me
->me_mountdir
= strdup (thisent
+ vmp
->vmt_data
[VMT_STUB
].vmt_off
);
601 me
->me_type
= strdup (fstype_to_string (vmp
->vmt_gfstype
));
602 me
->me_dev
= -1; /* vmt_fsid might be the info we want. */
605 /* Add to the linked list. */
611 #endif /* MOUNTED_VMOUNT */
613 /* Free the dummy head. */
615 mlist
= mlist
->me_next
;
619 #endif /* HAVE_INFOMOUNT_LIST */
621 #ifdef HAVE_INFOMOUNT_QNX
623 ** QNX has no [gs]etmnt*(), [gs]etfs*(), or /etc/mnttab, but can do
624 ** this via the following code.
625 ** Note that, as this is based on CWD, it only fills one mount_entry
626 ** structure. See my_statfs() in utilunix.c for the "other side" of
630 static struct mount_entry
*
631 read_filesystem_list(int need_fs_type
, int all_fs
)
633 struct _disk_entry de
;
636 char *tp
, dev
[_POSIX_NAME_MAX
], dir
[_POSIX_PATH_MAX
];
638 static struct mount_entry
*me
= NULL
;
642 if (me
->me_devname
) free(me
->me_devname
);
643 if (me
->me_mountdir
) free(me
->me_mountdir
);
644 if (me
->me_type
) free(me
->me_type
);
647 me
= (struct mount_entry
*)malloc(sizeof(struct mount_entry
));
649 if (!getcwd(dir
, _POSIX_PATH_MAX
)) return (NULL
);
651 if ((fd
= open(dir
, O_RDONLY
)) == -1) return (NULL
);
653 i
= disk_get_entry(fd
, &de
);
657 if (i
== -1) return (NULL
);
659 switch (de
.disk_type
)
661 case _UNMOUNTED
: tp
= "unmounted"; break;
662 case _FLOPPY
: tp
= "Floppy"; break;
663 case _HARD
: tp
= "Hard"; break;
664 case _RAMDISK
: tp
= "Ram"; break;
665 case _REMOVABLE
: tp
= "Removable"; break;
666 case _TAPE
: tp
= "Tape"; break;
667 case _CDROM
: tp
= "CDROM"; break;
668 default: tp
= "unknown";
671 if (fsys_get_mount_dev(dir
, &dev
) == -1) return (NULL
);
673 if (fsys_get_mount_pt(dev
, &dir
) == -1) return (NULL
);
675 me
->me_devname
= strdup(dev
);
676 me
->me_mountdir
= strdup(dir
);
677 me
->me_type
= strdup(tp
);
678 me
->me_dev
= de
.disk_type
;
681 fprintf(stderr
, "disk_get_entry():\n\tdisk_type=%d (%s)\n\tdriver_name='%-*.*s'\n\tdisk_drv=%d\n",
682 de
.disk_type
, tp
, _DRIVER_NAME_LEN
, _DRIVER_NAME_LEN
, de
.driver_name
, de
.disk_drv
);
683 fprintf(stderr
, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev
);
684 fprintf(stderr
, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir
);
689 #endif /* HAVE_INFOMOUNT_QNX */
692 init_my_statfs (void)
694 #ifdef HAVE_INFOMOUNT_LIST
696 struct mount_entry
*next
= mount_list
->me_next
;
697 free_mount_entry (mount_list
);
701 mount_list
= read_filesystem_list (1, 1);
702 #endif /* HAVE_INFOMOUNT_LIST */
706 my_statfs (struct my_statfs
*myfs_stats
, const char *path
)
708 #ifdef HAVE_INFOMOUNT_LIST
710 struct mount_entry
*entry
= NULL
;
711 struct mount_entry
*temp
= mount_list
;
712 struct fs_usage fs_use
;
715 i
= strlen (temp
->me_mountdir
);
716 if (i
> len
&& (strncmp (path
, temp
->me_mountdir
, i
) == 0))
717 if (!entry
|| (path
[i
] == PATH_SEP
|| path
[i
] == 0)){
721 temp
= temp
->me_next
;
725 memset (&fs_use
, 0, sizeof (struct fs_usage
));
726 get_fs_usage (entry
->me_mountdir
, &fs_use
);
728 myfs_stats
->type
= entry
->me_dev
;
729 myfs_stats
->typename
= entry
->me_type
;
730 myfs_stats
->mpoint
= entry
->me_mountdir
;
731 myfs_stats
->device
= entry
->me_devname
;
732 myfs_stats
->avail
= getuid () ? fs_use
.fsu_bavail
/2 : fs_use
.fsu_bfree
/2;
733 myfs_stats
->total
= fs_use
.fsu_blocks
/2;
734 myfs_stats
->nfree
= fs_use
.fsu_ffree
;
735 myfs_stats
->nodes
= fs_use
.fsu_files
;
737 #endif /* HAVE_INFOMOUNT_LIST */
739 #ifdef HAVE_INFOMOUNT_QNX
741 ** This is the "other side" of the hack to read_filesystem_list() in
743 ** It's not the most efficient approach, but consumes less memory. It
744 ** also accomodates QNX's ability to mount filesystems on the fly.
746 struct mount_entry
*entry
;
747 struct fs_usage fs_use
;
749 if ((entry
= read_filesystem_list(0, 0)) != NULL
)
751 get_fs_usage(entry
->me_mountdir
, &fs_use
);
753 myfs_stats
->type
= entry
->me_dev
;
754 myfs_stats
->typename
= entry
->me_type
;
755 myfs_stats
->mpoint
= entry
->me_mountdir
;
756 myfs_stats
->device
= entry
->me_devname
;
758 myfs_stats
->avail
= fs_use
.fsu_bfree
/ 2;
759 myfs_stats
->total
= fs_use
.fsu_blocks
/ 2;
760 myfs_stats
->nfree
= fs_use
.fsu_ffree
;
761 myfs_stats
->nodes
= fs_use
.fsu_files
;
764 #endif /* HAVE_INFOMOUNT_QNX */
766 myfs_stats
->type
= 0;
767 myfs_stats
->mpoint
= "unknown";
768 myfs_stats
->device
= "unknown";
769 myfs_stats
->avail
= 0;
770 myfs_stats
->total
= 0;
771 myfs_stats
->nfree
= 0;
772 myfs_stats
->nodes
= 0;
776 #ifdef HAVE_INFOMOUNT
778 /* Return the number of TOSIZE-byte blocks used by
779 BLOCKS FROMSIZE-byte blocks, rounding away from zero.
780 TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */
783 fs_adjust_blocks (fsblkcnt_t blocks
, int fromsize
, int tosize
)
790 if (fromsize
== tosize
) /* E.g., from 512 to 512. */
792 else if (fromsize
> tosize
) /* E.g., from 2048 to 512. */
793 return blocks
* (fromsize
/ tosize
);
794 else /* E.g., from 256 to 512. */
795 return blocks
/ (tosize
/ fromsize
);
798 #if defined(_AIX) && defined(_I386)
799 /* AIX PS/2 does not supply statfs. */
800 static int aix_statfs (char *path
, struct statfs
*fsb
)
805 if (stat (path
, &stats
))
807 if (dustat (stats
.st_dev
, 0, &fsd
, sizeof (fsd
)))
810 fsb
->f_bsize
= fsd
.du_bsize
;
811 fsb
->f_blocks
= fsd
.du_fsize
- fsd
.du_isize
;
812 fsb
->f_bfree
= fsd
.du_tfree
;
813 fsb
->f_bavail
= fsd
.du_tfree
;
814 fsb
->f_files
= (fsd
.du_isize
- 2) * fsd
.du_inopb
;
815 fsb
->f_ffree
= fsd
.du_tinode
;
816 fsb
->f_fsid
.val
[0] = fsd
.du_site
;
817 fsb
->f_fsid
.val
[1] = fsd
.du_pckno
;
820 #define statfs(path,fsb) aix_statfs(path,fsb)
821 #endif /* _AIX && _I386 */
823 /* Fill in the fields of FSP with information about space usage for
824 the filesystem on which PATH resides.
825 Return 0 if successful, -1 if not. */
828 get_fs_usage (char *path
, struct fs_usage
*fsp
)
830 #ifdef STAT_STATFS3_OSF1
833 if (statfs (path
, &fsd
, sizeof (struct statfs
)) != 0)
835 #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512)
836 #endif /* STAT_STATFS3_OSF1 */
838 #ifdef STAT_STATFS2_FS_DATA /* Ultrix. */
841 if (statfs (path
, &fsd
) != 1)
843 #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), 1024, 512)
844 fsp
->fsu_blocks
= CONVERT_BLOCKS (fsd
.fd_req
.btot
);
845 fsp
->fsu_bfree
= CONVERT_BLOCKS (fsd
.fd_req
.bfree
);
846 fsp
->fsu_bavail
= CONVERT_BLOCKS (fsd
.fd_req
.bfreen
);
847 fsp
->fsu_files
= fsd
.fd_req
.gtot
;
848 fsp
->fsu_ffree
= fsd
.fd_req
.gfree
;
851 #ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX. */
854 if (statfs (path
, &fsd
) < 0)
856 #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512)
859 #ifdef STAT_STATFS2_FSIZE /* 4.4BSD. */
862 if (statfs (path
, &fsd
) < 0)
864 #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512)
867 #ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX. */
870 if (statfs (path
, &fsd
, sizeof fsd
, 0) < 0)
872 /* Empirically, the block counts on most SVR3 and SVR3-derived
873 systems seem to always be in terms of 512-byte blocks,
874 no matter what value f_bsize has. */
876 #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512)
878 #define CONVERT_BLOCKS(b) (b)
879 #ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx. */
880 #ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */
881 #define f_bavail f_bfree
887 #ifdef STAT_STATVFS /* SVR4. */
890 if (statvfs (path
, &fsd
) < 0)
892 /* f_frsize isn't guaranteed to be supported. */
893 #define CONVERT_BLOCKS(b) \
894 fs_adjust_blocks ((b), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
897 #if defined(CONVERT_BLOCKS) && !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ_FILSYS) /* !Ultrix && !SVR2. */
898 fsp
->fsu_blocks
= CONVERT_BLOCKS (fsd
.f_blocks
);
899 fsp
->fsu_bfree
= CONVERT_BLOCKS (fsd
.f_bfree
);
900 fsp
->fsu_bavail
= CONVERT_BLOCKS (fsd
.f_bavail
);
901 fsp
->fsu_files
= fsd
.f_files
;
902 fsp
->fsu_ffree
= fsd
.f_ffree
;
908 #endif /* HAVE_INFOMOUNT */