diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | README | 6 | ||||
-rw-r--r-- | configure.ac | 48 | ||||
-rw-r--r-- | guestfs.pod | 24 | ||||
-rw-r--r-- | libguestfs.spec.in | 19 | ||||
-rw-r--r-- | ocaml/guestfs_c.c | 25 | ||||
-rw-r--r-- | perl/Guestfs.xs | 147 | ||||
-rwxr-xr-x | perl/run-perl-tests | 3 | ||||
-rw-r--r-- | perl/t/050-lvcreate.t | 60 | ||||
-rw-r--r-- | python/Makefile.am | 19 | ||||
-rw-r--r-- | python/README-python-bindings | 7 | ||||
-rw-r--r-- | python/guestfs-py.c | 1883 | ||||
-rw-r--r-- | python/guestfs.py | 209 | ||||
-rw-r--r-- | python/t/005-import.py | 18 | ||||
-rw-r--r-- | python/t/010-launch.py | 26 | ||||
-rw-r--r-- | python/t/050-lvcreate.py | 37 | ||||
-rwxr-xr-x | src/generator.ml | 513 | ||||
-rw-r--r-- | src/guestfs.c | 26 | ||||
-rw-r--r-- | src/guestfs.h | 2 | ||||
-rw-r--r-- | tests.c | 92 |
20 files changed, 2904 insertions, 261 deletions
@@ -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 @@ -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 3f8807f1..e616374f 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 8fdc93d2..41234fdb 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<int> is that they return C<-1> to indicate an error. You can get additional information on -errors by calling C<guestfs_set_error_handler>. The default error -handler prints the information string to C<stderr>. +errors by calling C<guestfs_last_error> and/or by setting up an error +handler with C<guestfs_set_error_handler>. + +The default error handler prints the information string to C<stderr>. Out of memory errors are handled differently. The default action is to call L<abort(3)>. If this is undesirable, then you can set a handler using C<guestfs_set_out_of_memory_handler>. +=head2 guestfs_last_error + + const char *guestfs_last_error (guestfs_h *handle); + +This returns the last error message that happened on C<handle>. If +there has not been an error since the handle was created, then this +returns C<NULL>. + +The lifetime of the returned string is until the next error occurs, or +C<guestfs_close> is called. + +The error string is not localized (ie. is always in English), because +this makes searching for error messages in search engines give the +largest number of results. + =head2 guestfs_set_error_handler typedef void (*guestfs_error_handler_cb) (guestfs_h *handle, @@ -143,8 +160,7 @@ your own copy. The default handler prints messages on C<stderr>. -If you set C<cb> to C<NULL> then I<no> handler is called and the error -message is completely discarded. +If you set C<cb> to C<NULL> then I<no> handler is called. =head2 guestfs_get_error_handler diff --git a/libguestfs.spec.in b/libguestfs.spec.in index 92ec289c..0da3ce69 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 291c4308..87139b48 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 0f72c282..580b743d 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 d2280dd5..1a890fc6 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 00000000..418428c3 --- /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 509e87ca..b2cf3b34 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 4c5aa382..00000000 --- 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 00000000..9d2738c8 --- /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 <stdio.h> +#include <stdlib.h> +#include <assert.h> + +#include <Python.h> + +#include "guestfs.h" + +typedef struct { + PyObject_HEAD + guestfs_h *g; +} Pyguestfs_Object; + +static guestfs_h * +get_handle (PyObject *obj) +{ + assert (obj); + assert (obj != Py_None); + return ((Pyguestfs_Object *) obj)->g; +} + +static PyObject * +put_handle (guestfs_h *g) +{ + assert (g); + return + PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) "guestfs_h", NULL); +} + +/* This list should be freed (but not the strings) after use. */ +static const char ** +get_string_list (PyObject *obj) +{ + int i, len; + const char **r; + + assert (obj); + + if (!PyList_Check (obj)) { + PyErr_SetString (PyExc_RuntimeError, "expecting a list parameter"); + return NULL; + } + + len = PyList_Size (obj); + r = malloc (sizeof (char *) * (len+1)); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, "get_string_list: out of memory"); + return NULL; + } + + for (i = 0; i < len; ++i) + r[i] = PyString_AsString (PyList_GetItem (obj, i)); + r[len] = NULL; + + return r; +} + +static PyObject * +put_string_list (char * const * const argv) +{ + PyObject *list; + int argc, i; + + for (argc = 0; argv[argc] != NULL; ++argc) + ; + + list = PyList_New (argc); + for (i = 0; i < argc; ++i) + PyList_SetItem (list, i, PyString_FromString (argv[i])); + + return list; +} + +static void +free_strings (char **argv) +{ + int argc; + + for (argc = 0; argv[argc] != NULL; ++argc) + free (argv[argc]); + free (argv); +} + +static PyObject * +py_guestfs_create (PyObject *self, PyObject *args) +{ + guestfs_h *g; + + g = guestfs_create (); + if (g == NULL) { + PyErr_SetString (PyExc_RuntimeError, + "guestfs.create: failed to allocate handle"); + return NULL; + } + guestfs_set_error_handler (g, NULL, NULL); + return put_handle (g); +} + +static PyObject * +py_guestfs_close (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_close", &py_g)) + return NULL; + g = get_handle (py_g); + + guestfs_close (g); + + Py_INCREF (Py_None); + return Py_None; +} + +static PyObject * +put_lvm_pv (struct guestfs_lvm_pv *pv) +{ + PyObject *dict; + + dict = PyDict_New (); + PyDict_SetItemString (dict, "pv_name", + PyString_FromString (pv->pv_name)); + PyDict_SetItemString (dict, "pv_uuid", + PyString_FromStringAndSize (pv->pv_uuid, 32)); + PyDict_SetItemString (dict, "pv_fmt", + PyString_FromString (pv->pv_fmt)); + PyDict_SetItemString (dict, "pv_size", + PyLong_FromUnsignedLongLong (pv->pv_size)); + PyDict_SetItemString (dict, "dev_size", + PyLong_FromUnsignedLongLong (pv->dev_size)); + PyDict_SetItemString (dict, "pv_free", + PyLong_FromUnsignedLongLong (pv->pv_free)); + PyDict_SetItemString (dict, "pv_used", + PyLong_FromUnsignedLongLong (pv->pv_used)); + PyDict_SetItemString (dict, "pv_attr", + PyString_FromString (pv->pv_attr)); + PyDict_SetItemString (dict, "pv_pe_count", + PyLong_FromLongLong (pv->pv_pe_count)); + PyDict_SetItemString (dict, "pv_pe_alloc_count", + PyLong_FromLongLong (pv->pv_pe_alloc_count)); + PyDict_SetItemString (dict, "pv_tags", + PyString_FromString (pv->pv_tags)); + PyDict_SetItemString (dict, "pe_start", + PyLong_FromUnsignedLongLong (pv->pe_start)); + PyDict_SetItemString (dict, "pv_mda_count", + PyLong_FromLongLong (pv->pv_mda_count)); + PyDict_SetItemString (dict, "pv_mda_free", + PyLong_FromUnsignedLongLong (pv->pv_mda_free)); + return dict; +}; + +static PyObject * +put_lvm_pv_list (struct guestfs_lvm_pv_list *pvs) +{ + PyObject *list; + int i; + + list = PyList_New (pvs->len); + for (i = 0; i < pvs->len; ++i) + PyList_SetItem (list, i, put_lvm_pv (&pvs->val[i])); + return list; +}; + +static PyObject * +put_lvm_vg (struct guestfs_lvm_vg *vg) +{ + PyObject *dict; + + dict = PyDict_New (); + PyDict_SetItemString (dict, "vg_name", + PyString_FromString (vg->vg_name)); + PyDict_SetItemString (dict, "vg_uuid", + PyString_FromStringAndSize (vg->vg_uuid, 32)); + PyDict_SetItemString (dict, "vg_fmt", + PyString_FromString (vg->vg_fmt)); + PyDict_SetItemString (dict, "vg_attr", + PyString_FromString (vg->vg_attr)); + PyDict_SetItemString (dict, "vg_size", + PyLong_FromUnsignedLongLong (vg->vg_size)); + PyDict_SetItemString (dict, "vg_free", + PyLong_FromUnsignedLongLong (vg->vg_free)); + PyDict_SetItemString (dict, "vg_sysid", + PyString_FromString (vg->vg_sysid)); + PyDict_SetItemString (dict, "vg_extent_size", + PyLong_FromUnsignedLongLong (vg->vg_extent_size)); + PyDict_SetItemString (dict, "vg_extent_count", + PyLong_FromLongLong (vg->vg_extent_count)); + PyDict_SetItemString (dict, "vg_free_count", + PyLong_FromLongLong (vg->vg_free_count)); + PyDict_SetItemString (dict, "max_lv", + PyLong_FromLongLong (vg->max_lv)); + PyDict_SetItemString (dict, "max_pv", + PyLong_FromLongLong (vg->max_pv)); + PyDict_SetItemString (dict, "pv_count", + PyLong_FromLongLong (vg->pv_count)); + PyDict_SetItemString (dict, "lv_count", + PyLong_FromLongLong (vg->lv_count)); + PyDict_SetItemString (dict, "snap_count", + PyLong_FromLongLong (vg->snap_count)); + PyDict_SetItemString (dict, "vg_seqno", + PyLong_FromLongLong (vg->vg_seqno)); + PyDict_SetItemString (dict, "vg_tags", + PyString_FromString (vg->vg_tags)); + PyDict_SetItemString (dict, "vg_mda_count", + PyLong_FromLongLong (vg->vg_mda_count)); + PyDict_SetItemString (dict, "vg_mda_free", + PyLong_FromUnsignedLongLong (vg->vg_mda_free)); + return dict; +}; + +static PyObject * +put_lvm_vg_list (struct guestfs_lvm_vg_list *vgs) +{ + PyObject *list; + int i; + + list = PyList_New (vgs->len); + for (i = 0; i < vgs->len; ++i) + PyList_SetItem (list, i, put_lvm_vg (&vgs->val[i])); + return list; +}; + +static PyObject * +put_lvm_lv (struct guestfs_lvm_lv *lv) +{ + PyObject *dict; + + dict = PyDict_New (); + PyDict_SetItemString (dict, "lv_name", + PyString_FromString (lv->lv_name)); + PyDict_SetItemString (dict, "lv_uuid", + PyString_FromStringAndSize (lv->lv_uuid, 32)); + PyDict_SetItemString (dict, "lv_attr", + PyString_FromString (lv->lv_attr)); + PyDict_SetItemString (dict, "lv_major", + PyLong_FromLongLong (lv->lv_major)); + PyDict_SetItemString (dict, "lv_minor", + PyLong_FromLongLong (lv->lv_minor)); + PyDict_SetItemString (dict, "lv_kernel_major", + PyLong_FromLongLong (lv->lv_kernel_major)); + PyDict_SetItemString (dict, "lv_kernel_minor", + PyLong_FromLongLong (lv->lv_kernel_minor)); + PyDict_SetItemString (dict, "lv_size", + PyLong_FromUnsignedLongLong (lv->lv_size)); + PyDict_SetItemString (dict, "seg_count", + PyLong_FromLongLong (lv->seg_count)); + PyDict_SetItemString (dict, "origin", + PyString_FromString (lv->origin)); + if (lv->snap_percent >= 0) + PyDict_SetItemString (dict, "snap_percent", + PyFloat_FromDouble ((double) lv->snap_percent)); + else { + Py_INCREF (Py_None); + PyDict_SetItemString (dict, "snap_percent", Py_None); } + if (lv->copy_percent >= 0) + PyDict_SetItemString (dict, "copy_percent", + PyFloat_FromDouble ((double) lv->copy_percent)); + else { + Py_INCREF (Py_None); + PyDict_SetItemString (dict, "copy_percent", Py_None); } + PyDict_SetItemString (dict, "move_pv", + PyString_FromString (lv->move_pv)); + PyDict_SetItemString (dict, "lv_tags", + PyString_FromString (lv->lv_tags)); + PyDict_SetItemString (dict, "mirror_log", + PyString_FromString (lv->mirror_log)); + PyDict_SetItemString (dict, "modules", + PyString_FromString (lv->modules)); + return dict; +}; + +static PyObject * +put_lvm_lv_list (struct guestfs_lvm_lv_list *lvs) +{ + PyObject *list; + int i; + + list = PyList_New (lvs->len); + for (i = 0; i < lvs->len; ++i) + PyList_SetItem (list, i, put_lvm_lv (&lvs->val[i])); + return list; +}; + +static PyObject * +py_guestfs_launch (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_launch", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_launch (g); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_wait_ready (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_wait_ready", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_wait_ready (g); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_kill_subprocess (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_kill_subprocess", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_kill_subprocess (g); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_add_drive (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *filename; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_add_drive", + &py_g, &filename)) + return NULL; + g = get_handle (py_g); + + r = guestfs_add_drive (g, filename); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_add_cdrom (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *filename; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_add_cdrom", + &py_g, &filename)) + return NULL; + g = get_handle (py_g); + + r = guestfs_add_cdrom (g, filename); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_config (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *qemuparam; + const char *qemuvalue; + + if (!PyArg_ParseTuple (args, (char *) "Osz:guestfs_config", + &py_g, &qemuparam, &qemuvalue)) + return NULL; + g = get_handle (py_g); + + r = guestfs_config (g, qemuparam, qemuvalue); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_set_path (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_set_path", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_set_path (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_get_path (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + const char *r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_get_path", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_get_path (g); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyString_FromString (r); + return py_r; +} + +static PyObject * +py_guestfs_set_autosync (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + int autosync; + + if (!PyArg_ParseTuple (args, (char *) "Oi:guestfs_set_autosync", + &py_g, &autosync)) + return NULL; + g = get_handle (py_g); + + r = guestfs_set_autosync (g, autosync); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_get_autosync (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_get_autosync", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_get_autosync (g); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyInt_FromLong ((long) r); + return py_r; +} + +static PyObject * +py_guestfs_set_verbose (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + int verbose; + + if (!PyArg_ParseTuple (args, (char *) "Oi:guestfs_set_verbose", + &py_g, &verbose)) + return NULL; + g = get_handle (py_g); + + r = guestfs_set_verbose (g, verbose); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_get_verbose (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_get_verbose", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_get_verbose (g); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyInt_FromLong ((long) r); + return py_r; +} + +static PyObject * +py_guestfs_mount (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *device; + const char *mountpoint; + + if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_mount", + &py_g, &device, &mountpoint)) + return NULL; + g = get_handle (py_g); + + r = guestfs_mount (g, device, mountpoint); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_sync (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_sync", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_sync (g); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_touch (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_touch", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_touch (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_cat (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char *r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_cat", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_cat (g, path); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyString_FromString (r); + free (r); + return py_r; +} + +static PyObject * +py_guestfs_ll (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char *r; + const char *directory; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_ll", + &py_g, &directory)) + return NULL; + g = get_handle (py_g); + + r = guestfs_ll (g, directory); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyString_FromString (r); + free (r); + return py_r; +} + +static PyObject * +py_guestfs_ls (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char **r; + const char *directory; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_ls", + &py_g, &directory)) + return NULL; + g = get_handle (py_g); + + r = guestfs_ls (g, directory); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_string_list (r); + free_strings (r); + return py_r; +} + +static PyObject * +py_guestfs_list_devices (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char **r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_list_devices", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_list_devices (g); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_string_list (r); + free_strings (r); + return py_r; +} + +static PyObject * +py_guestfs_list_partitions (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char **r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_list_partitions", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_list_partitions (g); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_string_list (r); + free_strings (r); + return py_r; +} + +static PyObject * +py_guestfs_pvs (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char **r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_pvs", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_pvs (g); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_string_list (r); + free_strings (r); + return py_r; +} + +static PyObject * +py_guestfs_vgs (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char **r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_vgs", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_vgs (g); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_string_list (r); + free_strings (r); + return py_r; +} + +static PyObject * +py_guestfs_lvs (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char **r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_lvs", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_lvs (g); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_string_list (r); + free_strings (r); + return py_r; +} + +static PyObject * +py_guestfs_pvs_full (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + struct guestfs_lvm_pv_list *r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_pvs_full", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_pvs_full (g); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_lvm_pv_list (r); + guestfs_free_lvm_pv_list (r); + return py_r; +} + +static PyObject * +py_guestfs_vgs_full (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + struct guestfs_lvm_vg_list *r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_vgs_full", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_vgs_full (g); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_lvm_vg_list (r); + guestfs_free_lvm_vg_list (r); + return py_r; +} + +static PyObject * +py_guestfs_lvs_full (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + struct guestfs_lvm_lv_list *r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_lvs_full", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_lvs_full (g); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_lvm_lv_list (r); + guestfs_free_lvm_lv_list (r); + return py_r; +} + +static PyObject * +py_guestfs_read_lines (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char **r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_read_lines", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_read_lines (g, path); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_string_list (r); + free_strings (r); + return py_r; +} + +static PyObject * +py_guestfs_aug_init (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *root; + int flags; + + if (!PyArg_ParseTuple (args, (char *) "Osi:guestfs_aug_init", + &py_g, &root, &flags)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_init (g, root, flags); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_aug_close (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_aug_close", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_close (g); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_aug_defvar (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *name; + const char *expr; + + if (!PyArg_ParseTuple (args, (char *) "Osz:guestfs_aug_defvar", + &py_g, &name, &expr)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_defvar (g, name, expr); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyInt_FromLong ((long) r); + return py_r; +} + +static PyObject * +py_guestfs_aug_defnode (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + struct guestfs_int_bool *r; + const char *name; + const char *expr; + const char *val; + + if (!PyArg_ParseTuple (args, (char *) "Osss:guestfs_aug_defnode", + &py_g, &name, &expr, &val)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_defnode (g, name, expr, val); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyTuple_New (2); + PyTuple_SetItem (py_r, 0, PyInt_FromLong ((long) r->i)); + PyTuple_SetItem (py_r, 1, PyInt_FromLong ((long) r->b)); + guestfs_free_int_bool (r); + return py_r; +} + +static PyObject * +py_guestfs_aug_get (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char *r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_aug_get", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_get (g, path); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyString_FromString (r); + free (r); + return py_r; +} + +static PyObject * +py_guestfs_aug_set (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + const char *val; + + if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_aug_set", + &py_g, &path, &val)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_set (g, path, val); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_aug_insert (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + const char *label; + int before; + + if (!PyArg_ParseTuple (args, (char *) "Ossi:guestfs_aug_insert", + &py_g, &path, &label, &before)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_insert (g, path, label, before); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_aug_rm (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_aug_rm", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_rm (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyInt_FromLong ((long) r); + return py_r; +} + +static PyObject * +py_guestfs_aug_mv (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *src; + const char *dest; + + if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_aug_mv", + &py_g, &src, &dest)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_mv (g, src, dest); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_aug_match (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char **r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_aug_match", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_match (g, path); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_string_list (r); + free_strings (r); + return py_r; +} + +static PyObject * +py_guestfs_aug_save (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_aug_save", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_save (g); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_aug_load (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + + if (!PyArg_ParseTuple (args, (char *) "O:guestfs_aug_load", + &py_g)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_load (g); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_aug_ls (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + char **r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_aug_ls", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_aug_ls (g, path); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_string_list (r); + free_strings (r); + return py_r; +} + +static PyObject * +py_guestfs_rm (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_rm", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_rm (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_rmdir (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_rmdir", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_rmdir (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_rm_rf (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_rm_rf", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_rm_rf (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_mkdir (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_mkdir", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_mkdir (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_mkdir_p (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_mkdir_p", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_mkdir_p (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_chmod (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + int mode; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Ois:guestfs_chmod", + &py_g, &mode, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_chmod (g, mode, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_chown (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + int owner; + int group; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Oiis:guestfs_chown", + &py_g, &owner, &group, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_chown (g, owner, group, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_exists (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_exists", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_exists (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyInt_FromLong ((long) r); + return py_r; +} + +static PyObject * +py_guestfs_is_file (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_is_file", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_is_file (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyInt_FromLong ((long) r); + return py_r; +} + +static PyObject * +py_guestfs_is_dir (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_is_dir", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_is_dir (g, path); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyInt_FromLong ((long) r); + return py_r; +} + +static PyObject * +py_guestfs_pvcreate (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *device; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_pvcreate", + &py_g, &device)) + return NULL; + g = get_handle (py_g); + + r = guestfs_pvcreate (g, device); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_vgcreate (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *volgroup; + PyObject *py_physvols; + const char **physvols; + + if (!PyArg_ParseTuple (args, (char *) "OsO:guestfs_vgcreate", + &py_g, &volgroup, &py_physvols)) + return NULL; + g = get_handle (py_g); + physvols = get_string_list (py_physvols); + if (!physvols) return NULL; + + r = guestfs_vgcreate (g, volgroup, physvols); + free (physvols); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_lvcreate (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *logvol; + const char *volgroup; + int mbytes; + + if (!PyArg_ParseTuple (args, (char *) "Ossi:guestfs_lvcreate", + &py_g, &logvol, &volgroup, &mbytes)) + return NULL; + g = get_handle (py_g); + + r = guestfs_lvcreate (g, logvol, volgroup, mbytes); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_mkfs (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *fstype; + const char *device; + + if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_mkfs", + &py_g, &fstype, &device)) + return NULL; + g = get_handle (py_g); + + r = guestfs_mkfs (g, fstype, device); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_sfdisk (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *device; + int cyls; + int heads; + int sectors; + PyObject *py_lines; + const char **lines; + + if (!PyArg_ParseTuple (args, (char *) "OsiiiO:guestfs_sfdisk", + &py_g, &device, &cyls, &heads, §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 00000000..fc57d8de --- /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 00000000..5896d15d --- /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 00000000..c2bdd1d0 --- /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 00000000..98227e23 --- /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 28e1cb62..06a95a9d 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<sync> and C<noatime> are set with this call, in order to improve reliability."); ("sync", (RErr, []), 2, [], - [ InitNone, TestRun [["sync"]]], + [ InitEmpty, TestRun [["sync"]]], "sync disks, writes are flushed through to the disk image", "\ This syncs the disk, so that any writes are flushed through to the @@ -332,7 +337,7 @@ You should always call this if you have modified a disk image, before closing the handle."); ("touch", (RErr, [String "path"]), 3, [], - [InitEmpty, TestOutputTrue ( + [InitBasicFS, TestOutputTrue ( [["touch"; "/new"]; ["exists"; "/new"]])], "update file timestamps or create a new file", @@ -342,7 +347,7 @@ update the timestamps on a file, or, if the file does not exist, to create a new zero-length file."); ("cat", (RString "content", [String "path"]), 4, [ProtocolLimitWarning], - [InitEmpty, TestOutput ( + [InitBasicFS, TestOutput ( [["write_file"; "/new"; "new file contents"; "0"]; ["cat"; "/new"]], "new file contents")], "list the contents of a file", @@ -367,7 +372,7 @@ This command is mostly useful for interactive sessions. It is I<not> intended that you try to parse the output string."); ("ls", (RStringList "listing", [String "directory"]), 6, [], - [InitEmpty, TestOutputList ( + [InitBasicFS, TestOutputList ( [["touch"; "/new"]; ["touch"; "/newer"]; ["touch"; "/newest"]; @@ -382,7 +387,7 @@ This command is mostly useful for interactive sessions. Programs should probably use C<guestfs_readdir> instead."); ("list_devices", (RStringList "devices", []), 7, [], - [InitNone, TestOutputList ( + [InitEmpty, TestOutputList ( [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"])], "list the block devices", "\ @@ -391,9 +396,9 @@ List all the block devices. The full block device names are returned, eg. C</dev/sda>"); ("list_partitions", (RStringList "partitions", []), 8, [], - [InitEmpty, TestOutputList ( + [InitBasicFS, TestOutputList ( [["list_partitions"]], ["/dev/sda1"]); - InitNone, TestOutputList ( + InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])], "list the partitions", @@ -406,9 +411,9 @@ This does not return logical volumes. For that you will need to call C<guestfs_lvs>."); ("pvs", (RStringList "physvols", []), 9, [], - [InitEmptyLVM, TestOutputList ( + [InitBasicFSonLVM, TestOutputList ( [["pvs"]], ["/dev/sda1"]); - InitNone, TestOutputList ( + InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -425,9 +430,9 @@ PVs (eg. C</dev/sda2>). See also C<guestfs_pvs_full>."); ("vgs", (RStringList "volgroups", []), 10, [], - [InitEmptyLVM, TestOutputList ( + [InitBasicFSonLVM, TestOutputList ( [["vgs"]], ["VG"]); - InitNone, TestOutputList ( + InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -446,9 +451,9 @@ detected (eg. C<VolGroup00>). See also C<guestfs_vgs_full>."); ("lvs", (RStringList "logvols", []), 11, [], - [InitEmptyLVM, TestOutputList ( + [InitBasicFSonLVM, TestOutputList ( [["lvs"]], ["/dev/VG/LV"]); - InitNone, TestOutputList ( + InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -470,7 +475,7 @@ This returns a list of the logical volume device names See also C<guestfs_lvs_full>."); ("pvs_full", (RPVList "physvols", []), 12, [], - [InitEmptyLVM, TestOutputLength ( + [InitBasicFSonLVM, TestOutputLength ( [["pvs"]], 1)], "list the LVM physical volumes (PVs)", "\ @@ -478,7 +483,7 @@ List all the physical volumes detected. This is the equivalent of the L<pvs(8)> command. The \"full\" version includes all fields."); ("vgs_full", (RVGList "volgroups", []), 13, [], - [InitEmptyLVM, TestOutputLength ( + [InitBasicFSonLVM, TestOutputLength ( [["pvs"]], 1)], "list the LVM volume groups (VGs)", "\ @@ -486,7 +491,7 @@ List all the volumes groups detected. This is the equivalent of the L<vgs(8)> command. The \"full\" version includes all fields."); ("lvs_full", (RLVList "logvols", []), 14, [], - [InitEmptyLVM, TestOutputLength ( + [InitBasicFSonLVM, TestOutputLength ( [["pvs"]], 1)], "list the LVM logical volumes (LVs)", "\ @@ -494,10 +499,10 @@ List all the logical volumes detected. This is the equivalent of the L<lvs(8)> command. The \"full\" version includes all fields."); ("read_lines", (RStringList "lines", [String "path"]), 15, [], - [InitEmpty, TestOutputList ( + [InitBasicFS, TestOutputList ( [["write_file"; "/new"; "line1\r\nline2\nline3"; "0"]; ["read_lines"; "/new"]], ["line1"; "line2"; "line3"]); - InitEmpty, TestOutputList ( + InitBasicFS, TestOutputList ( [["write_file"; "/new"; ""; "0"]; ["read_lines"; "/new"]], [])], "read file as lines", @@ -672,12 +677,12 @@ This is just a shortcut for listing C<guestfs_aug_match> C<path/*> and sorting the resulting nodes into alphabetical order."); ("rm", (RErr, [String "path"]), 29, [], - [InitEmpty, TestRun + [InitBasicFS, TestRun [["touch"; "/new"]; ["rm"; "/new"]]; - InitEmpty, TestLastFail + InitBasicFS, TestLastFail [["rm"; "/new"]]; - InitEmpty, TestLastFail + InitBasicFS, TestLastFail [["mkdir"; "/new"]; ["rm"; "/new"]]], "remove a file", @@ -685,12 +690,12 @@ C<path/*> and sorting the resulting nodes into alphabetical order."); Remove the single file C<path>."); ("rmdir", (RErr, [String "path"]), 30, [], - [InitEmpty, TestRun + [InitBasicFS, TestRun [["mkdir"; "/new"]; ["rmdir"; "/new"]]; - InitEmpty, TestLastFail + InitBasicFS, TestLastFail [["rmdir"; "/new"]]; - InitEmpty, TestLastFail + InitBasicFS, TestLastFail [["touch"; "/new"]; ["rmdir"; "/new"]]], "remove a directory", @@ -698,7 +703,7 @@ Remove the single file C<path>."); Remove the single directory C<path>."); ("rm_rf", (RErr, [String "path"]), 31, [], - [InitEmpty, TestOutputFalse + [InitBasicFS, TestOutputFalse [["mkdir"; "/new"]; ["mkdir"; "/new/foo"]; ["touch"; "/new/foo/bar"]; @@ -711,23 +716,23 @@ contents if its a directory. This is like the C<rm -rf> shell command."); ("mkdir", (RErr, [String "path"]), 32, [], - [InitEmpty, TestOutputTrue + [InitBasicFS, TestOutputTrue [["mkdir"; "/new"]; ["is_dir"; "/new"]]; - InitEmpty, TestLastFail + InitBasicFS, TestLastFail [["mkdir"; "/new/foo/bar"]]], "create a directory", "\ Create a directory named C<path>."); ("mkdir_p", (RErr, [String "path"]), 33, [], - [InitEmpty, TestOutputTrue + [InitBasicFS, TestOutputTrue [["mkdir_p"; "/new/foo/bar"]; ["is_dir"; "/new/foo/bar"]]; - InitEmpty, TestOutputTrue + InitBasicFS, TestOutputTrue [["mkdir_p"; "/new/foo/bar"]; ["is_dir"; "/new/foo"]]; - InitEmpty, TestOutputTrue + InitBasicFS, TestOutputTrue [["mkdir_p"; "/new/foo/bar"]; ["is_dir"; "/new"]]], "create a directory and parents", @@ -753,10 +758,10 @@ names, you will need to locate and parse the password file yourself (Augeas support makes this relatively easy)."); ("exists", (RBool "existsflag", [String "path"]), 36, [], - [InitEmpty, TestOutputTrue ( + [InitBasicFS, TestOutputTrue ( [["touch"; "/new"]; ["exists"; "/new"]]); - InitEmpty, TestOutputTrue ( + InitBasicFS, TestOutputTrue ( [["mkdir"; "/new"]; ["exists"; "/new"]])], "test if file or directory exists", @@ -767,10 +772,10 @@ This returns C<true> if and only if there is a file, directory See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>."); ("is_file", (RBool "fileflag", [String "path"]), 37, [], - [InitEmpty, TestOutputTrue ( + [InitBasicFS, TestOutputTrue ( [["touch"; "/new"]; ["is_file"; "/new"]]); - InitEmpty, TestOutputFalse ( + InitBasicFS, TestOutputFalse ( [["mkdir"; "/new"]; ["is_file"; "/new"]])], "test if file exists", @@ -782,10 +787,10 @@ other objects like directories. See also C<guestfs_stat>."); ("is_dir", (RBool "dirflag", [String "path"]), 38, [], - [InitEmpty, TestOutputFalse ( + [InitBasicFS, TestOutputFalse ( [["touch"; "/new"]; ["is_dir"; "/new"]]); - InitEmpty, TestOutputTrue ( + InitBasicFS, TestOutputTrue ( [["mkdir"; "/new"]; ["is_dir"; "/new"]])], "test if file exists", @@ -797,7 +802,7 @@ other objects like files. See also C<guestfs_stat>."); ("pvcreate", (RErr, [String "device"]), 39, [], - [InitNone, TestOutputList ( + [InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -810,7 +815,7 @@ where C<device> should usually be a partition name such as C</dev/sda1>."); ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [], - [InitNone, TestOutputList ( + [InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -824,7 +829,7 @@ This creates an LVM volume group called C<volgroup> from the non-empty list of physical volumes C<physvols>."); ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [], - [InitNone, TestOutputList ( + [InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; ["pvcreate"; "/dev/sda1"]; ["pvcreate"; "/dev/sda2"]; @@ -845,7 +850,7 @@ This creates an LVM volume group called C<logvol> on the volume group C<volgroup>, with C<size> megabytes."); ("mkfs", (RErr, [String "fstype"; String "device"]), 42, [], - [InitNone, TestOutput ( + [InitEmpty, TestOutput ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]; @@ -884,7 +889,7 @@ pass C<lines> as a single element list, when the single element being the string C<,> (comma)."); ("write_file", (RErr, [String "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning], - [InitNone, TestOutput ( + [InitEmpty, TestOutput ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]; @@ -901,12 +906,12 @@ then the length is calculated using C<strlen> (so in this case the content cannot contain embedded ASCII NULs)."); ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"], - [InitNone, TestOutputList ( + [InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]; ["mounts"]], ["/dev/sda1"]); - InitNone, TestOutputList ( + InitEmpty, TestOutputList ( [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]; @@ -919,7 +924,7 @@ specified either by its mountpoint (path) or the device which contains the filesystem."); ("mounts", (RStringList "devices", []), 46, [], - [InitEmpty, TestOutputList ( + [InitBasicFS, TestOutputList ( [["mounts"]], ["/dev/sda1"])], "show mounted filesystems", "\ @@ -929,7 +934,7 @@ the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>). Some internal mounts are not shown."); ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"], - [InitEmpty, TestOutputList ( + [InitBasicFS, TestOutputList ( [["umount_all"]; ["mounts"]], [])], "unmount all filesystems", @@ -2242,21 +2247,22 @@ and generate_one_test name i (init, test) = pr "{\n"; (match init with - | InitNone -> - pr " /* InitNone for %s (%d) */\n" name i; + | InitNone -> () + | InitEmpty -> + pr " /* InitEmpty for %s (%d) */\n" name i; List.iter (generate_test_command_call test_name) [["umount_all"]; ["lvm_remove_all"]] - | InitEmpty -> - pr " /* InitEmpty for %s (%d): create ext2 on /dev/sda1 */\n" name i; + | InitBasicFS -> + pr " /* InitBasicFS for %s (%d): create ext2 on /dev/sda1 */\n" name i; List.iter (generate_test_command_call test_name) [["umount_all"]; ["lvm_remove_all"]; ["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","]; ["mkfs"; "ext2"; "/dev/sda1"]; ["mount"; "/dev/sda1"; "/"]] - | InitEmptyLVM -> - pr " /* InitEmptyLVM for %s (%d): create ext2 on /dev/VG/LV */\n" + | InitBasicFSonLVM -> + pr " /* InitBasicFSonLVM for %s (%d): create ext2 on /dev/VG/LV */\n" name i; List.iter (generate_test_command_call test_name) [["umount_all"]; @@ -3244,22 +3250,6 @@ my_newSVull(unsigned long long val) { #endif } -/* XXX Not thread-safe, and in general not safe if the caller is - * issuing multiple requests in parallel (on different guestfs - * handles). We should use the guestfs_h handle passed to the - * error handle to distinguish these cases. - */ -static char *last_error = NULL; - -static void -error_handler (guestfs_h *g, - void *data, - const char *msg) -{ - if (last_error != NULL) free (last_error); - last_error = strdup (msg); -} - /* http://www.perlmonks.org/?node_id=680842 */ static char ** XS_unpack_charPtrPtr (SV *arg) { @@ -3277,14 +3267,13 @@ XS_unpack_charPtrPtr (SV *arg) { for (i = 0; i <= av_len (av); i++) { SV **elem = av_fetch (av, i, 0); - if (!elem || !*elem) { - croak (\"missing element in list\"); - } + if (!elem || !*elem) + croak (\"missing element in list\"); - ret[i] = SvPV_nolen (*elem); + ret[i] = SvPV_nolen (*elem); } - ret[i + 1] = NULL; + ret[i] = NULL; return ret; } @@ -3297,7 +3286,7 @@ _create () RETVAL = guestfs_create (); if (!RETVAL) croak (\"could not create guestfs handle\"); - guestfs_set_error_handler (RETVAL, error_handler, NULL); + guestfs_set_error_handler (RETVAL, NULL, NULL); OUTPUT: RETVAL @@ -3355,7 +3344,7 @@ DESTROY (g) generate_call_args ~handle:"g" style; pr " == -1) {\n"; do_cleanups (); - pr " croak (\"%s: %%s\", last_error);\n" name; + pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; pr " }\n" | RInt n | RBool n -> @@ -3367,7 +3356,7 @@ DESTROY (g) pr ";\n"; pr " if (%s == -1) {\n" n; do_cleanups (); - pr " croak (\"%s: %%s\", last_error);\n" name; + pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; pr " }\n"; pr " RETVAL = newSViv (%s);\n" n; pr " OUTPUT:\n"; @@ -3381,7 +3370,7 @@ DESTROY (g) pr ";\n"; pr " if (%s == NULL) {\n" n; do_cleanups (); - pr " croak (\"%s: %%s\", last_error);\n" name; + pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; pr " }\n"; pr " RETVAL = newSVpv (%s, 0);\n" n; pr " OUTPUT:\n"; @@ -3395,7 +3384,7 @@ DESTROY (g) pr ";\n"; pr " if (%s == NULL) {\n" n; do_cleanups (); - pr " croak (\"%s: %%s\", last_error);\n" name; + pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; pr " }\n"; pr " RETVAL = newSVpv (%s, 0);\n" n; pr " free (%s);\n" n; @@ -3411,7 +3400,7 @@ DESTROY (g) pr ";\n"; pr " if (%s == NULL) {\n" n; do_cleanups (); - pr " croak (\"%s: %%s\", last_error);\n" name; + pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; pr " }\n"; pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n; pr " EXTEND (SP, n);\n"; @@ -3429,7 +3418,7 @@ DESTROY (g) pr ";\n"; pr " if (r == NULL) {\n"; do_cleanups (); - pr " croak (\"%s: %%s\", last_error);\n" name; + pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; pr " }\n"; pr " EXTEND (SP, 2);\n"; pr " PUSHs (sv_2mortal (newSViv (r->i)));\n"; @@ -3458,7 +3447,7 @@ and generate_perl_lvm_code typ cols name style n = generate_call_args ~handle:"g" style; pr ";\n"; pr " if (%s == NULL)\n" n; - pr " croak (\"%s: %%s\", last_error);\n" name; + pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name; pr " EXTEND (SP, %s->len);\n" n; pr " for (i = 0; i < %s->len; ++i) {\n" n; pr " hv = newHV ();\n"; @@ -3630,6 +3619,354 @@ and generate_perl_prototype name style = ) (snd style); pr ");" +(* Generate Python C module. *) +and generate_python_c () = + generate_header CStyle LGPLv2; + + pr "\ +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> + +#include <Python.h> + +#include \"guestfs.h\" + +typedef struct { + PyObject_HEAD + guestfs_h *g; +} Pyguestfs_Object; + +static guestfs_h * +get_handle (PyObject *obj) +{ + assert (obj); + assert (obj != Py_None); + return ((Pyguestfs_Object *) obj)->g; +} + +static PyObject * +put_handle (guestfs_h *g) +{ + assert (g); + return + PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL); +} + +/* This list should be freed (but not the strings) after use. */ +static const char ** +get_string_list (PyObject *obj) +{ + int i, len; + const char **r; + + assert (obj); + + if (!PyList_Check (obj)) { + PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\"); + return NULL; + } + + len = PyList_Size (obj); + r = malloc (sizeof (char *) * (len+1)); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\"); + return NULL; + } + + for (i = 0; i < len; ++i) + r[i] = PyString_AsString (PyList_GetItem (obj, i)); + r[len] = NULL; + + return r; +} + +static PyObject * +put_string_list (char * const * const argv) +{ + PyObject *list; + int argc, i; + + for (argc = 0; argv[argc] != NULL; ++argc) + ; + + list = PyList_New (argc); + for (i = 0; i < argc; ++i) + PyList_SetItem (list, i, PyString_FromString (argv[i])); + + return list; +} + +static void +free_strings (char **argv) +{ + int argc; + + for (argc = 0; argv[argc] != NULL; ++argc) + free (argv[argc]); + free (argv); +} + +static PyObject * +py_guestfs_create (PyObject *self, PyObject *args) +{ + guestfs_h *g; + + g = guestfs_create (); + if (g == NULL) { + PyErr_SetString (PyExc_RuntimeError, + \"guestfs.create: failed to allocate handle\"); + return NULL; + } + guestfs_set_error_handler (g, NULL, NULL); + return put_handle (g); +} + +static PyObject * +py_guestfs_close (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + + if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g)) + return NULL; + g = get_handle (py_g); + + guestfs_close (g); + + Py_INCREF (Py_None); + return Py_None; +} + +"; + + (* LVM structures, turned into Python dictionaries. *) + List.iter ( + fun (typ, cols) -> + pr "static PyObject *\n"; + pr "put_lvm_%s (struct guestfs_lvm_%s *%s)\n" typ typ typ; + pr "{\n"; + pr " PyObject *dict;\n"; + pr "\n"; + pr " dict = PyDict_New ();\n"; + List.iter ( + function + | name, `String -> + pr " PyDict_SetItemString (dict, \"%s\",\n" name; + pr " PyString_FromString (%s->%s));\n" + typ name + | name, `UUID -> + pr " PyDict_SetItemString (dict, \"%s\",\n" name; + pr " PyString_FromStringAndSize (%s->%s, 32));\n" + typ name + | name, `Bytes -> + pr " PyDict_SetItemString (dict, \"%s\",\n" name; + pr " PyLong_FromUnsignedLongLong (%s->%s));\n" + typ name + | name, `Int -> + pr " PyDict_SetItemString (dict, \"%s\",\n" name; + pr " PyLong_FromLongLong (%s->%s));\n" + typ name + | name, `OptPercent -> + pr " if (%s->%s >= 0)\n" typ name; + pr " PyDict_SetItemString (dict, \"%s\",\n" name; + pr " PyFloat_FromDouble ((double) %s->%s));\n" + typ name; + pr " else {\n"; + pr " Py_INCREF (Py_None);\n"; + pr " PyDict_SetItemString (dict, \"%s\", Py_None);" name; + pr " }\n" + ) cols; + pr " return dict;\n"; + pr "};\n"; + pr "\n"; + + pr "static PyObject *\n"; + pr "put_lvm_%s_list (struct guestfs_lvm_%s_list *%ss)\n" typ typ typ; + pr "{\n"; + pr " PyObject *list;\n"; + pr " int i;\n"; + pr "\n"; + pr " list = PyList_New (%ss->len);\n" typ; + pr " for (i = 0; i < %ss->len; ++i)\n" typ; + pr " PyList_SetItem (list, i, put_lvm_%s (&%ss->val[i]));\n" typ typ; + pr " return list;\n"; + pr "};\n"; + pr "\n" + ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]; + + (* Python wrapper functions. *) + List.iter ( + fun (name, style, _, _, _, _, _) -> + pr "static PyObject *\n"; + pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name; + pr "{\n"; + + pr " PyObject *py_g;\n"; + pr " guestfs_h *g;\n"; + pr " PyObject *py_r;\n"; + + let error_code = + match fst style with + | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1" + | RConstString _ -> pr " const char *r;\n"; "NULL" + | RString _ -> pr " char *r;\n"; "NULL" + | RStringList _ -> pr " char **r;\n"; "NULL" + | RIntBool _ -> pr " struct guestfs_int_bool *r;\n"; "NULL" + | RPVList n -> pr " struct guestfs_lvm_pv_list *r;\n"; "NULL" + | RVGList n -> pr " struct guestfs_lvm_vg_list *r;\n"; "NULL" + | RLVList n -> pr " struct guestfs_lvm_lv_list *r;\n"; "NULL" in + + List.iter ( + function + | String n -> pr " const char *%s;\n" n + | OptString n -> pr " const char *%s;\n" n + | StringList n -> + pr " PyObject *py_%s;\n" n; + pr " const char **%s;\n" n + | Bool n -> pr " int %s;\n" n + | Int n -> pr " int %s;\n" n + ) (snd style); + + pr "\n"; + + (* Convert the parameters. *) + pr " if (!PyArg_ParseTuple (args, (char *) \"O"; + List.iter ( + function + | String _ -> pr "s" + | OptString _ -> pr "z" + | StringList _ -> pr "O" + | Bool _ -> pr "i" (* XXX Python has booleans? *) + | Int _ -> pr "i" + ) (snd style); + pr ":guestfs_%s\",\n" name; + pr " &py_g"; + List.iter ( + function + | String n -> pr ", &%s" n + | OptString n -> pr ", &%s" n + | StringList n -> pr ", &py_%s" n + | Bool n -> pr ", &%s" n + | Int n -> pr ", &%s" n + ) (snd style); + + pr "))\n"; + pr " return NULL;\n"; + + pr " g = get_handle (py_g);\n"; + List.iter ( + function + | String _ | OptString _ | Bool _ | Int _ -> () + | StringList n -> + pr " %s = get_string_list (py_%s);\n" n n; + pr " if (!%s) return NULL;\n" n + ) (snd style); + + pr "\n"; + + pr " r = guestfs_%s " name; + generate_call_args ~handle:"g" style; + pr ";\n"; + + List.iter ( + function + | String _ | OptString _ | Bool _ | Int _ -> () + | StringList n -> + pr " free (%s);\n" n + ) (snd style); + + pr " if (r == %s) {\n" error_code; + pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n"; + pr " return NULL;\n"; + pr " }\n"; + pr "\n"; + + (match fst style with + | RErr -> + pr " Py_INCREF (Py_None);\n"; + pr " py_r = Py_None;\n" + | RInt _ + | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n" + | RConstString _ -> pr " py_r = PyString_FromString (r);\n" + | RString _ -> + pr " py_r = PyString_FromString (r);\n"; + pr " free (r);\n" + | RStringList _ -> + pr " py_r = put_string_list (r);\n"; + pr " free_strings (r);\n" + | RIntBool _ -> + pr " py_r = PyTuple_New (2);\n"; + pr " PyTuple_SetItem (py_r, 0, PyInt_FromLong ((long) r->i));\n"; + pr " PyTuple_SetItem (py_r, 1, PyInt_FromLong ((long) r->b));\n"; + pr " guestfs_free_int_bool (r);\n" + | RPVList n -> + pr " py_r = put_lvm_pv_list (r);\n"; + pr " guestfs_free_lvm_pv_list (r);\n" + | RVGList n -> + pr " py_r = put_lvm_vg_list (r);\n"; + pr " guestfs_free_lvm_vg_list (r);\n" + | RLVList n -> + pr " py_r = put_lvm_lv_list (r);\n"; + pr " guestfs_free_lvm_lv_list (r);\n" + ); + + pr " return py_r;\n"; + pr "}\n"; + pr "\n" + ) all_functions; + + (* Table of functions. *) + pr "static PyMethodDef methods[] = {\n"; + pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n"; + pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n"; + List.iter ( + fun (name, _, _, _, _, _, _) -> + pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n" + name name + ) all_functions; + pr " { NULL, NULL, 0, NULL }\n"; + pr "};\n"; + pr "\n"; + + (* Init function. *) + pr "\ +void +initlibguestfsmod (void) +{ + static int initialized = 0; + + if (initialized) return; + Py_InitModule ((char *) \"libguestfsmod\", methods); + initialized = 1; +} +" + +(* Generate Python module. *) +and generate_python_py () = + generate_header HashStyle LGPLv2; + + pr "import libguestfsmod\n"; + pr "\n"; + pr "class guestfs:\n"; + pr " def __init__ (self):\n"; + pr " self._o = libguestfsmod.create ()\n"; + pr "\n"; + pr " def __del__ (self):\n"; + pr " libguestfsmod.close (self._o)\n"; + pr "\n"; + + List.iter ( + fun (name, style, _, _, _, _, _) -> + pr " def %s " name; + generate_call_args ~handle:"self" style; + pr ":\n"; + pr " return libguestfsmod.%s " name; + generate_call_args ~handle:"self._o" style; + pr "\n"; + pr "\n"; + ) all_functions + let output_to filename = let filename_new = filename ^ ".new" in chan := open_out filename_new; @@ -3717,3 +4054,11 @@ Run it from the top source directory using the command let close = output_to "perl/lib/Sys/Guestfs.pm" in generate_perl_pm (); close (); + + let close = output_to "python/guestfs-py.c" in + generate_python_c (); + close (); + + let close = output_to "python/guestfs.py" in + generate_python_py (); + close (); diff --git a/src/guestfs.c b/src/guestfs.c index cab264a4..e1046330 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 c677730a..3905554c 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); @@ -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; |