[Libguestfs] [PATCH 1/2] daemon: Reimplement statvfs API in OCaml.

Richard W.M. Jones rjones at redhat.com
Mon Oct 2 21:43:54 UTC 2017


common/mlutils: Unix_utils.StatVFS.statvfs: This commit implements a
full-featured binding for the statvfs(3) function which also includes
the statfs(2) f_type field.

We then use this to reimplement the daemon statvfs API in OCaml.

Note that the Gnulib fallback is fixed in this commit.  It previously
referenced non-existent field names in the fs_usage struct.
---
 common/mlutils/unix_utils-c.c | 171 ++++++++++++++++++++++++++++++++++++---
 common/mlutils/unix_utils.ml  |  22 ++++-
 common/mlutils/unix_utils.mli |  26 +++++-
 daemon/Makefile.am            |  11 ++-
 daemon/statvfs.c              | 184 ------------------------------------------
 daemon/statvfs.ml             |  43 ++++++++++
 daemon/statvfs.mli            |  33 ++++++++
 docs/C_SOURCE_FILES           |   1 -
 generator/actions_core.ml     |   1 +
 m4/guestfs_libraries.m4       |   5 +-
 po/POTFILES                   |   1 -
 sparsify/copying.ml           |   2 +-
 v2v/v2v.ml                    |   2 +-
 13 files changed, 294 insertions(+), 208 deletions(-)

diff --git a/common/mlutils/unix_utils-c.c b/common/mlutils/unix_utils-c.c
index 631f1fddd..95501ba22 100644
--- a/common/mlutils/unix_utils-c.c
+++ b/common/mlutils/unix_utils-c.c
@@ -27,7 +27,18 @@
 #include <fnmatch.h>
 #include <errno.h>
 #include <sys/types.h>
+
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
+
+#ifdef HAVE_SYS_STATVFS_H
 #include <sys/statvfs.h>
+#endif
+
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
 
 #if MAJOR_IN_MKDEV
 #include <sys/mkdev.h>
@@ -36,12 +47,20 @@
 /* else it's in sys/types.h, included above */
 #endif
 
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
 #include <caml/alloc.h>
 #include <caml/fail.h>
 #include <caml/memory.h>
 #include <caml/mlvalues.h>
 #include <caml/unixsupport.h>
 
+#include "fsusage.h"
+
+#include "cleanups.h"
+
 extern value guestfs_int_mllib_dev_t_makedev (value majv, value minv);
 extern value guestfs_int_mllib_dev_t_major (value devv);
 extern value guestfs_int_mllib_dev_t_minor (value devv);
@@ -52,7 +71,7 @@ extern value guestfs_int_mllib_sync (value unitv);
 extern value guestfs_int_mllib_fsync_file (value filenamev);
 extern value guestfs_int_mllib_mkdtemp (value val_pattern);
 extern value guestfs_int_mllib_realpath (value pathv);
-extern value guestfs_int_mllib_statvfs_free_space (value pathv);
+extern value guestfs_int_mllib_statvfs_statvfs (value pathv);
 
 /* NB: This is a "noalloc" call. */
 value
@@ -207,20 +226,150 @@ guestfs_int_mllib_realpath (value pathv)
 }
 
 value
-guestfs_int_mllib_statvfs_free_space (value pathv)
+guestfs_int_mllib_statvfs_statvfs (value pathv)
 {
   CAMLparam1 (pathv);
-  CAMLlocal1 (rv);
-  struct statvfs buf;
-  int64_t free_space;
+  int64_t f_bsize;
+  int64_t f_frsize;
+  int64_t f_blocks;
+  int64_t f_bfree;
+  int64_t f_bavail;
+  int64_t f_files;
+  int64_t f_ffree;
+  int64_t f_favail;
+  int64_t f_fsid;
+  int64_t f_flag;
+  int64_t f_namemax;
+  int64_t f_type;
+  CAMLlocal2 (rv, v);
 
-  if (statvfs (String_val (pathv), &buf) == -1) {
-    perror ("statvfs");
-    caml_failwith ("statvfs");
-  }
+#ifdef HAVE_FSTATVFS
+  CLEANUP_CLOSE int fd = -1;
+  struct statvfs buf1;
+#ifdef HAVE_FSTATFS
+  struct statfs buf2;
+#endif
 
-  free_space = (int64_t) buf.f_bsize * buf.f_bavail;
-  rv = caml_copy_int64 (free_space);
+  fd = open (String_val (pathv), O_RDONLY);
+  if (fd == -1)
+    unix_error (errno, (char *) "statvfs: open", pathv);
+  if (fstatvfs (fd, &buf1) == -1)
+    unix_error (errno, (char *) "statvfs: statvfs", pathv);
+#ifdef HAVE_FSTATFS
+  if (fstatfs (fd, &buf2) == -1)
+    unix_error (errno, (char *) "statvfs: statfs", pathv);
+#endif
+
+  f_bsize = buf1.f_bsize;
+  f_frsize = buf1.f_frsize;
+  f_blocks = buf1.f_blocks;
+  f_bfree = buf1.f_bfree;
+  f_bavail = buf1.f_bavail;
+  f_files = buf1.f_files;
+  f_ffree = buf1.f_ffree;
+  f_favail = buf1.f_favail;
+  f_fsid = buf1.f_fsid;
+  f_flag = buf1.f_flag;
+  f_namemax = buf1.f_namemax;
+#ifdef HAVE_FSTATFS
+  f_type = buf2.f_type;
+#else
+  f_type = -1;
+#endif
+
+#else /* !HAVE_FSTATVFS */
+#  if WIN32
+  ULONGLONG free_bytes_available; /* for user - similar to bavail */
+  ULONGLONG total_number_of_bytes;
+  ULONGLONG total_number_of_free_bytes; /* for everyone - bfree */
+
+  if (!GetDiskFreeSpaceEx (String_val (pathv),
+                           (PULARGE_INTEGER) &free_bytes_available,
+                           (PULARGE_INTEGER) &total_number_of_bytes,
+                           (PULARGE_INTEGER) &total_number_of_free_bytes))
+    unix_error (EIO, (char *) "statvfs: GetDiskFreeSpaceEx", pathv);
+
+  /* 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 < UINT64_C (16) * 1024 * 1024 * 1024 * 1024)
+    f_bsize = 4096;
+  else if (total_number_of_bytes < UINT64_C (32) * 1024 * 1024 * 1024 * 1024)
+    f_bsize = 8192;
+  else if (total_number_of_bytes < UINT64_C (64) * 1024 * 1024 * 1024 * 1024)
+    f_bsize = 16384;
+  else if (total_number_of_bytes < UINT64_C (128) * 1024 * 1024 * 1024 * 1024)
+    f_bsize = 32768;
+  else
+    f_bsize = 65536;
+
+  /* As with stat, -1 indicates a field is not known. */
+  f_frsize = ret->bsize;
+  f_blocks = total_number_of_bytes / ret->bsize;
+  f_bfree = total_number_of_free_bytes / ret->bsize;
+  f_bavail = free_bytes_available / ret->bsize;
+  f_files = -1;
+  f_ffree = -1;
+  f_favail = -1;
+  f_fsid = -1;
+  f_flag = -1;
+  f_namemax = FILENAME_MAX;
+  f_type = -1;
+
+#  else /* !WIN32 */
+  /* This replacement function is provided by Gnulib. */
+  struct fs_usage fsu;
+
+  if (get_fs_usage (String_val (pathv), String_val (pathv), &fsu) == -1)
+    unix_error (EIO, (char *) "statvfs: get_fs_usage", pathv);
+
+  /* As with stat, -1 indicates a field is not known. */
+  f_bsize = fsu.fsu_bsize;
+  f_frsize = -1;
+  f_blocks = fsu.fsu_blocks;
+  f_bfree = fsu.fsu_bfree;
+  f_bavail = fsu.fsu_bavail;
+  f_files = fsu.fsu_files;
+  f_free = fsu.fsu_ffree;
+  f_favail = -1;
+  f_fsid = -1;
+  f_flag = -1;
+  f_namemax = -1;
+  f_type = -1;
+
+#  endif /* !WIN32 */
+#endif /* !HAVE_FSTATVFS */
+
+  /* Construct the return struct. */
+  rv = caml_alloc (12, 0);
+  v = caml_copy_int64 (f_bsize);
+  Store_field (rv, 0, v);
+  v = caml_copy_int64 (f_frsize);
+  Store_field (rv, 1, v);
+  v = caml_copy_int64 (f_blocks);
+  Store_field (rv, 2, v);
+  v = caml_copy_int64 (f_bfree);
+  Store_field (rv, 3, v);
+  v = caml_copy_int64 (f_bavail);
+  Store_field (rv, 4, v);
+  v = caml_copy_int64 (f_files);
+  Store_field (rv, 5, v);
+  v = caml_copy_int64 (f_ffree);
+  Store_field (rv, 6, v);
+  v = caml_copy_int64 (f_favail);
+  Store_field (rv, 7, v);
+  v = caml_copy_int64 (f_fsid);
+  Store_field (rv, 8, v);
+  v = caml_copy_int64 (f_flag);
+  Store_field (rv, 9, v);
+  v = caml_copy_int64 (f_namemax);
+  Store_field (rv, 10, v);
+  v = caml_copy_int64 (f_type);
+  Store_field (rv, 11, v);
 
   CAMLreturn (rv);
 }
diff --git a/common/mlutils/unix_utils.ml b/common/mlutils/unix_utils.ml
index b135bcaee..3eb3ac890 100644
--- a/common/mlutils/unix_utils.ml
+++ b/common/mlutils/unix_utils.ml
@@ -16,6 +16,8 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
+open Std_utils
+
 module Dev_t = struct
   external makedev : int -> int -> int = "guestfs_int_mllib_dev_t_makedev" "noalloc"
   external major : int -> int = "guestfs_int_mllib_dev_t_major" "noalloc"
@@ -61,6 +63,22 @@ module Realpath = struct
 end
 
 module StatVFS = struct
-  external free_space : string -> int64 =
-    "guestfs_int_mllib_statvfs_free_space"
+  type statvfs = {
+    f_bsize : int64;
+    f_frsize : int64;
+    f_blocks : int64;
+    f_bfree : int64;
+    f_bavail : int64;
+    f_files : int64;
+    f_ffree : int64;
+    f_favail : int64;
+    f_fsid : int64;
+    f_flag : int64;
+    f_namemax : int64;
+    f_type : int64;
+  }
+  external statvfs : string -> statvfs =
+    "guestfs_int_mllib_statvfs_statvfs"
+
+  let free_space { f_bsize = bsize; f_bavail = bavail } = bsize *^ bavail
 end
diff --git a/common/mlutils/unix_utils.mli b/common/mlutils/unix_utils.mli
index f4f8ca578..385791cac 100644
--- a/common/mlutils/unix_utils.mli
+++ b/common/mlutils/unix_utils.mli
@@ -94,7 +94,29 @@ module Realpath : sig
 end
 
 module StatVFS : sig
-  val free_space : string -> int64
-  (** [free_space path] returns the free space available on the
+  type statvfs = {
+    f_bsize : int64;            (** Filesystem block size *)
+    f_frsize : int64;           (** Fragment size *)
+    f_blocks : int64;           (** Size of fs in f_frsize units *)
+    f_bfree : int64;            (** Number of free blocks *)
+    f_bavail : int64;           (** Number of free blocks for non-root *)
+    f_files : int64;            (** Number of inodes *)
+    f_ffree : int64;            (** Number of free inodes *)
+    f_favail : int64;           (** Number of free inodes for non-root *)
+    f_fsid : int64;             (** Filesystem ID *)
+    f_flag : int64;             (** Mount flags *)
+    f_namemax : int64;          (** Maximum length of filenames *)
+    f_type : int64;             (** Type of filesystem (see statfs(2)) *)
+  }
+  val statvfs : string -> statvfs
+  (** This is a combination of [statvfs(3)] and one extra field from
+      [statfs(2)].  The main fields are returned by calling [statvfs(3)]
+      on the given path.  The [f_type] field is returned from [statfs(2)].
+
+      In case of non-Linux or non-POSIX, this call is emulated as best
+      we can with missing fields returned as [-1]. *)
+
+  val free_space : statvfs -> int64
+  (** [free_space (statvfs path)] returns the free space available on the
       filesystem that contains [path], in bytes. *)
 end
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 61cfb5caa..070fe4ddc 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -154,7 +154,6 @@ guestfsd_SOURCES = \
 	sleuthkit.c \
 	squashfs.c \
 	stat.c \
-	statvfs.c \
 	strings.c \
 	structs-cleanups.c \
 	structs-cleanups.h \
@@ -274,6 +273,7 @@ SOURCES_MLI = \
 	optgroups.mli \
 	parted.mli \
 	realpath.mli \
+	statvfs.mli \
 	structs.mli \
 	sysroot.mli \
 	utils.mli
@@ -300,6 +300,7 @@ SOURCES_ML = \
 	parted.ml \
 	listfs.ml \
 	realpath.ml \
+	statvfs.ml \
 	inspect_types.ml \
 	inspect_utils.ml \
 	inspect_fs_unix_fstab.ml \
@@ -348,8 +349,10 @@ camldaemon.o: $(OBJECTS)
 	$(OCAMLFIND) $(BEST) -output-obj -o $@ \
 	    $(OCAMLFLAGS) $(OCAMLPACKAGES) \
 	    -linkpkg \
-	    mlaugeas.$(MLARCHIVE) mlpcre.$(MLARCHIVE) \
-	    mlcutils.$(MLARCHIVE) mlstdutils.$(MLARCHIVE) \
+	    mlaugeas.$(MLARCHIVE) \
+	    mlpcre.$(MLARCHIVE) \
+	    mlstdutils.$(MLARCHIVE) \
+	    mlcutils.$(MLARCHIVE) \
 	    $(OBJECTS)
 
 # OCaml dependencies.
@@ -399,8 +402,8 @@ endif
 
 OCAMLLINKFLAGS = \
 	mlpcre.$(MLARCHIVE) \
-	mlcutils.$(MLARCHIVE) \
 	mlstdutils.$(MLARCHIVE) \
+	mlcutils.$(MLARCHIVE) \
 	mlaugeas.$(MLARCHIVE) \
 	$(LINK_CUSTOM_OCAMLC_ONLY)
 
diff --git a/daemon/statvfs.c b/daemon/statvfs.c
deleted file mode 100644
index 987537d1f..000000000
--- a/daemon/statvfs.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#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 <fcntl.h>
-#include <unistd.h>
-#include <stdint.h>
-
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-
-#include <fsusage.h>
-
-#include "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;
-
-  CHROOT_IN;
-  r = statvfs (path, &statbuf);
-  CHROOT_OUT;
-
-  if (r == -1) {
-    reply_with_perror ("statvfs");
-    return NULL;
-  }
-
-  ret = malloc (sizeof *ret);
-  if (ret == NULL) {
-    reply_with_perror ("malloc");
-    return NULL;
-  }
-
-  ret->bsize = statbuf.f_bsize;
-  ret->frsize = statbuf.f_frsize;
-  ret->blocks = statbuf.f_blocks;
-  ret->bfree = statbuf.f_bfree;
-  ret->bavail = statbuf.f_bavail;
-  ret->files = statbuf.f_files;
-  ret->ffree = statbuf.f_ffree;
-  ret->favail = statbuf.f_favail;
-  ret->fsid = statbuf.f_fsid;
-  ret->flag = statbuf.f_flag;
-  ret->namemax = statbuf.f_namemax;
-
-  return ret;
-
-#else /* !HAVE_STATVFS */
-#  if WIN32
-
-  CLEANUP_FREE char *disk = NULL;
-  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");
-    return NULL;
-  }
-
-  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 < UINT64_C (16) * 1024 * 1024 * 1024 * 1024)
-    ret->bsize = 4096;
-  else if (total_number_of_bytes < UINT64_C (32) * 1024 * 1024 * 1024 * 1024)
-    ret->bsize = 8192;
-  else if (total_number_of_bytes < UINT64_C (64) * 1024 * 1024 * 1024 * 1024)
-    ret->bsize = 16384;
-  else if (total_number_of_bytes < UINT64_C (128) * 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 */
-
-  CLEANUP_FREE char *disk = NULL;
-  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);
-
-  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 */
-}
diff --git a/daemon/statvfs.ml b/daemon/statvfs.ml
new file mode 100644
index 000000000..9e1ad7ec9
--- /dev/null
+++ b/daemon/statvfs.ml
@@ -0,0 +1,43 @@
+(* guestfs-inspection
+ * Copyright (C) 2009-2017 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Unix_utils
+
+include Structs
+
+let statvfs path =
+  let chroot = Chroot.create ~name:(Printf.sprintf "statvfs: %s" path) () in
+  let r = Chroot.f chroot Unix_utils.StatVFS.statvfs path in
+
+  (* [r : Unix_utils.StatVFS.statvfs] is superficially similar to
+   * the guestfs [statvfs] structure, but not the same.  We have to
+   * copy the fields.
+   *)
+  {
+    bsize = r.f_bsize;
+    frsize = r.f_frsize;
+    blocks = r.f_blocks;
+    bfree = r.f_bfree;
+    bavail = r.f_bavail;
+    files = r.f_files;
+    ffree = r.f_ffree;
+    favail = r.f_favail;
+    fsid = r.f_fsid;
+    flag = r.f_flag;
+    namemax = r.f_namemax;
+  }
diff --git a/daemon/statvfs.mli b/daemon/statvfs.mli
new file mode 100644
index 000000000..163ea9a15
--- /dev/null
+++ b/daemon/statvfs.mli
@@ -0,0 +1,33 @@
+(* guestfs-inspection
+ * Copyright (C) 2009-2017 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+type statvfs = {
+  bsize : int64;
+  frsize : int64;
+  blocks : int64;
+  bfree : int64;
+  bavail : int64;
+  files : int64;
+  ffree : int64;
+  favail : int64;
+  fsid : int64;
+  flag : int64;
+  namemax : int64;
+}
+
+val statvfs : string -> statvfs
diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES
index 41bb6c9eb..f3ee61e0d 100644
--- a/docs/C_SOURCE_FILES
+++ b/docs/C_SOURCE_FILES
@@ -166,7 +166,6 @@ daemon/sleep.c
 daemon/sleuthkit.c
 daemon/squashfs.c
 daemon/stat.c
-daemon/statvfs.c
 daemon/strings.c
 daemon/structs-cleanups.c
 daemon/structs-cleanups.h
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
index 81cb99ea8..604620673 100644
--- a/generator/actions_core.ml
+++ b/generator/actions_core.ml
@@ -2319,6 +2319,7 @@ See also: C<guestfs_sh_lines>" };
   { defaults with
     name = "statvfs"; added = (1, 9, 2);
     style = RStruct ("statbuf", "statvfs"), [String (Pathname, "path")], [];
+    impl = OCaml "Statvfs.statvfs";
     tests = [
       InitISOFS, Always, TestResult (
         [["statvfs"; "/"]], "ret->namemax == 255"), []
diff --git a/m4/guestfs_libraries.m4 b/m4/guestfs_libraries.m4
index b8fa1446a..a3b730572 100644
--- a/m4/guestfs_libraries.m4
+++ b/m4/guestfs_libraries.m4
@@ -48,10 +48,12 @@ AC_CHECK_HEADERS([\
     sys/inotify.h \
     sys/resource.h \
     sys/socket.h \
+    sys/statfs.h \
     sys/statvfs.h \
     sys/time.h \
     sys/types.h \
     sys/un.h \
+    sys/vfs.h \
     sys/wait.h \
     windows.h \
     sys/xattr.h])
@@ -59,6 +61,8 @@ AC_CHECK_HEADERS([\
 dnl Functions.
 AC_CHECK_FUNCS([\
     be32toh \
+    fstatfs \
+    fstatvfs \
     fsync \
     futimens \
     getxattr \
@@ -80,7 +84,6 @@ AC_CHECK_FUNCS([\
     setrlimit \
     setxattr \
     sigaction \
-    statvfs \
     sync])
 
 dnl Which header file defines major, minor, makedev.
diff --git a/po/POTFILES b/po/POTFILES
index 40c0708a0..a049d66fe 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -149,7 +149,6 @@ daemon/sleep.c
 daemon/sleuthkit.c
 daemon/squashfs.c
 daemon/stat.c
-daemon/statvfs.c
 daemon/strings.c
 daemon/structs-cleanups.c
 daemon/stubs-0.c
diff --git a/sparsify/copying.ml b/sparsify/copying.ml
index 7d004b550..0c0b27c94 100644
--- a/sparsify/copying.ml
+++ b/sparsify/copying.ml
@@ -99,7 +99,7 @@ let run indisk outdisk check_tmpdir compress convert
           virtual_size (human_size virtual_size);
 
     let print_warning () =
-      let free_space = StatVFS.free_space tmpdir in
+      let free_space = StatVFS.free_space (StatVFS.statvfs tmpdir) in
       let extra_needed = virtual_size -^ free_space in
       if extra_needed > 0L then (
         warning (f_"\
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index 74ba66a3d..f54838e5e 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -272,7 +272,7 @@ and overlay_dir = (open_guestfs ())#get_cachedir ()
  * guestfs appliance which is also stored here.
  *)
 and check_host_free_space () =
-  let free_space = StatVFS.free_space overlay_dir in
+  let free_space = StatVFS.free_space (StatVFS.statvfs overlay_dir) in
   debug "check_host_free_space: overlay_dir=%s free_space=%Ld"
         overlay_dir free_space;
   if free_space < 1_073_741_824L then
-- 
2.13.2




More information about the Libguestfs mailing list