summaryrefslogtreecommitdiffstats
path: root/gl/fsusage.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/fsusage.c')
-rw-r--r--gl/fsusage.c100
1 files changed, 82 insertions, 18 deletions
diff --git a/gl/fsusage.c b/gl/fsusage.c
index 17102aad..0657555f 100644
--- a/gl/fsusage.c
+++ b/gl/fsusage.c
@@ -1,6 +1,6 @@
1/* fsusage.c -- return space usage of mounted file systems 1/* fsusage.c -- return space usage of mounted file systems
2 2
3 Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2010 Free Software 3 Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2013 Free Software
4 Foundation, Inc. 4 Foundation, Inc.
5 5
6 This program is free software: you can redistribute it and/or modify 6 This program is free software: you can redistribute it and/or modify
@@ -23,7 +23,7 @@
23#include <limits.h> 23#include <limits.h>
24#include <sys/types.h> 24#include <sys/types.h>
25 25
26#if STAT_STATVFS /* POSIX 1003.1-2001 (and later) with XSI */ 26#if STAT_STATVFS || STAT_STATVFS64 /* POSIX 1003.1-2001 (and later) with XSI */
27# include <sys/statvfs.h> 27# include <sys/statvfs.h>
28#else 28#else
29/* Don't include backward-compatibility files unless they're needed. 29/* Don't include backward-compatibility files unless they're needed.
@@ -31,15 +31,15 @@
31# include <fcntl.h> 31# include <fcntl.h>
32# include <unistd.h> 32# include <unistd.h>
33# include <sys/stat.h> 33# include <sys/stat.h>
34# if HAVE_SYS_PARAM_H 34#if HAVE_SYS_PARAM_H
35# include <sys/param.h> 35# include <sys/param.h>
36# endif 36#endif
37# if HAVE_SYS_MOUNT_H 37#if HAVE_SYS_MOUNT_H
38# include <sys/mount.h> 38# include <sys/mount.h>
39# endif 39#endif
40# if HAVE_SYS_VFS_H 40#if HAVE_SYS_VFS_H
41# include <sys/vfs.h> 41# include <sys/vfs.h>
42# endif 42#endif
43# if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */ 43# if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */
44# include <sys/fs/s5param.h> 44# include <sys/fs/s5param.h>
45# endif 45# endif
@@ -84,6 +84,35 @@
84 otherwise, use PROPAGATE_ALL_ONES. */ 84 otherwise, use PROPAGATE_ALL_ONES. */
85#define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1)) 85#define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1))
86 86
87#ifdef STAT_STATVFS
88/* Return true if statvfs works. This is false for statvfs on systems
89 with GNU libc on Linux kernels before 2.6.36, which stats all
90 preceding entries in /proc/mounts; that makes df hang if even one
91 of the corresponding file systems is hard-mounted but not available. */
92# if ! (__linux__ && (__GLIBC__ || __UCLIBC__))
93/* The FRSIZE fallback is not required in this case. */
94# undef STAT_STATFS2_FRSIZE
95static int statvfs_works (void) { return 1; }
96# else
97# include <string.h> /* for strverscmp */
98# include <sys/utsname.h>
99# include <sys/statfs.h>
100# define STAT_STATFS2_BSIZE 1
101
102static int
103statvfs_works (void)
104{
105 static int statvfs_works_cache = -1;
106 struct utsname name;
107 if (statvfs_works_cache < 0)
108 statvfs_works_cache = (uname (&name) == 0
109 && 0 <= strverscmp (name.release, "2.6.36"));
110 return statvfs_works_cache;
111}
112# endif
113#endif
114
115
87/* Fill in the fields of FSP with information about space usage for 116/* Fill in the fields of FSP with information about space usage for
88 the file system on which FILE resides. 117 the file system on which FILE resides.
89 DISK is the device on which FILE is mounted, for space-getting 118 DISK is the device on which FILE is mounted, for space-getting
@@ -94,11 +123,36 @@
94int 123int
95get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp) 124get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
96{ 125{
97#if defined STAT_STATVFS /* POSIX, except glibc/Linux */ 126#ifdef STAT_STATVFS /* POSIX, except pre-2.6.36 glibc/Linux */
127
128 if (statvfs_works ())
129 {
130 struct statvfs vfsd;
131
132 if (statvfs (file, &vfsd) < 0)
133 return -1;
134
135 /* f_frsize isn't guaranteed to be supported. */
136 fsp->fsu_blocksize = (vfsd.f_frsize
137 ? PROPAGATE_ALL_ONES (vfsd.f_frsize)
138 : PROPAGATE_ALL_ONES (vfsd.f_bsize));
139
140 fsp->fsu_blocks = PROPAGATE_ALL_ONES (vfsd.f_blocks);
141 fsp->fsu_bfree = PROPAGATE_ALL_ONES (vfsd.f_bfree);
142 fsp->fsu_bavail = PROPAGATE_TOP_BIT (vfsd.f_bavail);
143 fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (vfsd.f_bavail) != 0;
144 fsp->fsu_files = PROPAGATE_ALL_ONES (vfsd.f_files);
145 fsp->fsu_ffree = PROPAGATE_ALL_ONES (vfsd.f_ffree);
146 return 0;
147 }
148
149#endif
150
151#if defined STAT_STATVFS64 /* AIX */
98 152
99 struct statvfs fsd; 153 struct statvfs64 fsd;
100 154
101 if (statvfs (file, &fsd) < 0) 155 if (statvfs64 (file, &fsd) < 0)
102 return -1; 156 return -1;
103 157
104 /* f_frsize isn't guaranteed to be supported. */ 158 /* f_frsize isn't guaranteed to be supported. */
@@ -165,8 +219,17 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
165 219
166 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); 220 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
167 221
168#elif defined STAT_STATFS2_BSIZE /* glibc/Linux, 4.3BSD, SunOS 4, \ 222#elif defined STAT_STATFS2_FRSIZE /* 2.6 < glibc/Linux < 2.6.36 */
169 MacOS X < 10.4, FreeBSD < 5.0, \ 223
224 struct statfs fsd;
225
226 if (statfs (file, &fsd) < 0)
227 return -1;
228
229 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_frsize);
230
231#elif defined STAT_STATFS2_BSIZE /* glibc/Linux < 2.6, 4.3BSD, SunOS 4, \
232 Mac OS X < 10.4, FreeBSD < 5.0, \
170 NetBSD < 3.0, OpenBSD < 4.4 */ 233 NetBSD < 3.0, OpenBSD < 4.4 */
171 234
172 struct statfs fsd; 235 struct statfs fsd;
@@ -223,8 +286,9 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
223 286
224#endif 287#endif
225 288
226#if (defined STAT_STATVFS \ 289#if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1 \
227 || (!defined STAT_STATFS2_FS_DATA && !defined STAT_READ_FILSYS)) 290 || defined STAT_STATFS2_FRSIZE || defined STAT_STATFS2_BSIZE \
291 || defined STAT_STATFS2_FSIZE || defined STAT_STATFS4)
228 292
229 fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks); 293 fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);
230 fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree); 294 fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree);