From b3f11c5f62f725fa3f09452b38d52dba764f80d0 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Mon, 13 Apr 2009 18:32:03 +0100 Subject: [PATCH] Lots, mainly Python bindings. --- .gitignore | 1 + README | 6 +- configure.ac | 48 +- guestfs.pod | 24 +- libguestfs.spec.in | 19 +- ocaml/guestfs_c.c | 25 +- perl/Guestfs.xs | 147 ++-- perl/run-perl-tests | 3 +- perl/t/050-lvcreate.t | 60 ++ python/Makefile.am | 19 +- python/README-python-bindings | 7 - python/guestfs-py.c | 1883 +++++++++++++++++++++++++++++++++++++++++ python/guestfs.py | 209 +++++ python/t/005-import.py | 18 + python/t/010-launch.py | 26 + python/t/050-lvcreate.py | 37 + src/generator.ml | 513 +++++++++-- src/guestfs.c | 26 +- src/guestfs.h | 2 + tests.c | 92 +- 20 files changed, 2904 insertions(+), 261 deletions(-) create mode 100644 perl/t/050-lvcreate.t delete mode 100644 python/README-python-bindings create mode 100644 python/guestfs-py.c create mode 100644 python/guestfs.py create mode 100644 python/t/005-import.py create mode 100644 python/t/010-launch.py create mode 100644 python/t/050-lvcreate.py diff --git a/.gitignore b/.gitignore index eedd8a8..f3fc531 100644 --- a/.gitignore +++ b/.gitignore @@ -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 --- 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. diff --git a/configure.ac b/configure.ac index 3f8807f..e616374 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/guestfs.pod b/guestfs.pod index 8fdc93d..41234fd 100644 --- a/guestfs.pod +++ b/guestfs.pod @@ -117,13 +117,30 @@ This closes the connection handle and frees up all resources used. The convention in all functions that return C is that they return C<-1> to indicate an error. You can get additional information on -errors by calling C. The default error -handler prints the information string to C. +errors by calling C and/or by setting up an error +handler with C. + +The default error handler prints the information string to C. Out of memory errors are handled differently. The default action is to call L. If this is undesirable, then you can set a handler using C. +=head2 guestfs_last_error + + const char *guestfs_last_error (guestfs_h *handle); + +This returns the last error message that happened on C. If +there has not been an error since the handle was created, then this +returns C. + +The lifetime of the returned string is until the next error occurs, or +C 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. -If you set C to C then I handler is called and the error -message is completely discarded. +If you set C to C then I handler is called. =head2 guestfs_get_error_handler diff --git a/libguestfs.spec.in b/libguestfs.spec.in index 92ec289..0da3ce6 100644 --- a/libguestfs.spec.in +++ b/libguestfs.spec.in @@ -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 diff --git a/ocaml/guestfs_c.c b/ocaml/guestfs_c.c index 291c430..87139b4 100644 --- a/ocaml/guestfs_c.c +++ b/ocaml/guestfs_c.c @@ -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); diff --git a/perl/Guestfs.xs b/perl/Guestfs.xs index 0f72c28..580b743 100644 --- a/perl/Guestfs.xs +++ b/perl/Guestfs.xs @@ -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)); } diff --git a/perl/run-perl-tests b/perl/run-perl-tests index d2280dd..1a890fc 100755 --- a/perl/run-perl-tests +++ b/perl/run-perl-tests @@ -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 index 0000000..418428c --- /dev/null +++ b/perl/t/050-lvcreate.t @@ -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"); diff --git a/python/Makefile.am b/python/Makefile.am index 509e87c..b2cf3b3 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -15,10 +15,27 @@ # 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 index 4c5aa38..0000000 --- a/python/README-python-bindings +++ /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 index 0000000..9d2738c --- /dev/null +++ b/python/guestfs-py.c @@ -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 +#include +#include + +#include + +#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, §ors, &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 index 0000000..fc57d8d --- /dev/null +++ b/python/guestfs.py @@ -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 index 0000000..5896d15 --- /dev/null +++ b/python/t/005-import.py @@ -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 index 0000000..c2bdd1d --- /dev/null +++ b/python/t/010-launch.py @@ -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 index 0000000..98227e2 --- /dev/null +++ b/python/t/050-lvcreate.py @@ -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") diff --git a/src/generator.ml b/src/generator.ml index 28e1cb6..06a95a9 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -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 and C 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 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 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"); ("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."); ("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). See also C."); ("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). See also C."); ("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."); ("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 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 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 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 C 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 and sorting the resulting nodes into alphabetical order."); Remove the single file C."); ("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."); Remove the single directory C."); ("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 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."); ("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 if and only if there is a file, directory See also C, C, C."); ("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."); ("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."); ("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 should usually be a partition name such as C."); ("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 from the non-empty list of physical volumes C."); ("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 on the volume group C, with C 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 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 (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, C). 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 +#include +#include + +#include + +#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 (); diff --git a/src/guestfs.c b/src/guestfs.c index cab264a..e104633 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -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); } diff --git a/src/guestfs.h b/src/guestfs.h index c677730..3905554 100644 --- a/src/guestfs.h +++ b/src/guestfs.h @@ -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 --- 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; -- 1.8.3.1