[Libguestfs] [PATCH 2/2] daemon/Win32: Implement statvfs using GetDiskFreeSpaceEx.

Richard W.M. Jones rjones at redhat.com
Wed Nov 25 13:15:04 UTC 2009


-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
virt-top is 'top' for virtual machines.  Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://et.redhat.com/~rjones/virt-top
-------------- next part --------------
>From c55f7b7e21a392cb7a5d05fb56a34597688adc0e Mon Sep 17 00:00:00 2001
From: Richard Jones <rjones at redhat.com>
Date: Wed, 25 Nov 2009 13:07:05 +0000
Subject: [PATCH 2/2] 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 955f7f9..5924eb3 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
@@ -89,6 +90,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
@@ -96,6 +99,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
@@ -137,6 +141,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 d929a0d..1cc065d 100644
--- a/daemon/configure.ac
+++ b/daemon/configure.ac
@@ -182,6 +182,7 @@ AC_CHECK_FUNCS([\
         pread \
         removexattr \
         setxattr \
+        statvfs \
         sync])
 
 dnl Headers.
@@ -189,6 +190,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 5e1d99c..280757d 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 <config.h>
 
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
-#include <sys/statvfs.h>
 #include <fcntl.h>
 #include <unistd.h>
 
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+
+#include <fsusage.h>
+
 #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.6.5.2



More information about the Libguestfs mailing list