summaryrefslogtreecommitdiffstats
path: root/gl/fsusage.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/fsusage.c')
-rw-r--r--gl/fsusage.c107
1 files changed, 87 insertions, 20 deletions
diff --git a/gl/fsusage.c b/gl/fsusage.c
index 10db467..0657555 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 */ 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. */
@@ -156,7 +210,7 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
156 : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1)); 210 : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1));
157 fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode); 211 fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode);
158 212
159#elif defined STAT_STATFS3_OSF1 213#elif defined STAT_STATFS3_OSF1 /* OSF/1 */
160 214
161 struct statfs fsd; 215 struct statfs fsd;
162 216
@@ -165,7 +219,18 @@ 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 /* 4.3BSD, SunOS 4, HP-UX, AIX */ 222#elif defined STAT_STATFS2_FRSIZE /* 2.6 < glibc/Linux < 2.6.36 */
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, \
233 NetBSD < 3.0, OpenBSD < 4.4 */
169 234
170 struct statfs fsd; 235 struct statfs fsd;
171 236
@@ -189,7 +254,7 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
189 } 254 }
190# endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ 255# endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
191 256
192#elif defined STAT_STATFS2_FSIZE /* 4.4BSD */ 257#elif defined STAT_STATFS2_FSIZE /* 4.4BSD and older NetBSD */
193 258
194 struct statfs fsd; 259 struct statfs fsd;
195 260
@@ -198,7 +263,8 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
198 263
199 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); 264 fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
200 265
201#elif defined STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ 266#elif defined STAT_STATFS4 /* SVR3, Dynix, old Irix, old AIX, \
267 Dolphin */
202 268
203# if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN 269# if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN
204# define f_bavail f_bfree 270# define f_bavail f_bfree
@@ -220,8 +286,9 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
220 286
221#endif 287#endif
222 288
223#if (defined STAT_STATVFS \ 289#if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1 \
224 || (!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)
225 292
226 fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks); 293 fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);
227 fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree); 294 fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree);