1
0
mirror of https://git.savannah.gnu.org/git/gnulib.git synced 2025-08-17 12:41:05 +03:00

fsusage: check for GNU/Linux statvfs problem dynamically

Problem reported by Nikolaus Rath in <http://bugs.gnu.org/11406>.
* lib/fsusage.c [STAT_STATVFS && __linux__ && (__GLIBC__||__UCLIBC__)]:
Define STAT_STATFS2_BSIZE too, since in this case the code now
checks dynamically whether statvfs is reliable, falling back on
Linux-style statfs otherwise.
(statvfs_works): New function, for dynamically testing statvfs.
(get_fs_usage) [STAT_STATVFS]: Use it.
* m4/fsusage.m4 (gl_FILE_SYSTEM_USAGE): Remove static check for
statvfs on GNU/Linux hosts, since it's now done dynamically.
This commit is contained in:
Paul Eggert
2012-05-11 20:54:15 -07:00
parent 1f96aa01f7
commit c25bdbae48
3 changed files with 62 additions and 18 deletions

View File

@@ -1,3 +1,15 @@
2012-05-11 Paul Eggert <eggert@cs.ucla.edu>
fsusage: check for GNU/Linux statvfs problem dynamically
* lib/fsusage.c [STAT_STATVFS && __linux__ && (__GLIBC__||__UCLIBC__)]:
Define STAT_STATFS2_BSIZE too, since in this case the code now
checks dynamically whether statvfs is reliable, falling back on
Linux-style statfs otherwise.
(statvfs_works): New function, for dynamically testing statvfs.
(get_fs_usage) [STAT_STATVFS]: Use it.
* m4/fsusage.m4 (gl_FILE_SYSTEM_USAGE): Remove static check for
statvfs on GNU/Linux hosts, since it's now done dynamically.
2012-05-10 Bruno Haible <bruno@clisp.org> 2012-05-10 Bruno Haible <bruno@clisp.org>
system-quote, execute, spawn-pipe: Escape '?' on Windows. system-quote, execute, spawn-pipe: Escape '?' on Windows.

View File

@@ -84,6 +84,33 @@
otherwise, use PROPAGATE_ALL_ONES. */ otherwise, use PROPAGATE_ALL_ONES. */
#define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1)) #define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1))
#ifdef STAT_STATVFS
/* Return true if statvfs works. This is false for statvfs on systems
with GNU libc on Linux kernels before 2.6.36, which stats all
preceding entries in /proc/mounts; that makes df hang if even one
of the corresponding file systems is hard-mounted but not available. */
# if ! (__linux__ && (__GLIBC__ || __UCLIBC__))
static int statvfs_works (void) { return 1; }
# else
# include <string.h> /* for strverscmp */
# include <sys/utsname.h>
# include <sys/statfs.h>
# define STAT_STATFS2_BSIZE 1
static int
statvfs_works (void)
{
static int statvfs_works_cache = -1;
struct utsname name;
if (statvfs_works_cache < 0)
statvfs_works_cache = (uname (&name) == 0
&& 0 <= strverscmp (name.release, "2.6.36"));
return statvfs_works_cache;
}
# endif
#endif
/* Fill in the fields of FSP with information about space usage for /* Fill in the fields of FSP with information about space usage for
the file system on which FILE resides. the file system on which FILE resides.
DISK is the device on which FILE is mounted, for space-getting DISK is the device on which FILE is mounted, for space-getting
@@ -94,19 +121,32 @@
int int
get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp) get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
{ {
#if defined STAT_STATVFS /* POSIX, except glibc/Linux */ #ifdef STAT_STATVFS /* POSIX, except pre-2.6.36 glibc/Linux */
struct statvfs fsd; if (statvfs_works ())
{
struct statvfs vfsd;
if (statvfs (file, &fsd) < 0) if (statvfs (file, &vfsd) < 0)
return -1; return -1;
/* f_frsize isn't guaranteed to be supported. */ /* f_frsize isn't guaranteed to be supported. */
fsp->fsu_blocksize = (fsd.f_frsize fsp->fsu_blocksize = (vfsd.f_frsize
? PROPAGATE_ALL_ONES (fsd.f_frsize) ? PROPAGATE_ALL_ONES (vfsd.f_frsize)
: PROPAGATE_ALL_ONES (fsd.f_bsize)); : PROPAGATE_ALL_ONES (vfsd.f_bsize));
#elif defined STAT_STATVFS64 /* AIX */ fsp->fsu_blocks = PROPAGATE_ALL_ONES (vfsd.f_blocks);
fsp->fsu_bfree = PROPAGATE_ALL_ONES (vfsd.f_bfree);
fsp->fsu_bavail = PROPAGATE_TOP_BIT (vfsd.f_bavail);
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (vfsd.f_bavail) != 0;
fsp->fsu_files = PROPAGATE_ALL_ONES (vfsd.f_files);
fsp->fsu_ffree = PROPAGATE_ALL_ONES (vfsd.f_ffree);
return 0;
}
#endif
#if defined STAT_STATVFS64 /* AIX */
struct statvfs64 fsd; struct statvfs64 fsd;
@@ -235,7 +275,7 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
#endif #endif
#if (defined STAT_STATVFS || defined STAT_STATVFS64 \ #if (defined STAT_STATVFS64 \
|| (!defined STAT_STATFS2_FS_DATA && !defined STAT_READ_FILSYS)) || (!defined STAT_STATFS2_FS_DATA && !defined STAT_READ_FILSYS))
fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks); fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);

View File

@@ -50,14 +50,6 @@ if test $ac_fsusage_space = no; then
# OpenBSD >= 4.4, AIX, HP-UX, IRIX, Solaris, Cygwin, Interix, BeOS. # OpenBSD >= 4.4, AIX, HP-UX, IRIX, Solaris, Cygwin, Interix, BeOS.
AC_CACHE_CHECK([for statvfs function (SVR4)], [fu_cv_sys_stat_statvfs], AC_CACHE_CHECK([for statvfs function (SVR4)], [fu_cv_sys_stat_statvfs],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h> [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#if (defined __GLIBC__ || defined __UCLIBC__) && defined __linux__
Do not use statvfs on systems with GNU libc on Linux, because that function
stats all preceding entries in /proc/mounts, and that makes df hang if even
one of the corresponding file systems is hard-mounted, but not available.
statvfs in GNU libc on Hurd, BeOS, Haiku operates differently: it only makes
a system call.
#endif
#ifdef __osf__ #ifdef __osf__
"Do not use Tru64's statvfs implementation" "Do not use Tru64's statvfs implementation"
#endif #endif