From a5f68bd57d887c8c8818dbb92a9f8b7643f67827 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Thu, 16 Apr 2009 22:13:20 +0100 Subject: [PATCH] Ruby bindings. --- .gitignore | 3 + Makefile.am | 3 + README | 2 + TODO | 4 - configure.ac | 14 +- daemon/configure.ac | 2 +- libguestfs.spec.in | 30 + ruby/Makefile.am | 43 + ruby/Rakefile.in | 103 ++ ruby/ext/guestfs/_guestfs.c | 2064 +++++++++++++++++++++++++++++++++++++++++ ruby/ext/guestfs/extconf.rb | 30 + ruby/lib/guestfs.rb | 18 + ruby/run-ruby-tests | 22 + ruby/tests/tc_010_load.rb | 28 + ruby/tests/tc_050_lvcreate.rb | 49 + src/generator.ml | 240 +++++ 16 files changed, 2648 insertions(+), 7 deletions(-) create mode 100644 ruby/Makefile.am create mode 100644 ruby/Rakefile.in create mode 100644 ruby/ext/guestfs/_guestfs.c create mode 100644 ruby/ext/guestfs/extconf.rb create mode 100644 ruby/lib/guestfs.rb create mode 100755 ruby/run-ruby-tests create mode 100644 ruby/tests/tc_010_load.rb create mode 100644 ruby/tests/tc_050_lvcreate.rb diff --git a/.gitignore b/.gitignore index 1b11a24..174489e 100644 --- a/.gitignore +++ b/.gitignore @@ -63,6 +63,9 @@ perl/Makefile.PL perl/blib perl/pm_to_blib python/guestfs.pyc +ruby/Rakefile +ruby/ext/guestfs/extconf.h +ruby/ext/guestfs/mkmf.log pod2htm?.tmp stamp-h1 test*.img diff --git a/Makefile.am b/Makefile.am index f6289e4..710e39d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,6 +28,9 @@ endif if HAVE_PYTHON SUBDIRS += python endif +if HAVE_RUBY +SUBDIRS += ruby +endif EXTRA_DIST = \ make-initramfs.sh update-initramfs.sh \ diff --git a/README b/README index 2db1725..ec05bdd 100644 --- a/README +++ b/README @@ -50,6 +50,8 @@ also to build the OCaml bindings - (Optional) Python if you want to build the python bindings +- (Optional) Ruby, rake if you want to build the ruby bindings + Running ./configure will check you have all the requirements installed on your machine. diff --git a/TODO b/TODO index 3655b70..17829c2 100644 --- a/TODO +++ b/TODO @@ -3,10 +3,6 @@ https://www.redhat.com/archives/fedora-virt/2009-April/msg00114.html ---------------------------------------------------------------------- -Several people have asked for Ruby bindings. - ----------------------------------------------------------------------- - We badly need to actually implement the FTP server mentioned in the documentation. diff --git a/configure.ac b/configure.ac index ad9361c..a771cdf 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -AC_INIT([libguestfs],[0.9.9]) +AC_INIT([libguestfs],[1.0.0]) AM_INIT_AUTOMAKE AC_CONFIG_MACRO_DIR([m4]) @@ -188,7 +188,16 @@ AC_SUBST(PYTHON_INCLUDEDIR) AC_SUBST(PYTHON_SITE_PACKAGES) AM_CONDITIONAL([HAVE_PYTHON], - [test "x$PYTHON_INCLUDEDIR" != "x" && test "x$PYTHON_SITE_PACKAGES" != "x"]) + [test "x$PYTHON_INCLUDEDIR" != "x" -a "x$PYTHON_SITE_PACKAGES" != "x"]) + +dnl Check for Ruby and rake (optional, for Ruby bindings). +old_libs="$LIBS" +AC_CHECK_LIB([ruby],[ruby_init]) +LIBS="$old_libs" +AC_CHECK_PROG([RAKE],[rake],[rake],[no]) + +AM_CONDITIONAL([HAVE_RUBY], + [test "x$RAKE" != "xno" -a -n "x$HAVE_LIBRUBY"]) dnl Run in subdirs. AC_CONFIG_SUBDIRS([daemon]) @@ -200,6 +209,7 @@ AC_CONFIG_FILES([Makefile src/Makefile fish/Makefile examples/Makefile ocaml/Makefile ocaml/examples/Makefile perl/Makefile python/Makefile + ruby/Makefile ruby/Rakefile make-initramfs.sh update-initramfs.sh libguestfs.spec ocaml/META perl/Makefile.PL]) diff --git a/daemon/configure.ac b/daemon/configure.ac index 8edcb2d..0bd37b0 100644 --- a/daemon/configure.ac +++ b/daemon/configure.ac @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -AC_INIT([libguestfs-daemon],[0.8.2]) +AC_INIT([libguestfs-daemon],[1.0.0]) AM_INIT_AUTOMAKE AC_CONFIG_MACRO_DIR([m4]) diff --git a/libguestfs.spec.in b/libguestfs.spec.in index fc70b01..c1e3e49 100644 --- a/libguestfs.spec.in +++ b/libguestfs.spec.in @@ -35,6 +35,8 @@ BuildRequires: perl-Test-Pod BuildRequires: perl-Test-Pod-Coverage BuildRequires: perl-ExtUtils-MakeMaker BuildRequires: python-devel +BuildRequires: ruby-devel +BuildRequires: rubygem-rake # Runtime requires: Requires: qemu >= 0.10-7 @@ -70,6 +72,8 @@ For OCaml bindings, see 'libguestfs-ocaml-devel'. For Python bindings, see 'libguestfs-python'. +For Ruby bindings, see 'libguestfs-ruby'. + %package devel Summary: Development tools and libraries for %{name} @@ -143,6 +147,20 @@ Requires: %{name} = %{version}-%{release} %{name}-python contains Python bindings for %{name}. +%package ruby +Summary: Ruby bindings for %{name} +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +Requires: ruby(abi) = 1.8 +Provides: ruby(guestfs) = %{version} + +%{!?ruby_sitelib: %define ruby_sitelib %(ruby -rrbconfig -e "puts Config::CONFIG['sitelibdir']")} +%{!?ruby_sitearch: %define ruby_sitearch %(ruby -rrbconfig -e "puts Config::CONFIG['sitearchdir']")} + +%description ruby +%{name}-ruby contains Ruby bindings for %{name}. + + %prep %setup -q @@ -196,6 +214,12 @@ if [ "$RPM_BUILD_ROOT%{python_sitearch}" != "$RPM_BUILD_ROOT%{python_sitelib}" ] $RPM_BUILD_ROOT%{python_sitelib}/ fi +# Install ruby bindings by hand. +mkdir -p $RPM_BUILD_ROOT%{ruby_sitelib} +mkdir -p $RPM_BUILD_ROOT%{ruby_sitearch} +install -p -m0644 ruby/lib/libvirt.rb $RPM_BUILD_ROOT%{ruby_sitelib} +install -p -m0755 ruby/ext/libvirt/_libvirt.so $RPM_BUILD_ROOT%{ruby_sitearch} + %clean rm -rf $RPM_BUILD_ROOT @@ -266,6 +290,12 @@ rm -rf $RPM_BUILD_ROOT %{python_sitelib}/*.pyo +%files ruby +%defattr(-,root,root,-) +%{ruby_sitelib}/guestfs.rb +%{ruby_sitearch}/_guestfs.so + + %changelog * Thu Apr 16 2009 Richard Jones - @VERSION@-1 - New upstream version @VERSION@. diff --git a/ruby/Makefile.am b/ruby/Makefile.am new file mode 100644 index 0000000..2b4b201 --- /dev/null +++ b/ruby/Makefile.am @@ -0,0 +1,43 @@ +# libguestfs Ruby 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. + +EXTRA_DIST = \ + Rakefile.in \ + ext/guestfs/_guestfs.c \ + ext/guestfs/extconf.rb \ + lib/guestfs.rb \ + run-ruby-tests \ + tests/tc_*.rb + +CLEANFILES = *~ \ + lib/*~ \ + tests/*~ \ + ext/guestfs/*~ \ + ext/guestfs/extconf.h \ + ext/guestfs/_guestfs.o \ + ext/guestfs/_guestfs.so \ + ext/guestfs/mkmf.log \ + ext/guestfs/Makefile + +if HAVE_RUBY + +TESTS = run-ruby-tests + +all: + rake build + +endif \ No newline at end of file diff --git a/ruby/Rakefile.in b/ruby/Rakefile.in new file mode 100644 index 0000000..fc95f3f --- /dev/null +++ b/ruby/Rakefile.in @@ -0,0 +1,103 @@ +# libguestfs Ruby bindings -*- ruby -*- +# @configure_input@ +# 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. + +require 'rake/clean' +require 'rake/rdoctask' +require 'rake/testtask' +require 'rake/gempackagetask' + +PKG_NAME='@PACKAGE_NAME@' +PKG_VERSION='@PACKAGE_VERSION@' + +EXT_CONF='ext/guestfs/extconf.rb' +MAKEFILE='ext/guestfs/Makefile' +GUESTFS_MODULE='ext/guestfs/_guestfs.so' +GUESTFS_SRC='ext/guestfs/_guestfs.c' + +CLEAN.include [ "ext/**/*.o", GUESTFS_MODULE, + "ext/**/depend" ] + +CLOBBER.include [ "config.save", "ext/**/mkmf.log", + MAKEFILE ] + +# Build locally + +file MAKEFILE => EXT_CONF do |t| + Dir::chdir(File::dirname(EXT_CONF)) do + unless sh "ruby #{File::basename(EXT_CONF)}" + $stderr.puts "Failed to run extconf" + break + end + end +end +file GUESTFS_MODULE => [ MAKEFILE, GUESTFS_SRC ] do |t| + Dir::chdir(File::dirname(EXT_CONF)) do + unless sh "make" + $stderr.puts "make failed" + break + end + end +end +desc "Build the native library" +task :build => GUESTFS_MODULE + +Rake::TestTask.new(:test) do |t| + t.test_files = FileList['tests/tc_*.rb'] + t.libs = [ 'lib', 'ext/guestfs' ] +end +task :test => :build + +Rake::RDocTask.new do |rd| + rd.main = "README.rdoc" + rd.rdoc_dir = "doc/site/api" + rd.rdoc_files.include("README.rdoc", "lib/**/*.rb", "ext/**/*.[ch]") +end + +# Package tasks + +PKG_FILES = FileList[ + "Rakefile", "COPYING", "README", "NEWS", "README.rdoc", + "lib/**/*.rb", + "ext/**/*.[ch]", "ext/**/MANIFEST", "ext/**/extconf.rb", + "tests/**/*", + "spec/**/*" +] + +DIST_FILES = FileList[ + "pkg/*.src.rpm", "pkg/*.gem", "pkg/*.zip", "pkg/*.tgz" +] + +SPEC = Gem::Specification.new do |s| + s.name = PKG_NAME + s.version = PKG_VERSION + s.email = "rjones@redhat.com" + s.homepage = "http://et.redhat.com/~rjones/libguestfs/" + s.summary = "Ruby bindings for libguestfs" + s.files = PKG_FILES + s.autorequire = "guestfs" + s.required_ruby_version = '>= 1.8.1' + s.extensions = "ext/guestfs/extconf.rb" + s.description = < +#include + +#include + +#include "guestfs.h" + +#include "extconf.h" + +static VALUE m_guestfs; /* guestfs module */ +static VALUE c_guestfs; /* guestfs_h handle */ +static VALUE e_Error; /* used for all errors */ + +static void ruby_guestfs_free (void *p) +{ + if (!p) return; + guestfs_close ((guestfs_h *) p); +} + +static VALUE ruby_guestfs_create (VALUE m) +{ + guestfs_h *g; + + g = guestfs_create (); + if (!g) + rb_raise (e_Error, "failed to create guestfs handle"); + + /* Don't print error messages to stderr by default. */ + guestfs_set_error_handler (g, NULL, NULL); + + /* Wrap it, and make sure the close function is called when the + * handle goes away. + */ + return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g); +} + +static VALUE ruby_guestfs_close (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + + ruby_guestfs_free (g); + DATA_PTR (gv) = NULL; + + return Qnil; +} + +static VALUE ruby_guestfs_launch (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "launch"); + + + int r; + + r = guestfs_launch (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_wait_ready (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "wait_ready"); + + + int r; + + r = guestfs_wait_ready (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_kill_subprocess (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "kill_subprocess"); + + + int r; + + r = guestfs_kill_subprocess (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_add_drive (VALUE gv, VALUE filenamev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "add_drive"); + + const char *filename = StringValueCStr (filenamev); + if (!filename) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "filename", "add_drive"); + + int r; + + r = guestfs_add_drive (g, filename); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_add_cdrom (VALUE gv, VALUE filenamev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "add_cdrom"); + + const char *filename = StringValueCStr (filenamev); + if (!filename) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "filename", "add_cdrom"); + + int r; + + r = guestfs_add_cdrom (g, filename); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_config (VALUE gv, VALUE qemuparamv, VALUE qemuvaluev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "config"); + + const char *qemuparam = StringValueCStr (qemuparamv); + if (!qemuparam) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "qemuparam", "config"); + const char *qemuvalue = StringValueCStr (qemuvaluev); + + int r; + + r = guestfs_config (g, qemuparam, qemuvalue); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_set_path (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "set_path"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "set_path"); + + int r; + + r = guestfs_set_path (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_get_path (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "get_path"); + + + const char *r; + + r = guestfs_get_path (g); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return rb_str_new2 (r); +} + +static VALUE ruby_guestfs_set_autosync (VALUE gv, VALUE autosyncv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "set_autosync"); + + int autosync = NUM2INT (autosyncv); + + int r; + + r = guestfs_set_autosync (g, autosync); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_get_autosync (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "get_autosync"); + + + int r; + + r = guestfs_get_autosync (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + +static VALUE ruby_guestfs_set_verbose (VALUE gv, VALUE verbosev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "set_verbose"); + + int verbose = NUM2INT (verbosev); + + int r; + + r = guestfs_set_verbose (g, verbose); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_get_verbose (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "get_verbose"); + + + int r; + + r = guestfs_get_verbose (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + +static VALUE ruby_guestfs_mount (VALUE gv, VALUE devicev, VALUE mountpointv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "mount"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "mount"); + const char *mountpoint = StringValueCStr (mountpointv); + if (!mountpoint) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "mountpoint", "mount"); + + int r; + + r = guestfs_mount (g, device, mountpoint); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_sync (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "sync"); + + + int r; + + r = guestfs_sync (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_touch (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "touch"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "touch"); + + int r; + + r = guestfs_touch (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_cat (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "cat"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "cat"); + + char *r; + + r = guestfs_cat (g, path); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_str_new2 (r); + free (r); + return rv; +} + +static VALUE ruby_guestfs_ll (VALUE gv, VALUE directoryv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "ll"); + + const char *directory = StringValueCStr (directoryv); + if (!directory) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "directory", "ll"); + + char *r; + + r = guestfs_ll (g, directory); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_str_new2 (r); + free (r); + return rv; +} + +static VALUE ruby_guestfs_ls (VALUE gv, VALUE directoryv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "ls"); + + const char *directory = StringValueCStr (directoryv); + if (!directory) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "directory", "ls"); + + char **r; + + r = guestfs_ls (g, directory); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_list_devices (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "list_devices"); + + + char **r; + + r = guestfs_list_devices (g); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_list_partitions (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "list_partitions"); + + + char **r; + + r = guestfs_list_partitions (g); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_pvs (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "pvs"); + + + char **r; + + r = guestfs_pvs (g); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_vgs (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "vgs"); + + + char **r; + + r = guestfs_vgs (g); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_lvs (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "lvs"); + + + char **r; + + r = guestfs_lvs (g); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_pvs_full (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "pvs_full"); + + + struct guestfs_lvm_pv_list *r; + + r = guestfs_pvs_full (g); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_ary_new2 (r->len); + int i; + for (i = 0; i < r->len; ++i) { + VALUE hv = rb_hash_new (); + rb_hash_aset (rv, rb_str_new2 ("pv_name"), rb_str_new2 (r->val[i].pv_name)); + rb_hash_aset (rv, rb_str_new2 ("pv_uuid"), rb_str_new (r->val[i].pv_uuid, 32)); + rb_hash_aset (rv, rb_str_new2 ("pv_fmt"), rb_str_new2 (r->val[i].pv_fmt)); + rb_hash_aset (rv, rb_str_new2 ("pv_size"), ULL2NUM (r->val[i].pv_size)); + rb_hash_aset (rv, rb_str_new2 ("dev_size"), ULL2NUM (r->val[i].dev_size)); + rb_hash_aset (rv, rb_str_new2 ("pv_free"), ULL2NUM (r->val[i].pv_free)); + rb_hash_aset (rv, rb_str_new2 ("pv_used"), ULL2NUM (r->val[i].pv_used)); + rb_hash_aset (rv, rb_str_new2 ("pv_attr"), rb_str_new2 (r->val[i].pv_attr)); + rb_hash_aset (rv, rb_str_new2 ("pv_pe_count"), ULL2NUM (r->val[i].pv_pe_count)); + rb_hash_aset (rv, rb_str_new2 ("pv_pe_alloc_count"), ULL2NUM (r->val[i].pv_pe_alloc_count)); + rb_hash_aset (rv, rb_str_new2 ("pv_tags"), rb_str_new2 (r->val[i].pv_tags)); + rb_hash_aset (rv, rb_str_new2 ("pe_start"), ULL2NUM (r->val[i].pe_start)); + rb_hash_aset (rv, rb_str_new2 ("pv_mda_count"), ULL2NUM (r->val[i].pv_mda_count)); + rb_hash_aset (rv, rb_str_new2 ("pv_mda_free"), ULL2NUM (r->val[i].pv_mda_free)); + rb_ary_push (rv, hv); + } + guestfs_free_lvm_pv_list (r); + return rv; +} + +static VALUE ruby_guestfs_vgs_full (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "vgs_full"); + + + struct guestfs_lvm_vg_list *r; + + r = guestfs_vgs_full (g); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_ary_new2 (r->len); + int i; + for (i = 0; i < r->len; ++i) { + VALUE hv = rb_hash_new (); + rb_hash_aset (rv, rb_str_new2 ("vg_name"), rb_str_new2 (r->val[i].vg_name)); + rb_hash_aset (rv, rb_str_new2 ("vg_uuid"), rb_str_new (r->val[i].vg_uuid, 32)); + rb_hash_aset (rv, rb_str_new2 ("vg_fmt"), rb_str_new2 (r->val[i].vg_fmt)); + rb_hash_aset (rv, rb_str_new2 ("vg_attr"), rb_str_new2 (r->val[i].vg_attr)); + rb_hash_aset (rv, rb_str_new2 ("vg_size"), ULL2NUM (r->val[i].vg_size)); + rb_hash_aset (rv, rb_str_new2 ("vg_free"), ULL2NUM (r->val[i].vg_free)); + rb_hash_aset (rv, rb_str_new2 ("vg_sysid"), rb_str_new2 (r->val[i].vg_sysid)); + rb_hash_aset (rv, rb_str_new2 ("vg_extent_size"), ULL2NUM (r->val[i].vg_extent_size)); + rb_hash_aset (rv, rb_str_new2 ("vg_extent_count"), ULL2NUM (r->val[i].vg_extent_count)); + rb_hash_aset (rv, rb_str_new2 ("vg_free_count"), ULL2NUM (r->val[i].vg_free_count)); + rb_hash_aset (rv, rb_str_new2 ("max_lv"), ULL2NUM (r->val[i].max_lv)); + rb_hash_aset (rv, rb_str_new2 ("max_pv"), ULL2NUM (r->val[i].max_pv)); + rb_hash_aset (rv, rb_str_new2 ("pv_count"), ULL2NUM (r->val[i].pv_count)); + rb_hash_aset (rv, rb_str_new2 ("lv_count"), ULL2NUM (r->val[i].lv_count)); + rb_hash_aset (rv, rb_str_new2 ("snap_count"), ULL2NUM (r->val[i].snap_count)); + rb_hash_aset (rv, rb_str_new2 ("vg_seqno"), ULL2NUM (r->val[i].vg_seqno)); + rb_hash_aset (rv, rb_str_new2 ("vg_tags"), rb_str_new2 (r->val[i].vg_tags)); + rb_hash_aset (rv, rb_str_new2 ("vg_mda_count"), ULL2NUM (r->val[i].vg_mda_count)); + rb_hash_aset (rv, rb_str_new2 ("vg_mda_free"), ULL2NUM (r->val[i].vg_mda_free)); + rb_ary_push (rv, hv); + } + guestfs_free_lvm_vg_list (r); + return rv; +} + +static VALUE ruby_guestfs_lvs_full (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "lvs_full"); + + + struct guestfs_lvm_lv_list *r; + + r = guestfs_lvs_full (g); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_ary_new2 (r->len); + int i; + for (i = 0; i < r->len; ++i) { + VALUE hv = rb_hash_new (); + rb_hash_aset (rv, rb_str_new2 ("lv_name"), rb_str_new2 (r->val[i].lv_name)); + rb_hash_aset (rv, rb_str_new2 ("lv_uuid"), rb_str_new (r->val[i].lv_uuid, 32)); + rb_hash_aset (rv, rb_str_new2 ("lv_attr"), rb_str_new2 (r->val[i].lv_attr)); + rb_hash_aset (rv, rb_str_new2 ("lv_major"), ULL2NUM (r->val[i].lv_major)); + rb_hash_aset (rv, rb_str_new2 ("lv_minor"), ULL2NUM (r->val[i].lv_minor)); + rb_hash_aset (rv, rb_str_new2 ("lv_kernel_major"), ULL2NUM (r->val[i].lv_kernel_major)); + rb_hash_aset (rv, rb_str_new2 ("lv_kernel_minor"), ULL2NUM (r->val[i].lv_kernel_minor)); + rb_hash_aset (rv, rb_str_new2 ("lv_size"), ULL2NUM (r->val[i].lv_size)); + rb_hash_aset (rv, rb_str_new2 ("seg_count"), ULL2NUM (r->val[i].seg_count)); + rb_hash_aset (rv, rb_str_new2 ("origin"), rb_str_new2 (r->val[i].origin)); + rb_hash_aset (rv, rb_str_new2 ("snap_percent"), rb_dbl2big (r->val[i].snap_percent)); + rb_hash_aset (rv, rb_str_new2 ("copy_percent"), rb_dbl2big (r->val[i].copy_percent)); + rb_hash_aset (rv, rb_str_new2 ("move_pv"), rb_str_new2 (r->val[i].move_pv)); + rb_hash_aset (rv, rb_str_new2 ("lv_tags"), rb_str_new2 (r->val[i].lv_tags)); + rb_hash_aset (rv, rb_str_new2 ("mirror_log"), rb_str_new2 (r->val[i].mirror_log)); + rb_hash_aset (rv, rb_str_new2 ("modules"), rb_str_new2 (r->val[i].modules)); + rb_ary_push (rv, hv); + } + guestfs_free_lvm_lv_list (r); + return rv; +} + +static VALUE ruby_guestfs_read_lines (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "read_lines"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "read_lines"); + + char **r; + + r = guestfs_read_lines (g, path); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_aug_init (VALUE gv, VALUE rootv, VALUE flagsv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_init"); + + const char *root = StringValueCStr (rootv); + if (!root) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "root", "aug_init"); + int flags = NUM2INT (flagsv); + + int r; + + r = guestfs_aug_init (g, root, flags); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_aug_close (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_close"); + + + int r; + + r = guestfs_aug_close (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_aug_defvar (VALUE gv, VALUE namev, VALUE exprv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_defvar"); + + const char *name = StringValueCStr (namev); + if (!name) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "name", "aug_defvar"); + const char *expr = StringValueCStr (exprv); + + int r; + + r = guestfs_aug_defvar (g, name, expr); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + +static VALUE ruby_guestfs_aug_defnode (VALUE gv, VALUE namev, VALUE exprv, VALUE valv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_defnode"); + + const char *name = StringValueCStr (namev); + if (!name) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "name", "aug_defnode"); + const char *expr = StringValueCStr (exprv); + if (!expr) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "expr", "aug_defnode"); + const char *val = StringValueCStr (valv); + if (!val) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "val", "aug_defnode"); + + struct guestfs_int_bool *r; + + r = guestfs_aug_defnode (g, name, expr, val); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_ary_new2 (2); + rb_ary_push (rv, INT2NUM (r->i)); + rb_ary_push (rv, INT2NUM (r->b)); + guestfs_free_int_bool (r); + return rv; +} + +static VALUE ruby_guestfs_aug_get (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_get"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "aug_get"); + + char *r; + + r = guestfs_aug_get (g, path); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_str_new2 (r); + free (r); + return rv; +} + +static VALUE ruby_guestfs_aug_set (VALUE gv, VALUE pathv, VALUE valv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_set"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "aug_set"); + const char *val = StringValueCStr (valv); + if (!val) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "val", "aug_set"); + + int r; + + r = guestfs_aug_set (g, path, val); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_aug_insert (VALUE gv, VALUE pathv, VALUE labelv, VALUE beforev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_insert"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "aug_insert"); + const char *label = StringValueCStr (labelv); + if (!label) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "label", "aug_insert"); + int before = NUM2INT (beforev); + + int r; + + r = guestfs_aug_insert (g, path, label, before); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_aug_rm (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_rm"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "aug_rm"); + + int r; + + r = guestfs_aug_rm (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + +static VALUE ruby_guestfs_aug_mv (VALUE gv, VALUE srcv, VALUE destv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_mv"); + + const char *src = StringValueCStr (srcv); + if (!src) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "src", "aug_mv"); + const char *dest = StringValueCStr (destv); + if (!dest) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "dest", "aug_mv"); + + int r; + + r = guestfs_aug_mv (g, src, dest); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_aug_match (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_match"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "aug_match"); + + char **r; + + r = guestfs_aug_match (g, path); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_aug_save (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_save"); + + + int r; + + r = guestfs_aug_save (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_aug_load (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_load"); + + + int r; + + r = guestfs_aug_load (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_aug_ls (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "aug_ls"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "aug_ls"); + + char **r; + + r = guestfs_aug_ls (g, path); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_rm (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "rm"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "rm"); + + int r; + + r = guestfs_rm (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_rmdir (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "rmdir"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "rmdir"); + + int r; + + r = guestfs_rmdir (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_rm_rf (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "rm_rf"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "rm_rf"); + + int r; + + r = guestfs_rm_rf (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_mkdir (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "mkdir"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "mkdir"); + + int r; + + r = guestfs_mkdir (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_mkdir_p (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "mkdir_p"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "mkdir_p"); + + int r; + + r = guestfs_mkdir_p (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_chmod (VALUE gv, VALUE modev, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "chmod"); + + int mode = NUM2INT (modev); + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "chmod"); + + int r; + + r = guestfs_chmod (g, mode, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_chown (VALUE gv, VALUE ownerv, VALUE groupv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "chown"); + + int owner = NUM2INT (ownerv); + int group = NUM2INT (groupv); + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "chown"); + + int r; + + r = guestfs_chown (g, owner, group, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_exists (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "exists"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "exists"); + + int r; + + r = guestfs_exists (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + +static VALUE ruby_guestfs_is_file (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "is_file"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "is_file"); + + int r; + + r = guestfs_is_file (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + +static VALUE ruby_guestfs_is_dir (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "is_dir"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "is_dir"); + + int r; + + r = guestfs_is_dir (g, path); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + +static VALUE ruby_guestfs_pvcreate (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "pvcreate"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "pvcreate"); + + int r; + + r = guestfs_pvcreate (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_vgcreate (VALUE gv, VALUE volgroupv, VALUE physvolsv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "vgcreate"); + + const char *volgroup = StringValueCStr (volgroupv); + if (!volgroup) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "volgroup", "vgcreate"); + char **physvols; { + int i, len; + len = RARRAY_LEN (physvolsv); + physvols = malloc (sizeof (char *) * (len+1)); + for (i = 0; i < len; ++i) { + VALUE v = rb_ary_entry (physvolsv, i); + physvols[i] = StringValueCStr (v); + } + } + + int r; + + r = guestfs_vgcreate (g, volgroup, physvols); + free (physvols); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_lvcreate (VALUE gv, VALUE logvolv, VALUE volgroupv, VALUE mbytesv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "lvcreate"); + + const char *logvol = StringValueCStr (logvolv); + if (!logvol) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "logvol", "lvcreate"); + const char *volgroup = StringValueCStr (volgroupv); + if (!volgroup) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "volgroup", "lvcreate"); + int mbytes = NUM2INT (mbytesv); + + int r; + + r = guestfs_lvcreate (g, logvol, volgroup, mbytes); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_mkfs (VALUE gv, VALUE fstypev, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "mkfs"); + + const char *fstype = StringValueCStr (fstypev); + if (!fstype) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "fstype", "mkfs"); + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "mkfs"); + + int r; + + r = guestfs_mkfs (g, fstype, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_sfdisk (VALUE gv, VALUE devicev, VALUE cylsv, VALUE headsv, VALUE sectorsv, VALUE linesv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "sfdisk"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "sfdisk"); + int cyls = NUM2INT (cylsv); + int heads = NUM2INT (headsv); + int sectors = NUM2INT (sectorsv); + char **lines; { + int i, len; + len = RARRAY_LEN (linesv); + lines = malloc (sizeof (char *) * (len+1)); + for (i = 0; i < len; ++i) { + VALUE v = rb_ary_entry (linesv, i); + lines[i] = StringValueCStr (v); + } + } + + int r; + + r = guestfs_sfdisk (g, device, cyls, heads, sectors, lines); + free (lines); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_write_file (VALUE gv, VALUE pathv, VALUE contentv, VALUE sizev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "write_file"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "write_file"); + const char *content = StringValueCStr (contentv); + if (!content) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "content", "write_file"); + int size = NUM2INT (sizev); + + int r; + + r = guestfs_write_file (g, path, content, size); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_umount (VALUE gv, VALUE pathordevicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "umount"); + + const char *pathordevice = StringValueCStr (pathordevicev); + if (!pathordevice) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "pathordevice", "umount"); + + int r; + + r = guestfs_umount (g, pathordevice); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_mounts (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "mounts"); + + + char **r; + + r = guestfs_mounts (g); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_umount_all (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "umount_all"); + + + int r; + + r = guestfs_umount_all (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_lvm_remove_all (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "lvm_remove_all"); + + + int r; + + r = guestfs_lvm_remove_all (g); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_file (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "file"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "file"); + + char *r; + + r = guestfs_file (g, path); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_str_new2 (r); + free (r); + return rv; +} + +static VALUE ruby_guestfs_command (VALUE gv, VALUE argumentsv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "command"); + + char **arguments; { + int i, len; + len = RARRAY_LEN (argumentsv); + arguments = malloc (sizeof (char *) * (len+1)); + for (i = 0; i < len; ++i) { + VALUE v = rb_ary_entry (argumentsv, i); + arguments[i] = StringValueCStr (v); + } + } + + char *r; + + r = guestfs_command (g, arguments); + free (arguments); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_str_new2 (r); + free (r); + return rv; +} + +static VALUE ruby_guestfs_command_lines (VALUE gv, VALUE argumentsv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "command_lines"); + + char **arguments; { + int i, len; + len = RARRAY_LEN (argumentsv); + arguments = malloc (sizeof (char *) * (len+1)); + for (i = 0; i < len; ++i) { + VALUE v = rb_ary_entry (argumentsv, i); + arguments[i] = StringValueCStr (v); + } + } + + char **r; + + r = guestfs_command_lines (g, arguments); + free (arguments); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + int i, len = 0; + for (i = 0; r[i] != NULL; ++i) len++; + VALUE rv = rb_ary_new2 (len); + for (i = 0; r[i] != NULL; ++i) { + rb_ary_push (rv, rb_str_new2 (r[i])); + free (r[i]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_stat (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "stat"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "stat"); + + struct guestfs_stat *r; + + r = guestfs_stat (g, path); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_hash_new (); + rb_hash_aset (rv, rb_str_new2 ("dev"), ULL2NUM (r->dev)); + rb_hash_aset (rv, rb_str_new2 ("ino"), ULL2NUM (r->ino)); + rb_hash_aset (rv, rb_str_new2 ("mode"), ULL2NUM (r->mode)); + rb_hash_aset (rv, rb_str_new2 ("nlink"), ULL2NUM (r->nlink)); + rb_hash_aset (rv, rb_str_new2 ("uid"), ULL2NUM (r->uid)); + rb_hash_aset (rv, rb_str_new2 ("gid"), ULL2NUM (r->gid)); + rb_hash_aset (rv, rb_str_new2 ("rdev"), ULL2NUM (r->rdev)); + rb_hash_aset (rv, rb_str_new2 ("size"), ULL2NUM (r->size)); + rb_hash_aset (rv, rb_str_new2 ("blksize"), ULL2NUM (r->blksize)); + rb_hash_aset (rv, rb_str_new2 ("blocks"), ULL2NUM (r->blocks)); + rb_hash_aset (rv, rb_str_new2 ("atime"), ULL2NUM (r->atime)); + rb_hash_aset (rv, rb_str_new2 ("mtime"), ULL2NUM (r->mtime)); + rb_hash_aset (rv, rb_str_new2 ("ctime"), ULL2NUM (r->ctime)); + free (r); + return rv; +} + +static VALUE ruby_guestfs_lstat (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "lstat"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "lstat"); + + struct guestfs_stat *r; + + r = guestfs_lstat (g, path); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_hash_new (); + rb_hash_aset (rv, rb_str_new2 ("dev"), ULL2NUM (r->dev)); + rb_hash_aset (rv, rb_str_new2 ("ino"), ULL2NUM (r->ino)); + rb_hash_aset (rv, rb_str_new2 ("mode"), ULL2NUM (r->mode)); + rb_hash_aset (rv, rb_str_new2 ("nlink"), ULL2NUM (r->nlink)); + rb_hash_aset (rv, rb_str_new2 ("uid"), ULL2NUM (r->uid)); + rb_hash_aset (rv, rb_str_new2 ("gid"), ULL2NUM (r->gid)); + rb_hash_aset (rv, rb_str_new2 ("rdev"), ULL2NUM (r->rdev)); + rb_hash_aset (rv, rb_str_new2 ("size"), ULL2NUM (r->size)); + rb_hash_aset (rv, rb_str_new2 ("blksize"), ULL2NUM (r->blksize)); + rb_hash_aset (rv, rb_str_new2 ("blocks"), ULL2NUM (r->blocks)); + rb_hash_aset (rv, rb_str_new2 ("atime"), ULL2NUM (r->atime)); + rb_hash_aset (rv, rb_str_new2 ("mtime"), ULL2NUM (r->mtime)); + rb_hash_aset (rv, rb_str_new2 ("ctime"), ULL2NUM (r->ctime)); + free (r); + return rv; +} + +static VALUE ruby_guestfs_statvfs (VALUE gv, VALUE pathv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "statvfs"); + + const char *path = StringValueCStr (pathv); + if (!path) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "path", "statvfs"); + + struct guestfs_statvfs *r; + + r = guestfs_statvfs (g, path); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_hash_new (); + rb_hash_aset (rv, rb_str_new2 ("bsize"), ULL2NUM (r->bsize)); + rb_hash_aset (rv, rb_str_new2 ("frsize"), ULL2NUM (r->frsize)); + rb_hash_aset (rv, rb_str_new2 ("blocks"), ULL2NUM (r->blocks)); + rb_hash_aset (rv, rb_str_new2 ("bfree"), ULL2NUM (r->bfree)); + rb_hash_aset (rv, rb_str_new2 ("bavail"), ULL2NUM (r->bavail)); + rb_hash_aset (rv, rb_str_new2 ("files"), ULL2NUM (r->files)); + rb_hash_aset (rv, rb_str_new2 ("ffree"), ULL2NUM (r->ffree)); + rb_hash_aset (rv, rb_str_new2 ("favail"), ULL2NUM (r->favail)); + rb_hash_aset (rv, rb_str_new2 ("fsid"), ULL2NUM (r->fsid)); + rb_hash_aset (rv, rb_str_new2 ("flag"), ULL2NUM (r->flag)); + rb_hash_aset (rv, rb_str_new2 ("namemax"), ULL2NUM (r->namemax)); + free (r); + return rv; +} + +static VALUE ruby_guestfs_tune2fs_l (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "tune2fs_l"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "tune2fs_l"); + + char **r; + + r = guestfs_tune2fs_l (g, device); + if (r == NULL) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + VALUE rv = rb_hash_new (); + int i; + for (i = 0; r[i] != NULL; i+=2) { + rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1])); + free (r[i]); + free (r[i+1]); + } + free (r); + return rv; +} + +static VALUE ruby_guestfs_blockdev_setro (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "blockdev_setro"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "blockdev_setro"); + + int r; + + r = guestfs_blockdev_setro (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_blockdev_setrw (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "blockdev_setrw"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "blockdev_setrw"); + + int r; + + r = guestfs_blockdev_setrw (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_blockdev_getro (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "blockdev_getro"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "blockdev_getro"); + + int r; + + r = guestfs_blockdev_getro (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + +static VALUE ruby_guestfs_blockdev_getss (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "blockdev_getss"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "blockdev_getss"); + + int r; + + r = guestfs_blockdev_getss (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + +static VALUE ruby_guestfs_blockdev_getbsz (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "blockdev_getbsz"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "blockdev_getbsz"); + + int r; + + r = guestfs_blockdev_getbsz (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + +static VALUE ruby_guestfs_blockdev_setbsz (VALUE gv, VALUE devicev, VALUE blocksizev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "blockdev_setbsz"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "blockdev_setbsz"); + int blocksize = NUM2INT (blocksizev); + + int r; + + r = guestfs_blockdev_setbsz (g, device, blocksize); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_blockdev_getsz (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "blockdev_getsz"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "blockdev_getsz"); + + int64_t r; + + r = guestfs_blockdev_getsz (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return ULL2NUM (r); +} + +static VALUE ruby_guestfs_blockdev_getsize64 (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "blockdev_getsize64"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "blockdev_getsize64"); + + int64_t r; + + r = guestfs_blockdev_getsize64 (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return ULL2NUM (r); +} + +static VALUE ruby_guestfs_blockdev_flushbufs (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "blockdev_flushbufs"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "blockdev_flushbufs"); + + int r; + + r = guestfs_blockdev_flushbufs (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_blockdev_rereadpt (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "blockdev_rereadpt"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "blockdev_rereadpt"); + + int r; + + r = guestfs_blockdev_rereadpt (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +/* Initialize the module. */ +void Init__guestfs () +{ + m_guestfs = rb_define_module ("Guestfs"); + c_guestfs = rb_define_class_under (m_guestfs, "Guestfs", rb_cObject); + e_Error = rb_define_class_under (m_guestfs, "Error", rb_eStandardError); + + rb_define_module_function (m_guestfs, "create", ruby_guestfs_create, 0); + rb_define_method (c_guestfs, "close", ruby_guestfs_close, 0); + + rb_define_method (c_guestfs, "launch", + ruby_guestfs_launch, 0); + rb_define_method (c_guestfs, "wait_ready", + ruby_guestfs_wait_ready, 0); + rb_define_method (c_guestfs, "kill_subprocess", + ruby_guestfs_kill_subprocess, 0); + rb_define_method (c_guestfs, "add_drive", + ruby_guestfs_add_drive, 1); + rb_define_method (c_guestfs, "add_cdrom", + ruby_guestfs_add_cdrom, 1); + rb_define_method (c_guestfs, "config", + ruby_guestfs_config, 2); + rb_define_method (c_guestfs, "set_path", + ruby_guestfs_set_path, 1); + rb_define_method (c_guestfs, "get_path", + ruby_guestfs_get_path, 0); + rb_define_method (c_guestfs, "set_autosync", + ruby_guestfs_set_autosync, 1); + rb_define_method (c_guestfs, "get_autosync", + ruby_guestfs_get_autosync, 0); + rb_define_method (c_guestfs, "set_verbose", + ruby_guestfs_set_verbose, 1); + rb_define_method (c_guestfs, "get_verbose", + ruby_guestfs_get_verbose, 0); + rb_define_method (c_guestfs, "mount", + ruby_guestfs_mount, 2); + rb_define_method (c_guestfs, "sync", + ruby_guestfs_sync, 0); + rb_define_method (c_guestfs, "touch", + ruby_guestfs_touch, 1); + rb_define_method (c_guestfs, "cat", + ruby_guestfs_cat, 1); + rb_define_method (c_guestfs, "ll", + ruby_guestfs_ll, 1); + rb_define_method (c_guestfs, "ls", + ruby_guestfs_ls, 1); + rb_define_method (c_guestfs, "list_devices", + ruby_guestfs_list_devices, 0); + rb_define_method (c_guestfs, "list_partitions", + ruby_guestfs_list_partitions, 0); + rb_define_method (c_guestfs, "pvs", + ruby_guestfs_pvs, 0); + rb_define_method (c_guestfs, "vgs", + ruby_guestfs_vgs, 0); + rb_define_method (c_guestfs, "lvs", + ruby_guestfs_lvs, 0); + rb_define_method (c_guestfs, "pvs_full", + ruby_guestfs_pvs_full, 0); + rb_define_method (c_guestfs, "vgs_full", + ruby_guestfs_vgs_full, 0); + rb_define_method (c_guestfs, "lvs_full", + ruby_guestfs_lvs_full, 0); + rb_define_method (c_guestfs, "read_lines", + ruby_guestfs_read_lines, 1); + rb_define_method (c_guestfs, "aug_init", + ruby_guestfs_aug_init, 2); + rb_define_method (c_guestfs, "aug_close", + ruby_guestfs_aug_close, 0); + rb_define_method (c_guestfs, "aug_defvar", + ruby_guestfs_aug_defvar, 2); + rb_define_method (c_guestfs, "aug_defnode", + ruby_guestfs_aug_defnode, 3); + rb_define_method (c_guestfs, "aug_get", + ruby_guestfs_aug_get, 1); + rb_define_method (c_guestfs, "aug_set", + ruby_guestfs_aug_set, 2); + rb_define_method (c_guestfs, "aug_insert", + ruby_guestfs_aug_insert, 3); + rb_define_method (c_guestfs, "aug_rm", + ruby_guestfs_aug_rm, 1); + rb_define_method (c_guestfs, "aug_mv", + ruby_guestfs_aug_mv, 2); + rb_define_method (c_guestfs, "aug_match", + ruby_guestfs_aug_match, 1); + rb_define_method (c_guestfs, "aug_save", + ruby_guestfs_aug_save, 0); + rb_define_method (c_guestfs, "aug_load", + ruby_guestfs_aug_load, 0); + rb_define_method (c_guestfs, "aug_ls", + ruby_guestfs_aug_ls, 1); + rb_define_method (c_guestfs, "rm", + ruby_guestfs_rm, 1); + rb_define_method (c_guestfs, "rmdir", + ruby_guestfs_rmdir, 1); + rb_define_method (c_guestfs, "rm_rf", + ruby_guestfs_rm_rf, 1); + rb_define_method (c_guestfs, "mkdir", + ruby_guestfs_mkdir, 1); + rb_define_method (c_guestfs, "mkdir_p", + ruby_guestfs_mkdir_p, 1); + rb_define_method (c_guestfs, "chmod", + ruby_guestfs_chmod, 2); + rb_define_method (c_guestfs, "chown", + ruby_guestfs_chown, 3); + rb_define_method (c_guestfs, "exists", + ruby_guestfs_exists, 1); + rb_define_method (c_guestfs, "is_file", + ruby_guestfs_is_file, 1); + rb_define_method (c_guestfs, "is_dir", + ruby_guestfs_is_dir, 1); + rb_define_method (c_guestfs, "pvcreate", + ruby_guestfs_pvcreate, 1); + rb_define_method (c_guestfs, "vgcreate", + ruby_guestfs_vgcreate, 2); + rb_define_method (c_guestfs, "lvcreate", + ruby_guestfs_lvcreate, 3); + rb_define_method (c_guestfs, "mkfs", + ruby_guestfs_mkfs, 2); + rb_define_method (c_guestfs, "sfdisk", + ruby_guestfs_sfdisk, 5); + rb_define_method (c_guestfs, "write_file", + ruby_guestfs_write_file, 3); + rb_define_method (c_guestfs, "umount", + ruby_guestfs_umount, 1); + rb_define_method (c_guestfs, "mounts", + ruby_guestfs_mounts, 0); + rb_define_method (c_guestfs, "umount_all", + ruby_guestfs_umount_all, 0); + rb_define_method (c_guestfs, "lvm_remove_all", + ruby_guestfs_lvm_remove_all, 0); + rb_define_method (c_guestfs, "file", + ruby_guestfs_file, 1); + rb_define_method (c_guestfs, "command", + ruby_guestfs_command, 1); + rb_define_method (c_guestfs, "command_lines", + ruby_guestfs_command_lines, 1); + rb_define_method (c_guestfs, "stat", + ruby_guestfs_stat, 1); + rb_define_method (c_guestfs, "lstat", + ruby_guestfs_lstat, 1); + rb_define_method (c_guestfs, "statvfs", + ruby_guestfs_statvfs, 1); + rb_define_method (c_guestfs, "tune2fs_l", + ruby_guestfs_tune2fs_l, 1); + rb_define_method (c_guestfs, "blockdev_setro", + ruby_guestfs_blockdev_setro, 1); + rb_define_method (c_guestfs, "blockdev_setrw", + ruby_guestfs_blockdev_setrw, 1); + rb_define_method (c_guestfs, "blockdev_getro", + ruby_guestfs_blockdev_getro, 1); + rb_define_method (c_guestfs, "blockdev_getss", + ruby_guestfs_blockdev_getss, 1); + rb_define_method (c_guestfs, "blockdev_getbsz", + ruby_guestfs_blockdev_getbsz, 1); + rb_define_method (c_guestfs, "blockdev_setbsz", + ruby_guestfs_blockdev_setbsz, 2); + rb_define_method (c_guestfs, "blockdev_getsz", + ruby_guestfs_blockdev_getsz, 1); + rb_define_method (c_guestfs, "blockdev_getsize64", + ruby_guestfs_blockdev_getsize64, 1); + rb_define_method (c_guestfs, "blockdev_flushbufs", + ruby_guestfs_blockdev_flushbufs, 1); + rb_define_method (c_guestfs, "blockdev_rereadpt", + ruby_guestfs_blockdev_rereadpt, 1); +} diff --git a/ruby/ext/guestfs/extconf.rb b/ruby/ext/guestfs/extconf.rb new file mode 100644 index 0000000..67389fd --- /dev/null +++ b/ruby/ext/guestfs/extconf.rb @@ -0,0 +1,30 @@ +# libguestfs Ruby bindings -*- ruby -*- +# @configure_input@ +# 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. + +require 'mkmf' + +extension_name = '_guestfs' + +dir_config(extension_name) + +unless have_library("guestfs", "guestfs_create") + raise "libguestfs not found" +end + +create_header +create_makefile(extension_name) diff --git a/ruby/lib/guestfs.rb b/ruby/lib/guestfs.rb new file mode 100644 index 0000000..28c3785 --- /dev/null +++ b/ruby/lib/guestfs.rb @@ -0,0 +1,18 @@ +# libvirt Ruby bindings +# 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 + +require '_guestfs' diff --git a/ruby/run-ruby-tests b/ruby/run-ruby-tests new file mode 100755 index 0000000..9e8908c --- /dev/null +++ b/ruby/run-ruby-tests @@ -0,0 +1,22 @@ +#!/bin/sh - +# libguestfs Ruby 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. + +export LD_LIBRARY_PATH=../src/.libs +export LIBGUESTFS_PATH=$(cd .. && pwd) +rake test "$@" + diff --git a/ruby/tests/tc_010_load.rb b/ruby/tests/tc_010_load.rb new file mode 100644 index 0000000..6d882db --- /dev/null +++ b/ruby/tests/tc_010_load.rb @@ -0,0 +1,28 @@ +# libguestfs Ruby bindings -*- ruby -*- +# 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. + +require 'test/unit' +$:.unshift(File::join(File::dirname(__FILE__), "..", "lib")) +$:.unshift(File::join(File::dirname(__FILE__), "..", "ext", "guestfs")) +require 'guestfs' + +class TestLoad < Test::Unit::TestCase + def test_load + g = Guestfs::create() + assert_not_nil (g) + end +end diff --git a/ruby/tests/tc_050_lvcreate.rb b/ruby/tests/tc_050_lvcreate.rb new file mode 100644 index 0000000..ea87e39 --- /dev/null +++ b/ruby/tests/tc_050_lvcreate.rb @@ -0,0 +1,49 @@ +# libguestfs Ruby bindings -*- ruby -*- +# 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. + +require 'test/unit' +$:.unshift(File::join(File::dirname(__FILE__), "..", "lib")) +$:.unshift(File::join(File::dirname(__FILE__), "..", "ext", "guestfs")) +require 'guestfs' + +class TestLoad < Test::Unit::TestCase + def test_lvcreate + g = Guestfs::create() + + File.open("test.img", "w") { + |f| f.seek(500*1024*1024); f.write("\0") + } + + 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); + + lvs = g.lvs() + if lvs != ["/dev/VG/LV1", "/dev/VG/LV2"] + raise "incorrect lvs returned" + end + + g.sync() + + File.unlink("test.img") + end +end diff --git a/src/generator.ml b/src/generator.ml index 41fc0c8..c0a4740 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -4863,6 +4863,242 @@ and pod2text ~width name longdesc = | Unix.WSIGNALED i | Unix.WSTOPPED i -> failwithf "pod2text: process signalled or stopped by signal %d" i +(* Generate ruby bindings. *) +and generate_ruby_c () = + generate_header CStyle LGPLv2; + + pr "\ +#include +#include + +#include + +#include \"guestfs.h\" + +#include \"extconf.h\" + +static VALUE m_guestfs; /* guestfs module */ +static VALUE c_guestfs; /* guestfs_h handle */ +static VALUE e_Error; /* used for all errors */ + +static void ruby_guestfs_free (void *p) +{ + if (!p) return; + guestfs_close ((guestfs_h *) p); +} + +static VALUE ruby_guestfs_create (VALUE m) +{ + guestfs_h *g; + + g = guestfs_create (); + if (!g) + rb_raise (e_Error, \"failed to create guestfs handle\"); + + /* Don't print error messages to stderr by default. */ + guestfs_set_error_handler (g, NULL, NULL); + + /* Wrap it, and make sure the close function is called when the + * handle goes away. + */ + return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g); +} + +static VALUE ruby_guestfs_close (VALUE gv) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + + ruby_guestfs_free (g); + DATA_PTR (gv) = NULL; + + return Qnil; +} + +"; + + List.iter ( + fun (name, style, _, _, _, _, _) -> + pr "static VALUE ruby_guestfs_%s (VALUE gv" name; + List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style); + pr ")\n"; + pr "{\n"; + pr " guestfs_h *g;\n"; + pr " Data_Get_Struct (gv, guestfs_h, g);\n"; + pr " if (!g)\n"; + pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n" + name; + pr "\n"; + + List.iter ( + function + | String n -> + pr " const char *%s = StringValueCStr (%sv);\n" n n; + pr " if (!%s)\n" n; + pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n"; + pr " \"%s\", \"%s\");\n" n name + | OptString n -> + pr " const char *%s = StringValueCStr (%sv);\n" n n + | StringList n -> + pr " char **%s;" n; + pr " {\n"; + pr " int i, len;\n"; + pr " len = RARRAY_LEN (%sv);\n" n; + pr " %s = malloc (sizeof (char *) * (len+1));\n" n; + pr " for (i = 0; i < len; ++i) {\n"; + pr " VALUE v = rb_ary_entry (%sv, i);\n" n; + pr " %s[i] = StringValueCStr (v);\n" n; + pr " }\n"; + pr " }\n"; + | Bool n + | Int n -> + pr " int %s = NUM2INT (%sv);\n" n n + ) (snd style); + pr "\n"; + + let error_code = + match fst style with + | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1" + | RInt64 _ -> pr " int64_t r;\n"; "-1" + | RConstString _ -> pr " const char *r;\n"; "NULL" + | RString _ -> pr " char *r;\n"; "NULL" + | RStringList _ | RHashtable _ -> 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" + | RStat n -> pr " struct guestfs_stat *r;\n"; "NULL" + | RStatVFS n -> pr " struct guestfs_statvfs *r;\n"; "NULL" in + 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 " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n"; + pr "\n"; + + (match fst style with + | RErr -> + pr " return Qnil;\n" + | RInt _ | RBool _ -> + pr " return INT2NUM (r);\n" + | RInt64 _ -> + pr " return ULL2NUM (r);\n" + | RConstString _ -> + pr " return rb_str_new2 (r);\n"; + | RString _ -> + pr " VALUE rv = rb_str_new2 (r);\n"; + pr " free (r);\n"; + pr " return rv;\n"; + | RStringList _ -> + pr " int i, len = 0;\n"; + pr " for (i = 0; r[i] != NULL; ++i) len++;\n"; + pr " VALUE rv = rb_ary_new2 (len);\n"; + pr " for (i = 0; r[i] != NULL; ++i) {\n"; + pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n"; + pr " free (r[i]);\n"; + pr " }\n"; + pr " free (r);\n"; + pr " return rv;\n" + | RIntBool _ -> + pr " VALUE rv = rb_ary_new2 (2);\n"; + pr " rb_ary_push (rv, INT2NUM (r->i));\n"; + pr " rb_ary_push (rv, INT2NUM (r->b));\n"; + pr " guestfs_free_int_bool (r);\n"; + pr " return rv;\n" + | RPVList n -> + generate_ruby_lvm_code "pv" pv_cols + | RVGList n -> + generate_ruby_lvm_code "vg" vg_cols + | RLVList n -> + generate_ruby_lvm_code "lv" lv_cols + | RStat n -> + pr " VALUE rv = rb_hash_new ();\n"; + List.iter ( + function + | name, `Int -> + pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name + ) stat_cols; + pr " free (r);\n"; + pr " return rv;\n" + | RStatVFS n -> + pr " VALUE rv = rb_hash_new ();\n"; + List.iter ( + function + | name, `Int -> + pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name + ) statvfs_cols; + pr " free (r);\n"; + pr " return rv;\n" + | RHashtable _ -> + pr " VALUE rv = rb_hash_new ();\n"; + pr " int i;\n"; + pr " for (i = 0; r[i] != NULL; i+=2) {\n"; + pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n"; + pr " free (r[i]);\n"; + pr " free (r[i+1]);\n"; + pr " }\n"; + pr " free (r);\n"; + pr " return rv;\n" + ); + + pr "}\n"; + pr "\n" + ) all_functions; + + pr "\ +/* Initialize the module. */ +void Init__guestfs () +{ + m_guestfs = rb_define_module (\"Guestfs\"); + c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject); + e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError); + + rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0); + rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0); + +"; + (* Define the rest of the methods. *) + List.iter ( + fun (name, style, _, _, _, _, _) -> + pr " rb_define_method (c_guestfs, \"%s\",\n" name; + pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style)) + ) all_functions; + + pr "}\n" + +(* Ruby code to return an LVM struct list. *) +and generate_ruby_lvm_code typ cols = + pr " VALUE rv = rb_ary_new2 (r->len);\n"; + pr " int i;\n"; + pr " for (i = 0; i < r->len; ++i) {\n"; + pr " VALUE hv = rb_hash_new ();\n"; + List.iter ( + function + | name, `String -> + pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name + | name, `UUID -> + pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name + | name, `Bytes + | name, `Int -> + pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name + | name, `OptPercent -> + pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name + ) cols; + pr " rb_ary_push (rv, hv);\n"; + pr " }\n"; + pr " guestfs_free_lvm_%s_list (r);\n" typ; + pr " return rv;\n" + let output_to filename = let filename_new = filename ^ ".new" in chan := open_out filename_new; @@ -4962,3 +5198,7 @@ Run it from the top source directory using the command let close = output_to "python/guestfs.py" in generate_python_py (); close (); + + let close = output_to "ruby/ext/guestfs/_guestfs.c" in + generate_ruby_c (); + close (); -- 1.8.3.1