From 579465ec1f4fdb1789bf94ac7356a3c961f3ae93 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Wed, 25 Nov 2009 13:07:05 +0000 Subject: [PATCH] daemon/Win32: Implement statvfs using GetDiskFreeSpaceEx. At the time of writing Gnulib didn't support Win32 for its fsusage API. Therefore this patch uses GetDiskFreeSpaceEx if it's available (on Windows) otherwise falls back to using Gnulib fsusage. --- daemon/.gitignore | 5 ++ daemon/configure.ac | 2 + daemon/m4/gnulib-cache.m4 | 3 +- daemon/statvfs.c | 120 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 128 insertions(+), 2 deletions(-) diff --git a/daemon/.gitignore b/daemon/.gitignore index 9168142..0cc1e13 100644 --- a/daemon/.gitignore +++ b/daemon/.gitignore @@ -30,6 +30,7 @@ m4/fcntl_h.m4 m4/fdopendir.m4 m4/float_h.m4 m4/fnmatch.m4 +m4/fsusage.m4 m4/futimens.m4 m4/getcwd-abort-bug.m4 m4/getcwd-path-max.m4 @@ -91,6 +92,8 @@ m4/rawmemchr.m4 m4/readlink.m4 m4/realloc.m4 m4/rmdir.m4 +m4/safe-read.m4 +m4/safe-write.m4 m4/save-cwd.m4 m4/select.m4 m4/size_max.m4 @@ -98,6 +101,7 @@ m4/sleep.m4 m4/sockets.m4 m4/socklen.m4 m4/sockpfaf.m4 +m4/ssize_t.m4 m4/stat-time.m4 m4/stat.m4 m4/stdbool.m4 @@ -139,6 +143,7 @@ m4/wchar_t.m4 m4/wctob.m4 m4/wctype.m4 m4/wint_t.m4 +m4/write.m4 m4/xalloc.m4 m4/xgetcwd.m4 m4/xsize.m4 diff --git a/daemon/configure.ac b/daemon/configure.ac index c7025dd..bd0bdbe 100644 --- a/daemon/configure.ac +++ b/daemon/configure.ac @@ -181,6 +181,7 @@ AC_CHECK_FUNCS([\ posix_fallocate \ removexattr \ setxattr \ + statvfs \ sync]) dnl Headers. @@ -188,6 +189,7 @@ AC_CHECK_HEADERS([\ attr/xattr.h \ printf.h \ sys/inotify.h \ + sys/statvfs.h \ sys/xattr.h \ windows.h]) diff --git a/daemon/m4/gnulib-cache.m4 b/daemon/m4/gnulib-cache.m4 index 2b63258..a9b19e9 100644 --- a/daemon/m4/gnulib-cache.m4 +++ b/daemon/m4/gnulib-cache.m4 @@ -15,12 +15,13 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --with-tests --no-libtool --macro-prefix=gl c-ctype futimens getline glob hash ignore-value manywarnings mkdtemp netdb openat readlink select sleep strchrnul strndup sys_select sys_wait vasprintf warnings +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --with-tests --no-libtool --macro-prefix=gl c-ctype fsusage futimens getline glob hash ignore-value manywarnings mkdtemp netdb openat readlink select sleep strchrnul strndup sys_select sys_wait vasprintf warnings # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) gl_MODULES([ c-ctype + fsusage futimens getline glob diff --git a/daemon/statvfs.c b/daemon/statvfs.c index 40df9b9..e71b19a 100644 --- a/daemon/statvfs.c +++ b/daemon/statvfs.c @@ -18,14 +18,23 @@ #include +#ifdef HAVE_WINDOWS_H +#include +#endif + #include #include #include #include -#include #include #include +#ifdef HAVE_SYS_STATVFS_H +#include +#endif + +#include + #include "../src/guestfs_protocol.h" #include "daemon.h" #include "actions.h" @@ -33,6 +42,7 @@ guestfs_int_statvfs * do_statvfs (const char *path) { +#ifdef HAVE_STATVFS int r; guestfs_int_statvfs *ret; struct statvfs statbuf; @@ -65,4 +75,112 @@ do_statvfs (const char *path) ret->namemax = statbuf.f_namemax; return ret; + +#else /* !HAVE_STATVFS */ +# if WIN32 + + char *disk; + guestfs_int_statvfs *ret; + ULONGLONG free_bytes_available; /* for user - similar to bavail */ + ULONGLONG total_number_of_bytes; + ULONGLONG total_number_of_free_bytes; /* for everyone - bfree */ + + disk = sysroot_path (path); + if (!disk) { + reply_with_perror ("malloc"); + return NULL; + } + + if (!GetDiskFreeSpaceEx (disk, + (PULARGE_INTEGER) &free_bytes_available, + (PULARGE_INTEGER) &total_number_of_bytes, + (PULARGE_INTEGER) &total_number_of_free_bytes)) { + reply_with_perror ("GetDiskFreeSpaceEx"); + free (disk); + return NULL; + } + free (disk); + + ret = malloc (sizeof *ret); + if (ret == NULL) { + reply_with_perror ("malloc"); + return NULL; + } + + /* XXX I couldn't determine how to get block size. MSDN has a + * unhelpful hard-coded list here: + * http://support.microsoft.com/kb/140365 + * but this depends on the filesystem type, the size of the disk and + * the version of Windows. So this code assumes the disk is NTFS + * and the version of Windows is >= Win2K. + */ + if (total_number_of_bytes < 16ULL * 1024 * 1024 * 1024 * 1024) + ret->bsize = 4096; + else if (total_number_of_bytes < 32ULL * 1024 * 1024 * 1024 * 1024) + ret->bsize = 8192; + else if (total_number_of_bytes < 64ULL * 1024 * 1024 * 1024 * 1024) + ret->bsize = 16384; + else if (total_number_of_bytes < 128ULL * 1024 * 1024 * 1024 * 1024) + ret->bsize = 32768; + else + ret->bsize = 65536; + + /* As with stat, -1 indicates a field is not known. */ + ret->frsize = ret->bsize; + ret->blocks = total_number_of_bytes / ret->bsize; + ret->bfree = total_number_of_free_bytes / ret->bsize; + ret->bavail = free_bytes_available / ret->bsize; + ret->files = -1; + ret->ffree = -1; + ret->favail = -1; + ret->fsid = -1; + ret->flag = -1; + ret->namemax = FILENAME_MAX; + + return ret; + +# else /* !WIN32 */ + + char *disk; + int r; + guestfs_int_statvfs *ret; + struct fs_usage fsu; + + disk = sysroot_path (path); + if (!disk) { + reply_with_perror ("malloc"); + return NULL; + } + + r = get_fs_usage (disk, disk, &fsu); + free (disk); + + if (r == -1) { + reply_with_perror ("get_fs_usage: %s", path); + return NULL; + } + + ret = malloc (sizeof *ret); + if (ret == NULL) { + reply_with_perror ("malloc"); + return NULL; + } + + /* As with stat, -1 indicates a field is not known. */ + ret->bsize = fsu.f_bsize; + ret->frsize = -1; + ret->blocks = fsu.f_blocks; + ret->bfree = fsu.f_bfree; + ret->bavail = fsu.f_bavail; + ret->files = fsu.f_files; + ret->ffree = fsu.f_ffree; + ret->favail = -1; + ret->fsid = -1; + ret->flag = -1; + ret->namemax = -1; + + return ret; + +# endif /* !WIN32 */ +#endif /* !HAVE_STATVFS */ } -- 1.8.3.1