From: Amos Jeffries Date: Thu, 2 Oct 2014 12:07:26 +0000 (-0700) Subject: Portability: provide xstatvfs() shim for system call statvfs() X-Git-Tag: SQUID_3_5_0_1~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=615540cd6b5cf323733e3bfd5eead37f8358d478;p=thirdparty%2Fsquid.git Portability: provide xstatvfs() shim for system call statvfs() statfs() and struct statfs have been deprecated for years. Hoewver the POSIX statvfs replacements are still not universally available. Remove deprecated statfs() and struct statfs usage from Squid. Although they may still be used by the xstatvfs() compatibility wrapper if they are the only available API. --- diff --git a/acinclude/os-deps.m4 b/acinclude/os-deps.m4 index 14e5a583b3..0e13eaf5f0 100644 --- a/acinclude/os-deps.m4 +++ b/acinclude/os-deps.m4 @@ -619,6 +619,27 @@ SQUID_DEFINE_BOOL(HAVE_STATVFS,$ac_cv_func_statvfs,[set to 1 if our system has s ]) +dnl Check whether this OS defines f_frsize as a member of struct statfs +AC_DEFUN([SQUID_CHECK_F_FRSIZE_IN_STATFS],[ +AC_CACHE_CHECK([for f_frsize field in struct statfs], + ac_cv_have_f_frsize_in_struct_statfs, [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if HAVE_SYS_STATFS_H +#include +#endif +#if HAVE_SYS_STATVFS_H +#include +#endif +#if HAVE_SYS_VFS_H +#include +#endif + ]], [[ struct statfs s; s.f_frsize = 0; ]])],[ ac_cv_have_f_frsize_in_struct_statfs="yes" ],[ ac_cv_have_f_frsize_in_struct_statfs="no" + ]) +]) +SQUID_DEFINE_BOOL(HAVE_F_FRSIZE_IN_STATFS,$ac_cv_have_f_frsize_in_struct_statfs,[Define if struct statfs has field f_frsize (Linux 2.6 or later)]) +]) + + dnl check that we can use the libresolv _dns_ttl_ hack dnl sets the ac_cv_libresolv_dns_ttl_hack shell variable and defines LIBRESOLV_DNS_TTL_HACK diff --git a/compat/Makefile.am b/compat/Makefile.am index bde70b54d8..80669a21eb 100644 --- a/compat/Makefile.am +++ b/compat/Makefile.am @@ -44,6 +44,8 @@ libcompat_squid_la_SOURCES = \ psignal.h \ shm.cc \ shm.h \ + statvfs.h \ + statvfs.cc \ stdio.h \ stdvarargs.h \ strnstr.cc \ diff --git a/compat/compat.h b/compat/compat.h index 8b689dd93e..e0218e86ff 100644 --- a/compat/compat.h +++ b/compat/compat.h @@ -92,6 +92,9 @@ /* cstdio has a bunch of problems with 64-bit definitions */ #include "compat/stdio.h" +/* POSIX statvfs() is still not universal */ +#include "compat/statvfs.h" + /*****************************************************/ /* component-specific portabilities */ /*****************************************************/ diff --git a/compat/mswindows.cc b/compat/mswindows.cc index 2db599f853..c348e5cbf2 100644 --- a/compat/mswindows.cc +++ b/compat/mswindows.cc @@ -125,42 +125,6 @@ gettimeofday(struct timeval *pcur_time, void *tzp) } #endif /* !HAVE_GETTIMEOFDAY */ -#if !_SQUID_MINGW_ -int -statfs(const char *path, struct statfs *sfs) -{ - char drive[4]; - DWORD spc, bps, freec, totalc; - DWORD vsn, maxlen, flags; - - if (!sfs) { - errno = EINVAL; - return -1; - } - strncpy(drive, path, 2); - drive[2] = '\0'; - strcat(drive, "\\"); - - if (!GetDiskFreeSpace(drive, &spc, &bps, &freec, &totalc)) { - errno = ENOENT; - return -1; - } - if (!GetVolumeInformation(drive, NULL, 0, &vsn, &maxlen, &flags, NULL, 0)) { - errno = ENOENT; - return -1; - } - sfs->f_type = flags; - sfs->f_bsize = spc * bps; - sfs->f_blocks = totalc; - sfs->f_bfree = sfs->f_bavail = freec; - sfs->f_files = -1; - sfs->f_ffree = -1; - sfs->f_fsid = vsn; - sfs->f_namelen = maxlen; - return 0; -} -#endif - #if !_SQUID_MINGW_ int WIN32_ftruncate(int fd, off_t size) diff --git a/compat/os/mswindows.h b/compat/os/mswindows.h index ff06137af2..dfe053b1c3 100644 --- a/compat/os/mswindows.h +++ b/compat/os/mswindows.h @@ -245,21 +245,6 @@ struct group { char **gr_mem; /* group members */ }; -#if !_SQUID_MINGW_ -struct statfs { - long f_type; /* type of filesystem (see below) */ - long f_bsize; /* optimal transfer block size */ - long f_blocks; /* total data blocks in file system */ - long f_bfree; /* free blocks in fs */ - long f_bavail; /* free blocks avail to non-superuser */ - long f_files; /* total file nodes in file system */ - long f_ffree; /* free file nodes in fs */ - long f_fsid; /* file system id */ - long f_namelen; /* maximum length of filenames */ - long f_spare[6]; /* spare for later */ -}; -#endif - #if !HAVE_GETTIMEOFDAY struct timezone { int tz_minuteswest; /* minutes west of Greenwich */ @@ -865,9 +850,6 @@ struct rusage { SQUIDCEXTERN int chroot(const char *dirname); SQUIDCEXTERN int kill(pid_t, int); -#if !_SQUID_MINGW_ -SQUIDCEXTERN int statfs(const char *, struct statfs *); -#endif SQUIDCEXTERN struct passwd * getpwnam(char *unused); SQUIDCEXTERN struct group * getgrnam(char *unused); diff --git a/compat/statvfs.cc b/compat/statvfs.cc new file mode 100644 index 0000000000..8f83f20e5d --- /dev/null +++ b/compat/statvfs.cc @@ -0,0 +1,76 @@ +#include "squid.h" +#include "compat/statvfs.h" + +#if !HAVE_STATVFS + +// struct statfs has some member differences between OS versions +#if HAVE_F_FRSIZE_IN_STATFS +#define STATFS_FRSIZE(x) (x).f_frsize +#else +#define STATFS_FRSIZE(x) (x).f_bsize +#endif + +int +xstatvfs(const char *path, struct statvfs *sfs) +{ +#if !HAVE_STATFS && _SQUID_WINDOWS_ + char drive[4]; + DWORD spc, bps, freec, totalc; + DWORD vsn, maxlen, flags; + + if (!sfs) { + errno = EINVAL; + return -1; + } + strncpy(drive, path, 2); + drive[2] = '\0'; + strcat(drive, "\\"); + + if (!GetDiskFreeSpace(drive, &spc, &bps, &freec, &totalc)) { + errno = ENOENT; + return -1; + } + if (!GetVolumeInformation(drive, NULL, 0, &vsn, &maxlen, &flags, NULL, 0)) { + errno = ENOENT; + return -1; + } + + memset(sfs, 0, sizeof(*sfs)); + + sfs->f_bsize = sfs->f_frsize = spc * bps; /* file system block size, fragment size */ + sfs->f_blocks = totalc; /* size of fs in f_frsize units */ + sfs->f_bfree = sfs->f_bavail = freec; /* # free blocks total, and available for unprivileged users */ + sfs->f_files = sfs->f_ffree = sfs->f_favail = -1; /* # inodes total, free, and available for unprivileged users */ + sfs->f_fsid = vsn; /* file system ID */ + sfs->f_namemax = maxlen; /* maximum filename length */ + return 0; + +#elif HAVE_STATFS + // use statfs() and map results from struct statfs to struct statvfs + struct statfs tmpSfs; + + if (int x = statfs(path, &tmpSfs)) + return x; + + memset(sfs, 0, sizeof(*sfs)); + + sfs->f_bsize = tmpSfs.f_bsize; /* file system block size */ + sfs->f_frsize = STATFS_FRSIZE(tmpSfs); /* fragment size */ + sfs->f_blocks = tmpSfs.f_blocks; /* size of fs in f_frsize units */ + sfs->f_bfree = tmpSfs.f_bfree; /* # free blocks */ + sfs->f_bavail = tmpSfs.f_bavail; /* # free blocks for unprivileged users */ + sfs->f_files = tmpSfs.f_files; /* # inodes */ + sfs->f_ffree = tmpSfs.f_ffree; /* # free inodes */ + sfs->f_favail = tmpSfs.f_ffree; /* # free inodes for unprivileged users */ + sfs->f_fsid = tmpSfs.f_fsid; /* file system ID */ + sfs->f_namemax = tmpSfs.f_namelen; /* maximum filename length */ + +#else +#error Both statvfs() and statfs() system calls are missing. + errno = ENOSYS; + return -1; + +#endif +} + +#endif /* HAVE_STATVFS */ diff --git a/compat/statvfs.h b/compat/statvfs.h new file mode 100644 index 0000000000..3b292ad203 --- /dev/null +++ b/compat/statvfs.h @@ -0,0 +1,57 @@ +#ifndef _SQUID_COMPAT_XSTATVFS_H +#define _SQUID_COMPAT_XSTATVFS_H + +#if HAVE_SYS_STATVFS_H && HAVE_STATVFS +#include +#endif + +/* Windows and Linux use sys/vfs.h */ +#if HAVE_SYS_VFS_H +#include +#endif + +/* BSD and old Linux use sys/statfs.h */ +#if !HAVE_STATVFS +#if HAVE_SYS_STATFS_H +#include +#endif +/* statfs() needs and on BSD systems */ +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_MOUNT_H +#include +#endif +#endif /* !HAVE_STATVFS */ + + +#if HAVE_STATVFS +#define xstatvfs statvfs + +#else + +typedef unsigned long fsblkcnt_t; +typedef unsigned long fsfilcnt_t; + +struct statvfs { + unsigned long f_bsize; /* file system block size */ + unsigned long f_frsize; /* fragment size */ + fsblkcnt_t f_blocks; /* size of fs in f_frsize units */ + fsblkcnt_t f_bfree; /* # free blocks */ + fsblkcnt_t f_bavail; /* # free blocks for unprivileged users */ + fsfilcnt_t f_files; /* # inodes */ + fsfilcnt_t f_ffree; /* # free inodes */ + fsfilcnt_t f_favail; /* # free inodes for unprivileged users */ + unsigned long f_fsid; /* file system ID */ + unsigned long f_flag; /* mount flags */ + unsigned long f_namemax; /* maximum filename length */ +}; + +#if defined(__cplusplus) +extern "C" +#endif +int xstatvfs(const char *path, struct statvfs *buf); + +#endif + +#endif /* _SQUID_COMPAT_XSTATVFS_H */ diff --git a/configure.ac b/configure.ac index 0256b9286f..e4e85c420a 100644 --- a/configure.ac +++ b/configure.ac @@ -2804,7 +2804,6 @@ AC_CHECK_HEADERS( \ sys/shm.h \ sys/socket.h \ sys/stat.h \ - sys/statvfs.h \ syscall.h \ sys/syscall.h \ sys/time.h \ @@ -3300,11 +3299,6 @@ if test "x$ac_cv_func_poll" = "x" ; then esac fi -dnl Override statfs() detect on MinGW because it is emulated in source code -if test "x$squid_host_os" = "xmingw" ; then - ac_cv_func_statfs='yes' -fi - dnl Check for library functions AC_CHECK_FUNCS(\ backtrace_symbols_fd \ @@ -3361,7 +3355,6 @@ AC_CHECK_FUNCS(\ socketpair \ srand48 \ srandom \ - statfs \ sysconf \ syslog \ timegm \ @@ -3666,10 +3659,15 @@ SQUID_CHECK_MAXPATHLEN SQUID_CHECK_LIBRESOLV_DNS_TTL_HACK SQUID_CHECK_RESOLVER_FIELDS +AC_CHECK_HEADERS(sys/statvfs.h) if test "x$ac_cv_header_sys_statvfs_h" = "xyes" ; then SQUID_CHECK_WORKING_STATVFS fi - +if test "x$ac_cv_func_statvfs" != "xyes" ; then + AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/vfs.h sys/statfs.h) + AC_CHECK_FUNCS(statfs) + SQUID_CHECK_F_FRSIZE_IN_STATFS +fi dnl Squid will not usually attempt to translate templates when building AC_ARG_ENABLE(translation, diff --git a/src/store_dir.cc b/src/store_dir.cc index 812466665c..c79954102e 100644 --- a/src/store_dir.cc +++ b/src/store_dir.cc @@ -27,22 +27,6 @@ #include #include -#if HAVE_STATVFS -#if HAVE_SYS_STATVFS_H -#include -#endif -#endif /* HAVE_STATVFS */ -/* statfs() needs and on BSD systems */ -#if HAVE_SYS_PARAM_H -#include -#endif -#if HAVE_SYS_MOUNT_H -#include -#endif -/* Windows and Linux use sys/vfs.h */ -#if HAVE_SYS_VFS_H -#include -#endif #if HAVE_SYS_WAIT_H #include #endif @@ -556,33 +540,17 @@ StoreController::callback() int storeDirGetBlkSize(const char *path, int *blksize) { -#if HAVE_STATVFS - struct statvfs sfs; - if (statvfs(path, &sfs)) { + if (xstatvfs(path, &sfs)) { debugs(50, DBG_IMPORTANT, "" << path << ": " << xstrerror()); *blksize = 2048; return 1; } *blksize = (int) sfs.f_frsize; -#else - - struct statfs sfs; - - if (statfs(path, &sfs)) { - debugs(50, DBG_IMPORTANT, "" << path << ": " << xstrerror()); - *blksize = 2048; - return 1; - } - - *blksize = (int) sfs.f_bsize; -#endif - /* - * Sanity check; make sure we have a meaningful value. - */ + // Sanity check; make sure we have a meaningful value. if (*blksize < 512) *blksize = 2048; @@ -595,11 +563,9 @@ storeDirGetBlkSize(const char *path, int *blksize) int storeDirGetUFSStats(const char *path, int *totl_kb, int *free_kb, int *totl_in, int *free_in) { -#if HAVE_STATVFS - struct statvfs sfs; - if (statvfs(path, &sfs)) { + if (xstatvfs(path, &sfs)) { debugs(50, DBG_IMPORTANT, "" << path << ": " << xstrerror()); return 1; } @@ -608,21 +574,6 @@ storeDirGetUFSStats(const char *path, int *totl_kb, int *free_kb, int *totl_in, *free_kb = (int) fsbtoblk(sfs.f_bfree, sfs.f_frsize, 1024); *totl_in = (int) sfs.f_files; *free_in = (int) sfs.f_ffree; -#else - - struct statfs sfs; - - if (statfs(path, &sfs)) { - debugs(50, DBG_IMPORTANT, "" << path << ": " << xstrerror()); - return 1; - } - - *totl_kb = (int) fsbtoblk(sfs.f_blocks, sfs.f_bsize, 1024); - *free_kb = (int) fsbtoblk(sfs.f_bfree, sfs.f_bsize, 1024); - *totl_in = (int) sfs.f_files; - *free_in = (int) sfs.f_ffree; -#endif - return 0; }