statvfs64 does not work as expected
Thorsten Kukuk
kukuk@suse.de
Fri Apr 2 12:17:00 GMT 2004
Hi,
On Tue, Mar 23, Thorsten Kukuk wrote:
> if you have very large filesystems, compiles your program with large
> file support and uses statvfs, statvfs will fail on 32bit systems.
>
> The reason is, that statvfs64 calls statvfs, which calls statfs,
> which will return with a EOVERFLOW error.
Attached is a try from me to fix this. It works fine, but I have now
idea how to implement it more nifty without copying the internal_statvfs.c
content.
Thorsten
--
Thorsten Kukuk http://www.suse.de/~kukuk/ kukuk@suse.de
SuSE Linux AG Maxfeldstr. 5 D-90409 Nuernberg
--------------------------------------------------------------------
Key fingerprint = A368 676B 5E1B 3E46 CFCE 2D97 F8FD 4E23 56C6 FB4B
-------------- next part --------------
2004-04-02 Thorsten Kukuk <kukuk@suse.de>
* sysdeps/unix/sysv/linux/internal_statvfs.c: Use another
prototype for __internal_statvfs if included from statvfs64.c
* sysdeps/unix/sysv/linux/statvfs64.c: Call statvfs
--- sysdeps/unix/sysv/linux/internal_statvfs.c
+++ sysdeps/unix/sysv/linux/internal_statvfs.c 2004/04/02 09:08:45
@@ -31,9 +31,15 @@
#include "linux_fsinfo.h"
+#ifdef USE_64BIT_VERSION
+static void
+__internal_statvfs64 (const char *name, struct statvfs64 *buf,
+ struct statfs64 *fsbuf, struct stat64 *st)
+#else
void
__internal_statvfs (const char *name, struct statvfs *buf,
struct statfs *fsbuf, struct stat64 *st)
+#endif
{
/* Now fill in the fields we have information for. */
buf->f_bsize = fsbuf->f_bsize;
--- sysdeps/unix/sysv/linux/statvfs64.c
+++ sysdeps/unix/sysv/linux/statvfs64.c 2004/04/02 09:12:29
@@ -1,5 +1,5 @@
/* Return information about the filesystem on which FILE resides.
- Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2000, 2001, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,33 +17,55 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sys/statvfs.h>
#include <stddef.h>
#include <string.h>
+
+#define USE_64BIT_VERSION 1
+
+#include "internal_statvfs.c"
/* Return information about the filesystem on which FILE resides. */
int
__statvfs64 (const char *file, struct statvfs64 *buf)
{
- struct statvfs buf32;
-
- if (statvfs (file, &buf32) < 0)
- return -1;
+ struct statfs64 fsbuf;
+ struct stat64 st;
- buf->f_bsize = buf32.f_bsize;
- buf->f_frsize = buf32.f_frsize;
- buf->f_blocks = buf32.f_blocks;
- buf->f_bfree = buf32.f_bfree;
- buf->f_bavail = buf32.f_bavail;
- buf->f_files = buf32.f_files;
- buf->f_ffree = buf32.f_ffree;
- buf->f_favail = buf32.f_favail;
- buf->f_fsid = buf32.f_fsid;
- buf->f_flag = buf32.f_flag;
- buf->f_namemax = buf32.f_namemax;
- memcpy (buf->__f_spare, buf32.__f_spare, sizeof (buf32.__f_spare));
+ /* Get as much information as possible from the system. */
+ if (__statfs64 (file, &fsbuf) < 0)
+ {
+ struct statvfs buf32;
+
+ if (errno != ENOSYS)
+ return -1;
+
+ /* No statfs64, fallback to 32bit version. */
+ if (statvfs (file, &buf32) < 0)
+ return -1;
+
+ buf->f_bsize = buf32.f_bsize;
+ buf->f_frsize = buf32.f_frsize;
+ buf->f_blocks = buf32.f_blocks;
+ buf->f_bfree = buf32.f_bfree;
+ buf->f_bavail = buf32.f_bavail;
+ buf->f_files = buf32.f_files;
+ buf->f_ffree = buf32.f_ffree;
+ buf->f_favail = buf32.f_favail;
+ buf->f_fsid = buf32.f_fsid;
+ buf->f_flag = buf32.f_flag;
+ buf->f_namemax = buf32.f_namemax;
+ memcpy (buf->__f_spare, buf32.__f_spare, sizeof (buf32.__f_spare));
+
+ return 0;
+ }
+
+ /* Convert the result. */
+ __internal_statvfs64 (file, buf, &fsbuf,
+ stat64 (file, &st) == -1 ? NULL : &st);
+ /* We signal success if the statfs call succeeded. */
return 0;
}
weak_alias (__statvfs64, statvfs64)
More information about the Libc-alpha
mailing list