#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"
guestfs_int_statvfs *
do_statvfs (const char *path)
{
+#ifdef HAVE_STATVFS
int r;
guestfs_int_statvfs *ret;
struct statvfs statbuf;
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 */
}