Merge branch '2906_copy_crash_on_solaris'

* 2906_copy_crash_on_solaris:
  (get_fs_usage): avoid compile warning about mixed declarations and code.
  Sync with gnulib ffe10f3d20c2eb77efd56b68f2c22b2a810c289d.
  Sync with gnulib 2ab2617ee340ff35a9a4c713004fb302868d41b0
  Sync with gnulib 0a6dafee2bb8f69a931345a1f67d835ee5062967
  Sync with gnulib b1fac377605c0eef8844fc8d3818d360f37d6fa4:
  Ticket #2906: crash on Solaris while trying to copy a file.
This commit is contained in:
Andrew Borodin 2012-10-12 13:59:52 +04:00
commit 80bfefe0ff
3 changed files with 221 additions and 109 deletions

View File

@ -50,14 +50,6 @@ if test $ac_fsusage_space = no; then
# OpenBSD >= 4.4, AIX, HP-UX, IRIX, Solaris, Cygwin, Interix, BeOS.
AC_CACHE_CHECK([for statvfs function (SVR4)], [fu_cv_sys_stat_statvfs],
[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__
"Do not use Tru64's statvfs implementation"
#endif
@ -110,6 +102,38 @@ int check_f_blocks_size[sizeof fsd.f_blocks * CHAR_BIT <= 32 ? -1 : 1];
fi
fi
# Check for this unconditionally so we have a
# good fallback on glibc/Linux > 2.6 < 2.6.36
AC_MSG_CHECKING([for two-argument statfs with statfs.f_frsize member])
AC_CACHE_VAL([fu_cv_sys_stat_statfs2_frsize],
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
int
main ()
{
struct statfs fsd;
fsd.f_frsize = 0;
return statfs (".", &fsd) != 0;
}]])],
[fu_cv_sys_stat_statfs2_frsize=yes],
[fu_cv_sys_stat_statfs2_frsize=no],
[fu_cv_sys_stat_statfs2_frsize=no])])
AC_MSG_RESULT([$fu_cv_sys_stat_statfs2_frsize])
if test $fu_cv_sys_stat_statfs2_frsize = yes; then
ac_fsusage_space=yes
AC_DEFINE([STAT_STATFS2_FRSIZE], [1],
[ Define if statfs takes 2 args and struct statfs has a field named f_frsize.
(glibc/Linux > 2.6)])
fi
if test $ac_fsusage_space = no; then
# DEC Alpha running OSF/1
AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)])

View File

@ -91,14 +91,43 @@
#endif
#if USE_STATVFS
#define STRUCT_STATVFS struct statvfs
#if ! STAT_STATVFS && STAT_STATVFS64
#define STRUCT_STATVFS struct statvfs64
#define STATFS statvfs64
#else
#define STRUCT_STATVFS struct statvfs
#define STATFS 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
#else
#define STATFS statfs
#define STRUCT_STATVFS struct statfs
#if HAVE_OS_H /* BeOS */
/* BeOS has a statvfs function, but it does not return sensible values
for f_files, f_ffree and f_favail, and lacks f_type, f_basetype and
@ -237,16 +266,21 @@ typedef struct
static gboolean
filegui__check_attrs_on_fs (const char *fs_path)
{
#ifdef USE_STATVFS
STRUCT_STATVFS stfs;
if (!setup_copymove_persistent_attr)
return FALSE;
if (statfs (fs_path, &stfs) != 0)
#if USE_STATVFS && defined(STAT_STATVFS)
if (statvfs_works () && statvfs (fs_path, &stfs) != 0)
return TRUE;
#else
if (STATFS (fs_path, &stfs) != 0)
return TRUE;
#endif
#ifdef __linux__
#if (USE_STATVFS && defined(HAVE_STRUCT_STATVFS_F_TYPE)) || \
(!USE_STATVFS && defined(HAVE_STRUCT_STATFS_F_TYPE))
switch ((filegui_nonattrs_fs_t) stfs.f_type)
{
case MSDOS_SUPER_MAGIC:
@ -259,8 +293,7 @@ filegui__check_attrs_on_fs (const char *fs_path)
default:
break;
}
#elif defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) \
|| defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
#elif defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME) || defined(HAVE_STRUCT_STATFS_F_FSTYPENAME)
if (strcmp (stfs.STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME, "msdos") == 0
|| strcmp (stfs.STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME, "msdosfs") == 0
|| strcmp (stfs.STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME, "ntfs") == 0
@ -276,7 +309,6 @@ filegui__check_attrs_on_fs (const char *fs_path)
|| strcmp (stfs.STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME, "fuse") == 0)
return FALSE;
#endif
#endif /* USE_STATVFS */
return TRUE;
}

View File

@ -270,6 +270,38 @@ me_remote (char const *fs_name, char const *fs_type _GL_UNUSED)
otherwise, use PROPAGATE_ALL_ONES. */
#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__))
/* The FRSIZE fallback is not required in this case. */
#undef STAT_STATFS2_FRSIZE
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
#ifdef STAT_READ_FILSYS /* SVR2 */
/* Set errno to zero upon EOF. */
#define ZERO_BYTE_TRANSFER_ERRNO 0
@ -1300,126 +1332,146 @@ full_read (int fd, void *buf, size_t count)
static int
get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
{
#ifdef 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)
return -1;
if (statvfs (file, &vfsd) < 0)
return -1;
/* f_frsize isn't guaranteed to be supported. */
/* *INDENT-OFF* */
fsp->fsu_blocksize = fsd.f_frsize
? PROPAGATE_ALL_ONES (fsd.f_frsize)
: PROPAGATE_ALL_ONES (fsd.f_bsize);
/* *INDENT-ON* */
/* f_frsize isn't guaranteed to be supported. */
fsp->fsu_blocksize = (vfsd.f_frsize
? PROPAGATE_ALL_ONES (vfsd.f_frsize)
: 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);
}
else
#endif
struct statvfs64 fsd;
{
#if defined STAT_STATVFS64 /* AIX */
if (statvfs64 (file, &fsd) < 0)
return -1;
struct statvfs64 fsd;
/* f_frsize isn't guaranteed to be supported. */
/* *INDENT-OFF* */
fsp->fsu_blocksize = fsd.f_frsize
? PROPAGATE_ALL_ONES (fsd.f_frsize)
: PROPAGATE_ALL_ONES (fsd.f_bsize);
/* *INDENT-ON* */
if (statvfs64 (file, &fsd) < 0)
return -1;
/* f_frsize isn't guaranteed to be supported. */
/* *INDENT-OFF* */
fsp->fsu_blocksize = fsd.f_frsize
? PROPAGATE_ALL_ONES (fsd.f_frsize)
: PROPAGATE_ALL_ONES (fsd.f_bsize);
/* *INDENT-ON* */
#elif defined STAT_STATFS2_FS_DATA /* Ultrix */
struct fs_data fsd;
struct fs_data fsd;
if (statfs (file, &fsd) != 1)
return -1;
if (statfs (file, &fsd) != 1)
return -1;
fsp->fsu_blocksize = 1024;
fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.fd_req.btot);
fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.fd_req.bfree);
fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.fd_req.bfreen);
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0;
fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot);
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree);
fsp->fsu_blocksize = 1024;
fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.fd_req.btot);
fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.fd_req.bfree);
fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.fd_req.bfreen);
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0;
fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot);
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree);
#elif defined STAT_READ_FILSYS /* SVR2 */
#ifndef SUPERBOFF
#define SUPERBOFF (SUPERB * 512)
#endif
struct filsys fsd;
int fd;
struct filsys fsd;
int fd;
if (!disk)
{
errno = 0;
return -1;
}
if (!disk)
{
errno = 0;
return -1;
}
fd = open (disk, O_RDONLY);
if (fd < 0)
return -1;
lseek (fd, (off_t) SUPERBOFF, 0);
if (full_read (fd, (char *) &fsd, sizeof (fsd)) != sizeof (fsd))
{
fd = open (disk, O_RDONLY);
if (fd < 0)
return -1;
lseek (fd, (off_t) SUPERBOFF, 0);
if (full_read (fd, (char *) &fsd, sizeof (fsd)) != sizeof (fsd))
{
close (fd);
return -1;
}
close (fd);
return -1;
}
close (fd);
fsp->fsu_blocksize = (fsd.s_type == Fs2b ? 1024 : 512);
fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.s_fsize);
fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.s_tfree);
fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.s_tfree);
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.s_tfree) != 0;
fsp->fsu_files = (fsd.s_isize == -1
? UINTMAX_MAX : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1));
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode);
fsp->fsu_blocksize = (fsd.s_type == Fs2b ? 1024 : 512);
fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.s_fsize);
fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.s_tfree);
fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.s_tfree);
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.s_tfree) != 0;
fsp->fsu_files = (fsd.s_isize == -1
? UINTMAX_MAX : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1));
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode);
#elif defined STAT_STATFS3_OSF1 /* OSF/1 */
struct statfs fsd;
struct statfs fsd;
if (statfs (file, &fsd, sizeof (struct statfs)) != 0)
return -1;
if (statfs (file, &fsd, sizeof (struct statfs)) != 0)
return -1;
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
#elif defined STAT_STATFS2_BSIZE /* glibc/Linux, 4.3BSD, SunOS 4, \
#elif defined STAT_STATFS2_FRSIZE /* 2.6 < glibc/Linux < 2.6.36 */
struct statfs fsd;
if (statfs (file, &fsd) < 0)
return -1;
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_frsize);
#elif defined STAT_STATFS2_BSIZE /* glibc/Linux < 2.6, 4.3BSD, SunOS 4, \
Mac OS X < 10.4, FreeBSD < 5.0, \
NetBSD < 3.0, OpenBSD < 4.4 */
struct statfs fsd;
struct statfs fsd;
if (statfs (file, &fsd) < 0)
return -1;
if (statfs (file, &fsd) < 0)
return -1;
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
#ifdef STATFS_TRUNCATES_BLOCK_COUNTS
/* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
struct statfs are truncated to 2GB. These conditions detect that
truncation, presumably without botching the 4.1.1 case, in which
the values are not truncated. The correct counts are stored in
undocumented spare fields. */
if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0)
{
fsd.f_blocks = fsd.f_spare[0];
fsd.f_bfree = fsd.f_spare[1];
fsd.f_bavail = fsd.f_spare[2];
}
/* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the
struct statfs are truncated to 2GB. These conditions detect that
truncation, presumably without botching the 4.1.1 case, in which
the values are not truncated. The correct counts are stored in
undocumented spare fields. */
if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0)
{
fsd.f_blocks = fsd.f_spare[0];
fsd.f_bfree = fsd.f_spare[1];
fsd.f_bavail = fsd.f_spare[2];
}
#endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
#elif defined STAT_STATFS2_FSIZE /* 4.4BSD and older NetBSD */
struct statfs fsd;
struct statfs fsd;
if (statfs (file, &fsd) < 0)
return -1;
if (statfs (file, &fsd) < 0)
return -1;
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
#elif defined STAT_STATFS4 /* SVR3, Dynix, old Irix, old AIX, \
Dolphin */
@ -1428,34 +1480,38 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
#define f_bavail f_bfree
#endif
struct statfs fsd;
struct statfs fsd;
if (statfs (file, &fsd, sizeof (fsd), 0) < 0)
return -1;
if (statfs (file, &fsd, sizeof (fsd), 0) < 0)
return -1;
/* Empirically, the block counts on most SVR3 and SVR3-derived
systems seem to always be in terms of 512-byte blocks,
no matter what value f_bsize has. */
/* Empirically, the block counts on most SVR3 and SVR3-derived
systems seem to always be in terms of 512-byte blocks,
no matter what value f_bsize has. */
#if defined _AIX || defined _CRAY
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
#else
fsp->fsu_blocksize = 512;
fsp->fsu_blocksize = 512;
#endif
#endif
#if (defined STAT_STATVFS || defined STAT_STATVFS64 \
|| (!defined STAT_STATFS2_FS_DATA && !defined STAT_READ_FILSYS))
#if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1 \
|| defined STAT_STATFS2_FRSIZE || defined STAT_STATFS2_BSIZE \
|| defined STAT_STATFS2_FSIZE || defined STAT_STATFS4)
fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);
fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree);
fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail);
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0;
fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files);
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree);
fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);
fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree);
fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail);
fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0;
fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files);
fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree);
#endif
}
(void) disk; /* avoid argument-unused warning */
return 0;
}
#endif /* HAVE_INFOMOUNT */