Lots, mainly Python bindings.
authorRichard Jones <rjones@redhat.com>
Mon, 13 Apr 2009 17:32:03 +0000 (18:32 +0100)
committerRichard Jones <rjones@redhat.com>
Mon, 13 Apr 2009 17:32:03 +0000 (18:32 +0100)
20 files changed:
.gitignore
README
configure.ac
guestfs.pod
libguestfs.spec.in
ocaml/guestfs_c.c
perl/Guestfs.xs
perl/run-perl-tests
perl/t/050-lvcreate.t [new file with mode: 0644]
python/Makefile.am
python/README-python-bindings [deleted file]
python/guestfs-py.c [new file with mode: 0644]
python/guestfs.py [new file with mode: 0644]
python/t/005-import.py [new file with mode: 0644]
python/t/010-launch.py [new file with mode: 0644]
python/t/050-lvcreate.py [new file with mode: 0644]
src/generator.ml
src/guestfs.c
src/guestfs.h
tests.c

index eedd8a8..f3fc531 100644 (file)
@@ -62,6 +62,7 @@ perl/Makefile-pl
 perl/Makefile.PL
 perl/blib
 perl/pm_to_blib
+python/guestfs.pyc
 pod2htm?.tmp
 stamp-h1
 test*.img
diff --git a/README b/README
index ecb5362..f32c859 100644 (file)
--- a/README
+++ b/README
@@ -40,13 +40,15 @@ Requirements
 - perldoc (pod2man, pod2text) to generate the manual pages and
 other documentation.
 
-- (Optional) OCaml if you want to modify the code or rebuild certain
-generated files, and also to build the OCaml bindings
+- (Optional) OCaml if you want to rebuild the generated files, and
+also to build the OCaml bindings
 
 - (Optional) local Fedora mirror
 
 - (Optional) Perl if you want to build the perl bindings
 
+- (Optional) Python if you want to build the python bindings
+
 Running ./configure will check you have all the requirements installed
 on your machine.
 
index 3f8807f..e616374 100644 (file)
@@ -122,9 +122,53 @@ AC_CHECK_PROG([PERL],[perl],[perl],[no])
 AM_CONDITIONAL([HAVE_PERL],[test "x$PERL" != "xno"])
 
 dnl Check for Python (optional, for Python bindings).
-dnl XXX This isn't quite right, we should check for devel libraries.
 AC_CHECK_PROG([PYTHON],[python],[python],[no])
-AM_CONDITIONAL([HAVE_PYTHON],[test "x$PYTHON" != "xno"])
+
+PYTHON_PREFIX=
+PYTHON_VERSION=
+PYTHON_INCLUDEDIR=
+PYTHON_SITE_PACKAGES=
+
+if test "x$PYTHON" != "xno"; then
+    PYTHON_PREFIX=`$PYTHON -c "import sys; print sys.prefix"`
+    PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[[0:3]]"`
+    for d in \
+        $PYTHON_PREFIX/include/python$PYTHON_VERSION \
+        /usr/include/python$PYTHON_VERSION \
+        /usr/local/include/python$PYTHON_VERSION
+    do
+        AC_MSG_CHECKING([Python.h in $d])
+        if test -r "$d/Python.h"; then
+           AC_MSG_RESULT([found])
+           PYTHON_INCLUDEDIR=$d
+           break
+       fi
+       AC_MSG_RESULT([not found])
+    done
+    for d in \
+        $PYTHON_PREFIX/lib64/python$PYTHON_VERSION/site-packages \
+        $PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages \
+        /usr/lib64/python$PYTHON_VERSION/site-packages \
+        /usr/lib/python$PYTHON_VERSION/site-packages \
+        /usr/local/lib/python$PYTHON_VERSION/site-packages
+    do
+        AC_MSG_CHECKING([for $d])
+        if test -d "$d"; then
+           AC_MSG_RESULT([found])
+           PYTHON_SITE_PACKAGES=$d
+           break
+       fi
+       AC_MSG_RESULT([not found])
+    done
+fi
+
+AC_SUBST(PYTHON_PREFIX)
+AC_SUBST(PYTHON_VERSION)
+AC_SUBST(PYTHON_INCLUDEDIR)
+AC_SUBST(PYTHON_SITE_PACKAGES)
+
+AM_CONDITIONAL([HAVE_PYTHON],
+    [test "x$PYTHON_INCLUDEDIR" != "x" && test "x$PYTHON_SITE_PACKAGES" != "x"])
 
 dnl Run in subdirs.
 AC_CONFIG_SUBDIRS([daemon])
index 8fdc93d..41234fd 100644 (file)
@@ -117,13 +117,30 @@ This closes the connection handle and frees up all resources used.
 
 The convention in all functions that return C<int> is that they return
 C<-1> to indicate an error.  You can get additional information on
-errors by calling C<guestfs_set_error_handler>.  The default error
-handler prints the information string to C<stderr>.
+errors by calling C<guestfs_last_error> and/or by setting up an error
+handler with C<guestfs_set_error_handler>.
+
+The default error handler prints the information string to C<stderr>.
 
 Out of memory errors are handled differently.  The default action is
 to call L<abort(3)>.  If this is undesirable, then you can set a
 handler using C<guestfs_set_out_of_memory_handler>.
 
+=head2 guestfs_last_error
+
+ const char *guestfs_last_error (guestfs_h *handle);
+
+This returns the last error message that happened on C<handle>.  If
+there has not been an error since the handle was created, then this
+returns C<NULL>.
+
+The lifetime of the returned string is until the next error occurs, or
+C<guestfs_close> is called.
+
+The error string is not localized (ie. is always in English), because
+this makes searching for error messages in search engines give the
+largest number of results.
+
 =head2 guestfs_set_error_handler
 
  typedef void (*guestfs_error_handler_cb) (guestfs_h *handle,
@@ -143,8 +160,7 @@ your own copy.
 
 The default handler prints messages on C<stderr>.
 
-If you set C<cb> to C<NULL> then I<no> handler is called and the error
-message is completely discarded.
+If you set C<cb> to C<NULL> then I<no> handler is called.
 
 =head2 guestfs_get_error_handler
 
index 92ec289..0da3ce6 100644 (file)
@@ -23,10 +23,11 @@ BuildRequires: qemu
 BuildRequires: ocaml
 BuildRequires: ocaml-findlib-devel
 BuildRequires: perl-devel
+BuildRequires: perl-Test-Simple
 BuildRequires: perl-Test-Pod
 BuildRequires: perl-Test-Pod-Coverage
 BuildRequires: perl-ExtUtils-MakeMaker
-BuildRequires: python-devel
+BuildRequires: python-devel
 
 # Runtime requires:
 Requires:    qemu
@@ -117,14 +118,14 @@ Requires:    perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)
 %{name}-perl contains Perl bindings for %{name}.
 
 
-%package python
-Summary:     Python bindings for %{name}
-Group:       Development/Libraries
-Requires:    %{name} = %{version}-%{release}
+%package python
+Summary:     Python bindings for %{name}
+Group:       Development/Libraries
+Requires:    %{name} = %{version}-%{release}
 
 
-%description python
-%{name}-python contains Python bindings for %{name}.
+%description python
+%{name}-python contains Python bindings for %{name}.
 
 
 %prep
@@ -233,8 +234,8 @@ rm -rf $RPM_BUILD_ROOT
 %{_mandir}/man3/Sys::Guestfs.3pm*
 
 
-%files python
-%defattr(-,root,root,-)
+%files python
+%defattr(-,root,root,-)
 
 
 %changelog
index 291c430..87139b4 100644 (file)
@@ -62,28 +62,19 @@ Val_guestfs (guestfs_h *g)
   CAMLreturn (rv);
 }
 
-/* Handle errors. */
-/* XXX Like the current Perl bindings, this is unsafe in a multi-
- * threaded environment.
- */
-static char *last_error = NULL;
-
-static void
-error_handler (guestfs_h *g,
-              void *data,
-              const char *msg)
-{
-  if (last_error != NULL) free (last_error);
-  last_error = strdup (msg);
-}
-
 void
 ocaml_guestfs_raise_error (guestfs_h *g, const char *func)
 {
   CAMLparam0 ();
   CAMLlocal1 (v);
+  const char *msg;
+
+  msg = guestfs_last_error (g);
 
-  v = caml_copy_string (last_error);
+  if (msg)
+    v = caml_copy_string (msg);
+  else
+    v = caml_copy_string (func);
   caml_raise_with_arg (*caml_named_value ("ocaml_guestfs_error"), v);
   CAMLnoreturn;
 }
@@ -100,7 +91,7 @@ ocaml_guestfs_create (void)
   if (g == NULL)
     caml_failwith ("failed to create guestfs handle");
 
-  guestfs_set_error_handler (g, error_handler, NULL);
+  guestfs_set_error_handler (g, NULL, NULL);
 
   gv = Val_guestfs (g);
   CAMLreturn (gv);
index 0f72c28..580b743 100644 (file)
@@ -57,22 +57,6 @@ my_newSVull(unsigned long long val) {
 #endif
 }
 
-/* XXX Not thread-safe, and in general not safe if the caller is
- * issuing multiple requests in parallel (on different guestfs
- * handles).  We should use the guestfs_h handle passed to the
- * error handle to distinguish these cases.
- */
-static char *last_error = NULL;
-
-static void
-error_handler (guestfs_h *g,
-              void *data,
-              const char *msg)
-{
-  if (last_error != NULL) free (last_error);
-  last_error = strdup (msg);
-}
-
 /* http://www.perlmonks.org/?node_id=680842 */
 static char **
 XS_unpack_charPtrPtr (SV *arg) {
@@ -90,14 +74,13 @@ XS_unpack_charPtrPtr (SV *arg) {
   for (i = 0; i <= av_len (av); i++) {
     SV **elem = av_fetch (av, i, 0);
 
-      if (!elem || !*elem) {
-        croak ("missing element in list");
-      }
+    if (!elem || !*elem)
+      croak ("missing element in list");
 
-      ret[i] = SvPV_nolen (*elem);
+    ret[i] = SvPV_nolen (*elem);
   }
 
-  ret[i + 1] = NULL;
+  ret[i] = NULL;
 
   return ret;
 }
@@ -110,7 +93,7 @@ _create ()
       RETVAL = guestfs_create ();
       if (!RETVAL)
         croak ("could not create guestfs handle");
-      guestfs_set_error_handler (RETVAL, error_handler, NULL);
+      guestfs_set_error_handler (RETVAL, NULL, NULL);
  OUTPUT:
       RETVAL
 
@@ -125,7 +108,7 @@ launch (g)
       guestfs_h *g;
  PPCODE:
       if (guestfs_launch (g) == -1) {
-        croak ("launch: %s", last_error);
+        croak ("launch: %s", guestfs_last_error (g));
       }
 
 void
@@ -133,7 +116,7 @@ wait_ready (g)
       guestfs_h *g;
  PPCODE:
       if (guestfs_wait_ready (g) == -1) {
-        croak ("wait_ready: %s", last_error);
+        croak ("wait_ready: %s", guestfs_last_error (g));
       }
 
 void
@@ -141,7 +124,7 @@ kill_subprocess (g)
       guestfs_h *g;
  PPCODE:
       if (guestfs_kill_subprocess (g) == -1) {
-        croak ("kill_subprocess: %s", last_error);
+        croak ("kill_subprocess: %s", guestfs_last_error (g));
       }
 
 void
@@ -150,7 +133,7 @@ add_drive (g, filename)
       char *filename;
  PPCODE:
       if (guestfs_add_drive (g, filename) == -1) {
-        croak ("add_drive: %s", last_error);
+        croak ("add_drive: %s", guestfs_last_error (g));
       }
 
 void
@@ -159,7 +142,7 @@ add_cdrom (g, filename)
       char *filename;
  PPCODE:
       if (guestfs_add_cdrom (g, filename) == -1) {
-        croak ("add_cdrom: %s", last_error);
+        croak ("add_cdrom: %s", guestfs_last_error (g));
       }
 
 void
@@ -169,7 +152,7 @@ config (g, qemuparam, qemuvalue)
       char *qemuvalue;
  PPCODE:
       if (guestfs_config (g, qemuparam, qemuvalue) == -1) {
-        croak ("config: %s", last_error);
+        croak ("config: %s", guestfs_last_error (g));
       }
 
 void
@@ -178,7 +161,7 @@ set_path (g, path)
       char *path;
  PPCODE:
       if (guestfs_set_path (g, path) == -1) {
-        croak ("set_path: %s", last_error);
+        croak ("set_path: %s", guestfs_last_error (g));
       }
 
 SV *
@@ -189,7 +172,7 @@ PREINIT:
    CODE:
       path = guestfs_get_path (g);
       if (path == NULL) {
-        croak ("get_path: %s", last_error);
+        croak ("get_path: %s", guestfs_last_error (g));
       }
       RETVAL = newSVpv (path, 0);
  OUTPUT:
@@ -201,7 +184,7 @@ set_autosync (g, autosync)
       int autosync;
  PPCODE:
       if (guestfs_set_autosync (g, autosync) == -1) {
-        croak ("set_autosync: %s", last_error);
+        croak ("set_autosync: %s", guestfs_last_error (g));
       }
 
 SV *
@@ -212,7 +195,7 @@ PREINIT:
    CODE:
       autosync = guestfs_get_autosync (g);
       if (autosync == -1) {
-        croak ("get_autosync: %s", last_error);
+        croak ("get_autosync: %s", guestfs_last_error (g));
       }
       RETVAL = newSViv (autosync);
  OUTPUT:
@@ -224,7 +207,7 @@ set_verbose (g, verbose)
       int verbose;
  PPCODE:
       if (guestfs_set_verbose (g, verbose) == -1) {
-        croak ("set_verbose: %s", last_error);
+        croak ("set_verbose: %s", guestfs_last_error (g));
       }
 
 SV *
@@ -235,7 +218,7 @@ PREINIT:
    CODE:
       verbose = guestfs_get_verbose (g);
       if (verbose == -1) {
-        croak ("get_verbose: %s", last_error);
+        croak ("get_verbose: %s", guestfs_last_error (g));
       }
       RETVAL = newSViv (verbose);
  OUTPUT:
@@ -248,7 +231,7 @@ mount (g, device, mountpoint)
       char *mountpoint;
  PPCODE:
       if (guestfs_mount (g, device, mountpoint) == -1) {
-        croak ("mount: %s", last_error);
+        croak ("mount: %s", guestfs_last_error (g));
       }
 
 void
@@ -256,7 +239,7 @@ sync (g)
       guestfs_h *g;
  PPCODE:
       if (guestfs_sync (g) == -1) {
-        croak ("sync: %s", last_error);
+        croak ("sync: %s", guestfs_last_error (g));
       }
 
 void
@@ -265,7 +248,7 @@ touch (g, path)
       char *path;
  PPCODE:
       if (guestfs_touch (g, path) == -1) {
-        croak ("touch: %s", last_error);
+        croak ("touch: %s", guestfs_last_error (g));
       }
 
 SV *
@@ -277,7 +260,7 @@ PREINIT:
    CODE:
       content = guestfs_cat (g, path);
       if (content == NULL) {
-        croak ("cat: %s", last_error);
+        croak ("cat: %s", guestfs_last_error (g));
       }
       RETVAL = newSVpv (content, 0);
       free (content);
@@ -293,7 +276,7 @@ PREINIT:
    CODE:
       listing = guestfs_ll (g, directory);
       if (listing == NULL) {
-        croak ("ll: %s", last_error);
+        croak ("ll: %s", guestfs_last_error (g));
       }
       RETVAL = newSVpv (listing, 0);
       free (listing);
@@ -310,7 +293,7 @@ PREINIT:
  PPCODE:
       listing = guestfs_ls (g, directory);
       if (listing == NULL) {
-        croak ("ls: %s", last_error);
+        croak ("ls: %s", guestfs_last_error (g));
       }
       for (n = 0; listing[n] != NULL; ++n) /**/;
       EXTEND (SP, n);
@@ -329,7 +312,7 @@ PREINIT:
  PPCODE:
       devices = guestfs_list_devices (g);
       if (devices == NULL) {
-        croak ("list_devices: %s", last_error);
+        croak ("list_devices: %s", guestfs_last_error (g));
       }
       for (n = 0; devices[n] != NULL; ++n) /**/;
       EXTEND (SP, n);
@@ -348,7 +331,7 @@ PREINIT:
  PPCODE:
       partitions = guestfs_list_partitions (g);
       if (partitions == NULL) {
-        croak ("list_partitions: %s", last_error);
+        croak ("list_partitions: %s", guestfs_last_error (g));
       }
       for (n = 0; partitions[n] != NULL; ++n) /**/;
       EXTEND (SP, n);
@@ -367,7 +350,7 @@ PREINIT:
  PPCODE:
       physvols = guestfs_pvs (g);
       if (physvols == NULL) {
-        croak ("pvs: %s", last_error);
+        croak ("pvs: %s", guestfs_last_error (g));
       }
       for (n = 0; physvols[n] != NULL; ++n) /**/;
       EXTEND (SP, n);
@@ -386,7 +369,7 @@ PREINIT:
  PPCODE:
       volgroups = guestfs_vgs (g);
       if (volgroups == NULL) {
-        croak ("vgs: %s", last_error);
+        croak ("vgs: %s", guestfs_last_error (g));
       }
       for (n = 0; volgroups[n] != NULL; ++n) /**/;
       EXTEND (SP, n);
@@ -405,7 +388,7 @@ PREINIT:
  PPCODE:
       logvols = guestfs_lvs (g);
       if (logvols == NULL) {
-        croak ("lvs: %s", last_error);
+        croak ("lvs: %s", guestfs_last_error (g));
       }
       for (n = 0; logvols[n] != NULL; ++n) /**/;
       EXTEND (SP, n);
@@ -425,7 +408,7 @@ PREINIT:
  PPCODE:
       physvols = guestfs_pvs_full (g);
       if (physvols == NULL)
-        croak ("pvs_full: %s", last_error);
+        croak ("pvs_full: %s", guestfs_last_error (g));
       EXTEND (SP, physvols->len);
       for (i = 0; i < physvols->len; ++i) {
         hv = newHV ();
@@ -457,7 +440,7 @@ PREINIT:
  PPCODE:
       volgroups = guestfs_vgs_full (g);
       if (volgroups == NULL)
-        croak ("vgs_full: %s", last_error);
+        croak ("vgs_full: %s", guestfs_last_error (g));
       EXTEND (SP, volgroups->len);
       for (i = 0; i < volgroups->len; ++i) {
         hv = newHV ();
@@ -494,7 +477,7 @@ PREINIT:
  PPCODE:
       logvols = guestfs_lvs_full (g);
       if (logvols == NULL)
-        croak ("lvs_full: %s", last_error);
+        croak ("lvs_full: %s", guestfs_last_error (g));
       EXTEND (SP, logvols->len);
       for (i = 0; i < logvols->len; ++i) {
         hv = newHV ();
@@ -528,7 +511,7 @@ PREINIT:
  PPCODE:
       lines = guestfs_read_lines (g, path);
       if (lines == NULL) {
-        croak ("read_lines: %s", last_error);
+        croak ("read_lines: %s", guestfs_last_error (g));
       }
       for (n = 0; lines[n] != NULL; ++n) /**/;
       EXTEND (SP, n);
@@ -545,7 +528,7 @@ aug_init (g, root, flags)
       int flags;
  PPCODE:
       if (guestfs_aug_init (g, root, flags) == -1) {
-        croak ("aug_init: %s", last_error);
+        croak ("aug_init: %s", guestfs_last_error (g));
       }
 
 void
@@ -553,7 +536,7 @@ aug_close (g)
       guestfs_h *g;
  PPCODE:
       if (guestfs_aug_close (g) == -1) {
-        croak ("aug_close: %s", last_error);
+        croak ("aug_close: %s", guestfs_last_error (g));
       }
 
 SV *
@@ -566,7 +549,7 @@ PREINIT:
    CODE:
       nrnodes = guestfs_aug_defvar (g, name, expr);
       if (nrnodes == -1) {
-        croak ("aug_defvar: %s", last_error);
+        croak ("aug_defvar: %s", guestfs_last_error (g));
       }
       RETVAL = newSViv (nrnodes);
  OUTPUT:
@@ -583,7 +566,7 @@ PREINIT:
  PPCODE:
       r = guestfs_aug_defnode (g, name, expr, val);
       if (r == NULL) {
-        croak ("aug_defnode: %s", last_error);
+        croak ("aug_defnode: %s", guestfs_last_error (g));
       }
       EXTEND (SP, 2);
       PUSHs (sv_2mortal (newSViv (r->i)));
@@ -599,7 +582,7 @@ PREINIT:
    CODE:
       val = guestfs_aug_get (g, path);
       if (val == NULL) {
-        croak ("aug_get: %s", last_error);
+        croak ("aug_get: %s", guestfs_last_error (g));
       }
       RETVAL = newSVpv (val, 0);
       free (val);
@@ -613,7 +596,7 @@ aug_set (g, path, val)
       char *val;
  PPCODE:
       if (guestfs_aug_set (g, path, val) == -1) {
-        croak ("aug_set: %s", last_error);
+        croak ("aug_set: %s", guestfs_last_error (g));
       }
 
 void
@@ -624,7 +607,7 @@ aug_insert (g, path, label, before)
       int before;
  PPCODE:
       if (guestfs_aug_insert (g, path, label, before) == -1) {
-        croak ("aug_insert: %s", last_error);
+        croak ("aug_insert: %s", guestfs_last_error (g));
       }
 
 SV *
@@ -636,7 +619,7 @@ PREINIT:
    CODE:
       nrnodes = guestfs_aug_rm (g, path);
       if (nrnodes == -1) {
-        croak ("aug_rm: %s", last_error);
+        croak ("aug_rm: %s", guestfs_last_error (g));
       }
       RETVAL = newSViv (nrnodes);
  OUTPUT:
@@ -649,7 +632,7 @@ aug_mv (g, src, dest)
       char *dest;
  PPCODE:
       if (guestfs_aug_mv (g, src, dest) == -1) {
-        croak ("aug_mv: %s", last_error);
+        croak ("aug_mv: %s", guestfs_last_error (g));
       }
 
 void
@@ -662,7 +645,7 @@ PREINIT:
  PPCODE:
       matches = guestfs_aug_match (g, path);
       if (matches == NULL) {
-        croak ("aug_match: %s", last_error);
+        croak ("aug_match: %s", guestfs_last_error (g));
       }
       for (n = 0; matches[n] != NULL; ++n) /**/;
       EXTEND (SP, n);
@@ -677,7 +660,7 @@ aug_save (g)
       guestfs_h *g;
  PPCODE:
       if (guestfs_aug_save (g) == -1) {
-        croak ("aug_save: %s", last_error);
+        croak ("aug_save: %s", guestfs_last_error (g));
       }
 
 void
@@ -685,7 +668,7 @@ aug_load (g)
       guestfs_h *g;
  PPCODE:
       if (guestfs_aug_load (g) == -1) {
-        croak ("aug_load: %s", last_error);
+        croak ("aug_load: %s", guestfs_last_error (g));
       }
 
 void
@@ -698,7 +681,7 @@ PREINIT:
  PPCODE:
       matches = guestfs_aug_ls (g, path);
       if (matches == NULL) {
-        croak ("aug_ls: %s", last_error);
+        croak ("aug_ls: %s", guestfs_last_error (g));
       }
       for (n = 0; matches[n] != NULL; ++n) /**/;
       EXTEND (SP, n);
@@ -714,7 +697,7 @@ rm (g, path)
       char *path;
  PPCODE:
       if (guestfs_rm (g, path) == -1) {
-        croak ("rm: %s", last_error);
+        croak ("rm: %s", guestfs_last_error (g));
       }
 
 void
@@ -723,7 +706,7 @@ rmdir (g, path)
       char *path;
  PPCODE:
       if (guestfs_rmdir (g, path) == -1) {
-        croak ("rmdir: %s", last_error);
+        croak ("rmdir: %s", guestfs_last_error (g));
       }
 
 void
@@ -732,7 +715,7 @@ rm_rf (g, path)
       char *path;
  PPCODE:
       if (guestfs_rm_rf (g, path) == -1) {
-        croak ("rm_rf: %s", last_error);
+        croak ("rm_rf: %s", guestfs_last_error (g));
       }
 
 void
@@ -741,7 +724,7 @@ mkdir (g, path)
       char *path;
  PPCODE:
       if (guestfs_mkdir (g, path) == -1) {
-        croak ("mkdir: %s", last_error);
+        croak ("mkdir: %s", guestfs_last_error (g));
       }
 
 void
@@ -750,7 +733,7 @@ mkdir_p (g, path)
       char *path;
  PPCODE:
       if (guestfs_mkdir_p (g, path) == -1) {
-        croak ("mkdir_p: %s", last_error);
+        croak ("mkdir_p: %s", guestfs_last_error (g));
       }
 
 void
@@ -760,7 +743,7 @@ chmod (g, mode, path)
       char *path;
  PPCODE:
       if (guestfs_chmod (g, mode, path) == -1) {
-        croak ("chmod: %s", last_error);
+        croak ("chmod: %s", guestfs_last_error (g));
       }
 
 void
@@ -771,7 +754,7 @@ chown (g, owner, group, path)
       char *path;
  PPCODE:
       if (guestfs_chown (g, owner, group, path) == -1) {
-        croak ("chown: %s", last_error);
+        croak ("chown: %s", guestfs_last_error (g));
       }
 
 SV *
@@ -783,7 +766,7 @@ PREINIT:
    CODE:
       existsflag = guestfs_exists (g, path);
       if (existsflag == -1) {
-        croak ("exists: %s", last_error);
+        croak ("exists: %s", guestfs_last_error (g));
       }
       RETVAL = newSViv (existsflag);
  OUTPUT:
@@ -798,7 +781,7 @@ PREINIT:
    CODE:
       fileflag = guestfs_is_file (g, path);
       if (fileflag == -1) {
-        croak ("is_file: %s", last_error);
+        croak ("is_file: %s", guestfs_last_error (g));
       }
       RETVAL = newSViv (fileflag);
  OUTPUT:
@@ -813,7 +796,7 @@ PREINIT:
    CODE:
       dirflag = guestfs_is_dir (g, path);
       if (dirflag == -1) {
-        croak ("is_dir: %s", last_error);
+        croak ("is_dir: %s", guestfs_last_error (g));
       }
       RETVAL = newSViv (dirflag);
  OUTPUT:
@@ -825,7 +808,7 @@ pvcreate (g, device)
       char *device;
  PPCODE:
       if (guestfs_pvcreate (g, device) == -1) {
-        croak ("pvcreate: %s", last_error);
+        croak ("pvcreate: %s", guestfs_last_error (g));
       }
 
 void
@@ -836,7 +819,7 @@ vgcreate (g, volgroup, physvols)
  PPCODE:
       if (guestfs_vgcreate (g, volgroup, physvols) == -1) {
         free (physvols);
-        croak ("vgcreate: %s", last_error);
+        croak ("vgcreate: %s", guestfs_last_error (g));
       }
         free (physvols);
 
@@ -848,7 +831,7 @@ lvcreate (g, logvol, volgroup, mbytes)
       int mbytes;
  PPCODE:
       if (guestfs_lvcreate (g, logvol, volgroup, mbytes) == -1) {
-        croak ("lvcreate: %s", last_error);
+        croak ("lvcreate: %s", guestfs_last_error (g));
       }
 
 void
@@ -858,7 +841,7 @@ mkfs (g, fstype, device)
       char *device;
  PPCODE:
       if (guestfs_mkfs (g, fstype, device) == -1) {
-        croak ("mkfs: %s", last_error);
+        croak ("mkfs: %s", guestfs_last_error (g));
       }
 
 void
@@ -872,7 +855,7 @@ sfdisk (g, device, cyls, heads, sectors, lines)
  PPCODE:
       if (guestfs_sfdisk (g, device, cyls, heads, sectors, lines) == -1) {
         free (lines);
-        croak ("sfdisk: %s", last_error);
+        croak ("sfdisk: %s", guestfs_last_error (g));
       }
         free (lines);
 
@@ -884,7 +867,7 @@ write_file (g, path, content, size)
       int size;
  PPCODE:
       if (guestfs_write_file (g, path, content, size) == -1) {
-        croak ("write_file: %s", last_error);
+        croak ("write_file: %s", guestfs_last_error (g));
       }
 
 void
@@ -893,7 +876,7 @@ umount (g, pathordevice)
       char *pathordevice;
  PPCODE:
       if (guestfs_umount (g, pathordevice) == -1) {
-        croak ("umount: %s", last_error);
+        croak ("umount: %s", guestfs_last_error (g));
       }
 
 void
@@ -905,7 +888,7 @@ PREINIT:
  PPCODE:
       devices = guestfs_mounts (g);
       if (devices == NULL) {
-        croak ("mounts: %s", last_error);
+        croak ("mounts: %s", guestfs_last_error (g));
       }
       for (n = 0; devices[n] != NULL; ++n) /**/;
       EXTEND (SP, n);
@@ -920,7 +903,7 @@ umount_all (g)
       guestfs_h *g;
  PPCODE:
       if (guestfs_umount_all (g) == -1) {
-        croak ("umount_all: %s", last_error);
+        croak ("umount_all: %s", guestfs_last_error (g));
       }
 
 void
@@ -928,6 +911,6 @@ lvm_remove_all (g)
       guestfs_h *g;
  PPCODE:
       if (guestfs_lvm_remove_all (g) == -1) {
-        croak ("lvm_remove_all: %s", last_error);
+        croak ("lvm_remove_all: %s", guestfs_last_error (g));
       }
 
index d2280dd..1a890fc 100755 (executable)
@@ -17,4 +17,5 @@
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 export LD_LIBRARY_PATH=../src/.libs
-make -f Makefile-pl test
+export LIBGUESTFS_PATH=$(cd .. && pwd)
+make -f Makefile-pl test "$@"
diff --git a/perl/t/050-lvcreate.t b/perl/t/050-lvcreate.t
new file mode 100644 (file)
index 0000000..418428c
--- /dev/null
@@ -0,0 +1,60 @@
+# libguestfs Perl bindings -*- perl -*-
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+use strict;
+use warnings;
+use Test::More tests => 12;
+
+use Sys::Guestfs;
+
+my $h = Sys::Guestfs->new ();
+ok ($h);
+open FILE, ">test.img";
+truncate FILE, 500*1024*1024;
+close FILE;
+ok (1);
+
+$h->add_drive ("test.img");
+ok (1);
+
+$h->launch ();
+ok (1);
+$h->wait_ready ();
+ok (1);
+
+$h->pvcreate ("/dev/sda");
+ok (1);
+$h->vgcreate ("VG", ["/dev/sda"]);
+ok (1);
+$h->lvcreate ("LV1", "VG", 200);
+ok (1);
+$h->lvcreate ("LV2", "VG", 200);
+ok (1);
+
+my @lvs = $h->lvs ();
+if (@lvs != 2 || $lvs[0] ne "/dev/VG/LV1" || $lvs[1] ne "/dev/VG/LV2") {
+    die "h->lvs() returned incorrect result"
+}
+ok (1);
+
+$h->sync ();
+ok (1);
+
+undef $h;
+ok (1);
+
+#unlink ("test.img");
index 509e87c..b2cf3b3 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-EXTRA_DIST = README-python-bindings
+EXTRA_DIST = \
+       guestfs.py \
+       guestfs-py.c \
+       t/*.py
 
 CLEANFILES = *~
 
 if HAVE_PYTHON
 
+pythondir = $(PYTHON_SITE_PACKAGES)
+
+python_LTLIBRARIES = libguestfsmod.la
+
+libguestfsmod_la_SOURCES = guestfs-py.c
+libguestfsmod_la_CFLAGS = -Wall -I$(PYTHON_INCLUDEDIR) -I$(top_builddir)/src
+libguestfsmod_la_LIBADD = $(top_builddir)/src/libguestfs.la
+
+TESTS_ENVIRONMENT = \
+       LIBGUESTFS_PATH=$(abs_top_builddir) \
+       PYTHONPATH=$(abs_top_builddir)/python:$(abs_top_builddir)/python/.libs \
+       $(PYTHON)
+TESTS = t/005-import.py t/010-launch.py t/050-lvcreate.py
+
 endif
\ No newline at end of file
diff --git a/python/README-python-bindings b/python/README-python-bindings
deleted file mode 100644 (file)
index 4c5aa38..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-There are no Python bindings right now.
-
-Know Python?  Why not contribute some!
-
-You will need to autogenerate them by adding the appropriate code
-snippets to src/generator.ml.  For inspiration, I suggest looking at
-how the OCaml and Perl bindings were done.
diff --git a/python/guestfs-py.c b/python/guestfs-py.c
new file mode 100644 (file)
index 0000000..9d2738c
--- /dev/null
@@ -0,0 +1,1883 @@
+/* libguestfs generated file
+ * WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.
+ * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <Python.h>
+
+#include "guestfs.h"
+
+typedef struct {
+  PyObject_HEAD
+  guestfs_h *g;
+} Pyguestfs_Object;
+
+static guestfs_h *
+get_handle (PyObject *obj)
+{
+  assert (obj);
+  assert (obj != Py_None);
+  return ((Pyguestfs_Object *) obj)->g;
+}
+
+static PyObject *
+put_handle (guestfs_h *g)
+{
+  assert (g);
+  return
+    PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) "guestfs_h", NULL);
+}
+
+/* This list should be freed (but not the strings) after use. */
+static const char **
+get_string_list (PyObject *obj)
+{
+  int i, len;
+  const char **r;
+
+  assert (obj);
+
+  if (!PyList_Check (obj)) {
+    PyErr_SetString (PyExc_RuntimeError, "expecting a list parameter");
+    return NULL;
+  }
+
+  len = PyList_Size (obj);
+  r = malloc (sizeof (char *) * (len+1));
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, "get_string_list: out of memory");
+    return NULL;
+  }
+
+  for (i = 0; i < len; ++i)
+    r[i] = PyString_AsString (PyList_GetItem (obj, i));
+  r[len] = NULL;
+
+  return r;
+}
+
+static PyObject *
+put_string_list (char * const * const argv)
+{
+  PyObject *list;
+  int argc, i;
+
+  for (argc = 0; argv[argc] != NULL; ++argc)
+    ;
+
+  list = PyList_New (argc);
+  for (i = 0; i < argc; ++i)
+    PyList_SetItem (list, i, PyString_FromString (argv[i]));
+
+  return list;
+}
+
+static void
+free_strings (char **argv)
+{
+  int argc;
+
+  for (argc = 0; argv[argc] != NULL; ++argc)
+    free (argv[argc]);
+  free (argv);
+}
+
+static PyObject *
+py_guestfs_create (PyObject *self, PyObject *args)
+{
+  guestfs_h *g;
+
+  g = guestfs_create ();
+  if (g == NULL) {
+    PyErr_SetString (PyExc_RuntimeError,
+                     "guestfs.create: failed to allocate handle");
+    return NULL;
+  }
+  guestfs_set_error_handler (g, NULL, NULL);
+  return put_handle (g);
+}
+
+static PyObject *
+py_guestfs_close (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_close", &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  guestfs_close (g);
+
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+static PyObject *
+put_lvm_pv (struct guestfs_lvm_pv *pv)
+{
+  PyObject *dict;
+
+  dict = PyDict_New ();
+  PyDict_SetItemString (dict, "pv_name",
+                        PyString_FromString (pv->pv_name));
+  PyDict_SetItemString (dict, "pv_uuid",
+                        PyString_FromStringAndSize (pv->pv_uuid, 32));
+  PyDict_SetItemString (dict, "pv_fmt",
+                        PyString_FromString (pv->pv_fmt));
+  PyDict_SetItemString (dict, "pv_size",
+                        PyLong_FromUnsignedLongLong (pv->pv_size));
+  PyDict_SetItemString (dict, "dev_size",
+                        PyLong_FromUnsignedLongLong (pv->dev_size));
+  PyDict_SetItemString (dict, "pv_free",
+                        PyLong_FromUnsignedLongLong (pv->pv_free));
+  PyDict_SetItemString (dict, "pv_used",
+                        PyLong_FromUnsignedLongLong (pv->pv_used));
+  PyDict_SetItemString (dict, "pv_attr",
+                        PyString_FromString (pv->pv_attr));
+  PyDict_SetItemString (dict, "pv_pe_count",
+                        PyLong_FromLongLong (pv->pv_pe_count));
+  PyDict_SetItemString (dict, "pv_pe_alloc_count",
+                        PyLong_FromLongLong (pv->pv_pe_alloc_count));
+  PyDict_SetItemString (dict, "pv_tags",
+                        PyString_FromString (pv->pv_tags));
+  PyDict_SetItemString (dict, "pe_start",
+                        PyLong_FromUnsignedLongLong (pv->pe_start));
+  PyDict_SetItemString (dict, "pv_mda_count",
+                        PyLong_FromLongLong (pv->pv_mda_count));
+  PyDict_SetItemString (dict, "pv_mda_free",
+                        PyLong_FromUnsignedLongLong (pv->pv_mda_free));
+  return dict;
+};
+
+static PyObject *
+put_lvm_pv_list (struct guestfs_lvm_pv_list *pvs)
+{
+  PyObject *list;
+  int i;
+
+  list = PyList_New (pvs->len);
+  for (i = 0; i < pvs->len; ++i)
+    PyList_SetItem (list, i, put_lvm_pv (&pvs->val[i]));
+  return list;
+};
+
+static PyObject *
+put_lvm_vg (struct guestfs_lvm_vg *vg)
+{
+  PyObject *dict;
+
+  dict = PyDict_New ();
+  PyDict_SetItemString (dict, "vg_name",
+                        PyString_FromString (vg->vg_name));
+  PyDict_SetItemString (dict, "vg_uuid",
+                        PyString_FromStringAndSize (vg->vg_uuid, 32));
+  PyDict_SetItemString (dict, "vg_fmt",
+                        PyString_FromString (vg->vg_fmt));
+  PyDict_SetItemString (dict, "vg_attr",
+                        PyString_FromString (vg->vg_attr));
+  PyDict_SetItemString (dict, "vg_size",
+                        PyLong_FromUnsignedLongLong (vg->vg_size));
+  PyDict_SetItemString (dict, "vg_free",
+                        PyLong_FromUnsignedLongLong (vg->vg_free));
+  PyDict_SetItemString (dict, "vg_sysid",
+                        PyString_FromString (vg->vg_sysid));
+  PyDict_SetItemString (dict, "vg_extent_size",
+                        PyLong_FromUnsignedLongLong (vg->vg_extent_size));
+  PyDict_SetItemString (dict, "vg_extent_count",
+                        PyLong_FromLongLong (vg->vg_extent_count));
+  PyDict_SetItemString (dict, "vg_free_count",
+                        PyLong_FromLongLong (vg->vg_free_count));
+  PyDict_SetItemString (dict, "max_lv",
+                        PyLong_FromLongLong (vg->max_lv));
+  PyDict_SetItemString (dict, "max_pv",
+                        PyLong_FromLongLong (vg->max_pv));
+  PyDict_SetItemString (dict, "pv_count",
+                        PyLong_FromLongLong (vg->pv_count));
+  PyDict_SetItemString (dict, "lv_count",
+                        PyLong_FromLongLong (vg->lv_count));
+  PyDict_SetItemString (dict, "snap_count",
+                        PyLong_FromLongLong (vg->snap_count));
+  PyDict_SetItemString (dict, "vg_seqno",
+                        PyLong_FromLongLong (vg->vg_seqno));
+  PyDict_SetItemString (dict, "vg_tags",
+                        PyString_FromString (vg->vg_tags));
+  PyDict_SetItemString (dict, "vg_mda_count",
+                        PyLong_FromLongLong (vg->vg_mda_count));
+  PyDict_SetItemString (dict, "vg_mda_free",
+                        PyLong_FromUnsignedLongLong (vg->vg_mda_free));
+  return dict;
+};
+
+static PyObject *
+put_lvm_vg_list (struct guestfs_lvm_vg_list *vgs)
+{
+  PyObject *list;
+  int i;
+
+  list = PyList_New (vgs->len);
+  for (i = 0; i < vgs->len; ++i)
+    PyList_SetItem (list, i, put_lvm_vg (&vgs->val[i]));
+  return list;
+};
+
+static PyObject *
+put_lvm_lv (struct guestfs_lvm_lv *lv)
+{
+  PyObject *dict;
+
+  dict = PyDict_New ();
+  PyDict_SetItemString (dict, "lv_name",
+                        PyString_FromString (lv->lv_name));
+  PyDict_SetItemString (dict, "lv_uuid",
+                        PyString_FromStringAndSize (lv->lv_uuid, 32));
+  PyDict_SetItemString (dict, "lv_attr",
+                        PyString_FromString (lv->lv_attr));
+  PyDict_SetItemString (dict, "lv_major",
+                        PyLong_FromLongLong (lv->lv_major));
+  PyDict_SetItemString (dict, "lv_minor",
+                        PyLong_FromLongLong (lv->lv_minor));
+  PyDict_SetItemString (dict, "lv_kernel_major",
+                        PyLong_FromLongLong (lv->lv_kernel_major));
+  PyDict_SetItemString (dict, "lv_kernel_minor",
+                        PyLong_FromLongLong (lv->lv_kernel_minor));
+  PyDict_SetItemString (dict, "lv_size",
+                        PyLong_FromUnsignedLongLong (lv->lv_size));
+  PyDict_SetItemString (dict, "seg_count",
+                        PyLong_FromLongLong (lv->seg_count));
+  PyDict_SetItemString (dict, "origin",
+                        PyString_FromString (lv->origin));
+  if (lv->snap_percent >= 0)
+    PyDict_SetItemString (dict, "snap_percent",
+                          PyFloat_FromDouble ((double) lv->snap_percent));
+  else {
+    Py_INCREF (Py_None);
+    PyDict_SetItemString (dict, "snap_percent", Py_None);  }
+  if (lv->copy_percent >= 0)
+    PyDict_SetItemString (dict, "copy_percent",
+                          PyFloat_FromDouble ((double) lv->copy_percent));
+  else {
+    Py_INCREF (Py_None);
+    PyDict_SetItemString (dict, "copy_percent", Py_None);  }
+  PyDict_SetItemString (dict, "move_pv",
+                        PyString_FromString (lv->move_pv));
+  PyDict_SetItemString (dict, "lv_tags",
+                        PyString_FromString (lv->lv_tags));
+  PyDict_SetItemString (dict, "mirror_log",
+                        PyString_FromString (lv->mirror_log));
+  PyDict_SetItemString (dict, "modules",
+                        PyString_FromString (lv->modules));
+  return dict;
+};
+
+static PyObject *
+put_lvm_lv_list (struct guestfs_lvm_lv_list *lvs)
+{
+  PyObject *list;
+  int i;
+
+  list = PyList_New (lvs->len);
+  for (i = 0; i < lvs->len; ++i)
+    PyList_SetItem (list, i, put_lvm_lv (&lvs->val[i]));
+  return list;
+};
+
+static PyObject *
+py_guestfs_launch (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_launch",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_launch (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_wait_ready (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_wait_ready",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_wait_ready (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_kill_subprocess (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_kill_subprocess",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_kill_subprocess (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_add_drive (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *filename;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_add_drive",
+                         &py_g, &filename))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_add_drive (g, filename);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_add_cdrom (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *filename;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_add_cdrom",
+                         &py_g, &filename))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_add_cdrom (g, filename);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_config (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *qemuparam;
+  const char *qemuvalue;
+
+  if (!PyArg_ParseTuple (args, (char *) "Osz:guestfs_config",
+                         &py_g, &qemuparam, &qemuvalue))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_config (g, qemuparam, qemuvalue);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_set_path (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_set_path",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_set_path (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_get_path (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  const char *r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_get_path",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_get_path (g);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyString_FromString (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_set_autosync (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  int autosync;
+
+  if (!PyArg_ParseTuple (args, (char *) "Oi:guestfs_set_autosync",
+                         &py_g, &autosync))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_set_autosync (g, autosync);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_get_autosync (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_get_autosync",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_get_autosync (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyInt_FromLong ((long) r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_set_verbose (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  int verbose;
+
+  if (!PyArg_ParseTuple (args, (char *) "Oi:guestfs_set_verbose",
+                         &py_g, &verbose))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_set_verbose (g, verbose);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_get_verbose (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_get_verbose",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_get_verbose (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyInt_FromLong ((long) r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_mount (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *device;
+  const char *mountpoint;
+
+  if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_mount",
+                         &py_g, &device, &mountpoint))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_mount (g, device, mountpoint);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_sync (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_sync",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_sync (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_touch (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_touch",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_touch (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_cat (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char *r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_cat",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_cat (g, path);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyString_FromString (r);
+  free (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_ll (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char *r;
+  const char *directory;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_ll",
+                         &py_g, &directory))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_ll (g, directory);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyString_FromString (r);
+  free (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_ls (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char **r;
+  const char *directory;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_ls",
+                         &py_g, &directory))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_ls (g, directory);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_string_list (r);
+  free_strings (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_list_devices (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char **r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_list_devices",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_list_devices (g);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_string_list (r);
+  free_strings (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_list_partitions (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char **r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_list_partitions",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_list_partitions (g);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_string_list (r);
+  free_strings (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_pvs (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char **r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_pvs",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_pvs (g);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_string_list (r);
+  free_strings (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_vgs (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char **r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_vgs",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_vgs (g);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_string_list (r);
+  free_strings (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_lvs (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char **r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_lvs",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_lvs (g);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_string_list (r);
+  free_strings (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_pvs_full (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  struct guestfs_lvm_pv_list *r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_pvs_full",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_pvs_full (g);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_lvm_pv_list (r);
+  guestfs_free_lvm_pv_list (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_vgs_full (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  struct guestfs_lvm_vg_list *r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_vgs_full",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_vgs_full (g);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_lvm_vg_list (r);
+  guestfs_free_lvm_vg_list (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_lvs_full (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  struct guestfs_lvm_lv_list *r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_lvs_full",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_lvs_full (g);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_lvm_lv_list (r);
+  guestfs_free_lvm_lv_list (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_read_lines (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char **r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_read_lines",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_read_lines (g, path);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_string_list (r);
+  free_strings (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_init (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *root;
+  int flags;
+
+  if (!PyArg_ParseTuple (args, (char *) "Osi:guestfs_aug_init",
+                         &py_g, &root, &flags))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_init (g, root, flags);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_close (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_aug_close",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_close (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_defvar (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *name;
+  const char *expr;
+
+  if (!PyArg_ParseTuple (args, (char *) "Osz:guestfs_aug_defvar",
+                         &py_g, &name, &expr))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_defvar (g, name, expr);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyInt_FromLong ((long) r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_defnode (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  struct guestfs_int_bool *r;
+  const char *name;
+  const char *expr;
+  const char *val;
+
+  if (!PyArg_ParseTuple (args, (char *) "Osss:guestfs_aug_defnode",
+                         &py_g, &name, &expr, &val))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_defnode (g, name, expr, val);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyTuple_New (2);
+  PyTuple_SetItem (py_r, 0, PyInt_FromLong ((long) r->i));
+  PyTuple_SetItem (py_r, 1, PyInt_FromLong ((long) r->b));
+  guestfs_free_int_bool (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_get (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char *r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_aug_get",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_get (g, path);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyString_FromString (r);
+  free (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_set (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+  const char *val;
+
+  if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_aug_set",
+                         &py_g, &path, &val))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_set (g, path, val);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_insert (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+  const char *label;
+  int before;
+
+  if (!PyArg_ParseTuple (args, (char *) "Ossi:guestfs_aug_insert",
+                         &py_g, &path, &label, &before))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_insert (g, path, label, before);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_rm (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_aug_rm",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_rm (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyInt_FromLong ((long) r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_mv (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *src;
+  const char *dest;
+
+  if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_aug_mv",
+                         &py_g, &src, &dest))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_mv (g, src, dest);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_match (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char **r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_aug_match",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_match (g, path);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_string_list (r);
+  free_strings (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_save (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_aug_save",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_save (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_load (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_aug_load",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_load (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_aug_ls (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char **r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_aug_ls",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_aug_ls (g, path);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_string_list (r);
+  free_strings (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_rm (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_rm",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_rm (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_rmdir (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_rmdir",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_rmdir (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_rm_rf (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_rm_rf",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_rm_rf (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_mkdir (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_mkdir",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_mkdir (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_mkdir_p (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_mkdir_p",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_mkdir_p (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_chmod (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  int mode;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Ois:guestfs_chmod",
+                         &py_g, &mode, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_chmod (g, mode, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_chown (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  int owner;
+  int group;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Oiis:guestfs_chown",
+                         &py_g, &owner, &group, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_chown (g, owner, group, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_exists (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_exists",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_exists (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyInt_FromLong ((long) r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_is_file (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_is_file",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_is_file (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyInt_FromLong ((long) r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_is_dir (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_is_dir",
+                         &py_g, &path))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_is_dir (g, path);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = PyInt_FromLong ((long) r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_pvcreate (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *device;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_pvcreate",
+                         &py_g, &device))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_pvcreate (g, device);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_vgcreate (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *volgroup;
+  PyObject *py_physvols;
+  const char **physvols;
+
+  if (!PyArg_ParseTuple (args, (char *) "OsO:guestfs_vgcreate",
+                         &py_g, &volgroup, &py_physvols))
+    return NULL;
+  g = get_handle (py_g);
+  physvols = get_string_list (py_physvols);
+  if (!physvols) return NULL;
+
+  r = guestfs_vgcreate (g, volgroup, physvols);
+  free (physvols);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_lvcreate (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *logvol;
+  const char *volgroup;
+  int mbytes;
+
+  if (!PyArg_ParseTuple (args, (char *) "Ossi:guestfs_lvcreate",
+                         &py_g, &logvol, &volgroup, &mbytes))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_lvcreate (g, logvol, volgroup, mbytes);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_mkfs (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *fstype;
+  const char *device;
+
+  if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_mkfs",
+                         &py_g, &fstype, &device))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_mkfs (g, fstype, device);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_sfdisk (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *device;
+  int cyls;
+  int heads;
+  int sectors;
+  PyObject *py_lines;
+  const char **lines;
+
+  if (!PyArg_ParseTuple (args, (char *) "OsiiiO:guestfs_sfdisk",
+                         &py_g, &device, &cyls, &heads, &sectors, &py_lines))
+    return NULL;
+  g = get_handle (py_g);
+  lines = get_string_list (py_lines);
+  if (!lines) return NULL;
+
+  r = guestfs_sfdisk (g, device, cyls, heads, sectors, lines);
+  free (lines);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_write_file (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *path;
+  const char *content;
+  int size;
+
+  if (!PyArg_ParseTuple (args, (char *) "Ossi:guestfs_write_file",
+                         &py_g, &path, &content, &size))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_write_file (g, path, content, size);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_umount (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+  const char *pathordevice;
+
+  if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_umount",
+                         &py_g, &pathordevice))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_umount (g, pathordevice);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_mounts (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  char **r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_mounts",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_mounts (g);
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  py_r = put_string_list (r);
+  free_strings (r);
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_umount_all (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_umount_all",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_umount_all (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyObject *
+py_guestfs_lvm_remove_all (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+  PyObject *py_r;
+  int r;
+
+  if (!PyArg_ParseTuple (args, (char *) "O:guestfs_lvm_remove_all",
+                         &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  r = guestfs_lvm_remove_all (g);
+  if (r == -1) {
+    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+    return NULL;
+  }
+
+  Py_INCREF (Py_None);
+  py_r = Py_None;
+  return py_r;
+}
+
+static PyMethodDef methods[] = {
+  { (char *) "create", py_guestfs_create, METH_VARARGS, NULL },
+  { (char *) "close", py_guestfs_close, METH_VARARGS, NULL },
+  { (char *) "launch", py_guestfs_launch, METH_VARARGS, NULL },
+  { (char *) "wait_ready", py_guestfs_wait_ready, METH_VARARGS, NULL },
+  { (char *) "kill_subprocess", py_guestfs_kill_subprocess, METH_VARARGS, NULL },
+  { (char *) "add_drive", py_guestfs_add_drive, METH_VARARGS, NULL },
+  { (char *) "add_cdrom", py_guestfs_add_cdrom, METH_VARARGS, NULL },
+  { (char *) "config", py_guestfs_config, METH_VARARGS, NULL },
+  { (char *) "set_path", py_guestfs_set_path, METH_VARARGS, NULL },
+  { (char *) "get_path", py_guestfs_get_path, METH_VARARGS, NULL },
+  { (char *) "set_autosync", py_guestfs_set_autosync, METH_VARARGS, NULL },
+  { (char *) "get_autosync", py_guestfs_get_autosync, METH_VARARGS, NULL },
+  { (char *) "set_verbose", py_guestfs_set_verbose, METH_VARARGS, NULL },
+  { (char *) "get_verbose", py_guestfs_get_verbose, METH_VARARGS, NULL },
+  { (char *) "mount", py_guestfs_mount, METH_VARARGS, NULL },
+  { (char *) "sync", py_guestfs_sync, METH_VARARGS, NULL },
+  { (char *) "touch", py_guestfs_touch, METH_VARARGS, NULL },
+  { (char *) "cat", py_guestfs_cat, METH_VARARGS, NULL },
+  { (char *) "ll", py_guestfs_ll, METH_VARARGS, NULL },
+  { (char *) "ls", py_guestfs_ls, METH_VARARGS, NULL },
+  { (char *) "list_devices", py_guestfs_list_devices, METH_VARARGS, NULL },
+  { (char *) "list_partitions", py_guestfs_list_partitions, METH_VARARGS, NULL },
+  { (char *) "pvs", py_guestfs_pvs, METH_VARARGS, NULL },
+  { (char *) "vgs", py_guestfs_vgs, METH_VARARGS, NULL },
+  { (char *) "lvs", py_guestfs_lvs, METH_VARARGS, NULL },
+  { (char *) "pvs_full", py_guestfs_pvs_full, METH_VARARGS, NULL },
+  { (char *) "vgs_full", py_guestfs_vgs_full, METH_VARARGS, NULL },
+  { (char *) "lvs_full", py_guestfs_lvs_full, METH_VARARGS, NULL },
+  { (char *) "read_lines", py_guestfs_read_lines, METH_VARARGS, NULL },
+  { (char *) "aug_init", py_guestfs_aug_init, METH_VARARGS, NULL },
+  { (char *) "aug_close", py_guestfs_aug_close, METH_VARARGS, NULL },
+  { (char *) "aug_defvar", py_guestfs_aug_defvar, METH_VARARGS, NULL },
+  { (char *) "aug_defnode", py_guestfs_aug_defnode, METH_VARARGS, NULL },
+  { (char *) "aug_get", py_guestfs_aug_get, METH_VARARGS, NULL },
+  { (char *) "aug_set", py_guestfs_aug_set, METH_VARARGS, NULL },
+  { (char *) "aug_insert", py_guestfs_aug_insert, METH_VARARGS, NULL },
+  { (char *) "aug_rm", py_guestfs_aug_rm, METH_VARARGS, NULL },
+  { (char *) "aug_mv", py_guestfs_aug_mv, METH_VARARGS, NULL },
+  { (char *) "aug_match", py_guestfs_aug_match, METH_VARARGS, NULL },
+  { (char *) "aug_save", py_guestfs_aug_save, METH_VARARGS, NULL },
+  { (char *) "aug_load", py_guestfs_aug_load, METH_VARARGS, NULL },
+  { (char *) "aug_ls", py_guestfs_aug_ls, METH_VARARGS, NULL },
+  { (char *) "rm", py_guestfs_rm, METH_VARARGS, NULL },
+  { (char *) "rmdir", py_guestfs_rmdir, METH_VARARGS, NULL },
+  { (char *) "rm_rf", py_guestfs_rm_rf, METH_VARARGS, NULL },
+  { (char *) "mkdir", py_guestfs_mkdir, METH_VARARGS, NULL },
+  { (char *) "mkdir_p", py_guestfs_mkdir_p, METH_VARARGS, NULL },
+  { (char *) "chmod", py_guestfs_chmod, METH_VARARGS, NULL },
+  { (char *) "chown", py_guestfs_chown, METH_VARARGS, NULL },
+  { (char *) "exists", py_guestfs_exists, METH_VARARGS, NULL },
+  { (char *) "is_file", py_guestfs_is_file, METH_VARARGS, NULL },
+  { (char *) "is_dir", py_guestfs_is_dir, METH_VARARGS, NULL },
+  { (char *) "pvcreate", py_guestfs_pvcreate, METH_VARARGS, NULL },
+  { (char *) "vgcreate", py_guestfs_vgcreate, METH_VARARGS, NULL },
+  { (char *) "lvcreate", py_guestfs_lvcreate, METH_VARARGS, NULL },
+  { (char *) "mkfs", py_guestfs_mkfs, METH_VARARGS, NULL },
+  { (char *) "sfdisk", py_guestfs_sfdisk, METH_VARARGS, NULL },
+  { (char *) "write_file", py_guestfs_write_file, METH_VARARGS, NULL },
+  { (char *) "umount", py_guestfs_umount, METH_VARARGS, NULL },
+  { (char *) "mounts", py_guestfs_mounts, METH_VARARGS, NULL },
+  { (char *) "umount_all", py_guestfs_umount_all, METH_VARARGS, NULL },
+  { (char *) "lvm_remove_all", py_guestfs_lvm_remove_all, METH_VARARGS, NULL },
+  { NULL, NULL, 0, NULL }
+};
+
+void
+initlibguestfsmod (void)
+{
+  static int initialized = 0;
+
+  if (initialized) return;
+  Py_InitModule ((char *) "libguestfsmod", methods);
+  initialized = 1;
+}
diff --git a/python/guestfs.py b/python/guestfs.py
new file mode 100644 (file)
index 0000000..fc57d8d
--- /dev/null
@@ -0,0 +1,209 @@
+# libguestfs generated file
+# WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.
+# ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+#
+# Copyright (C) 2009 Red Hat Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+import libguestfsmod
+
+class guestfs:
+    def __init__ (self):
+        self._o = libguestfsmod.create ()
+
+    def __del__ (self):
+        libguestfsmod.close (self._o)
+
+    def launch (self):
+        return libguestfsmod.launch (self._o)
+
+    def wait_ready (self):
+        return libguestfsmod.wait_ready (self._o)
+
+    def kill_subprocess (self):
+        return libguestfsmod.kill_subprocess (self._o)
+
+    def add_drive (self, filename):
+        return libguestfsmod.add_drive (self._o, filename)
+
+    def add_cdrom (self, filename):
+        return libguestfsmod.add_cdrom (self._o, filename)
+
+    def config (self, qemuparam, qemuvalue):
+        return libguestfsmod.config (self._o, qemuparam, qemuvalue)
+
+    def set_path (self, path):
+        return libguestfsmod.set_path (self._o, path)
+
+    def get_path (self):
+        return libguestfsmod.get_path (self._o)
+
+    def set_autosync (self, autosync):
+        return libguestfsmod.set_autosync (self._o, autosync)
+
+    def get_autosync (self):
+        return libguestfsmod.get_autosync (self._o)
+
+    def set_verbose (self, verbose):
+        return libguestfsmod.set_verbose (self._o, verbose)
+
+    def get_verbose (self):
+        return libguestfsmod.get_verbose (self._o)
+
+    def mount (self, device, mountpoint):
+        return libguestfsmod.mount (self._o, device, mountpoint)
+
+    def sync (self):
+        return libguestfsmod.sync (self._o)
+
+    def touch (self, path):
+        return libguestfsmod.touch (self._o, path)
+
+    def cat (self, path):
+        return libguestfsmod.cat (self._o, path)
+
+    def ll (self, directory):
+        return libguestfsmod.ll (self._o, directory)
+
+    def ls (self, directory):
+        return libguestfsmod.ls (self._o, directory)
+
+    def list_devices (self):
+        return libguestfsmod.list_devices (self._o)
+
+    def list_partitions (self):
+        return libguestfsmod.list_partitions (self._o)
+
+    def pvs (self):
+        return libguestfsmod.pvs (self._o)
+
+    def vgs (self):
+        return libguestfsmod.vgs (self._o)
+
+    def lvs (self):
+        return libguestfsmod.lvs (self._o)
+
+    def pvs_full (self):
+        return libguestfsmod.pvs_full (self._o)
+
+    def vgs_full (self):
+        return libguestfsmod.vgs_full (self._o)
+
+    def lvs_full (self):
+        return libguestfsmod.lvs_full (self._o)
+
+    def read_lines (self, path):
+        return libguestfsmod.read_lines (self._o, path)
+
+    def aug_init (self, root, flags):
+        return libguestfsmod.aug_init (self._o, root, flags)
+
+    def aug_close (self):
+        return libguestfsmod.aug_close (self._o)
+
+    def aug_defvar (self, name, expr):
+        return libguestfsmod.aug_defvar (self._o, name, expr)
+
+    def aug_defnode (self, name, expr, val):
+        return libguestfsmod.aug_defnode (self._o, name, expr, val)
+
+    def aug_get (self, path):
+        return libguestfsmod.aug_get (self._o, path)
+
+    def aug_set (self, path, val):
+        return libguestfsmod.aug_set (self._o, path, val)
+
+    def aug_insert (self, path, label, before):
+        return libguestfsmod.aug_insert (self._o, path, label, before)
+
+    def aug_rm (self, path):
+        return libguestfsmod.aug_rm (self._o, path)
+
+    def aug_mv (self, src, dest):
+        return libguestfsmod.aug_mv (self._o, src, dest)
+
+    def aug_match (self, path):
+        return libguestfsmod.aug_match (self._o, path)
+
+    def aug_save (self):
+        return libguestfsmod.aug_save (self._o)
+
+    def aug_load (self):
+        return libguestfsmod.aug_load (self._o)
+
+    def aug_ls (self, path):
+        return libguestfsmod.aug_ls (self._o, path)
+
+    def rm (self, path):
+        return libguestfsmod.rm (self._o, path)
+
+    def rmdir (self, path):
+        return libguestfsmod.rmdir (self._o, path)
+
+    def rm_rf (self, path):
+        return libguestfsmod.rm_rf (self._o, path)
+
+    def mkdir (self, path):
+        return libguestfsmod.mkdir (self._o, path)
+
+    def mkdir_p (self, path):
+        return libguestfsmod.mkdir_p (self._o, path)
+
+    def chmod (self, mode, path):
+        return libguestfsmod.chmod (self._o, mode, path)
+
+    def chown (self, owner, group, path):
+        return libguestfsmod.chown (self._o, owner, group, path)
+
+    def exists (self, path):
+        return libguestfsmod.exists (self._o, path)
+
+    def is_file (self, path):
+        return libguestfsmod.is_file (self._o, path)
+
+    def is_dir (self, path):
+        return libguestfsmod.is_dir (self._o, path)
+
+    def pvcreate (self, device):
+        return libguestfsmod.pvcreate (self._o, device)
+
+    def vgcreate (self, volgroup, physvols):
+        return libguestfsmod.vgcreate (self._o, volgroup, physvols)
+
+    def lvcreate (self, logvol, volgroup, mbytes):
+        return libguestfsmod.lvcreate (self._o, logvol, volgroup, mbytes)
+
+    def mkfs (self, fstype, device):
+        return libguestfsmod.mkfs (self._o, fstype, device)
+
+    def sfdisk (self, device, cyls, heads, sectors, lines):
+        return libguestfsmod.sfdisk (self._o, device, cyls, heads, sectors, lines)
+
+    def write_file (self, path, content, size):
+        return libguestfsmod.write_file (self._o, path, content, size)
+
+    def umount (self, pathordevice):
+        return libguestfsmod.umount (self._o, pathordevice)
+
+    def mounts (self):
+        return libguestfsmod.mounts (self._o)
+
+    def umount_all (self):
+        return libguestfsmod.umount_all (self._o)
+
+    def lvm_remove_all (self):
+        return libguestfsmod.lvm_remove_all (self._o)
+
diff --git a/python/t/005-import.py b/python/t/005-import.py
new file mode 100644 (file)
index 0000000..5896d15
--- /dev/null
@@ -0,0 +1,18 @@
+# libguestfs Python bindings
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+import guestfs
diff --git a/python/t/010-launch.py b/python/t/010-launch.py
new file mode 100644 (file)
index 0000000..c2bdd1d
--- /dev/null
@@ -0,0 +1,26 @@
+# libguestfs Python bindings
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+import guestfs
+
+g = guestfs.guestfs()
+f = open ("test.img", "w")
+f.truncate (500 * 1024 * 1024)
+f.close ()
+g.add_drive ("test.img")
+g.launch ()
+g.wait_ready ()
diff --git a/python/t/050-lvcreate.py b/python/t/050-lvcreate.py
new file mode 100644 (file)
index 0000000..98227e2
--- /dev/null
@@ -0,0 +1,37 @@
+# libguestfs Python bindings
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+import guestfs
+
+g = guestfs.guestfs()
+f = open ("test.img", "w")
+f.truncate (500 * 1024 * 1024)
+f.close ()
+g.add_drive ("test.img")
+g.launch ()
+g.wait_ready ()
+g.pvcreate ("/dev/sda")
+g.vgcreate ("VG", ["/dev/sda"])
+g.lvcreate ("LV1", "VG", 200)
+g.lvcreate ("LV2", "VG", 200)
+if (g.lvs () != ["/dev/VG/LV1", "/dev/VG/LV2"]):
+    raise "Error: g.lvs() returned incorrect result"
+g.sync ()
+del g
+
+import os
+os.unlink ("test.img")
index 28e1cb6..06a95a9 100755 (executable)
@@ -148,21 +148,26 @@ and test =
 
 (* Some initial scenarios for testing. *)
 and test_init =
-    (* Do nothing, block devices could contain random stuff. *)
+    (* Do nothing, block devices could contain random stuff including
+     * LVM PVs, and some filesystems might be mounted.  This is usually
+     * a bad idea.
+     *)
   | InitNone
+    (* Block devices are empty and no filesystems are mounted. *)
+  | InitEmpty
     (* /dev/sda contains a single partition /dev/sda1, which is formatted
      * as ext2, empty [except for lost+found] and mounted on /.
      * /dev/sdb and /dev/sdc may have random content.
      * No LVM.
      *)
-  | InitEmpty
+  | InitBasicFS
     (* /dev/sda:
      *   /dev/sda1 (is a PV):
      *     /dev/VG/LV (size 8MB):
      *       formatted as ext2, empty [except for lost+found], mounted on /
      * /dev/sdb and /dev/sdc may have random content.
      *)
-  | InitEmptyLVM
+  | InitBasicFSonLVM
 
 (* Sequence of commands for testing. *)
 and seq = cmd list
@@ -296,7 +301,7 @@ This returns the verbose messages flag.")
 
 let daemon_functions = [
   ("mount", (RErr, [String "device"; String "mountpoint"]), 1, [],
-   [InitNone, TestOutput (
+   [InitEmpty, TestOutput (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
        ["mkfs"; "ext2"; "/dev/sda1"];
        ["mount"; "/dev/sda1"; "/"];
@@ -322,7 +327,7 @@ The filesystem options C<sync> and C<noatime> are set with this
 call, in order to improve reliability.");
 
   ("sync", (RErr, []), 2, [],
-   [ InitNone, TestRun [["sync"]]],
+   [ InitEmpty, TestRun [["sync"]]],
    "sync disks, writes are flushed through to the disk image",
    "\
 This syncs the disk, so that any writes are flushed through to the
@@ -332,7 +337,7 @@ You should always call this if you have modified a disk image, before
 closing the handle.");
 
   ("touch", (RErr, [String "path"]), 3, [],
-   [InitEmpty, TestOutputTrue (
+   [InitBasicFS, TestOutputTrue (
       [["touch"; "/new"];
        ["exists"; "/new"]])],
    "update file timestamps or create a new file",
@@ -342,7 +347,7 @@ update the timestamps on a file, or, if the file does not exist,
 to create a new zero-length file.");
 
   ("cat", (RString "content", [String "path"]), 4, [ProtocolLimitWarning],
-   [InitEmpty, TestOutput (
+   [InitBasicFS, TestOutput (
       [["write_file"; "/new"; "new file contents"; "0"];
        ["cat"; "/new"]], "new file contents")],
    "list the contents of a file",
@@ -367,7 +372,7 @@ This command is mostly useful for interactive sessions.  It
 is I<not> intended that you try to parse the output string.");
 
   ("ls", (RStringList "listing", [String "directory"]), 6, [],
-   [InitEmpty, TestOutputList (
+   [InitBasicFS, TestOutputList (
       [["touch"; "/new"];
        ["touch"; "/newer"];
        ["touch"; "/newest"];
@@ -382,7 +387,7 @@ This command is mostly useful for interactive sessions.  Programs
 should probably use C<guestfs_readdir> instead.");
 
   ("list_devices", (RStringList "devices", []), 7, [],
-   [InitNone, TestOutputList (
+   [InitEmpty, TestOutputList (
       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"])],
    "list the block devices",
    "\
@@ -391,9 +396,9 @@ List all the block devices.
 The full block device names are returned, eg. C</dev/sda>");
 
   ("list_partitions", (RStringList "partitions", []), 8, [],
-   [InitEmpty, TestOutputList (
+   [InitBasicFS, TestOutputList (
       [["list_partitions"]], ["/dev/sda1"]);
-    InitNone, TestOutputList (
+    InitEmpty, TestOutputList (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
    "list the partitions",
@@ -406,9 +411,9 @@ This does not return logical volumes.  For that you will need to
 call C<guestfs_lvs>.");
 
   ("pvs", (RStringList "physvols", []), 9, [],
-   [InitEmptyLVM, TestOutputList (
+   [InitBasicFSonLVM, TestOutputList (
       [["pvs"]], ["/dev/sda1"]);
-    InitNone, TestOutputList (
+    InitEmpty, TestOutputList (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
        ["pvcreate"; "/dev/sda1"];
        ["pvcreate"; "/dev/sda2"];
@@ -425,9 +430,9 @@ PVs (eg. C</dev/sda2>).
 See also C<guestfs_pvs_full>.");
 
   ("vgs", (RStringList "volgroups", []), 10, [],
-   [InitEmptyLVM, TestOutputList (
+   [InitBasicFSonLVM, TestOutputList (
       [["vgs"]], ["VG"]);
-    InitNone, TestOutputList (
+    InitEmpty, TestOutputList (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
        ["pvcreate"; "/dev/sda1"];
        ["pvcreate"; "/dev/sda2"];
@@ -446,9 +451,9 @@ detected (eg. C<VolGroup00>).
 See also C<guestfs_vgs_full>.");
 
   ("lvs", (RStringList "logvols", []), 11, [],
-   [InitEmptyLVM, TestOutputList (
+   [InitBasicFSonLVM, TestOutputList (
       [["lvs"]], ["/dev/VG/LV"]);
-    InitNone, TestOutputList (
+    InitEmpty, TestOutputList (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
        ["pvcreate"; "/dev/sda1"];
        ["pvcreate"; "/dev/sda2"];
@@ -470,7 +475,7 @@ This returns a list of the logical volume device names
 See also C<guestfs_lvs_full>.");
 
   ("pvs_full", (RPVList "physvols", []), 12, [],
-   [InitEmptyLVM, TestOutputLength (
+   [InitBasicFSonLVM, TestOutputLength (
       [["pvs"]], 1)],
    "list the LVM physical volumes (PVs)",
    "\
@@ -478,7 +483,7 @@ List all the physical volumes detected.  This is the equivalent
 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
 
   ("vgs_full", (RVGList "volgroups", []), 13, [],
-   [InitEmptyLVM, TestOutputLength (
+   [InitBasicFSonLVM, TestOutputLength (
       [["pvs"]], 1)],
    "list the LVM volume groups (VGs)",
    "\
@@ -486,7 +491,7 @@ List all the volumes groups detected.  This is the equivalent
 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
 
   ("lvs_full", (RLVList "logvols", []), 14, [],
-   [InitEmptyLVM, TestOutputLength (
+   [InitBasicFSonLVM, TestOutputLength (
       [["pvs"]], 1)],
    "list the LVM logical volumes (LVs)",
    "\
@@ -494,10 +499,10 @@ List all the logical volumes detected.  This is the equivalent
 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
 
   ("read_lines", (RStringList "lines", [String "path"]), 15, [],
-   [InitEmpty, TestOutputList (
+   [InitBasicFS, TestOutputList (
       [["write_file"; "/new"; "line1\r\nline2\nline3"; "0"];
        ["read_lines"; "/new"]], ["line1"; "line2"; "line3"]);
-    InitEmpty, TestOutputList (
+    InitBasicFS, TestOutputList (
       [["write_file"; "/new"; ""; "0"];
        ["read_lines"; "/new"]], [])],
    "read file as lines",
@@ -672,12 +677,12 @@ This is just a shortcut for listing C<guestfs_aug_match>
 C<path/*> and sorting the resulting nodes into alphabetical order.");
 
   ("rm", (RErr, [String "path"]), 29, [],
-   [InitEmpty, TestRun
+   [InitBasicFS, TestRun
       [["touch"; "/new"];
        ["rm"; "/new"]];
-    InitEmpty, TestLastFail
+    InitBasicFS, TestLastFail
       [["rm"; "/new"]];
-    InitEmpty, TestLastFail
+    InitBasicFS, TestLastFail
       [["mkdir"; "/new"];
        ["rm"; "/new"]]],
    "remove a file",
@@ -685,12 +690,12 @@ C<path/*> and sorting the resulting nodes into alphabetical order.");
 Remove the single file C<path>.");
 
   ("rmdir", (RErr, [String "path"]), 30, [],
-   [InitEmpty, TestRun
+   [InitBasicFS, TestRun
       [["mkdir"; "/new"];
        ["rmdir"; "/new"]];
-    InitEmpty, TestLastFail
+    InitBasicFS, TestLastFail
       [["rmdir"; "/new"]];
-    InitEmpty, TestLastFail
+    InitBasicFS, TestLastFail
       [["touch"; "/new"];
        ["rmdir"; "/new"]]],
    "remove a directory",
@@ -698,7 +703,7 @@ Remove the single file C<path>.");
 Remove the single directory C<path>.");
 
   ("rm_rf", (RErr, [String "path"]), 31, [],
-   [InitEmpty, TestOutputFalse
+   [InitBasicFS, TestOutputFalse
       [["mkdir"; "/new"];
        ["mkdir"; "/new/foo"];
        ["touch"; "/new/foo/bar"];
@@ -711,23 +716,23 @@ contents if its a directory.  This is like the C<rm -rf> shell
 command.");
 
   ("mkdir", (RErr, [String "path"]), 32, [],
-   [InitEmpty, TestOutputTrue
+   [InitBasicFS, TestOutputTrue
       [["mkdir"; "/new"];
        ["is_dir"; "/new"]];
-    InitEmpty, TestLastFail
+    InitBasicFS, TestLastFail
       [["mkdir"; "/new/foo/bar"]]],
    "create a directory",
    "\
 Create a directory named C<path>.");
 
   ("mkdir_p", (RErr, [String "path"]), 33, [],
-   [InitEmpty, TestOutputTrue
+   [InitBasicFS, TestOutputTrue
       [["mkdir_p"; "/new/foo/bar"];
        ["is_dir"; "/new/foo/bar"]];
-    InitEmpty, TestOutputTrue
+    InitBasicFS, TestOutputTrue
       [["mkdir_p"; "/new/foo/bar"];
        ["is_dir"; "/new/foo"]];
-    InitEmpty, TestOutputTrue
+    InitBasicFS, TestOutputTrue
       [["mkdir_p"; "/new/foo/bar"];
        ["is_dir"; "/new"]]],
    "create a directory and parents",
@@ -753,10 +758,10 @@ names, you will need to locate and parse the password file
 yourself (Augeas support makes this relatively easy).");
 
   ("exists", (RBool "existsflag", [String "path"]), 36, [],
-   [InitEmpty, TestOutputTrue (
+   [InitBasicFS, TestOutputTrue (
       [["touch"; "/new"];
        ["exists"; "/new"]]);
-    InitEmpty, TestOutputTrue (
+    InitBasicFS, TestOutputTrue (
       [["mkdir"; "/new"];
        ["exists"; "/new"]])],
    "test if file or directory exists",
@@ -767,10 +772,10 @@ This returns C<true> if and only if there is a file, directory
 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
 
   ("is_file", (RBool "fileflag", [String "path"]), 37, [],
-   [InitEmpty, TestOutputTrue (
+   [InitBasicFS, TestOutputTrue (
       [["touch"; "/new"];
        ["is_file"; "/new"]]);
-    InitEmpty, TestOutputFalse (
+    InitBasicFS, TestOutputFalse (
       [["mkdir"; "/new"];
        ["is_file"; "/new"]])],
    "test if file exists",
@@ -782,10 +787,10 @@ other objects like directories.
 See also C<guestfs_stat>.");
 
   ("is_dir", (RBool "dirflag", [String "path"]), 38, [],
-   [InitEmpty, TestOutputFalse (
+   [InitBasicFS, TestOutputFalse (
       [["touch"; "/new"];
        ["is_dir"; "/new"]]);
-    InitEmpty, TestOutputTrue (
+    InitBasicFS, TestOutputTrue (
       [["mkdir"; "/new"];
        ["is_dir"; "/new"]])],
    "test if file exists",
@@ -797,7 +802,7 @@ other objects like files.
 See also C<guestfs_stat>.");
 
   ("pvcreate", (RErr, [String "device"]), 39, [],
-   [InitNone, TestOutputList (
+   [InitEmpty, TestOutputList (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
        ["pvcreate"; "/dev/sda1"];
        ["pvcreate"; "/dev/sda2"];
@@ -810,7 +815,7 @@ where C<device> should usually be a partition name such
 as C</dev/sda1>.");
 
   ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [],
-   [InitNone, TestOutputList (
+   [InitEmpty, TestOutputList (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
        ["pvcreate"; "/dev/sda1"];
        ["pvcreate"; "/dev/sda2"];
@@ -824,7 +829,7 @@ This creates an LVM volume group called C<volgroup>
 from the non-empty list of physical volumes C<physvols>.");
 
   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
-   [InitNone, TestOutputList (
+   [InitEmpty, TestOutputList (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
        ["pvcreate"; "/dev/sda1"];
        ["pvcreate"; "/dev/sda2"];
@@ -845,7 +850,7 @@ This creates an LVM volume group called C<logvol>
 on the volume group C<volgroup>, with C<size> megabytes.");
 
   ("mkfs", (RErr, [String "fstype"; String "device"]), 42, [],
-   [InitNone, TestOutput (
+   [InitEmpty, TestOutput (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
        ["mkfs"; "ext2"; "/dev/sda1"];
        ["mount"; "/dev/sda1"; "/"];
@@ -884,7 +889,7 @@ pass C<lines> as a single element list, when the single element being
 the string C<,> (comma).");
 
   ("write_file", (RErr, [String "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
-   [InitNone, TestOutput (
+   [InitEmpty, TestOutput (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
        ["mkfs"; "ext2"; "/dev/sda1"];
        ["mount"; "/dev/sda1"; "/"];
@@ -901,12 +906,12 @@ then the length is calculated using C<strlen> (so in this case
 the content cannot contain embedded ASCII NULs).");
 
   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
-   [InitNone, TestOutputList (
+   [InitEmpty, TestOutputList (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
        ["mkfs"; "ext2"; "/dev/sda1"];
        ["mount"; "/dev/sda1"; "/"];
        ["mounts"]], ["/dev/sda1"]);
-    InitNone, TestOutputList (
+    InitEmpty, TestOutputList (
       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
        ["mkfs"; "ext2"; "/dev/sda1"];
        ["mount"; "/dev/sda1"; "/"];
@@ -919,7 +924,7 @@ specified either by its mountpoint (path) or the device which
 contains the filesystem.");
 
   ("mounts", (RStringList "devices", []), 46, [],
-   [InitEmpty, TestOutputList (
+   [InitBasicFS, TestOutputList (
       [["mounts"]], ["/dev/sda1"])],
    "show mounted filesystems",
    "\
@@ -929,7 +934,7 @@ the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
 Some internal mounts are not shown.");
 
   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
-   [InitEmpty, TestOutputList (
+   [InitBasicFS, TestOutputList (
       [["umount_all"];
        ["mounts"]], [])],
    "unmount all filesystems",
@@ -2242,21 +2247,22 @@ and generate_one_test name i (init, test) =
   pr "{\n";
 
   (match init with
-   | InitNone ->
-       pr "  /* InitNone for %s (%d) */\n" name i;
+   | InitNone -> ()
+   | InitEmpty ->
+       pr "  /* InitEmpty for %s (%d) */\n" name i;
        List.iter (generate_test_command_call test_name)
         [["umount_all"];
          ["lvm_remove_all"]]
-   | InitEmpty ->
-       pr "  /* InitEmpty for %s (%d): create ext2 on /dev/sda1 */\n" name i;
+   | InitBasicFS ->
+       pr "  /* InitBasicFS for %s (%d): create ext2 on /dev/sda1 */\n" name i;
        List.iter (generate_test_command_call test_name)
         [["umount_all"];
          ["lvm_remove_all"];
          ["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
          ["mkfs"; "ext2"; "/dev/sda1"];
          ["mount"; "/dev/sda1"; "/"]]
-   | InitEmptyLVM ->
-       pr "  /* InitEmptyLVM for %s (%d): create ext2 on /dev/VG/LV */\n"
+   | InitBasicFSonLVM ->
+       pr "  /* InitBasicFSonLVM for %s (%d): create ext2 on /dev/VG/LV */\n"
         name i;
        List.iter (generate_test_command_call test_name)
         [["umount_all"];
@@ -3244,22 +3250,6 @@ my_newSVull(unsigned long long val) {
 #endif
 }
 
-/* XXX Not thread-safe, and in general not safe if the caller is
- * issuing multiple requests in parallel (on different guestfs
- * handles).  We should use the guestfs_h handle passed to the
- * error handle to distinguish these cases.
- */
-static char *last_error = NULL;
-
-static void
-error_handler (guestfs_h *g,
-              void *data,
-              const char *msg)
-{
-  if (last_error != NULL) free (last_error);
-  last_error = strdup (msg);
-}
-
 /* http://www.perlmonks.org/?node_id=680842 */
 static char **
 XS_unpack_charPtrPtr (SV *arg) {
@@ -3277,14 +3267,13 @@ XS_unpack_charPtrPtr (SV *arg) {
   for (i = 0; i <= av_len (av); i++) {
     SV **elem = av_fetch (av, i, 0);
 
-      if (!elem || !*elem) {
-        croak (\"missing element in list\");
-      }
+    if (!elem || !*elem)
+      croak (\"missing element in list\");
 
-      ret[i] = SvPV_nolen (*elem);
+    ret[i] = SvPV_nolen (*elem);
   }
 
-  ret[i + 1] = NULL;
+  ret[i] = NULL;
 
   return ret;
 }
@@ -3297,7 +3286,7 @@ _create ()
       RETVAL = guestfs_create ();
       if (!RETVAL)
         croak (\"could not create guestfs handle\");
-      guestfs_set_error_handler (RETVAL, error_handler, NULL);
+      guestfs_set_error_handler (RETVAL, NULL, NULL);
  OUTPUT:
       RETVAL
 
@@ -3355,7 +3344,7 @@ DESTROY (g)
           generate_call_args ~handle:"g" style;
           pr " == -1) {\n";
           do_cleanups ();
-          pr "        croak (\"%s: %%s\", last_error);\n" name;
+          pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
           pr "      }\n"
        | RInt n
        | RBool n ->
@@ -3367,7 +3356,7 @@ DESTROY (g)
           pr ";\n";
           pr "      if (%s == -1) {\n" n;
           do_cleanups ();
-          pr "        croak (\"%s: %%s\", last_error);\n" name;
+          pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
           pr "      }\n";
           pr "      RETVAL = newSViv (%s);\n" n;
           pr " OUTPUT:\n";
@@ -3381,7 +3370,7 @@ DESTROY (g)
           pr ";\n";
           pr "      if (%s == NULL) {\n" n;
           do_cleanups ();
-          pr "        croak (\"%s: %%s\", last_error);\n" name;
+          pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
           pr "      }\n";
           pr "      RETVAL = newSVpv (%s, 0);\n" n;
           pr " OUTPUT:\n";
@@ -3395,7 +3384,7 @@ DESTROY (g)
           pr ";\n";
           pr "      if (%s == NULL) {\n" n;
           do_cleanups ();
-          pr "        croak (\"%s: %%s\", last_error);\n" name;
+          pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
           pr "      }\n";
           pr "      RETVAL = newSVpv (%s, 0);\n" n;
           pr "      free (%s);\n" n;
@@ -3411,7 +3400,7 @@ DESTROY (g)
           pr ";\n";
           pr "      if (%s == NULL) {\n" n;
           do_cleanups ();
-          pr "        croak (\"%s: %%s\", last_error);\n" name;
+          pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
           pr "      }\n";
           pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
           pr "      EXTEND (SP, n);\n";
@@ -3429,7 +3418,7 @@ DESTROY (g)
           pr ";\n";
           pr "      if (r == NULL) {\n";
           do_cleanups ();
-          pr "        croak (\"%s: %%s\", last_error);\n" name;
+          pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
           pr "      }\n";
           pr "      EXTEND (SP, 2);\n";
           pr "      PUSHs (sv_2mortal (newSViv (r->i)));\n";
@@ -3458,7 +3447,7 @@ and generate_perl_lvm_code typ cols name style n =
   generate_call_args ~handle:"g" style;
   pr ";\n";
   pr "      if (%s == NULL)\n" n;
-  pr "        croak (\"%s: %%s\", last_error);\n" name;
+  pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
   pr "      EXTEND (SP, %s->len);\n" n;
   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
   pr "        hv = newHV ();\n";
@@ -3630,6 +3619,354 @@ and generate_perl_prototype name style =
   ) (snd style);
   pr ");"
 
+(* Generate Python C module. *)
+and generate_python_c () =
+  generate_header CStyle LGPLv2;
+
+  pr "\
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <Python.h>
+
+#include \"guestfs.h\"
+
+typedef struct {
+  PyObject_HEAD
+  guestfs_h *g;
+} Pyguestfs_Object;
+
+static guestfs_h *
+get_handle (PyObject *obj)
+{
+  assert (obj);
+  assert (obj != Py_None);
+  return ((Pyguestfs_Object *) obj)->g;
+}
+
+static PyObject *
+put_handle (guestfs_h *g)
+{
+  assert (g);
+  return
+    PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
+}
+
+/* This list should be freed (but not the strings) after use. */
+static const char **
+get_string_list (PyObject *obj)
+{
+  int i, len;
+  const char **r;
+
+  assert (obj);
+
+  if (!PyList_Check (obj)) {
+    PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
+    return NULL;
+  }
+
+  len = PyList_Size (obj);
+  r = malloc (sizeof (char *) * (len+1));
+  if (r == NULL) {
+    PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
+    return NULL;
+  }
+
+  for (i = 0; i < len; ++i)
+    r[i] = PyString_AsString (PyList_GetItem (obj, i));
+  r[len] = NULL;
+
+  return r;
+}
+
+static PyObject *
+put_string_list (char * const * const argv)
+{
+  PyObject *list;
+  int argc, i;
+
+  for (argc = 0; argv[argc] != NULL; ++argc)
+    ;
+
+  list = PyList_New (argc);
+  for (i = 0; i < argc; ++i)
+    PyList_SetItem (list, i, PyString_FromString (argv[i]));
+
+  return list;
+}
+
+static void
+free_strings (char **argv)
+{
+  int argc;
+
+  for (argc = 0; argv[argc] != NULL; ++argc)
+    free (argv[argc]);
+  free (argv);
+}
+
+static PyObject *
+py_guestfs_create (PyObject *self, PyObject *args)
+{
+  guestfs_h *g;
+
+  g = guestfs_create ();
+  if (g == NULL) {
+    PyErr_SetString (PyExc_RuntimeError,
+                     \"guestfs.create: failed to allocate handle\");
+    return NULL;
+  }
+  guestfs_set_error_handler (g, NULL, NULL);
+  return put_handle (g);
+}
+
+static PyObject *
+py_guestfs_close (PyObject *self, PyObject *args)
+{
+  PyObject *py_g;
+  guestfs_h *g;
+
+  if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
+    return NULL;
+  g = get_handle (py_g);
+
+  guestfs_close (g);
+
+  Py_INCREF (Py_None);
+  return Py_None;
+}
+
+";
+
+  (* LVM structures, turned into Python dictionaries. *)
+  List.iter (
+    fun (typ, cols) ->
+      pr "static PyObject *\n";
+      pr "put_lvm_%s (struct guestfs_lvm_%s *%s)\n" typ typ typ;
+      pr "{\n";
+      pr "  PyObject *dict;\n";
+      pr "\n";
+      pr "  dict = PyDict_New ();\n";
+      List.iter (
+       function
+       | name, `String ->
+           pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
+           pr "                        PyString_FromString (%s->%s));\n"
+             typ name
+       | name, `UUID ->
+           pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
+           pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
+             typ name
+       | name, `Bytes ->
+           pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
+           pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
+             typ name
+       | name, `Int ->
+           pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
+           pr "                        PyLong_FromLongLong (%s->%s));\n"
+             typ name
+       | name, `OptPercent ->
+           pr "  if (%s->%s >= 0)\n" typ name;
+           pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
+           pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
+             typ name;
+           pr "  else {\n";
+           pr "    Py_INCREF (Py_None);\n";
+           pr "    PyDict_SetItemString (dict, \"%s\", Py_None);" name;
+           pr "  }\n"
+      ) cols;
+      pr "  return dict;\n";
+      pr "};\n";
+      pr "\n";
+
+      pr "static PyObject *\n";
+      pr "put_lvm_%s_list (struct guestfs_lvm_%s_list *%ss)\n" typ typ typ;
+      pr "{\n";
+      pr "  PyObject *list;\n";
+      pr "  int i;\n";
+      pr "\n";
+      pr "  list = PyList_New (%ss->len);\n" typ;
+      pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
+      pr "    PyList_SetItem (list, i, put_lvm_%s (&%ss->val[i]));\n" typ typ;
+      pr "  return list;\n";
+      pr "};\n";
+      pr "\n"
+  ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
+
+  (* Python wrapper functions. *)
+  List.iter (
+    fun (name, style, _, _, _, _, _) ->
+      pr "static PyObject *\n";
+      pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
+      pr "{\n";
+
+      pr "  PyObject *py_g;\n";
+      pr "  guestfs_h *g;\n";
+      pr "  PyObject *py_r;\n";
+
+      let error_code =
+       match fst style with
+       | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
+       | RConstString _ -> pr "  const char *r;\n"; "NULL"
+       | RString _ -> pr "  char *r;\n"; "NULL"
+       | RStringList _ -> pr "  char **r;\n"; "NULL"
+       | RIntBool _ -> pr "  struct guestfs_int_bool *r;\n"; "NULL"
+       | RPVList n -> pr "  struct guestfs_lvm_pv_list *r;\n"; "NULL"
+       | RVGList n -> pr "  struct guestfs_lvm_vg_list *r;\n"; "NULL"
+       | RLVList n -> pr "  struct guestfs_lvm_lv_list *r;\n"; "NULL" in
+
+      List.iter (
+       function
+       | String n -> pr "  const char *%s;\n" n
+       | OptString n -> pr "  const char *%s;\n" n
+       | StringList n ->
+           pr "  PyObject *py_%s;\n" n;
+           pr "  const char **%s;\n" n
+       | Bool n -> pr "  int %s;\n" n
+       | Int n -> pr "  int %s;\n" n
+      ) (snd style);
+
+      pr "\n";
+
+      (* Convert the parameters. *)
+      pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
+      List.iter (
+       function
+       | String _ -> pr "s"
+       | OptString _ -> pr "z"
+       | StringList _ -> pr "O"
+       | Bool _ -> pr "i" (* XXX Python has booleans? *)
+       | Int _ -> pr "i"
+      ) (snd style);
+      pr ":guestfs_%s\",\n" name;
+      pr "                         &py_g";
+      List.iter (
+       function
+       | String n -> pr ", &%s" n
+       | OptString n -> pr ", &%s" n
+       | StringList n -> pr ", &py_%s" n
+       | Bool n -> pr ", &%s" n
+       | Int n -> pr ", &%s" n
+      ) (snd style);
+
+      pr "))\n";
+      pr "    return NULL;\n";
+
+      pr "  g = get_handle (py_g);\n";
+      List.iter (
+       function
+       | String _ | OptString _ | Bool _ | Int _ -> ()
+       | StringList n ->
+           pr "  %s = get_string_list (py_%s);\n" n n;
+           pr "  if (!%s) return NULL;\n" n
+      ) (snd style);
+
+      pr "\n";
+
+      pr "  r = guestfs_%s " name;
+      generate_call_args ~handle:"g" style;
+      pr ";\n";
+
+      List.iter (
+       function
+       | String _ | OptString _ | Bool _ | Int _ -> ()
+       | StringList n ->
+           pr "  free (%s);\n" n
+      ) (snd style);
+
+      pr "  if (r == %s) {\n" error_code;
+      pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
+      pr "    return NULL;\n";
+      pr "  }\n";
+      pr "\n";
+
+      (match fst style with
+       | RErr ->
+          pr "  Py_INCREF (Py_None);\n";
+          pr "  py_r = Py_None;\n"
+       | RInt _
+       | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
+       | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
+       | RString _ ->
+          pr "  py_r = PyString_FromString (r);\n";
+          pr "  free (r);\n"
+       | RStringList _ ->
+          pr "  py_r = put_string_list (r);\n";
+          pr "  free_strings (r);\n"
+       | RIntBool _ ->
+          pr "  py_r = PyTuple_New (2);\n";
+          pr "  PyTuple_SetItem (py_r, 0, PyInt_FromLong ((long) r->i));\n";
+          pr "  PyTuple_SetItem (py_r, 1, PyInt_FromLong ((long) r->b));\n";
+          pr "  guestfs_free_int_bool (r);\n"
+       | RPVList n ->
+          pr "  py_r = put_lvm_pv_list (r);\n";
+          pr "  guestfs_free_lvm_pv_list (r);\n"
+       | RVGList n ->
+          pr "  py_r = put_lvm_vg_list (r);\n";
+          pr "  guestfs_free_lvm_vg_list (r);\n"
+       | RLVList n ->
+          pr "  py_r = put_lvm_lv_list (r);\n";
+          pr "  guestfs_free_lvm_lv_list (r);\n"
+      );
+
+      pr "  return py_r;\n";
+      pr "}\n";
+      pr "\n"
+  ) all_functions;
+
+  (* Table of functions. *)
+  pr "static PyMethodDef methods[] = {\n";
+  pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
+  pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
+  List.iter (
+    fun (name, _, _, _, _, _, _) ->
+      pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
+       name name
+  ) all_functions;
+  pr "  { NULL, NULL, 0, NULL }\n";
+  pr "};\n";
+  pr "\n";
+
+  (* Init function. *)
+  pr "\
+void
+initlibguestfsmod (void)
+{
+  static int initialized = 0;
+
+  if (initialized) return;
+  Py_InitModule ((char *) \"libguestfsmod\", methods);
+  initialized = 1;
+}
+"
+
+(* Generate Python module. *)
+and generate_python_py () =
+  generate_header HashStyle LGPLv2;
+
+  pr "import libguestfsmod\n";
+  pr "\n";
+  pr "class guestfs:\n";
+  pr "    def __init__ (self):\n";
+  pr "        self._o = libguestfsmod.create ()\n";
+  pr "\n";
+  pr "    def __del__ (self):\n";
+  pr "        libguestfsmod.close (self._o)\n";
+  pr "\n";
+
+  List.iter (
+    fun (name, style, _, _, _, _, _) ->
+      pr "    def %s " name;
+      generate_call_args ~handle:"self" style;
+      pr ":\n";
+      pr "        return libguestfsmod.%s " name;
+      generate_call_args ~handle:"self._o" style;
+      pr "\n";
+      pr "\n";
+  ) all_functions
+
 let output_to filename =
   let filename_new = filename ^ ".new" in
   chan := open_out filename_new;
@@ -3717,3 +4054,11 @@ Run it from the top source directory using the command
   let close = output_to "perl/lib/Sys/Guestfs.pm" in
   generate_perl_pm ();
   close ();
+
+  let close = output_to "python/guestfs-py.c" in
+  generate_python_c ();
+  close ();
+
+  let close = output_to "python/guestfs.py" in
+  generate_python_py ();
+  close ();
index cab264a..e104633 100644 (file)
@@ -121,6 +121,8 @@ struct guestfs_h
 
   const char *path;
 
+  char *last_error;
+
   /* Callbacks. */
   guestfs_abort_cb           abort_cb;
   guestfs_error_handler_cb   error_cb;
@@ -264,6 +266,7 @@ guestfs_close (guestfs_h *g)
   }
   /* release mutex (XXX) */
 
+  free (g->last_error);
   free (g);
 }
 
@@ -274,6 +277,19 @@ close_handles (void)
   while (handles) guestfs_close (handles);
 }
 
+const char *
+guestfs_last_error (guestfs_h *g)
+{
+  return g->last_error;
+}
+
+static void
+set_last_error (guestfs_h *g, const char *msg)
+{
+  free (g->last_error);
+  g->last_error = strdup (msg);
+}
+
 static void
 default_error_cb (guestfs_h *g, void *data, const char *msg)
 {
@@ -286,13 +302,12 @@ error (guestfs_h *g, const char *fs, ...)
   va_list args;
   char *msg;
 
-  if (!g->error_cb) return;
-
   va_start (args, fs);
   vasprintf (&msg, fs, args);
   va_end (args);
 
-  g->error_cb (g, g->error_cb_data, msg);
+  if (g->error_cb) g->error_cb (g, g->error_cb_data, msg);
+  set_last_error (g, msg);
 
   free (msg);
 }
@@ -304,8 +319,6 @@ perrorf (guestfs_h *g, const char *fs, ...)
   char *msg;
   int err = errno;
 
-  if (!g->error_cb) return;
-
   va_start (args, fs);
   vasprintf (&msg, fs, args);
   va_end (args);
@@ -323,7 +336,8 @@ perrorf (guestfs_h *g, const char *fs, ...)
   strcat (msg, ": ");
   strcat (msg, buf);
 
-  g->error_cb (g, g->error_cb_data, msg);
+  if (g->error_cb) g->error_cb (g, g->error_cb_data, msg);
+  set_last_error (g, msg);
 
   free (msg);
 }
index c677730..3905554 100644 (file)
@@ -33,6 +33,8 @@ extern guestfs_h *guestfs_create (void);
 extern void guestfs_close (guestfs_h *g);
 
 /* Error handling. */
+extern const char *guestfs_last_error (guestfs_h *g);
+
 typedef void (*guestfs_error_handler_cb) (guestfs_h *g, void *data, const char *msg);
 typedef void (*guestfs_abort_cb) (void);
 
diff --git a/tests.c b/tests.c
index 3e0fbd3..ebb5857 100644 (file)
--- a/tests.c
+++ b/tests.c
@@ -47,7 +47,7 @@ static void print_strings (char * const * const argv)
 
 static int test_mount_0 (void)
 {
-  /* InitNone for mount (0) */
+  /* InitEmpty for mount (0) */
   {
     int r;
     suppress_error = 0;
@@ -112,7 +112,7 @@ static int test_mount_0 (void)
 
 static int test_sync_0 (void)
 {
-  /* InitNone for sync (0) */
+  /* InitEmpty for sync (0) */
   {
     int r;
     suppress_error = 0;
@@ -140,7 +140,7 @@ static int test_sync_0 (void)
 
 static int test_touch_0 (void)
 {
-  /* InitEmpty for touch (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for touch (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -204,7 +204,7 @@ static int test_touch_0 (void)
 
 static int test_cat_0 (void)
 {
-  /* InitEmpty for cat (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for cat (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -269,7 +269,7 @@ static int test_cat_0 (void)
 
 static int test_ls_0 (void)
 {
-  /* InitEmpty for ls (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for ls (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -388,7 +388,7 @@ static int test_ls_0 (void)
 
 static int test_list_devices_0 (void)
 {
-  /* InitNone for list_devices (0) */
+  /* InitEmpty for list_devices (0) */
   {
     int r;
     suppress_error = 0;
@@ -452,7 +452,7 @@ static int test_list_devices_0 (void)
 
 static int test_list_partitions_0 (void)
 {
-  /* InitEmpty for list_partitions (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for list_partitions (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -523,7 +523,7 @@ static int test_list_partitions_0 (void)
 
 static int test_list_partitions_1 (void)
 {
-  /* InitNone for list_partitions (1) */
+  /* InitEmpty for list_partitions (1) */
   {
     int r;
     suppress_error = 0;
@@ -600,7 +600,7 @@ static int test_list_partitions_1 (void)
 
 static int test_pvs_0 (void)
 {
-  /* InitEmptyLVM for pvs (0): create ext2 on /dev/VG/LV */
+  /* InitBasicFSonLVM for pvs (0): create ext2 on /dev/VG/LV */
   {
     int r;
     suppress_error = 0;
@@ -696,7 +696,7 @@ static int test_pvs_0 (void)
 
 static int test_pvs_1 (void)
 {
-  /* InitNone for pvs (1) */
+  /* InitEmpty for pvs (1) */
   {
     int r;
     suppress_error = 0;
@@ -794,7 +794,7 @@ static int test_pvs_1 (void)
 
 static int test_vgs_0 (void)
 {
-  /* InitEmptyLVM for vgs (0): create ext2 on /dev/VG/LV */
+  /* InitBasicFSonLVM for vgs (0): create ext2 on /dev/VG/LV */
   {
     int r;
     suppress_error = 0;
@@ -890,7 +890,7 @@ static int test_vgs_0 (void)
 
 static int test_vgs_1 (void)
 {
-  /* InitNone for vgs (1) */
+  /* InitEmpty for vgs (1) */
   {
     int r;
     suppress_error = 0;
@@ -1002,7 +1002,7 @@ static int test_vgs_1 (void)
 
 static int test_lvs_0 (void)
 {
-  /* InitEmptyLVM for lvs (0): create ext2 on /dev/VG/LV */
+  /* InitBasicFSonLVM for lvs (0): create ext2 on /dev/VG/LV */
   {
     int r;
     suppress_error = 0;
@@ -1098,7 +1098,7 @@ static int test_lvs_0 (void)
 
 static int test_lvs_1 (void)
 {
-  /* InitNone for lvs (1) */
+  /* InitEmpty for lvs (1) */
   {
     int r;
     suppress_error = 0;
@@ -1240,7 +1240,7 @@ static int test_lvs_1 (void)
 
 static int test_pvs_full_0 (void)
 {
-  /* InitEmptyLVM for pvs_full (0): create ext2 on /dev/VG/LV */
+  /* InitBasicFSonLVM for pvs_full (0): create ext2 on /dev/VG/LV */
   {
     int r;
     suppress_error = 0;
@@ -1334,7 +1334,7 @@ static int test_pvs_full_0 (void)
 
 static int test_vgs_full_0 (void)
 {
-  /* InitEmptyLVM for vgs_full (0): create ext2 on /dev/VG/LV */
+  /* InitBasicFSonLVM for vgs_full (0): create ext2 on /dev/VG/LV */
   {
     int r;
     suppress_error = 0;
@@ -1428,7 +1428,7 @@ static int test_vgs_full_0 (void)
 
 static int test_lvs_full_0 (void)
 {
-  /* InitEmptyLVM for lvs_full (0): create ext2 on /dev/VG/LV */
+  /* InitBasicFSonLVM for lvs_full (0): create ext2 on /dev/VG/LV */
   {
     int r;
     suppress_error = 0;
@@ -1522,7 +1522,7 @@ static int test_lvs_full_0 (void)
 
 static int test_read_lines_0 (void)
 {
-  /* InitEmpty for read_lines (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for read_lines (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -1618,7 +1618,7 @@ static int test_read_lines_0 (void)
 
 static int test_read_lines_1 (void)
 {
-  /* InitEmpty for read_lines (1): create ext2 on /dev/sda1 */
+  /* InitBasicFS for read_lines (1): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -1687,7 +1687,7 @@ static int test_read_lines_1 (void)
 
 static int test_rm_0 (void)
 {
-  /* InitEmpty for rm (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for rm (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -1747,7 +1747,7 @@ static int test_rm_0 (void)
 
 static int test_rm_1 (void)
 {
-  /* InitEmpty for rm (1): create ext2 on /dev/sda1 */
+  /* InitBasicFS for rm (1): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -1800,7 +1800,7 @@ static int test_rm_1 (void)
 
 static int test_rm_2 (void)
 {
-  /* InitEmpty for rm (2): create ext2 on /dev/sda1 */
+  /* InitBasicFS for rm (2): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -1860,7 +1860,7 @@ static int test_rm_2 (void)
 
 static int test_rmdir_0 (void)
 {
-  /* InitEmpty for rmdir (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for rmdir (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -1920,7 +1920,7 @@ static int test_rmdir_0 (void)
 
 static int test_rmdir_1 (void)
 {
-  /* InitEmpty for rmdir (1): create ext2 on /dev/sda1 */
+  /* InitBasicFS for rmdir (1): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -1973,7 +1973,7 @@ static int test_rmdir_1 (void)
 
 static int test_rmdir_2 (void)
 {
-  /* InitEmpty for rmdir (2): create ext2 on /dev/sda1 */
+  /* InitBasicFS for rmdir (2): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2033,7 +2033,7 @@ static int test_rmdir_2 (void)
 
 static int test_rm_rf_0 (void)
 {
-  /* InitEmpty for rm_rf (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for rm_rf (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2118,7 +2118,7 @@ static int test_rm_rf_0 (void)
 
 static int test_mkdir_0 (void)
 {
-  /* InitEmpty for mkdir (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for mkdir (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2182,7 +2182,7 @@ static int test_mkdir_0 (void)
 
 static int test_mkdir_1 (void)
 {
-  /* InitEmpty for mkdir (1): create ext2 on /dev/sda1 */
+  /* InitBasicFS for mkdir (1): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2235,7 +2235,7 @@ static int test_mkdir_1 (void)
 
 static int test_mkdir_p_0 (void)
 {
-  /* InitEmpty for mkdir_p (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for mkdir_p (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2299,7 +2299,7 @@ static int test_mkdir_p_0 (void)
 
 static int test_mkdir_p_1 (void)
 {
-  /* InitEmpty for mkdir_p (1): create ext2 on /dev/sda1 */
+  /* InitBasicFS for mkdir_p (1): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2363,7 +2363,7 @@ static int test_mkdir_p_1 (void)
 
 static int test_mkdir_p_2 (void)
 {
-  /* InitEmpty for mkdir_p (2): create ext2 on /dev/sda1 */
+  /* InitBasicFS for mkdir_p (2): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2427,7 +2427,7 @@ static int test_mkdir_p_2 (void)
 
 static int test_exists_0 (void)
 {
-  /* InitEmpty for exists (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for exists (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2491,7 +2491,7 @@ static int test_exists_0 (void)
 
 static int test_exists_1 (void)
 {
-  /* InitEmpty for exists (1): create ext2 on /dev/sda1 */
+  /* InitBasicFS for exists (1): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2555,7 +2555,7 @@ static int test_exists_1 (void)
 
 static int test_is_file_0 (void)
 {
-  /* InitEmpty for is_file (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for is_file (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2619,7 +2619,7 @@ static int test_is_file_0 (void)
 
 static int test_is_file_1 (void)
 {
-  /* InitEmpty for is_file (1): create ext2 on /dev/sda1 */
+  /* InitBasicFS for is_file (1): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2683,7 +2683,7 @@ static int test_is_file_1 (void)
 
 static int test_is_dir_0 (void)
 {
-  /* InitEmpty for is_dir (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for is_dir (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2747,7 +2747,7 @@ static int test_is_dir_0 (void)
 
 static int test_is_dir_1 (void)
 {
-  /* InitEmpty for is_dir (1): create ext2 on /dev/sda1 */
+  /* InitBasicFS for is_dir (1): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -2811,7 +2811,7 @@ static int test_is_dir_1 (void)
 
 static int test_pvcreate_0 (void)
 {
-  /* InitNone for pvcreate (0) */
+  /* InitEmpty for pvcreate (0) */
   {
     int r;
     suppress_error = 0;
@@ -2909,7 +2909,7 @@ static int test_pvcreate_0 (void)
 
 static int test_vgcreate_0 (void)
 {
-  /* InitNone for vgcreate (0) */
+  /* InitEmpty for vgcreate (0) */
   {
     int r;
     suppress_error = 0;
@@ -3021,7 +3021,7 @@ static int test_vgcreate_0 (void)
 
 static int test_lvcreate_0 (void)
 {
-  /* InitNone for lvcreate (0) */
+  /* InitEmpty for lvcreate (0) */
   {
     int r;
     suppress_error = 0;
@@ -3195,7 +3195,7 @@ static int test_lvcreate_0 (void)
 
 static int test_mkfs_0 (void)
 {
-  /* InitNone for mkfs (0) */
+  /* InitEmpty for mkfs (0) */
   {
     int r;
     suppress_error = 0;
@@ -3260,7 +3260,7 @@ static int test_mkfs_0 (void)
 
 static int test_write_file_0 (void)
 {
-  /* InitNone for write_file (0) */
+  /* InitEmpty for write_file (0) */
   {
     int r;
     suppress_error = 0;
@@ -3325,7 +3325,7 @@ static int test_write_file_0 (void)
 
 static int test_umount_0 (void)
 {
-  /* InitNone for umount (0) */
+  /* InitEmpty for umount (0) */
   {
     int r;
     suppress_error = 0;
@@ -3396,7 +3396,7 @@ static int test_umount_0 (void)
 
 static int test_umount_1 (void)
 {
-  /* InitNone for umount (1) */
+  /* InitEmpty for umount (1) */
   {
     int r;
     suppress_error = 0;
@@ -3465,7 +3465,7 @@ static int test_umount_1 (void)
 
 static int test_mounts_0 (void)
 {
-  /* InitEmpty for mounts (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for mounts (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;
@@ -3536,7 +3536,7 @@ static int test_mounts_0 (void)
 
 static int test_umount_all_0 (void)
 {
-  /* InitEmpty for umount_all (0): create ext2 on /dev/sda1 */
+  /* InitBasicFS for umount_all (0): create ext2 on /dev/sda1 */
   {
     int r;
     suppress_error = 0;