Merge branch 'master' of git://git.et.redhat.com/libguestfs
authorRichard Jones <rjones@centos5x32.home.annexia.org>
Tue, 7 Jul 2009 15:55:51 +0000 (16:55 +0100)
committerRichard Jones <rjones@centos5x32.home.annexia.org>
Tue, 7 Jul 2009 15:55:51 +0000 (16:55 +0100)
106 files changed:
.gitignore
ABOUT-NLS [deleted file]
TODO
appliance/Makefile.am
appliance/debian/debirf.conf.in
appliance/debian/modules/a0_motd [deleted symlink]
appliance/debian/modules/network [deleted symlink]
appliance/debian/modules/root-bashrc [deleted symlink]
appliance/debian/modules/serial-terminal [deleted symlink]
appliance/make.sh.in
appliance/update.sh.in
autogen.sh
capitests/Makefile.am
configure.ac
daemon/Makefile.am
daemon/augeas.c
daemon/blockdev.c
daemon/checksum.c
daemon/cmp.c
daemon/command.c
daemon/configure.ac
daemon/cpmv.c
daemon/daemon.h
daemon/debug.c
daemon/devsparts.c
daemon/df.c
daemon/dir.c
daemon/dmesg.c
daemon/dropcaches.c
daemon/du.c
daemon/ext2.c
daemon/file.c
daemon/find.c
daemon/fsck.c
daemon/glob.c
daemon/grub.c
daemon/guestfsd.c
daemon/headtail.c
daemon/hexdump.c
daemon/initrd.c
daemon/ls.c
daemon/lvm.c
daemon/mknod.c
daemon/mount.c
daemon/ntfs.c
daemon/pingdaemon.c
daemon/proto.c
daemon/readdir.c
daemon/scrub.c
daemon/sfdisk.c
daemon/sleep.c
daemon/stat.c
daemon/strings.c
daemon/swap.c
daemon/sync.c
daemon/tar.c
daemon/umask.c
daemon/upload.c
daemon/wc.c
daemon/zero.c
daemon/zerofree.c
examples/Makefile.am
fish/Makefile.am
fish/alloc.c
fish/destpaths.c
fish/echo.c
fish/edit.c
fish/fish.c
fish/glob.c
fish/lcd.c
fish/more.c
fish/time.c
guestfish.pod
guestfs.pod
haskell/Makefile.am
images/Makefile.am
inspector/Makefile.am
inspector/virt-inspector.pl
java/Makefile.am
java/com/redhat/et/libguestfs/IntBool.java [deleted file]
libguestfs.pc.in
m4/intltool.m4
m4/intmax.m4 [deleted file]
ocaml/Makefile.am
perl/Makefile.PL.in
perl/Makefile.am
python/Makefile.am
recipes/clone.example
recipes/export2tar.example
recipes/iso2tar.example
regressions/Makefile.am
regressions/rhbz503169c10.sh
regressions/rhbz503169c13.sh
regressions/test-bootbootboot.sh
regressions/test-cancellation-download-librarycancels.sh [new file with mode: 0755]
regressions/test-cancellation-upload-daemoncancels.sh [new file with mode: 0755]
regressions/test-qemudie-killsub.sh [new file with mode: 0755]
regressions/test-qemudie-launchfail.sh [moved from regressions/test-cleanup.sh with 79% similarity]
regressions/test-qemudie-midcommand.sh [new file with mode: 0755]
regressions/test-qemudie-synch.sh [new file with mode: 0755]
ruby/Makefile.am
ruby/Rakefile.in
src/Makefile.am
src/generator.ml
src/guestfs.c
src/guestfs.h

index 8bffe89..d68982d 100644 (file)
@@ -1,24 +1,6 @@
-.deps
-.libs
-*.bak
-*.la
-*.lo
-*.o
 *~
-*.cmi
-*.cmo
-*.cmx
-*.cma
-*.cmxa
 *.a
-*.so
-*.class
-*.jar
-*.hi
-bindtests.tmp
-ChangeLog
-Makefile.in
-Makefile
+ABOUT-NLS
 aclocal.m4
 appliance/debian/debirf.conf
 appliance/initramfs.*.img
@@ -27,24 +9,34 @@ appliance/kmod.whitelist
 appliance/libguestfs-supermin-helper
 appliance/make.sh
 appliance/packagelist
+appliance/stamp-debirf-modules
+appliance/supermin.incfiles
 appliance/supermin-make.sh
 appliance/supermin-split.sh
-appliance/supermin.incfiles
 appliance/update.sh
 appliance/vmlinuz.*
 autom4te.cache
+*.bak
+bindtests.tmp
 capitests/test-command
 capitests/test*.img
-capitests/test*.tmp
-capitests/tests.c
 capitests/tests
+capitests/tests.c
+capitests/test*.tmp
+ChangeLog
+*.class
+*.cma
+*.cmi
+*.cmo
+*.cmx
+*.cmxa
 compile
+config.guess
 config.h
 config.h.in
-config.guess
-config.sub
 config.log
 config.status
+config.sub
 configure
 daemon/actions.h
 daemon/guestfsd
@@ -53,6 +45,7 @@ daemon/missing
 daemon/names.c
 daemon/stubs.c
 depcomp
+.deps
 emptydisk
 examples/hello
 examples/to-xml
@@ -61,22 +54,23 @@ fish/completion.c
 fish/guestfish
 guestfish.1
 guestfish-actions.pod
+guestfs.3
 guestfs-actions.pod
 guestfs-structs.pod
-guestfs.3
-haskell/Bindtests.hs
 haskell/Bindtests
-haskell/Guestfs.hs
+haskell/Bindtests.hs
 haskell/Guestfs005Load
 haskell/Guestfs010Launch
 haskell/Guestfs050LVCreate
+haskell/Guestfs.hs
+*.hi
 html/guestfish.1.html
 html/guestfs.3.html
 html/recipes.html
 html/virt-inspector.1.html
-images/100kallzeroes
 images/100kallnewlines
 images/100kallspaces
+images/100kallzeroes
 images/100krandom
 images/10klines
 images/initrd
@@ -85,66 +79,75 @@ initramfs
 initramfs.timestamp
 inspector/virt-inspector.1
 install-sh
+*.jar
 java/api
 java/Bindtests.java
-java/com_redhat_et_libguestfs_GuestFS.h
-java/com_redhat_et_libguestfs_GuestFS.c
 java/com/redhat/et/libguestfs/Dirent.java
+java/com_redhat_et_libguestfs_GuestFS.c
+java/com_redhat_et_libguestfs_GuestFS.h
 java/com/redhat/et/libguestfs/GuestFS.java
+java/com/redhat/et/libguestfs/IntBool.java
 java/com/redhat/et/libguestfs/LV.java
 java/com/redhat/et/libguestfs/PV.java
 java/com/redhat/et/libguestfs/Stat.java
 java/com/redhat/et/libguestfs/StatVFS.java
 java/com/redhat/et/libguestfs/VG.java
 java/doc-stamp
-missing
+*.la
 libguestfs.pc
 libguestfs.spec
 libguestfs-*.tar.gz
+.libs
 libtool
+*.lo
 ltmain.sh
+m4/intmax.m4
 m4/libtool.m4
+m4/lt~obsolete.m4
 m4/ltoptions.m4
 m4/ltsugar.m4
 m4/ltversion.m4
-m4/lt~obsolete.m4
-ocaml/META
-ocaml/bindtests.ml
+Makefile
+Makefile.in
+missing
+*.o
 ocaml/bindtests
+ocaml/bindtests.ml
 ocaml/examples/lvs
-ocaml/guestfs.mli
-ocaml/guestfs.ml
 ocaml/guestfs_c_actions.c
+ocaml/guestfs.ml
+ocaml/guestfs.mli
+ocaml/META
 ocaml/t/guestfs_005_load
 ocaml/t/guestfs_010_launch
 ocaml/t/guestfs_050_lvcreate
 ocaml/t/guestfs_060_readdir
 perl/bindtests.pl
 perl/blib
-perl/Guestfs.c
 perl/Guestfs.bs
+perl/Guestfs.c
 perl/Guestfs.xs
 perl/lib/Sys/Guestfs.pm
 perl/Makefile-pl
 perl/Makefile.PL
 perl/pm_to_blib
+pod2htm?.tmp
 po/*.gmo
 po/Makevars.template
 po/POTFILES
 po/remove-potcdate.sed
 po/stamp-it
 po/stamp-po
-pod2htm?.tmp
 python/bindtests.py
-python/guestfs-py.c
 python/guestfs.py
+python/guestfs-py.c
 python/guestfs.pyc
-ruby/Rakefile
 ruby/bindtests.rb
-ruby/ext/guestfs/_guestfs.c
 ruby/ext/guestfs/extconf.h
+ruby/ext/guestfs/_guestfs.c
 ruby/ext/guestfs/mkmf.log
-src/.pod2text.data
+ruby/Rakefile
+*.so
 src/guestfs-actions.c
 src/guestfs-actions.h
 src/guestfs-bindtests.c
@@ -152,5 +155,6 @@ src/guestfs_protocol.c
 src/guestfs_protocol.h
 src/guestfs_protocol.x
 src/guestfs-structs.h
+src/.pod2text.data
 src/stamp-generator
 stamp-h1
diff --git a/ABOUT-NLS b/ABOUT-NLS
deleted file mode 100644 (file)
index 2f50c66..0000000
--- a/ABOUT-NLS
+++ /dev/null
@@ -1,768 +0,0 @@
-Notes on the Free Translation Project
-*************************************
-
-Free software is going international!  The Free Translation Project is
-a way to get maintainers of free software, translators, and users all
-together, so that will gradually become able to speak many languages.
-A few packages already provide translations for their messages.
-
-   If you found this `ABOUT-NLS' file inside a distribution, you may
-assume that the distributed package does use GNU `gettext' internally,
-itself available at your nearest GNU archive site.  But you do _not_
-need to install GNU `gettext' prior to configuring, installing or using
-this package with messages translated.
-
-   Installers will find here some useful hints.  These notes also
-explain how users should proceed for getting the programs to use the
-available translations.  They tell how people wanting to contribute and
-work at translations should contact the appropriate team.
-
-   When reporting bugs in the `intl/' directory or bugs which may be
-related to internationalization, you should tell about the version of
-`gettext' which is used.  The information can be found in the
-`intl/VERSION' file, in internationalized packages.
-
-Quick configuration advice
-==========================
-
-If you want to exploit the full power of internationalization, you
-should configure it using
-
-     ./configure --with-included-gettext
-
-to force usage of internationalizing routines provided within this
-package, despite the existence of internationalizing capabilities in the
-operating system where this package is being installed.  So far, only
-the `gettext' implementation in the GNU C library version 2 provides as
-many features (such as locale alias, message inheritance, automatic
-charset conversion or plural form handling) as the implementation here.
-It is also not possible to offer this additional functionality on top
-of a `catgets' implementation.  Future versions of GNU `gettext' will
-very likely convey even more functionality.  So it might be a good idea
-to change to GNU `gettext' as soon as possible.
-
-   So you need _not_ provide this option if you are using GNU libc 2 or
-you have installed a recent copy of the GNU gettext package with the
-included `libintl'.
-
-INSTALL Matters
-===============
-
-Some packages are "localizable" when properly installed; the programs
-they contain can be made to speak your own native language.  Most such
-packages use GNU `gettext'.  Other packages have their own ways to
-internationalization, predating GNU `gettext'.
-
-   By default, this package will be installed to allow translation of
-messages.  It will automatically detect whether the system already
-provides the GNU `gettext' functions.  If not, the GNU `gettext' own
-library will be used.  This library is wholly contained within this
-package, usually in the `intl/' subdirectory, so prior installation of
-the GNU `gettext' package is _not_ required.  Installers may use
-special options at configuration time for changing the default
-behaviour.  The commands:
-
-     ./configure --with-included-gettext
-     ./configure --disable-nls
-
-will respectively bypass any pre-existing `gettext' to use the
-internationalizing routines provided within this package, or else,
-_totally_ disable translation of messages.
-
-   When you already have GNU `gettext' installed on your system and run
-configure without an option for your new package, `configure' will
-probably detect the previously built and installed `libintl.a' file and
-will decide to use this.  This might be not what is desirable.  You
-should use the more recent version of the GNU `gettext' library.  I.e.
-if the file `intl/VERSION' shows that the library which comes with this
-package is more recent, you should use
-
-     ./configure --with-included-gettext
-
-to prevent auto-detection.
-
-   The configuration process will not test for the `catgets' function
-and therefore it will not be used.  The reason is that even an
-emulation of `gettext' on top of `catgets' could not provide all the
-extensions of the GNU `gettext' library.
-
-   Internationalized packages have usually many `po/LL.po' files, where
-LL gives an ISO 639 two-letter code identifying the language.  Unless
-translations have been forbidden at `configure' time by using the
-`--disable-nls' switch, all available translations are installed
-together with the package.  However, the environment variable `LINGUAS'
-may be set, prior to configuration, to limit the installed set.
-`LINGUAS' should then contain a space separated list of two-letter
-codes, stating which languages are allowed.
-
-Using This Package
-==================
-
-As a user, if your language has been installed for this package, you
-only have to set the `LANG' environment variable to the appropriate
-`LL_CC' combination.  Here `LL' is an ISO 639 two-letter language code,
-and `CC' is an ISO 3166 two-letter country code.  For example, let's
-suppose that you speak German and live in Germany.  At the shell
-prompt, merely execute `setenv LANG de_DE' (in `csh'),
-`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').
-This can be done from your `.login' or `.profile' file, once and for
-all.
-
-   You might think that the country code specification is redundant.
-But in fact, some languages have dialects in different countries.  For
-example, `de_AT' is used for Austria, and `pt_BR' for Brazil.  The
-country code serves to distinguish the dialects.
-
-   The locale naming convention of `LL_CC', with `LL' denoting the
-language and `CC' denoting the country, is the one use on systems based
-on GNU libc.  On other systems, some variations of this scheme are
-used, such as `LL' or `LL_CC.ENCODING'.  You can get the list of
-locales supported by your system for your country by running the command
-`locale -a | grep '^LL''.
-
-   Not all programs have translations for all languages.  By default, an
-English message is shown in place of a nonexistent translation.  If you
-understand other languages, you can set up a priority list of languages.
-This is done through a different environment variable, called
-`LANGUAGE'.  GNU `gettext' gives preference to `LANGUAGE' over `LANG'
-for the purpose of message handling, but you still need to have `LANG'
-set to the primary language; this is required by other parts of the
-system libraries.  For example, some Swedish users who would rather
-read translations in German than English for when Swedish is not
-available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.
-
-   Special advice for Norwegian users: The language code for Norwegian
-bokma*l changed from `no' to `nb' recently (in 2003).  During the
-transition period, while some message catalogs for this language are
-installed under `nb' and some older ones under `no', it's recommended
-for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and
-older translations are used.
-
-   In the `LANGUAGE' environment variable, but not in the `LANG'
-environment variable, `LL_CC' combinations can be abbreviated as `LL'
-to denote the language's main dialect.  For example, `de' is equivalent
-to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'
-(Portuguese as spoken in Portugal) in this context.
-
-Translating Teams
-=================
-
-For the Free Translation Project to be a success, we need interested
-people who like their own language and write it well, and who are also
-able to synergize with other translators speaking the same language.
-Each translation team has its own mailing list.  The up-to-date list of
-teams can be found at the Free Translation Project's homepage,
-`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams"
-area.
-
-   If you'd like to volunteer to _work_ at translating messages, you
-should become a member of the translating team for your own language.
-The subscribing address is _not_ the same as the list itself, it has
-`-request' appended.  For example, speakers of Swedish can send a
-message to `sv-request@li.org', having this message body:
-
-     subscribe
-
-   Keep in mind that team members are expected to participate
-_actively_ in translations, or at solving translational difficulties,
-rather than merely lurking around.  If your team does not exist yet and
-you want to start one, or if you are unsure about what to do or how to
-get started, please write to `translation@iro.umontreal.ca' to reach the
-coordinator for all translator teams.
-
-   The English team is special.  It works at improving and uniformizing
-the terminology in use.  Proven linguistic skill are praised more than
-programming skill, here.
-
-Available Packages
-==================
-
-Languages are not equally supported in all packages.  The following
-matrix shows the current state of internationalization, as of January
-2004.  The matrix shows, in regard of each package, for which languages
-PO files have been submitted to translation coordination, with a
-translation percentage of at least 50%.
-
-     Ready PO files       af am ar az be bg bs ca cs da de el en en_GB eo es
-                        +----------------------------------------------------+
-     a2ps               |             []             [] [] []                |
-     aegis              |                               ()                   |
-     ant-phone          |                               ()                   |
-     anubis             |                                                    |
-     ap-utils           |                                                    |
-     aspell             |             []                                     |
-     bash               |                      []       []             [] [] |
-     batchelor          |                                                    |
-     bfd                |                            []                   [] |
-     binutils           |                            []                   [] |
-     bison              |                            [] []                [] |
-     bluez-pin          | []                      []                   []    |
-     clisp              |                                                    |
-     clisp              |                               []    []          [] |
-     console-tools      |                         []    []                   |
-     coreutils          |                      []    [] []                [] |
-     cpio               |                            [] []                [] |
-     darkstat           |                []          ()                   [] |
-     diffutils          |                      [] [] [] [] []          [] [] |
-     e2fsprogs          |                         []    []                [] |
-     enscript           |                      []    [] []        []         |
-     error              |                      []    [] []        []      [] |
-     fetchmail          |                      [] () [] [] []             [] |
-     fileutils          |                            [] []                [] |
-     findutils          |             []       []    [] [] []          [] [] |
-     flex               |                      []    [] []                [] |
-     fslint             |                                                    |
-     gas                |                                                 [] |
-     gawk               |                      []    [] []                [] |
-     gbiff              |                               []                   |
-     gcal               |                      []                            |
-     gcc                |                            []                   [] |
-     gettext            |             []       []    [] []                [] |
-     gettext-examples   | []                   []       []                [] |
-     gettext-runtime    |             []       []    [] []                [] |
-     gettext-tools      |                      []       []                [] |
-     gimp-print         |                         [] [] []        []      [] |
-     gliv               |                                                    |
-     glunarclock        |                            [] []                   |
-     gnubiff            |                               []                   |
-     gnucash            |                         []    ()        []      [] |
-     gnucash-glossary   |                            [] ()                [] |
-     gnupg              |                      [] ()    [] []          [] [] |
-     gpe-aerial         |                         []                         |
-     gpe-beam           |                         []    []                   |
-     gpe-calendar       |                         []    []                   |
-     gpe-clock          |                         []    []                   |
-     gpe-conf           |                         []    []                   |
-     gpe-contacts       |                         []    []                   |
-     gpe-edit           |                         []                         |
-     gpe-go             |                         []                         |
-     gpe-login          |                         []    []                   |
-     gpe-ownerinfo      |                         []    []                   |
-     gpe-sketchbook     |                         []    []                   |
-     gpe-su             |                         []    []                   |
-     gpe-taskmanager    |                         []    []                   |
-     gpe-timesheet      |                         []                         |
-     gpe-today          |                         []    []                   |
-     gpe-todo           |                         []    []                   |
-     gphoto2            |                         [] [] []                [] |
-     gprof              |                            [] []                [] |
-     gpsdrive           |                               ()    ()          () |
-     gramadoir          |                               []                   |
-     grep               |             [] []    []       [] []             [] |
-     gretl              |                                                 [] |
-     gtick              | []                            ()                   |
-     hello              |                      []    [] [] []          [] [] |
-     id-utils           |                            [] []                   |
-     indent             |                      []       []             [] [] |
-     iso_3166           |          []    [] [] [] [] [] [] []          [] [] |
-     iso_3166_1         |                      [] [] [] [] []             [] |
-     iso_3166_2         |                                                    |
-     iso_3166_3         |                               []                   |
-     iso_4217           |                      []    [] []                [] |
-     iso_639            |                                                    |
-     jpilot             |                         [] []                   [] |
-     jtag               |                                                    |
-     jwhois             |                                                 [] |
-     kbd                |                         [] [] [] []             [] |
-     latrine            |                               ()                   |
-     ld                 |                            []                   [] |
-     libc               |                      [] [] [] [] []             [] |
-     libgpewidget       |                         []    []                   |
-     libiconv           |                      []    [] []             [] [] |
-     lifelines          |                            [] ()                   |
-     lilypond           |                               []                   |
-     lingoteach         |                                                    |
-     lingoteach_lessons |                               ()                () |
-     lynx               |                      [] [] [] []                   |
-     m4                 |                         [] [] [] []                |
-     mailutils          |                      []                         [] |
-     make               |                            [] []                [] |
-     man-db             |                      [] () [] []                () |
-     minicom            |                         []    []                [] |
-     mysecretdiary      |                            [] []                [] |
-     nano               |                      [] () [] []                [] |
-     nano_1_0           |                      [] () [] []                [] |
-     opcodes            |                                                 [] |
-     parted             |                      [] [] [] []                [] |
-     ptx                |                      []    [] []             [] [] |
-     python             |                                                    |
-     radius             |                                                 [] |
-     recode             |             []       []    [] [] []          [] [] |
-     rpm                |                         [] []                      |
-     screem             |                                                    |
-     scrollkeeper       |             []       [] [] [] []                [] |
-     sed                | []                   []    [] []             [] [] |
-     sh-utils           |                            [] []                [] |
-     shared-mime-info   |                                                    |
-     sharutils          |                      [] [] [] [] []             [] |
-     silky              |                               ()                   |
-     skencil            |                            [] ()                [] |
-     sketch             |                            [] ()                [] |
-     soundtracker       |                            [] []                [] |
-     sp                 |                               []                   |
-     tar                |                         [] [] []                [] |
-     texinfo            |                            [] []             []    |
-     textutils          |                      []    [] []                [] |
-     tin                |                               ()        ()         |
-     tp-robot           |                                                    |
-     tuxpaint           |                      [] [] [] [] []     []      [] |
-     unicode-han-tra... |                                                    |
-     unicode-transla... |                                                    |
-     util-linux         |                      [] [] [] []                [] |
-     vorbis-tools       |             []          [] []                   [] |
-     wastesedge         |                               ()                   |
-     wdiff              |                      []    [] []                [] |
-     wget               |                []    []    [] [] []             [] |
-     xchat              |                      []       [] []             [] |
-     xfree86_xkb_xml    |                         [] []                      |
-     xpad               |                                                 [] |
-                        +----------------------------------------------------+
-                          af am ar az be bg bs ca cs da de el en en_GB eo es
-                           4  0  0  1  9  4  1 40 41 60 78 17  1   5   13 68
-     
-                          et eu fa fi fr ga gl he hr hu id is it ja ko lg
-                        +-------------------------------------------------+
-     a2ps               | []       [] []                      ()    ()    |
-     aegis              |                                                 |
-     ant-phone          |             []                                  |
-     anubis             |             []                                  |
-     ap-utils           |             []                                  |
-     aspell             |             [] []                               |
-     bash               |             []             []                   |
-     batchelor          |             [] []                               |
-     bfd                |             []                                  |
-     binutils           |             []                         []       |
-     bison              | []          []                []    []          |
-     bluez-pin          |          [] [] []          [] []                |
-     clisp              |                                                 |
-     clisp              |             []                                  |
-     console-tools      |                                                 |
-     coreutils          | []       [] [] []                   [] []       |
-     cpio               |             []    []       []             []    |
-     darkstat           |             () []          [] []                |
-     diffutils          |          [] []    [] []    [] []       []       |
-     e2fsprogs          |                                                 |
-     enscript           |             []          []                      |
-     error              |          [] [] []          []                   |
-     fetchmail          |                                        []       |
-     fileutils          | []          [] []          []       [] []       |
-     findutils          | []       [] [] [] []    [] [] []    [] [] []    |
-     flex               |             [] []                         []    |
-     fslint             |             []                                  |
-     gas                |             []                                  |
-     gawk               |             []       []                []       |
-     gbiff              |             []                                  |
-     gcal               |             []                                  |
-     gcc                |             []                                  |
-     gettext            |             []                         [] []    |
-     gettext-examples   |             []                         []       |
-     gettext-runtime    |          [] []                []       [] []    |
-     gettext-tools      |             []                         [] []    |
-     gimp-print         |             []                         []       |
-     gliv               |             ()                                  |
-     glunarclock        |          []    [] []       []                   |
-     gnubiff            |             []                                  |
-     gnucash            |             ()                      []          |
-     gnucash-glossary   |                                     []          |
-     gnupg              | []       [] []    []          []    [] []       |
-     gpe-aerial         |             []                                  |
-     gpe-beam           |             []                                  |
-     gpe-calendar       |             []             [] []                |
-     gpe-clock          |             []                                  |
-     gpe-conf           |             []                                  |
-     gpe-contacts       |             []             []                   |
-     gpe-edit           |             []                []                |
-     gpe-go             |             []                                  |
-     gpe-login          |             []             []                   |
-     gpe-ownerinfo      |             []             [] []                |
-     gpe-sketchbook     |             []                                  |
-     gpe-su             |             []                                  |
-     gpe-taskmanager    |             []                                  |
-     gpe-timesheet      |             [] []             []                |
-     gpe-today          |             [] []                               |
-     gpe-todo           |             []                []                |
-     gphoto2            |             []             []          []       |
-     gprof              |             []                []                |
-     gpsdrive           |             ()                      () ()       |
-     gramadoir          |             [] []                               |
-     grep               | []       [] [] [] [] [] [] [] []    [] []       |
-     gretl              |             []                      []          |
-     gtick              |          [] [] []                               |
-     hello              | []    [] [] [] [] [] [] [] [] []    [] [] []    |
-     id-utils           |             []             [] []    []          |
-     indent             | []       [] [] [] []       [] []    [] []       |
-     iso_3166           |    []       [] []       [] [] []    []          |
-     iso_3166_1         |    []       [] []          [] []                |
-     iso_3166_2         |                                                 |
-     iso_3166_3         |                                                 |
-     iso_4217           | []          []    []       []       [] []       |
-     iso_639            |                                                 |
-     jpilot             |             []                         ()       |
-     jtag               |             []                                  |
-     jwhois             |             []             [] []    []          |
-     kbd                |             []                                  |
-     latrine            |             []                                  |
-     ld                 |             []                                  |
-     libc               |          [] []    []       []          [] []    |
-     libgpewidget       |             [] []          [] []                |
-     libiconv           | []       [] [] [] []    [] [] []    []          |
-     lifelines          |             ()                                  |
-     lilypond           |             []                                  |
-     lingoteach         |             []                []                |
-     lingoteach_lessons |                                                 |
-     lynx               | []                         []       [] []       |
-     m4                 |             []    []          []       []       |
-     mailutils          |                                                 |
-     make               |             []    [] [] []             [] []    |
-     man-db             |                                     () ()       |
-     minicom            |          [] []             []          []       |
-     mysecretdiary      |             []                []                |
-     nano               |             []    []          []    []          |
-     nano_1_0           |             []    []          []    []          |
-     opcodes            |             []                                  |
-     parted             |             []    []                   []       |
-     ptx                | []       [] [] [] []       [] []                |
-     python             |                                                 |
-     radius             |             []                                  |
-     recode             |             []    [] []    [] []    []          |
-     rpm                |             []                            []    |
-     screem             |                                                 |
-     scrollkeeper       |                            []                   |
-     sed                | []       [] [] [] []       [] []    [] []       |
-     sh-utils           | []       [] [] []          []       [] []       |
-     shared-mime-info   |          [] []             []                   |
-     sharutils          | []          []    []       []          []       |
-     silky              |          () []             ()       ()          |
-     skencil            |             []                                  |
-     sketch             |             []                                  |
-     soundtracker       |             []                      []          |
-     sp                 |             []                         ()       |
-     tar                | []       [] []    []    [] [] []    [] []       |
-     texinfo            |             []       [] []             []       |
-     textutils          |             [] [] []       []          [] []    |
-     tin                | []          ()                                  |
-     tp-robot           |             []                                  |
-     tuxpaint           |          [] []       []    [] [] [] [] [] []    |
-     unicode-han-tra... |                                                 |
-     unicode-transla... |             [] []                               |
-     util-linux         | []       [] []             []       () []       |
-     vorbis-tools       |             []                                  |
-     wastesedge         |             ()                                  |
-     wdiff              | []          [] [] []       [] []                |
-     wget               | []       [] []    []    [] []          []       |
-     xchat              | []       [] []                                  |
-     xfree86_xkb_xml    |             []             []                   |
-     xpad               |             [] []                               |
-                        +-------------------------------------------------+
-                          et eu fa fi fr ga gl he hr hu id is it ja ko lg
-                          22  2  1 26 106 28 24  8 10 41 33  1 26 33 12  0
-     
-                          lt lv mk mn ms mt nb nl nn no nso pl pt pt_BR ro ru
-                        +-----------------------------------------------------+
-     a2ps               |             []       []    ()     ()     []   [] [] |
-     aegis              |                      ()                       () () |
-     ant-phone          |                      []                       []    |
-     anubis             |             []    [] []           []          [] [] |
-     ap-utils           |                      []           ()          []    |
-     aspell             |                      []                             |
-     bash               |                                          []   [] [] |
-     batchelor          |                                               []    |
-     bfd                |                                               []    |
-     binutils           |                                                  [] |
-     bison              |             []       []                  []   [] [] |
-     bluez-pin          |                      []           []          []    |
-     clisp              |                                                     |
-     clisp              |                      []                             |
-     console-tools      |                                                  [] |
-     coreutils          |                                   []             [] |
-     cpio               |                      []           []     []   [] [] |
-     darkstat           |             []       []                  []   []    |
-     diffutils          |             []       []           []     []   [] [] |
-     e2fsprogs          |                                   []                |
-     enscript           |                      []                  []   [] [] |
-     error              |                      []                  []   []    |
-     fetchmail          |                      []           []     ()      [] |
-     fileutils          |                                   []          [] [] |
-     findutils          |                      []           []     []   [] [] |
-     flex               |                                   []     []   [] [] |
-     fslint             |                      []                       []    |
-     gas                |                                                     |
-     gawk               |                                   []     []   []    |
-     gbiff              |                      []                       []    |
-     gcal               |                                                     |
-     gcc                |                                                     |
-     gettext            |                                   []          [] [] |
-     gettext-examples   |                      []           []          []    |
-     gettext-runtime    |                      []           []          [] [] |
-     gettext-tools      |                                   []          []    |
-     gimp-print         |                      []                             |
-     gliv               |                      []                  []   []    |
-     glunarclock        |             []       []                       [] [] |
-     gnubiff            |                      []                             |
-     gnucash            |                      []              []  ()      [] |
-     gnucash-glossary   |                      []              []             |
-     gnupg              |                                               []    |
-     gpe-aerial         |                      []              []       [] [] |
-     gpe-beam           |                      []              []       [] [] |
-     gpe-calendar       |                      []              []       [] [] |
-     gpe-clock          |                      []              []       [] [] |
-     gpe-conf           |                      []              []       [] [] |
-     gpe-contacts       |                      []              []       [] [] |
-     gpe-edit           |                      []              []       [] [] |
-     gpe-go             |                      []                       [] [] |
-     gpe-login          |                      []              []       [] [] |
-     gpe-ownerinfo      |                      []              []       [] [] |
-     gpe-sketchbook     |                      []              []       [] [] |
-     gpe-su             |                      []              []       [] [] |
-     gpe-taskmanager    |                      []              []       [] [] |
-     gpe-timesheet      |                      []              []       [] [] |
-     gpe-today          |                      []              []       [] [] |
-     gpe-todo           |                      []              []       [] [] |
-     gphoto2            |                                               []    |
-     gprof              |                                          []   []    |
-     gpsdrive           |                      ()    ()                 []    |
-     gramadoir          |                      ()                       []    |
-     grep               |                                   [] []  []   [] [] |
-     gretl              |                                                     |
-     gtick              |                      []                       [] [] |
-     hello              |    []       []    [] [] [] []     []     []   [] [] |
-     id-utils           |                      []                  []   [] [] |
-     indent             |                      []                  []   [] [] |
-     iso_3166           |          []                [] []                    |
-     iso_3166_1         |                      []    []                       |
-     iso_3166_2         |                                                     |
-     iso_3166_3         |                      []                             |
-     iso_4217           |          []          [] [] []     [] []  []      [] |
-     iso_639            |          []                                         |
-     jpilot             |                      ()    ()                       |
-     jtag               |                                                     |
-     jwhois             |                      []           []     []   [] () |
-     kbd                |                      []           []          []    |
-     latrine            |                                               []    |
-     ld                 |                                                     |
-     libc               |                   []       []     []     []         |
-     libgpewidget       |                      []              []       []    |
-     libiconv           |                      []           []     []   [] [] |
-     lifelines          |                                                     |
-     lilypond           |                                                     |
-     lingoteach         |                                                     |
-     lingoteach_lessons |                                                     |
-     lynx               |                      []                  []      [] |
-     m4                 |                      []           []     []   [] [] |
-     mailutils          |                                   []          [] [] |
-     make               |                      []           []     []      [] |
-     man-db             |                                               []    |
-     minicom            |                                   []     []   [] [] |
-     mysecretdiary      |                      []                  []   []    |
-     nano               |             []       []           []          [] [] |
-     nano_1_0           |             []    []    []        []          [] [] |
-     opcodes            |                      []                       []    |
-     parted             |                         []        [] []  []         |
-     ptx                |                   [] []    []     [] []  []   [] [] |
-     python             |                                                     |
-     radius             |                                   []             [] |
-     recode             |                                   []     []   [] [] |
-     rpm                |                                   [] []          [] |
-     screem             |                                                     |
-     scrollkeeper       |                   [] []           []          [] [] |
-     sed                |                                   []     []   []    |
-     sh-utils           |                   []                             [] |
-     shared-mime-info   |                      [] []                          |
-     sharutils          |                      []                          [] |
-     silky              |                                                  () |
-     skencil            |                                      []  []         |
-     sketch             |                                      []  []         |
-     soundtracker       |                                                     |
-     sp                 |                                                     |
-     tar                |             []    []       []     []     []   []    |
-     texinfo            |                   []              []          [] [] |
-     textutils          |                   []                             [] |
-     tin                |                                                     |
-     tp-robot           |                      []                             |
-     tuxpaint           | []          []       [] []        [] []  []   []    |
-     unicode-han-tra... |                                                     |
-     unicode-transla... |                                                     |
-     util-linux         |                      []                  []      [] |
-     vorbis-tools       |                      []                       [] [] |
-     wastesedge         |                                                     |
-     wdiff              |             []                    []     []   [] [] |
-     wget               |                                   []          [] [] |
-     xchat              |    []                []                          [] |
-     xfree86_xkb_xml    |                      []                          [] |
-     xpad               |                      []                       []    |
-                        +-----------------------------------------------------+
-                          lt lv mk mn ms mt nb nl nn no nso pl pt pt_BR ro ru
-                           1  2  0  3 12  0 10 69  6  7  1  40 26  36   76 63
-     
-                          sk sl sr sv ta th tr uk ven vi wa xh zh_CN zh_TW zu
-                        +-----------------------------------------------------+
-     a2ps               |    []    []       [] []                             | 16
-     aegis              |                                                     |  0
-     ant-phone          |                                                     |  3
-     anubis             |                   [] []                             |  9
-     ap-utils           |                      ()                             |  3
-     aspell             |                                                     |  4
-     bash               |                                                     |  9
-     batchelor          |                                                     |  3
-     bfd                |          []       []                                |  6
-     binutils           |          []       []                  []            |  8
-     bison              |          []       []                                | 14
-     bluez-pin          | []       []                    []                   | 14
-     clisp              |                                                     |  0
-     clisp              |                                                     |  5
-     console-tools      |                                                     |  3
-     coreutils          |    []    []       []                        []      | 16
-     cpio               |          []                           []            | 14
-     darkstat           | []    [] []                           ()    ()      | 12
-     diffutils          |          []       []                        []      | 23
-     e2fsprogs          |          []       []                                |  6
-     enscript           |          []       []                                | 12
-     error              | []                []                        []      | 15
-     fetchmail          | []                []                                | 11
-     fileutils          |    []    []       []                  []    []      | 17
-     findutils          | [] [] [] []       []                  []            | 29
-     flex               |          []       []                                | 13
-     fslint             |                                                     |  3
-     gas                |                   []                                |  3
-     gawk               |          []       []                                | 12
-     gbiff              |                                                     |  4
-     gcal               |          []       []                                |  4
-     gcc                |                   []                                |  4
-     gettext            | [] []    []       []                        []      | 16
-     gettext-examples   | []    [] []       []                  []            | 14
-     gettext-runtime    | [] [] [] []       [] []               []    []      | 22
-     gettext-tools      | [] [] [] []       []                  []            | 14
-     gimp-print         | []       []                                         | 10
-     gliv               |                                                     |  3
-     glunarclock        |       [] []                    []                   | 13
-     gnubiff            |                                                     |  3
-     gnucash            | []                                          []      |  9
-     gnucash-glossary   | []       []                                 []      |  8
-     gnupg              | []       []       []                        []      | 17
-     gpe-aerial         |          []                                         |  7
-     gpe-beam           |          []                                         |  8
-     gpe-calendar       | []       []                    []           []      | 13
-     gpe-clock          | []    [] []                                         | 10
-     gpe-conf           | []       []                                         |  9
-     gpe-contacts       | []       []                                 []      | 11
-     gpe-edit           | []    [] []                    []           []      | 12
-     gpe-go             |                                                     |  5
-     gpe-login          | []    [] []                    []           []      | 13
-     gpe-ownerinfo      | []    [] []                                 []      | 13
-     gpe-sketchbook     | []       []                                         |  9
-     gpe-su             | []    [] []                                         | 10
-     gpe-taskmanager    | []    [] []                                         | 10
-     gpe-timesheet      | []    [] []                                 []      | 12
-     gpe-today          | []    [] []                    []           []      | 13
-     gpe-todo           | []       []                    []           []      | 12
-     gphoto2            | []       []                           []            | 11
-     gprof              |          []       []                                |  9
-     gpsdrive           | []       []                                         |  3
-     gramadoir          | []                                                  |  5
-     grep               |    [] []          [] []                             | 26
-     gretl              |                                                     |  3
-     gtick              |                                                     |  7
-     hello              | []    [] []       [] []                             | 34
-     id-utils           |          []       []                                | 12
-     indent             | []    [] []       []                                | 21
-     iso_3166           | [] [] [] []       []    []     []                   | 27
-     iso_3166_1         | [] []             []                                | 16
-     iso_3166_2         |                                                     |  0
-     iso_3166_3         |                                                     |  2
-     iso_4217           | [] []    []       [] []               []            | 24
-     iso_639            |                                                     |  1
-     jpilot             |          []       []        []        []    []      |  9
-     jtag               | []                                                  |  2
-     jwhois             |          ()       []                        []      | 11
-     kbd                |          []       []                                | 11
-     latrine            |                                                     |  2
-     ld                 |          []       []                                |  5
-     libc               | []       []       []                  []            | 20
-     libgpewidget       | []    [] []                    []                   | 13
-     libiconv           | [] [] [] []       [] []        []     []            | 27
-     lifelines          |          []                                         |  2
-     lilypond           |          []                                         |  3
-     lingoteach         |                                                     |  2
-     lingoteach_lessons |                                       ()            |  0
-     lynx               |          []       [] []                             | 14
-     m4                 |          []                           []            | 15
-     mailutils          |                                                     |  5
-     make               |          []       []                  []            | 16
-     man-db             |          []                                         |  5
-     minicom            |                                                     | 11
-     mysecretdiary      |          []       []                                | 10
-     nano               |       [] []       [] []                             | 17
-     nano_1_0           |          []       [] []                             | 17
-     opcodes            |          []       []                                |  6
-     parted             |          []       []                  []            | 15
-     ptx                |          []       []                                | 22
-     python             |                                                     |  0
-     radius             |                                                     |  4
-     recode             |    []    []       []                                | 20
-     rpm                |          []       []                                |  9
-     screem             |          []                           []            |  2
-     scrollkeeper       | []    [] []                                         | 15
-     sed                | [] [] [] []       [] []                             | 24
-     sh-utils           |    []             []                                | 14
-     shared-mime-info   |       [] []                                         |  7
-     sharutils          |       [] []       []                        []      | 17
-     silky              | ()                                                  |  3
-     skencil            |          []                                         |  6
-     sketch             |          []                                         |  6
-     soundtracker       | []       []                                         |  7
-     sp                 |                   []                                |  3
-     tar                | [] []    []       []                  []            | 24
-     texinfo            |          []       []                  []            | 14
-     textutils          |    []    []       []                        []      | 16
-     tin                |                                                     |  1
-     tp-robot           |                                                     |  2
-     tuxpaint           | []       []       []           []     []            | 29
-     unicode-han-tra... |                                                     |  0
-     unicode-transla... |                                                     |  2
-     util-linux         |          []       []                                | 15
-     vorbis-tools       |                                                     |  8
-     wastesedge         |                                                     |  0
-     wdiff              | []       []       []                                | 18
-     wget               | [] [] [] []       [] []               []    []      | 24
-     xchat              | [] [] [] []                           []            | 15
-     xfree86_xkb_xml    | []    []          [] []               []            | 11
-     xpad               |                                                     |  5
-                        +-----------------------------------------------------+
-       63 teams           sk sl sr sv ta th tr uk ven vi wa xh zh_CN zh_TW zu
-      131 domains         47 19 28 83  0  0 59 13  1   1 11  0  22    22    0  1373
-
-   Some counters in the preceding matrix are higher than the number of
-visible blocks let us expect.  This is because a few extra PO files are
-used for implementing regional variants of languages, or language
-dialects.
-
-   For a PO file in the matrix above to be effective, the package to
-which it applies should also have been internationalized and
-distributed as such by its maintainer.  There might be an observable
-lag between the mere existence a PO file and its wide availability in a
-distribution.
-
-   If January 2004 seems to be old, you may fetch a more recent copy of
-this `ABOUT-NLS' file on most GNU archive sites.  The most up-to-date
-matrix with full percentage details can be found at
-`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'.
-
-Using `gettext' in new packages
-===============================
-
-If you are writing a freely available program and want to
-internationalize it you are welcome to use GNU `gettext' in your
-package.  Of course you have to respect the GNU Library General Public
-License which covers the use of the GNU `gettext' library.  This means
-in particular that even non-free programs can use `libintl' as a shared
-library, whereas only free software can use `libintl' as a static
-library or use modified versions of `libintl'.
-
-   Once the sources are changed appropriately and the setup can handle
-the use of `gettext' the only thing missing are the translations.  The
-Free Translation Project is also available for packages which are not
-developed inside the GNU project.  Therefore the information given above
-applies also for every other Free Software Project.  Contact
-`translation@iro.umontreal.ca' to make the `.pot' files available to
-the translation teams.
-
diff --git a/TODO b/TODO
index a38a8dc..5b4c843 100644 (file)
--- a/TODO
+++ b/TODO
@@ -124,7 +124,6 @@ Extra commands / functionality:
     readlink
     utime / utimes / futimes / futimens / l..
     more mk*temp calls
-    readdir / readdir-and-stat
     some sort of alloc/fallocate/posix_fallocate call to create empty space
     realpath
     trunc[ate??]
@@ -179,3 +178,11 @@ Other initrd-* commands, such as:
 
 initrd-extract
 initrd-replace
+
+----------------------------------------------------------------------
+
+Control guestfish from a pipe.
+
+For shell scripts - they can start up a long-running guestfish process
+and intermittently send it commands.  Avoids the start-up overhead,
+but how do we reliably signal errors?
\ No newline at end of file
index 03b2a7b..7abee80 100644 (file)
@@ -21,7 +21,11 @@ EXTRA_DIST = \
        kmod.whitelist \
        kmod.whitelist.in \
        packagelist.in \
-       init
+       init \
+       debian/modules/install_kernel \
+       debian/modules/y0_install-guestfsd \
+       debian/modules/z99_final-cleanups \
+       debian/debirf.conf.in
 
 # Build the root filesystem (appliance).
 # Currently this is arch-dependent, so it seems like putting it in
@@ -92,6 +96,21 @@ $(SUPERMINIMG): supermin.incfiles supermin-make.sh
 
 endif
 
+# Extra symlinks needed by the Debian appliance.
+debirf_symlinks = \
+       a0_prep-root \
+       z0_remove-aptitude \
+       z0_remove-locales \
+       z1_clean-root
+noinst_DATA = $(debirf_symlinks:%=debian/modules/%)
+$(debirf_symlinks:%=debian/modules/%): stamp-debirf-modules
+stamp-debirf-modules:
+       mkdir -p debian/modules
+       for f in $(debirf_symlinks); do \
+         ln -sf /usr/share/debirf/modules/$$f debian/modules/$$f; \
+       done
+       touch $@
+
 #----------------------------------------------------------------------
 # Extra rules for testing the appliance.
 
index a3dc16f..7efe25b 100644 (file)
@@ -1,5 +1,5 @@
 DEBIRF_LABEL="debirf-libguestfs"
 DEBIRF_SUITE=@REPO@
 DEBIRF_MIRROR=@MIRROR@/${DEBIRF_DISTRO}
-DEBIRF_KERNEL_ARCH=486
-
+DEBIRF_KERNEL_ARCH=@DEBIAN_KERNEL_ARCH@
+DEBIRF_METHOD=stupid_simple
diff --git a/appliance/debian/modules/a0_motd b/appliance/debian/modules/a0_motd
deleted file mode 120000 (symlink)
index 8e3ad2f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/debirf/modules/a0_motd
\ No newline at end of file
diff --git a/appliance/debian/modules/network b/appliance/debian/modules/network
deleted file mode 120000 (symlink)
index 979418d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/debirf/modules/network
\ No newline at end of file
diff --git a/appliance/debian/modules/root-bashrc b/appliance/debian/modules/root-bashrc
deleted file mode 120000 (symlink)
index 651d030..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/debirf/modules/root-bashrc
\ No newline at end of file
diff --git a/appliance/debian/modules/serial-terminal b/appliance/debian/modules/serial-terminal
deleted file mode 120000 (symlink)
index a5376da..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/debirf/modules/serial-terminal
\ No newline at end of file
index cf772e0..a132ed8 100755 (executable)
@@ -21,6 +21,7 @@
 unset CDPATH
 
 set -e
+set -x
 
 if [ "@DIST@" = "REDHAT" ]; then
   cd @top_builddir@
@@ -65,8 +66,8 @@ if [ "@DIST@" = "REDHAT" ]; then
   # Don't need any keyboard maps.
   @FEBOOTSTRAP_RUN@ initramfs -- rm -rf /lib/kbd
 
-  # Remove anything in home directory.  Because this is potentially
-  # liable to monstrous fuck-ups, we don't put a slash before 'home'.
+  # Remove anything in home directory.  Because of the potential for disaster
+  # we don't put a slash before 'home'.
   (cd initramfs && echo home/*) |
     xargs @FEBOOTSTRAP_RUN@ initramfs -- rm -rf
 
@@ -141,5 +142,7 @@ __EOF__
 elif [ "@DIST@" = "DEBIAN" ]; then
   cd @top_builddir@/appliance
   debirf make -n debian
+  mkdir -p @top_builddir@/initramfs
+  touch @top_builddir@/initramfs/fakeroot.log
 fi
 
index 01e22b6..cdc441b 100755 (executable)
@@ -28,7 +28,7 @@ if [ "@DIST@" = "REDHAT" ]; then
   output=appliance/initramfs.@REPO@.@host_cpu@.img
 
   # Create the init script.
-  @FEBOOTSTRAP_INSTALL@ initramfs appliance/init /init 0755 root.root
+  @FEBOOTSTRAP_INSTALL@ initramfs appliance/@top_srcdir@/appliance/init /init 0755 root.root
 
   # Copy the daemon into the filesystem.
   @FEBOOTSTRAP_INSTALL@ initramfs daemon/guestfsd /sbin/guestfsd 0755 root.root
index a1d7e27..ba4612c 100755 (executable)
 
 set -e
 set -v
-export AUTOMAKE='automake --foreign'
+
 mkdir -p daemon/m4
-aclocal
-libtoolize
-autoreconf -i
-pushd daemon
 autoreconf -i
-popd
-./configure "$@"
+
+CONFIGUREDIR=.
+
+# Run configure in BUILDDIR if it's set
+if [ ! -z "$BUILDDIR" ]; then
+    mkdir -p $BUILDDIR
+    cd $BUILDDIR
+
+    CONFIGUREDIR=..
+fi
+
+# If no arguments were specified and configure has run before, use the previous
+# arguments
+if [ $# == 0 -a -x ./config.status ]; then
+    ./config.status --recheck
+else
+    $CONFIGUREDIR/configure "$@"
+fi
index b52d2ed..ab91755 100644 (file)
@@ -24,8 +24,7 @@ EXTRA_DIST = \
 check_PROGRAMS = tests test-command
 
 tests_SOURCES = tests.c
-tests_CFLAGS = \
-       -I$(top_builddir)/src -Wall
+tests_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src -Wall
 tests_LDADD = $(top_builddir)/src/libguestfs.la
 
 TESTS = tests
index 4a57fa3..c70d104 100644 (file)
@@ -16,7 +16,7 @@
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 AC_INIT([libguestfs],[1.0.55])
-AM_INIT_AUTOMAKE
+AM_INIT_AUTOMAKE([foreign])
 
 AC_CONFIG_MACRO_DIR([m4])
 
@@ -167,6 +167,18 @@ else
   test "x$DEBIRF" = "xno" &&
         AC_MSG_ERROR([debirf must be installed])
   DIST="DEBIAN"
+  case $host_cpu in
+      *86)
+          DEBIAN_KERNEL_ARCH=486
+          ;;
+      x86_64)
+          DEBIAN_KERNEL_ARCH=amd64
+          ;;
+      *)
+         DEBIAN_KERNEL_ARCH=$host_cpu
+         ;;
+   esac
+   AC_SUBST(DEBIAN_KERNEL_ARCH)
 fi
 AC_SUBST(DIST)
 
index 141dfad..846a95c 100644 (file)
@@ -67,7 +67,7 @@ guestfsd_SOURCES = \
        wc.c \
        zero.c \
        zerofree.c \
-       ../src/guestfs_protocol.h \
-       ../src/guestfs_protocol.c
+       $(top_builddir)/../src/guestfs_protocol.h \
+       $(top_builddir)/../src/guestfs_protocol.c
 
 guestfsd_CFLAGS = -Wall
index 9b45f97..f75a1d6 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
@@ -122,21 +122,21 @@ do_aug_defvar (char *name, char *expr)
 #endif
 }
 
-guestfs_aug_defnode_ret *
+guestfs_int_int_bool *
 do_aug_defnode (char *name, char *expr, char *val)
 {
 #ifdef HAVE_AUG_DEFNODE
-  static guestfs_aug_defnode_ret r;
+  static guestfs_int_int_bool r;
   int created;
 
   NEED_AUG (NULL);
 
-  r.nrnodes = aug_defnode (aug, name, expr, val, &created);
-  if (r.nrnodes == -1) {
+  r.i = aug_defnode (aug, name, expr, val, &created);
+  if (r.i == -1) {
     reply_with_error ("Augeas defnode failed");
     return NULL;
   }
-  r.created = created;
+  r.b = created;
   return &r;
 #else
   reply_with_error ("%s is not available", __func__);
index 1b0185a..35d14bf 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 3654b65..bb30b05 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 04feba6..f650083 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index b33f2db..3f21807 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 6ecbb8a..238532e 100644 (file)
@@ -16,7 +16,7 @@
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 AC_INIT([libguestfs-daemon],[1.0.0])
-AM_INIT_AUTOMAKE
+AM_INIT_AUTOMAKE([foreign])
 
 AC_CONFIG_MACRO_DIR([m4])
 
index b87d7a4..5448a97 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 5f22a4f..814d2b1 100644 (file)
@@ -67,9 +67,9 @@ extern int root_mounted;
 
 /*-- in stubs.c (auto-generated) --*/
 extern void dispatch_incoming_message (XDR *);
-extern guestfs_lvm_int_pv_list *parse_command_line_pvs (void);
-extern guestfs_lvm_int_vg_list *parse_command_line_vgs (void);
-extern guestfs_lvm_int_lv_list *parse_command_line_lvs (void);
+extern guestfs_int_lvm_pv_list *parse_command_line_pvs (void);
+extern guestfs_int_lvm_vg_list *parse_command_line_vgs (void);
+extern guestfs_int_lvm_lv_list *parse_command_line_lvs (void);
 
 /*-- in proto.c --*/
 extern void main_loop (int sock);
index d6e469b..68320a3 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 4c7a643..32d2fa8 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 0a7303c..73604b4 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 753323d..6eb86bb 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 2e58eb9..adc3426 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 82d95ee..a818323 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 6287a20..6f1adba 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index c5e1415..5a1d0fd 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 3f07ffc..3ef7441 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 7ceeafa..85994b6 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 77e7c66..f1a9dc5 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index f39832e..f15d5e5 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 85a5ab9..29fe294 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index e5f2cf0..87065b9 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
@@ -572,19 +572,23 @@ commandrv (char **stdoutput, char **stderror, char * const* const argv)
    * trailing \n characters from the error buffer (not from stdout).
    */
   if (stdoutput) {
-    *stdoutput = realloc (*stdoutput, so_size+1);
-    if (*stdoutput == NULL) {
+    void *q = realloc (*stdoutput, so_size+1);
+    if (q == NULL) {
       perror ("realloc");
-      *stdoutput = NULL;
-    } else
+      free (*stdoutput);
+    }
+    *stdoutput = q;
+    if (*stdoutput)
       (*stdoutput)[so_size] = '\0';
   }
   if (stderror) {
-    *stderror = realloc (*stderror, se_size+1);
-    if (*stderror == NULL) {
+    void *q = realloc (*stderror, se_size+1);
+    if (q == NULL) {
       perror ("realloc");
-      *stderror = NULL;
-    } else {
+      free (*stderror);
+    }
+    *stderror = q;
+    if (*stderror) {
       (*stderror)[se_size] = '\0';
       se_size--;
       while (se_size >= 0 && (*stderror)[se_size] == '\n')
index b522c55..6d24851 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index ae7df92..a582c57 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 2d6cbdd..7b32a08 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 61055b6..a440080 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 0fba447..01b6435 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
@@ -152,19 +152,19 @@ do_lvs (void)
  * the code.  That code is in stubs.c, and it is generated as usual
  * by generator.ml.
  */
-guestfs_lvm_int_pv_list *
+guestfs_int_lvm_pv_list *
 do_pvs_full (void)
 {
   return parse_command_line_pvs ();
 }
 
-guestfs_lvm_int_vg_list *
+guestfs_int_lvm_vg_list *
 do_vgs_full (void)
 {
   return parse_command_line_vgs ();
 }
 
-guestfs_lvm_int_lv_list *
+guestfs_int_lvm_lv_list *
 do_lvs_full (void)
 {
   return parse_command_line_lvs ();
index 5af791f..315ea7d 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index b0cb496..1820f8a 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 87881b1..26c8d50 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 5417a1d..0a69afa 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 3ca4316..acd6601 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
@@ -266,9 +266,14 @@ reply (xdrproc_t xdrp, char *ret)
   }
 
   if (xdrp) {
+    /* This can fail if the reply body is too large, for example
+     * if it exceeds the maximum message size.  In that case
+     * we want to return an error message instead. (RHBZ#509597).
+     */
     if (!(*xdrp) (&xdr, ret)) {
-      fprintf (stderr, "guestfsd: failed to encode reply body\n");
-      exit (1);
+      reply_with_perror ("guestfsd: failed to encode reply body\n");
+      xdr_destroy (&xdr);
+      return;
     }
   }
 
index cea6fdd..e3851db 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
@@ -68,6 +68,8 @@ do_readdir (char *path)
     if (!p || !v.name) {
       reply_with_perror ("allocate");
       free (ret->guestfs_int_dirent_list_val);
+      free (p);
+      free (v.name);
       free (ret);
       closedir (dir);
       return NULL;
index 9b6d49d..2f14bcb 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index f1726fc..f512e26 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 2cf3ff7..3b5d395 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 6b12f4c..da360ce 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index d78f9fd..2c52532 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 7dac96e..faed7f6 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 70962df..b353b6c 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 0320604..9540827 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index ad8573d..22d2cc9 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 0f737af..6c5f6dc 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 91e1942..370ffdd 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 9d793e1..9c803d8 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index ed7a3fc..8000bb3 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 13302d9..fb3d656 100644 (file)
@@ -3,11 +3,11 @@
 noinst_PROGRAMS = hello to-xml
 
 hello_SOURCES = hello.c
-hello_CFLAGS = -I$(top_builddir)/src -Wall
+hello_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src -Wall
 hello_LDADD = $(top_builddir)/src/libguestfs.la
 
 to_xml_SOURCES = to-xml.c
-to_xml_CFLAGS = -I$(top_builddir)/src -Wall
+to_xml_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src -Wall
 to_xml_LDADD = $(top_builddir)/src/libguestfs.la
 
 CLEANFILES = $(noinst_PROGRAMS)
index 03e872c..1439a5d 100644 (file)
@@ -32,6 +32,6 @@ guestfish_SOURCES = \
        time.c
 
 guestfish_CFLAGS = \
-       -I$(top_builddir)/src -Wall \
+       -I$(top_srcdir)/src -I$(top_builddir)/src -Wall \
        -DGUESTFS_DEFAULT_PATH='"$(libdir)/guestfs"'
 guestfish_LDADD = $(top_builddir)/src/libguestfs.la $(LIBREADLINE)
index cdce73c..a7d115a 100644 (file)
@@ -1,5 +1,5 @@
 /* guestfish - the filesystem interactive shell
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 90970de..a9d65a5 100644 (file)
  * devices and LVM names.
  */
 
-int complete_dest_paths = 0; /* SEE NOTE */
+int complete_dest_paths = 1;
 
-/* NOTE: This is currently disabled by default (with no way to
- * enable it).  That's because it's not particularly natural.
- *
- * Also there is a quite serious performance problem.  When listing
- * even moderately long directories, this takes many seconds.  The
- * reason is because it calls guestfs_is_dir on each directory
- * entry, thus lots of round trips to the server.  We could have
- * a "readdir and stat each entry" call to ease this.
- */
+struct word {
+  char *name;
+  int is_dir;
+};
+
+static void
+free_words (struct word *words, int nr_words)
+{
+  size_t i;
+
+  /* NB. 'words' array is NOT NULL-terminated. */
+  for (i = 0; i < nr_words; ++i)
+    free (words[i].name);
+  free (words);
+}
 
 char *
 complete_dest_paths_generator (const char *text, int state)
@@ -71,9 +77,8 @@ complete_dest_paths_generator (const char *text, int state)
 #ifdef HAVE_LIBREADLINE
 
   static size_t len, index;
-  static char **words = NULL;
+  static struct word *words = NULL;
   static size_t nr_words = 0;
-  char *word;
   guestfs_error_handler_cb old_error_cb;
   void *old_error_cb_data;
 
@@ -94,13 +99,7 @@ complete_dest_paths_generator (const char *text, int state)
     len = strlen (text);
     index = 0;
 
-    if (words) {
-      size_t i;
-      /* NB. 'words' array is NOT NULL-terminated. */
-      for (i = 0; i < nr_words; ++i)
-       free (words[i]);
-      free (words);
-    }
+    if (words) free_words (words, nr_words);
 
     words = NULL;
     nr_words = 0;
@@ -111,17 +110,24 @@ complete_dest_paths_generator (const char *text, int state)
 #define APPEND_STRS_AND_FREE                                           \
   do {                                                                 \
     if (strs) {                                                                \
+      size_t i;                                                                \
       size_t n = count_strings (strs);                                 \
-      if ( ! xalloc_oversized (nr_words + n, sizeof (char *))) {       \
-       char *w = realloc (words, sizeof (char *) * (nr_words + n));    \
+                                                                       \
+      if ( ! xalloc_oversized (nr_words + n, sizeof (struct word))) {  \
+       struct word *w;                                                 \
+       w = realloc (words, sizeof (struct word) * (nr_words + n));     \
+                                                                       \
        if (w == NULL) {                                                \
-         free (words);                                                 \
+         free_words (words, nr_words);                                 \
          words = NULL;                                                 \
          nr_words = 0;                                                 \
        } else {                                                        \
-         size_t i;                                                     \
-         for (i = 0; i < n; ++i)                                       \
-           words[nr_words++] = strs[i];                                \
+         words = w;                                                    \
+         for (i = 0; i < n; ++i) {                                     \
+           words[nr_words].name = strs[i];                             \
+           words[nr_words].is_dir = 0;                                 \
+           nr_words++;                                                 \
+         }                                                             \
        }                                                               \
        free (strs);                                                    \
       }                                                                        \
@@ -146,30 +152,51 @@ complete_dest_paths_generator (const char *text, int state)
        * in that directory, otherwise list everything in /
        */
       char *p, *dir;
+      struct guestfs_dirent_list *dirents;
 
       p = strrchr (text, '/');
       dir = p && p > text ? strndup (text, p - text) : strdup ("/");
       if (dir) {
-       strs = guestfs_ls (g, dir);
+       dirents = guestfs_readdir (g, dir);
 
-       /* Prepend directory to names. */
-       if (strs) {
+       /* Prepend directory to names before adding them to the list
+        * of words.
+        */
+       if (dirents) {
          size_t i;
-         for (i = 0; strs[i]; ++i) {
+
+         for (i = 0; i < dirents->len; ++i) {
            int err;
-           if (strcmp (dir, "/") == 0)
-             err = asprintf (&p, "/%s", strs[i]);
-           else
-             err = asprintf (&p, "%s/%s", dir, strs[i]);
-           if (0 <= err) {
-             free (strs[i]);
-             strs[i] = p;
+
+           if (strcmp (dirents->val[i].name, ".") != 0 &&
+               strcmp (dirents->val[i].name, "..") != 0) {
+             if (strcmp (dir, "/") == 0)
+               err = asprintf (&p, "/%s", dirents->val[i].name);
+             else
+               err = asprintf (&p, "%s/%s", dir, dirents->val[i].name);
+             if (err >= 0) {
+               if (!xalloc_oversized (nr_words+1, sizeof (struct word))) {
+                 struct word *w;
+
+                 w = realloc (words, sizeof (struct word) * (nr_words+1));
+                 if (w == NULL) {
+                   free_words (words, nr_words);
+                   words = NULL;
+                   nr_words = 0;
+                 }
+                 else {
+                   words = w;
+                   words[nr_words].name = p;
+                   words[nr_words].is_dir = dirents->val[i].ftyp == 'd';
+                   nr_words++;
+                 }
+               }
+             }
            }
          }
-       }
 
-       free (dir);
-       APPEND_STRS_AND_FREE;
+         guestfs_free_dirent_list (dirents);
+       }
       }
     }
 
@@ -185,18 +212,16 @@ complete_dest_paths_generator (const char *text, int state)
 
   /* Complete the string. */
   while (index < nr_words) {
-    word = words[index];
+    struct word *word;
+
+    word = &words[index];
     index++;
-    if (strncasecmp (word, text, len) == 0) {
-      /* Is it a directory? */
-      if (strncmp (word, "/dev/", 5) != 0) {
-       SAVE_ERROR_CB
-       if (guestfs_is_dir (g, word) > 0)
-         rl_completion_append_character = '/';
-       RESTORE_ERROR_CB
-      }
 
-      return strdup (word);
+    if (strncasecmp (word->name, text, len) == 0) {
+      if (word->is_dir)
+       rl_completion_append_character = '/';
+
+      return strdup (word->name);
     }
   }
 
index b4b5cf1..33992d4 100644 (file)
@@ -1,5 +1,5 @@
 /* guestfish - the filesystem interactive shell
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index c72ad1d..3e6973e 100644 (file)
@@ -1,5 +1,5 @@
 /* guestfish - the filesystem interactive shell
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 59348c3..25483a1 100644 (file)
@@ -1,5 +1,5 @@
 /* guestfish - the filesystem interactive shell
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
@@ -732,8 +732,12 @@ issue_command (const char *cmd, char *argv[], const char *pipecmd)
   else
     r = run_action (cmd, argc, argv);
 
+  /* Always flush stdout after every command, so that messages, results
+   * etc appear immediately.
+   */
+  fflush (stdout);
+
   if (pipecmd) {
-    fflush (stdout);
     close (1);
     dup2 (stdout_saved_fd, 1);
     close (stdout_saved_fd);
index a8ac58a..581bc28 100644 (file)
@@ -1,5 +1,5 @@
 /* guestfish - the filesystem interactive shell
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 359d178..e631f21 100644 (file)
@@ -1,5 +1,5 @@
 /* guestfish - the filesystem interactive shell
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 8bc9d95..9abb51b 100644 (file)
@@ -1,5 +1,5 @@
 /* guestfish - the filesystem interactive shell
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index d2a2066..aae9afe 100644 (file)
@@ -1,5 +1,5 @@
 /* guestfish - the filesystem interactive shell
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
index 0c3fda6..4341e2a 100644 (file)
@@ -49,13 +49,13 @@ Remove C</boot/grub/menu.lst> (in reality not such a great idea):
 =head2 As an interactive shell
 
  $ guestfish
+
  Welcome to guestfish, the libguestfs filesystem interactive shell for
  editing virtual machine filesystems.
+
  Type: 'help' for help with commands
        'quit' to quit the shell
+
  ><fs> help
 
 =head2 As a script interpreter
index a41fd27..c7310a6 100644 (file)
@@ -7,7 +7,7 @@ guestfs - Library for accessing and modifying virtual machine images
 =head1 SYNOPSIS
 
  #include <guestfs.h>
+
  guestfs_h *handle = guestfs_create ();
  guestfs_add_drive (handle, "guest.img");
  guestfs_launch (handle);
@@ -49,28 +49,28 @@ If you are using the high-level API, then you should call the
 functions in the following order:
 
  guestfs_h *handle = guestfs_create ();
+
  guestfs_add_drive (handle, "guest.img");
  /* call guestfs_add_drive additional times if the guest has
   * multiple disks
   */
+
  guestfs_launch (handle);
  guestfs_wait_ready (handle);
 
  /* now you can examine what partitions, LVs etc are available
   * you have to mount / at least
-  */ 
+  */
  guestfs_mount (handle, "/dev/sda1", "/");
 
  /* now you can perform actions on the guest disk image */
  guestfs_touch (handle, "/hello");
+
  /* you only need to call guestfs_sync if you have made
   * changes to the guest image
   */
  guestfs_sync (handle);
+
  guestfs_close (handle);
 
 C<guestfs_wait_ready> and all of the actions including C<guestfs_sync>
@@ -168,7 +168,7 @@ If you set C<cb> to C<NULL> then I<no> handler is called.
 
 Returns the current error handler callback.
 
-=head2 guestfs_set_out_of_memory_handler 
+=head2 guestfs_set_out_of_memory_handler
 
  typedef void (*guestfs_abort_cb) (void);
  int guestfs_set_out_of_memory_handler (guestfs_h *handle,
index 3cb721f..dcaf18a 100644 (file)
@@ -30,7 +30,7 @@ TESTS = run-bindtests Guestfs005Load Guestfs010Launch Guestfs050LVCreate
 
 check_DATA = Bindtests
 
-GHCFLAGS = -I$(abs_top_builddir)/src -L$(abs_top_builddir)/src/.libs
+GHCFLAGS = -I$(top_builddir)/src -L$(top_builddir)/src/.libs
 
 Bindtests: Bindtests.hs Guestfs.hs
        $(GHC)  $(GHCFLAGS) -main-is $(shell basename $@) --make -o $@ $< -lguestfs
@@ -44,4 +44,4 @@ Guestfs010Launch: Guestfs010Launch.hs Guestfs.hs
 Guestfs050LVCreate: Guestfs050LVCreate.hs Guestfs.hs
        $(GHC)  $(GHCFLAGS) -main-is $(shell basename $@) --make -o $@ $< -lguestfs
 
-endif
\ No newline at end of file
+endif
index 8855382..9353e17 100644 (file)
@@ -28,9 +28,23 @@ CLEANFILES = \
        100kallzeroes 100kallnewlines 100kallspaces 100krandom 10klines \
        initrd
 
-squash_files = helloworld.tar helloworld.tar.gz empty known-1 known-2 known-3 \
-       100kallzeroes 100kallnewlines 100kallspaces 100krandom 10klines \
-       initrd
+squash_files_src = \
+    $(srcdir)/helloworld.tar \
+    $(srcdir)/helloworld.tar.gz \
+    $(srcdir)/empty \
+    $(srcdir)/known-1 \
+    $(srcdir)/known-2 \
+    $(srcdir)/known-3
+
+squash_files_build = \
+    $(builddir)/100kallzeroes \
+    $(builddir)/100kallnewlines \
+    $(builddir)/100kallspaces \
+    $(builddir)/100krandom \
+    $(builddir)/10klines \
+    $(builddir)/initrd
+
+squash_files = $(squash_files_src) $(squash_files_build)
 
 test.sqsh: $(squash_files)
        rm -f $@
index b43870d..a1df2ab 100644 (file)
@@ -23,7 +23,7 @@ if HAVE_INSPECTOR
 
 man_MANS = virt-inspector.1
 
-noinst_DATA = ../html/virt-inspector.1.html
+noinst_DATA = @top_builddir@/html/virt-inspector.1.html
 
 virt-inspector.1: virt-inspector.pl
        $(POD2MAN) \
@@ -32,8 +32,9 @@ virt-inspector.1: virt-inspector.pl
          --release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \
          $< > $@
 
-../html/virt-inspector.1.html: virt-inspector.pl
-       cd .. && pod2html \
+@top_builddir@/html/virt-inspector.1.html: virt-inspector.pl
+       mkdir -p @top_builddir@/html
+       cd @top_builddir@ && pod2html \
          --css 'pod.css' \
          --title 'virt-inspector, display OS version, kernel, drivers, mount points, applications, etc. in a virtual machine' \
          --htmldir html \
index 66b1553..3557a38 100755 (executable)
@@ -968,7 +968,7 @@ elsif ($output eq "perl") {
 elsif ($output eq "yaml") {
     die "virt-inspector: no YAML support\n"
        unless exists $INC{"YAML/Any.pm"};
-    
+
     print Dump(\%oses);
 }
 
index ea90a48..b682747 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-CPTH = com/redhat/et/libguestfs
+java_prefix = com/redhat/et/libguestfs
 
 java_sources = \
-       $(CPTH)/LibGuestFSException.java \
-       $(CPTH)/IntBool.java \
-       $(CPTH)/PV.java \
-       $(CPTH)/VG.java \
-       $(CPTH)/LV.java \
-       $(CPTH)/Stat.java \
-       $(CPTH)/StatVFS.java \
-       $(CPTH)/Dirent.java \
-       $(CPTH)/GuestFS.java
+       $(java_prefix)/LibGuestFSException.java \
+       $(java_prefix)/IntBool.java \
+       $(java_prefix)/PV.java \
+       $(java_prefix)/VG.java \
+       $(java_prefix)/LV.java \
+       $(java_prefix)/Stat.java \
+       $(java_prefix)/StatVFS.java \
+       $(java_prefix)/Dirent.java \
+       $(java_prefix)/GuestFS.java
 
 java_tests = \
        Bindtests.java \
@@ -50,7 +50,7 @@ libguestfs_jardir = $(JAR_INSTALL_DIR)
 libguestfs_jar_DATA = libguestfs-${VERSION}.jar
 libguestfs_jar_class_files = $(java_sources:.java=.class)
 $(libguestfs_jar_class_files): %.class: %.java
-       $(JAVAC) $(JAVAC_FLAGS) -classpath $(CPTH) $(java_sources)
+       $(JAVAC) $(JAVAC_FLAGS) -d @builddir@ -classpath @srcdir@:@builddir@ -sourcepath @srcdir@:@builddir@ $<
 
 libguestfs-${VERSION}.jar: $(libguestfs_jar_class_files)
        $(JAR) cf $@ $^
@@ -64,12 +64,12 @@ libguestfs_jni_la_SOURCES = \
 
 libguestfs_jni_la_LIBADD = $(top_builddir)/src/libguestfs.la
 libguestfs_jni_la_LDFLAGS = -version-info $(JNI_VERSION_INFO)
-libguestfs_jni_la_CFLAGS = -Wall -I$(top_builddir)/src $(JNI_CFLAGS)
+libguestfs_jni_la_CFLAGS = -Wall -I$(top_srcdir)/src -I$(top_builddir)/src $(JNI_CFLAGS)
 
 BUILT_SOURCES = com_redhat_et_libguestfs_GuestFS.h
 
-com_redhat_et_libguestfs_GuestFS.h: $(CPTH)/GuestFS.class
-       $(JAVAH) -classpath .:$(CPTH) com.redhat.et.libguestfs.GuestFS
+com_redhat_et_libguestfs_GuestFS.h: $(java_prefix)/GuestFS.class
+       $(JAVAH) -classpath @srcdir@:@builddir@ com.redhat.et.libguestfs.GuestFS
 
 # Documentation.
 
diff --git a/java/com/redhat/et/libguestfs/IntBool.java b/java/com/redhat/et/libguestfs/IntBool.java
deleted file mode 100644 (file)
index 23ea68f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* libguestfs Java 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
- */
-
-package com.redhat.et.libguestfs;
-
-/**
- * A pair (int, boolean)
- *
- * @author rjones
- * @see Exception
- */
-public class IntBool {
-    public int i;
-    public boolean b;
-}
index bcbc241..679ed7e 100644 (file)
@@ -7,5 +7,5 @@ Name: libguestfs
 Version: @VERSION@
 Description: libguestfs library for accessing and modifying VM images
 Requires:
-Cflags: 
+Cflags:
 Libs: -lguestfs @LIBS@
index 122d773..ba4c0b1 100644 (file)
@@ -55,23 +55,23 @@ if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT";
     AC_MSG_ERROR([The intltool scripts were not found. Please install intltool.])
 fi
 
-  INTLTOOL_DESKTOP_RULE='%.desktop:   %.desktop.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-     INTLTOOL_KEYS_RULE='%.keys:      %.keys.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-     INTLTOOL_PROP_RULE='%.prop:      %.prop.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+  INTLTOOL_DESKTOP_RULE='%.desktop:   %.desktop.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+     INTLTOOL_KEYS_RULE='%.keys:      %.keys.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+     INTLTOOL_PROP_RULE='%.prop:      %.prop.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
       INTLTOOL_OAF_RULE='%.oaf:       %.oaf.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -p $(top_srcdir)/po $< [$]@'
-     INTLTOOL_PONG_RULE='%.pong:      %.pong.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-   INTLTOOL_SERVER_RULE='%.server:    %.server.in    $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-    INTLTOOL_SHEET_RULE='%.sheet:     %.sheet.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-       INTLTOOL_UI_RULE='%.ui:        %.ui.in        $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-      INTLTOOL_XML_RULE='%.xml:       %.xml.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-      INTLTOOL_XML_NOMERGE_RULE='%.xml:       %.xml.in       $(INTLTOOL_MERGE) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< [$]@' 
-      INTLTOOL_XAM_RULE='%.xam:       %.xml.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-      INTLTOOL_KBD_RULE='%.kbd:       %.kbd.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-    INTLTOOL_CAVES_RULE='%.caves:     %.caves.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-  INTLTOOL_SCHEMAS_RULE='%.schemas:   %.schemas.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
-    INTLTOOL_THEME_RULE='%.theme:     %.theme.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+     INTLTOOL_PONG_RULE='%.pong:      %.pong.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+   INTLTOOL_SERVER_RULE='%.server:    %.server.in    $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+    INTLTOOL_SHEET_RULE='%.sheet:     %.sheet.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+       INTLTOOL_UI_RULE='%.ui:        %.ui.in        $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+      INTLTOOL_XML_RULE='%.xml:       %.xml.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+      INTLTOOL_XML_NOMERGE_RULE='%.xml:       %.xml.in       $(INTLTOOL_MERGE) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< [$]@'
+      INTLTOOL_XAM_RULE='%.xam:       %.xml.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+      INTLTOOL_KBD_RULE='%.kbd:       %.kbd.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+    INTLTOOL_CAVES_RULE='%.caves:     %.caves.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+  INTLTOOL_SCHEMAS_RULE='%.schemas:   %.schemas.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+    INTLTOOL_THEME_RULE='%.theme:     %.theme.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
     INTLTOOL_SERVICE_RULE='%.service: %.service.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
    INTLTOOL_POLICY_RULE='%.policy:    %.policy.in    $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
 
diff --git a/m4/intmax.m4 b/m4/intmax.m4
deleted file mode 100644 (file)
index dfb08cc..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# intmax.m4 serial 1 (gettext-0.12)
-dnl Copyright (C) 2002-2003 Free Software Foundation, Inc.
-dnl This file is free software, distributed under the terms of the GNU
-dnl General Public License.  As a special exception to the GNU General
-dnl Public License, this file may be distributed as part of a program
-dnl that contains a configuration script generated by Autoconf, under
-dnl the same distribution terms as the rest of that program.
-
-dnl From Bruno Haible.
-dnl Test whether the system has the 'intmax_t' type, but don't attempt to
-dnl find a replacement if it is lacking.
-
-AC_DEFUN([gt_TYPE_INTMAX_T],
-[
-  AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
-  AC_REQUIRE([jm_AC_HEADER_STDINT_H])
-  AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t,
-    [AC_TRY_COMPILE([
-#include <stddef.h> 
-#include <stdlib.h>
-#if HAVE_STDINT_H_WITH_UINTMAX
-#include <stdint.h>
-#endif
-#if HAVE_INTTYPES_H_WITH_UINTMAX
-#include <inttypes.h>
-#endif
-], [intmax_t x = -1;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)])
-  if test $gt_cv_c_intmax_t = yes; then
-    AC_DEFINE(HAVE_INTMAX_T, 1,
-      [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
-  fi
-])
index bed1f92..bf9760c 100644 (file)
@@ -39,10 +39,10 @@ mlguestfs.cmxa: guestfs_c.o guestfs_c_actions.o guestfs.cmx
        $(OCAMLMKLIB) -o mlguestfs $^ -L$(top_builddir)/src/.libs -lguestfs
 
 guestfs_c.o: guestfs_c.c
-       $(CC) $(CFLAGS) -I$(OCAMLLIB) -I$(top_builddir)/src -fPIC -Wall -c $<
+       $(CC) $(CFLAGS) -I$(OCAMLLIB) -I$(top_srcdir)/ocaml -I$(top_srcdir)/src -I$(top_builddir)/src -fPIC -Wall -c $<
 
 guestfs_c_actions.o: guestfs_c_actions.c
-       $(CC) $(CFLAGS) -I$(OCAMLLIB) -I$(top_builddir)/src -fPIC -Wall -c $<
+       $(CC) $(CFLAGS) -I$(OCAMLLIB) -I$(top_srcdir)/ocaml -I$(top_srcdir)/src -I$(top_builddir)/src -fPIC -Wall -c $<
 
 TESTS_ENVIRONMENT = \
        LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
@@ -60,15 +60,19 @@ bindtests: bindtests.ml mlguestfs.cmxa
        $(OCAMLFIND) ocamlopt -cclib -L$(top_builddir)/src/.libs -I . unix.cmxa mlguestfs.cmxa $< -o $@
 
 t/guestfs_005_load: t/guestfs_005_load.ml mlguestfs.cmxa
+       mkdir -p t
        $(OCAMLFIND) ocamlopt -cclib -L$(top_builddir)/src/.libs -I . unix.cmxa mlguestfs.cmxa $< -o $@
 
 t/guestfs_010_launch: t/guestfs_010_launch.ml mlguestfs.cmxa
+       mkdir -p t
        $(OCAMLFIND) ocamlopt -cclib -L$(top_builddir)/src/.libs -I . unix.cmxa mlguestfs.cmxa $< -o $@
 
 t/guestfs_050_lvcreate: t/guestfs_050_lvcreate.ml mlguestfs.cmxa
+       mkdir -p t
        $(OCAMLFIND) ocamlopt -cclib -L$(top_builddir)/src/.libs -I . unix.cmxa mlguestfs.cmxa $< -o $@
 
 t/guestfs_060_readdir: t/guestfs_060_readdir.ml mlguestfs.cmxa
+       mkdir -p t
        $(OCAMLFIND) ocamlopt -cclib -L$(top_builddir)/src/.libs -I . unix.cmxa mlguestfs.cmxa $< -o $@
 
 .mli.cmi:
index 40d1d6c..d18aba6 100644 (file)
@@ -23,7 +23,8 @@ WriteMakefile (
     NAME => 'Sys::Guestfs',
     VERSION => '@PACKAGE_VERSION@',
 
-    LIBS => '-L@abs_top_builddir@/src/.libs -lguestfs',
-    INC => '-I@abs_top_builddir@/src',
+    LIBS => '-L@top_builddir@/src/.libs -lguestfs',
+    INC => '-I@top_builddir@/src -I@top_srcdir@/src',
+    TYPEMAPS => [ '@srcdir@/typemap' ],
     CCFLAGS => '@CFLAGS@',
     );
index 747ac43..66d1d4b 100644 (file)
@@ -36,8 +36,8 @@ if HAVE_PERL
 TESTS = run-bindtests run-perl-tests
 
 TESTS_ENVIRONMENT = \
-       LD_LIBRARY_PATH=../src/.libs \
-       LIBGUESTFS_PATH=../appliance
+       LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
+       LIBGUESTFS_PATH=$(top_builddir)/appliance
 
 INSTALLDIRS = site
 
index dcd0625..2928f98 100644 (file)
@@ -32,12 +32,13 @@ python_DATA = guestfs.py
 python_LTLIBRARIES = libguestfsmod.la
 
 libguestfsmod_la_SOURCES = guestfs-py.c
-libguestfsmod_la_CFLAGS = -Wall -I$(PYTHON_INCLUDEDIR) -I$(top_builddir)/src
+libguestfsmod_la_CFLAGS = -Wall -I$(PYTHON_INCLUDEDIR) \
+                         -I$(top_srcdir)/src -I$(top_builddir)/src
 libguestfsmod_la_LIBADD = $(top_builddir)/src/libguestfs.la
 
 TESTS_ENVIRONMENT = \
        LIBGUESTFS_PATH=$(top_builddir)/appliance \
-       PYTHONPATH=$(top_builddir)/python:$(top_builddir)/python/.libs
+       PYTHONPATH=$(builddir):$(builddir)/.libs
 
 TESTS = run-bindtests run-python-tests
 
index 40b4df1..3ee96c5 100644 (file)
@@ -11,7 +11,7 @@ editing virtual machine filesystems.
 Type: 'help' for help with commands
       'quit' to quit the shell
 
-><fs> cat /etc/resolv.conf 
+><fs> cat /etc/resolv.conf
 nameserver 192.168.1.1
 ><fs> cat /etc/HOSTNAME
 newmachine
index 47033c8..7f222f3 100644 (file)
@@ -1,8 +1,8 @@
 $ ./export2tar.sh /dev/mapper/Guests-RHEL53PV32 /dev/VolGroup00/LogVol00 \
     /home /tmp/home.tar.gz
-$ ll /tmp/home.tar.gz 
+$ ll /tmp/home.tar.gz
 -rw-rw-r--. 1 rjones rjones 824 2009-04-25 12:33 /tmp/home.tar.gz
-$ tar ztf /tmp/home.tar.gz 
+$ tar ztf /tmp/home.tar.gz
 ./
 ./rjones/
 ./rjones/.bash_profile
index 16cb7da..5c796e1 100644 (file)
@@ -1,4 +1,4 @@
-$ ll -h /tmp/Fedora-11-Beta-i386-netinst.iso 
+$ ll -h /tmp/Fedora-11-Beta-i386-netinst.iso
 -r--r--r--. 1 rjones rjones 168M 2009-04-25 22:38 /tmp/Fedora-11-Beta-i386-netinst.iso
 $ ./iso2tar.sh /tmp/Fedora-11-Beta-i386-netinst.iso /tmp/cd.tar.gz
 $ ls -lh /tmp/cd.tar.gz
index 78ecfaa..2e1cb41 100644 (file)
 TESTS = \
        rhbz503169c10.sh \
        rhbz503169c13.sh \
+       test-cancellation-upload-daemoncancels.sh \
+       test-cancellation-download-librarycancels.sh \
+       test-qemudie-midcommand.sh \
+       test-qemudie-killsub.sh \
+       test-qemudie-synch.sh
+
+SKIPPED_TESTS = \
        test-bootbootboot.sh
 
+FAILING_TESTS = \
+       test-qemudie-launchfail.sh
+
+TESTS_ENVIRONMENT = \
+       LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
+       LIBGUESTFS_PATH=$(top_builddir)/appliance
+
 EXTRA_DIST = \
-       test-cleanup.sh \
+       $(FAILING_TESTS) \
+       $(SKIPPED_TESTS) \
        $(TESTS)
index 8cdad50..2cfdbca 100755 (executable)
@@ -24,8 +24,6 @@ set -e
 rm -f test1.img
 dd if=/dev/zero of=test1.img bs=1024k count=10
 
-export LIBGUESTFS_PATH=../appliance
-
 ../fish/guestfish -a test1.img <<EOF
 launch
 ll /../dev/console
index 71e29ce..b6b4b94 100755 (executable)
@@ -29,8 +29,6 @@ set -e
 rm -f test1.img
 dd if=/dev/zero of=test1.img bs=1024k count=10
 
-export LIBGUESTFS_PATH=../appliance
-
 ../fish/guestfish -a test1.img <<EOF
 run
 sfdisk /dev/sda 0 0 0 ,
index 05ff6df..4586aff 100755 (executable)
@@ -30,7 +30,6 @@ n=10
 if [ -n "$1" ]; then n=$1; fi
 
 export LIBGUESTFS_DEBUG=1
-export LIBGUESTFS_PATH=../appliance
 
 for i in $(seq 1 $n); do
   echo Test boot $i of $n ...
diff --git a/regressions/test-cancellation-download-librarycancels.sh b/regressions/test-cancellation-download-librarycancels.sh
new file mode 100755 (executable)
index 0000000..2cacdd3
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh -
+# libguestfs
+# 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.
+
+# Test download where the library cancels.
+#
+# 
+
+set -e
+
+rm -f test.img
+
+../fish/guestfish <<'EOF'
+add ../images/test.sqsh
+run
+
+mount /dev/sda /
+
+# Download a file to /dev/full.
+echo "Expect: write: /dev/full: No space left on device"
+-download /100krandom /dev/full
+
+ping-daemon
+EOF
+
+rm -f test.img
diff --git a/regressions/test-cancellation-upload-daemoncancels.sh b/regressions/test-cancellation-upload-daemoncancels.sh
new file mode 100755 (executable)
index 0000000..c56b1c2
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh -
+# libguestfs
+# 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.
+
+# Test upload where the daemon cancels.
+#
+# This is pretty easy - we just upload a too-large source file.
+
+set -e
+
+rm -f test.img
+
+../fish/guestfish <<'EOF'
+alloc test.img 10M
+run
+
+sfdiskM /dev/sda ,
+mkfs ext2 /dev/sda1
+mount /dev/sda1 /
+
+# Upload image, daemon should cancel because the image is too large
+# to upload into itself.
+echo "Expect: write: /test: No space left on device"
+-upload test.img /test
+
+ping-daemon
+EOF
+
+rm -f test.img
diff --git a/regressions/test-qemudie-killsub.sh b/regressions/test-qemudie-killsub.sh
new file mode 100755 (executable)
index 0000000..9848ebf
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh -
+# libguestfs
+# 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.
+
+# Test if we can handle qemu death from the kill-subprocess command.
+
+set -e
+
+rm -f test.img
+
+../fish/guestfish <<'EOF'
+alloc test.img 10M
+run
+
+# Kill the subprocess.
+kill-subprocess
+
+# XXX The following sleep should NOT be necessary.
+echo "Expect an error from the next command"
+-sleep 1
+
+# We should now be able to rerun the subprocess.
+run
+ping-daemon
+EOF
+
+rm -f test.img
similarity index 79%
rename from regressions/test-cleanup.sh
rename to regressions/test-qemudie-launchfail.sh
index 33194ab..7da1c35 100755 (executable)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-# XXX Unfortunately we can't enable this by default since it
-# requires './configure --enable-debug-command'
+# Test if we can handle qemu failure during launch.
 
-./fish/guestfish <<EOF
-alloc /tmp/test.img 100M
-run
+set -e
+
+rm -f test.img
 
-# Force a segfault inside the daemon.
--debug segv ''
+../fish/guestfish <<'EOF'
+alloc test.img 10M
+
+append "root=/dev/null"
+-run
 
 # We should now be able to rerun the subprocess.
+append ""
 run
 ping-daemon
 EOF
-  
\ No newline at end of file
+
+rm -f test.img
diff --git a/regressions/test-qemudie-midcommand.sh b/regressions/test-qemudie-midcommand.sh
new file mode 100755 (executable)
index 0000000..2aca922
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh -
+# libguestfs
+# 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.
+
+# Test if we can handle qemu death in the middle of a command.
+
+set -e
+
+rm -f test.pid test.img
+
+../fish/guestfish <<'EOF'
+alloc test.img 10M
+run
+
+# Kill the subprocess after a short wait.
+pid | cat > test.pid
+! sleep 2 ; kill $(cat test.pid) &
+
+echo "Expect: 'guestfs_sleep reply failed, see earlier error messages'"
+-sleep 1000
+
+# We should now be able to rerun the subprocess.
+run
+ping-daemon
+EOF
+
+rm -f test.pid test.img
diff --git a/regressions/test-qemudie-synch.sh b/regressions/test-qemudie-synch.sh
new file mode 100755 (executable)
index 0000000..96e879d
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/sh -
+# libguestfs
+# 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.
+
+# Test if we can handle qemu death synchronously.
+
+set -e
+
+rm -f test.pid test.img
+
+../fish/guestfish <<'EOF'
+alloc test.img 10M
+run
+
+# Kill subprocess.
+pid | cat > test.pid
+! kill $(cat test.pid) ; sleep 2
+
+# XXX The following sleep should NOT be necessary.
+echo "Expect an error from the next command"
+-sleep 1
+
+# We should now be able to rerun the subprocess.
+run
+ping-daemon
+EOF
+
+rm -f test.pid test.img
index 389399f..7ea0107 100644 (file)
@@ -40,10 +40,10 @@ if HAVE_RUBY
 TESTS = run-bindtests run-ruby-tests
 
 TESTS_ENVIRONMENT = \
-       LD_LIBRARY_PATH=../src/.libs \
-       LIBGUESTFS_PATH=../appliance
+       LD_LIBRARY_PATH=$(top_builddir)/src/.libs \
+       LIBGUESTFS_PATH=$(top_builddir)/appliance
 
 all:
        rake build
 
-endif
\ No newline at end of file
+endif
index 67f6b17..400ea0f 100644 (file)
@@ -24,26 +24,24 @@ 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'
+EXT_CONF='@srcdir@/ext/guestfs/extconf.rb'
+MAKEFILE='@builddir@/ext/guestfs/Makefile'
+GUESTFS_MODULE='@builddir@/ext/guestfs/_guestfs.so'
+GUESTFS_SRC='@builddir@/ext/guestfs/_guestfs.c'
 
-CLEAN.include [ "ext/**/*.o", GUESTFS_MODULE,
-                "ext/**/depend" ]
+CLEAN.include [ "@builddir@/ext/**/*.o", GUESTFS_MODULE,
+                "@builddir@/ext/**/depend" ]
 
-CLOBBER.include [ "config.save", "ext/**/mkmf.log",
+CLOBBER.include [ "@builddir@/config.save", "@builddir@/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)} --with-_guestfs-include=../../../src --with-_guestfs-lib=../../../src/.libs"
-             $stderr.puts "Failed to run extconf"
-             break
-         end
-    end
+     unless sh "top_srcdir=$(pwd)/@top_srcdir@; top_builddir=$(pwd)/@top_builddir@; cd #{File::dirname(EXT_CONF)}; ruby #{File::basename(EXT_CONF)} --with-_guestfs-include=$top_srcdir/src --with-_guestfs-lib=$top_builddir/src/.libs"
+         $stderr.puts "Failed to run extconf"
+         break
+     end
 end
 file GUESTFS_MODULE => [ MAKEFILE, GUESTFS_SRC ] do |t|
     Dir::chdir(File::dirname(EXT_CONF)) do
index 1c0fa0a..9dc8e99 100644 (file)
@@ -30,8 +30,10 @@ EXTRA_DIST = \
 noinst_DATA = stamp-generator
 
 stamp-generator: generator.ml
-       mkdir -p $(top_srcdir)/perl/lib/Sys
-       cd .. && ocaml -warn-error A $(srcdir)/src/$<
+       mkdir -p $(top_builddir)/perl/lib/Sys
+       mkdir -p $(top_builddir)/ruby/ext/guestfs
+       mkdir -p $(top_builddir)/java/com/redhat/et/libguestfs
+       cd $(top_builddir) && ocaml -warn-error A ./src/$<
 
 guestfs_protocol.x: stamp-generator
 
@@ -83,6 +85,8 @@ lib_LTLIBRARIES = libguestfs.la
 
 BUILT_SOURCES = \
   guestfs_protocol.x \
+  guestfs_protocol.c \
+  guestfs_protocol.h \
   guestfs-structs.h \
   guestfs-actions.h \
   guestfs-actions.c \
index ed5810b..e97472d 100755 (executable)
@@ -66,15 +66,16 @@ and ret =
     (* "RString" and "RStringList" are caller-frees. *)
   | RString of string
   | RStringList of string
-    (* Some limited tuples are possible: *)
-  | RIntBool of string * string
-    (* LVM PVs, VGs and LVs. *)
-  | RPVList of string
-  | RVGList of string
-  | RLVList of string
-    (* Stat buffers. *)
-  | RStat of string
-  | RStatVFS of string
+    (* "RStruct" is a function which returns a single named structure
+     * or an error indication (in C, a struct, and in other languages
+     * with varying representations, but usually very efficient).  See
+     * after the function list below for the structures. 
+     *)
+  | RStruct of string * string         (* name of retval, name of struct *)
+    (* "RStructList" is a function which returns either a list/array
+     * of structures (could be zero-length), or an error indication.
+     *)
+  | RStructList of string * string     (* name of retval, name of struct *)
     (* Key-value pairs of untyped strings.  Turns into a hashtable or
      * dictionary in languages which support it.  DON'T use this as a
      * general "bucket" for results.  Prefer a stronger typed return
@@ -83,8 +84,6 @@ and ret =
      * inefficient.  Keys should be unique.  NULLs are not permitted.
      *)
   | RHashtable of string
-    (* List of directory entries (the result of readdir(3)). *)
-  | RDirentList of string
 
 and args = argt list   (* Function parameters, guestfs handle is implicit. *)
 
@@ -121,7 +120,7 @@ type flags =
   | NotInDocs            (* do not add this function to documentation *)
 
 let protocol_limit_warning =
-  "Because of the message protocol, there is a transfer limit 
+  "Because of the message protocol, there is a transfer limit
 of somewhere between 2MB and 4MB.  To transfer large files you should use
 FTP."
 
@@ -281,12 +280,8 @@ let test_all_rets = [
   "test0rconststring", RConstString "valout";
   "test0rstring",      RString "valout";
   "test0rstringlist",  RStringList "valout";
-  "test0rintbool",     RIntBool ("valout", "valout");
-  "test0rpvlist",      RPVList "valout";
-  "test0rvglist",      RVGList "valout";
-  "test0rlvlist",      RLVList "valout";
-  "test0rstat",        RStat "valout";
-  "test0rstatvfs",     RStatVFS "valout";
+  "test0rstruct",      RStruct ("valout", "lvm_pv");
+  "test0rstructlist",  RStructList ("valout", "lvm_pv");
   "test0rhashtable",   RHashtable "valout";
 ]
 
@@ -632,6 +627,15 @@ then this returns the compiled-in default value for memsize.
 For more information on the architecture of libguestfs,
 see L<guestfs(3)>.");
 
+  ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
+   [],
+   "get PID of qemu subprocess",
+   "\
+Return the process ID of the qemu subprocess.  If there is no
+qemu subprocess, then this will return an error.
+
+This is an internal call used for debugging and testing.");
+
 ]
 
 (* daemon_functions are any functions which cause some action
@@ -813,21 +817,21 @@ This returns a list of the logical volume device names
 
 See also C<guestfs_lvs_full>.");
 
-  ("pvs_full", (RPVList "physvols", []), 12, [],
+  ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
    [], (* XXX how to test? *)
    "list the LVM physical volumes (PVs)",
    "\
 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, [],
+  ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
    [], (* XXX how to test? *)
    "list the LVM volume groups (VGs)",
    "\
 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, [],
+  ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
    [], (* XXX how to test? *)
    "list the LVM logical volumes (LVs)",
    "\
@@ -924,7 +928,7 @@ undefined.
 On success this returns the number of nodes in C<expr>, or
 C<0> if C<expr> evaluates to something which is not a nodeset.");
 
-  ("aug_defnode", (RIntBool ("nrnodes", "created"), [String "name"; String "expr"; String "val"]), 18, [],
+  ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
    [], (* XXX Augeas code needs tests. *)
    "define an Augeas node",
    "\
@@ -1478,7 +1482,7 @@ result into a list of lines.
 
 See also: C<guestfs_sh_lines>");
 
-  ("stat", (RStat "statbuf", [String "path"]), 52, [],
+  ("stat", (RStruct ("statbuf", "stat"), [String "path"]), 52, [],
    [InitBasicFS, Always, TestOutputStruct (
       [["touch"; "/new"];
        ["stat"; "/new"]], [CompareWithInt ("size", 0)])],
@@ -1488,7 +1492,7 @@ Returns file information for the given C<path>.
 
 This is the same as the C<stat(2)> system call.");
 
-  ("lstat", (RStat "statbuf", [String "path"]), 53, [],
+  ("lstat", (RStruct ("statbuf", "stat"), [String "path"]), 53, [],
    [InitBasicFS, Always, TestOutputStruct (
       [["touch"; "/new"];
        ["lstat"; "/new"]], [CompareWithInt ("size", 0)])],
@@ -1502,7 +1506,7 @@ refers to.
 
 This is the same as the C<lstat(2)> system call.");
 
-  ("statvfs", (RStatVFS "statbuf", [String "path"]), 54, [],
+  ("statvfs", (RStruct ("statbuf", "statvfs"), [String "path"]), 54, [],
    [InitBasicFS, Always, TestOutputStruct (
       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255);
                           CompareWithInt ("bsize", 1024)])],
@@ -2753,7 +2757,7 @@ See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
 
 This call returns the previous umask.");
 
-  ("readdir", (RDirentList "entries", [String "dir"]), 138, [],
+  ("readdir", (RStructList ("entries", "dirent"), [String "dir"]), 138, [],
    [],
    "read directories entries",
    "\
@@ -2790,107 +2794,153 @@ let all_functions_sorted =
   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
               compare n1 n2) all_functions
 
-(* Column names and types from LVM PVs/VGs/LVs. *)
-let pv_cols = [
-  "pv_name", `String;
-  "pv_uuid", `UUID;
-  "pv_fmt", `String;
-  "pv_size", `Bytes;
-  "dev_size", `Bytes;
-  "pv_free", `Bytes;
-  "pv_used", `Bytes;
-  "pv_attr", `String (* XXX *);
-  "pv_pe_count", `Int;
-  "pv_pe_alloc_count", `Int;
-  "pv_tags", `String;
-  "pe_start", `Bytes;
-  "pv_mda_count", `Int;
-  "pv_mda_free", `Bytes;
-(* Not in Fedora 10:
-  "pv_mda_size", `Bytes;
-*)
+(* Field types for structures. *)
+type field =
+  | FChar                      (* C 'char' (really, a 7 bit byte). *)
+  | FString                    (* nul-terminated ASCII string. *)
+  | FUInt32
+  | FInt32
+  | FUInt64
+  | FInt64
+  | FBytes                     (* Any int measure that counts bytes. *)
+  | FUUID                      (* 32 bytes long, NOT nul-terminated. *)
+  | FOptPercent                        (* [0..100], or -1 meaning "not present". *)
+
+(* Because we generate extra parsing code for LVM command line tools,
+ * we have to pull out the LVM columns separately here.
+ *)
+let lvm_pv_cols = [
+  "pv_name", FString;
+  "pv_uuid", FUUID;
+  "pv_fmt", FString;
+  "pv_size", FBytes;
+  "dev_size", FBytes;
+  "pv_free", FBytes;
+  "pv_used", FBytes;
+  "pv_attr", FString (* XXX *);
+  "pv_pe_count", FInt64;
+  "pv_pe_alloc_count", FInt64;
+  "pv_tags", FString;
+  "pe_start", FBytes;
+  "pv_mda_count", FInt64;
+  "pv_mda_free", FBytes;
+  (* Not in Fedora 10:
+     "pv_mda_size", FBytes;
+  *)
 ]
-let vg_cols = [
-  "vg_name", `String;
-  "vg_uuid", `UUID;
-  "vg_fmt", `String;
-  "vg_attr", `String (* XXX *);
-  "vg_size", `Bytes;
-  "vg_free", `Bytes;
-  "vg_sysid", `String;
-  "vg_extent_size", `Bytes;
-  "vg_extent_count", `Int;
-  "vg_free_count", `Int;
-  "max_lv", `Int;
-  "max_pv", `Int;
-  "pv_count", `Int;
-  "lv_count", `Int;
-  "snap_count", `Int;
-  "vg_seqno", `Int;
-  "vg_tags", `String;
-  "vg_mda_count", `Int;
-  "vg_mda_free", `Bytes;
-(* Not in Fedora 10:
-  "vg_mda_size", `Bytes;
-*)
+let lvm_vg_cols = [
+  "vg_name", FString;
+  "vg_uuid", FUUID;
+  "vg_fmt", FString;
+  "vg_attr", FString (* XXX *);
+  "vg_size", FBytes;
+  "vg_free", FBytes;
+  "vg_sysid", FString;
+  "vg_extent_size", FBytes;
+  "vg_extent_count", FInt64;
+  "vg_free_count", FInt64;
+  "max_lv", FInt64;
+  "max_pv", FInt64;
+  "pv_count", FInt64;
+  "lv_count", FInt64;
+  "snap_count", FInt64;
+  "vg_seqno", FInt64;
+  "vg_tags", FString;
+  "vg_mda_count", FInt64;
+  "vg_mda_free", FBytes;
+  (* Not in Fedora 10:
+     "vg_mda_size", FBytes;
+  *)
 ]
-let lv_cols = [
-  "lv_name", `String;
-  "lv_uuid", `UUID;
-  "lv_attr", `String (* XXX *);
-  "lv_major", `Int;
-  "lv_minor", `Int;
-  "lv_kernel_major", `Int;
-  "lv_kernel_minor", `Int;
-  "lv_size", `Bytes;
-  "seg_count", `Int;
-  "origin", `String;
-  "snap_percent", `OptPercent;
-  "copy_percent", `OptPercent;
-  "move_pv", `String;
-  "lv_tags", `String;
-  "mirror_log", `String;
-  "modules", `String;
+let lvm_lv_cols = [
+  "lv_name", FString;
+  "lv_uuid", FUUID;
+  "lv_attr", FString (* XXX *);
+  "lv_major", FInt64;
+  "lv_minor", FInt64;
+  "lv_kernel_major", FInt64;
+  "lv_kernel_minor", FInt64;
+  "lv_size", FBytes;
+  "seg_count", FInt64;
+  "origin", FString;
+  "snap_percent", FOptPercent;
+  "copy_percent", FOptPercent;
+  "move_pv", FString;
+  "lv_tags", FString;
+  "mirror_log", FString;
+  "modules", FString;
 ]
 
-(* Column names and types from stat structures.
- * NB. Can't use things like 'st_atime' because glibc header files
- * define some of these as macros.  Ugh.
+(* Names and fields in all structures (in RStruct and RStructList)
+ * that we support.
  *)
-let stat_cols = [
-  "dev", `Int;
-  "ino", `Int;
-  "mode", `Int;
-  "nlink", `Int;
-  "uid", `Int;
-  "gid", `Int;
-  "rdev", `Int;
-  "size", `Int;
-  "blksize", `Int;
-  "blocks", `Int;
-  "atime", `Int;
-  "mtime", `Int;
-  "ctime", `Int;
-]
-let statvfs_cols = [
-  "bsize", `Int;
-  "frsize", `Int;
-  "blocks", `Int;
-  "bfree", `Int;
-  "bavail", `Int;
-  "files", `Int;
-  "ffree", `Int;
-  "favail", `Int;
-  "fsid", `Int;
-  "flag", `Int;
-  "namemax", `Int;
-]
-
-(* Column names in dirent structure. *)
-let dirent_cols = [
-  "ino", `Int;
-  "ftyp", `Char; (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
-  "name", `String;
+let structs = [
+  (* The old RIntBool return type, only ever used for aug_defnode.  Do
+   * not use this struct in any new code.
+   *)
+  "int_bool", [
+    "i", FInt32;               (* for historical compatibility *)
+    "b", FInt32;               (* for historical compatibility *)
+  ];
+
+  (* LVM PVs, VGs, LVs. *)
+  "lvm_pv", lvm_pv_cols;
+  "lvm_vg", lvm_vg_cols;
+  "lvm_lv", lvm_lv_cols;
+
+  (* Column names and types from stat structures.
+   * NB. Can't use things like 'st_atime' because glibc header files
+   * define some of these as macros.  Ugh.
+   *)
+  "stat", [
+    "dev", FInt64;
+    "ino", FInt64;
+    "mode", FInt64;
+    "nlink", FInt64;
+    "uid", FInt64;
+    "gid", FInt64;
+    "rdev", FInt64;
+    "size", FInt64;
+    "blksize", FInt64;
+    "blocks", FInt64;
+    "atime", FInt64;
+    "mtime", FInt64;
+    "ctime", FInt64;
+  ];
+  "statvfs", [
+    "bsize", FInt64;
+    "frsize", FInt64;
+    "blocks", FInt64;
+    "bfree", FInt64;
+    "bavail", FInt64;
+    "files", FInt64;
+    "ffree", FInt64;
+    "favail", FInt64;
+    "fsid", FInt64;
+    "flag", FInt64;
+    "namemax", FInt64;
+  ];
+
+  (* Column names in dirent structure. *)
+  "dirent", [
+    "ino", FInt64;
+    (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
+    "ftyp", FChar;
+    "name", FString;
+  ];
+] (* end of structs *)
+
+(* Ugh, Java has to be different ..
+ * These names are also used by the Haskell bindings.
+ *)
+let java_structs = [
+  "int_bool", "IntBool";
+  "lvm_pv", "PV";
+  "lvm_vg", "VG";
+  "lvm_lv", "LV";
+  "stat", "Stat";
+  "statvfs", "StatVFS";
+  "dirent", "Dirent"
 ]
 
 (* Used for testing language bindings. *)
@@ -3027,6 +3077,17 @@ let name_of_argt = function
   | String n | OptString n | StringList n | Bool n | Int n
   | FileIn n | FileOut n -> n
 
+let java_name_of_struct typ =
+  try List.assoc typ java_structs
+  with Not_found ->
+    failwithf
+      "java_name_of_struct: no java_structs entry corresponding to %s" typ
+
+let cols_of_struct typ =
+  try List.assoc typ structs
+  with Not_found ->
+    failwithf "cols_of_struct: unknown struct %s" typ
+
 let seq_of_test = function
   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
   | TestOutputListOfDevices (s, _)
@@ -3086,14 +3147,9 @@ let check_functions () =
       (match fst style with
        | RErr -> ()
        | RInt n | RInt64 n | RBool n | RConstString n | RString n
-       | RStringList n | RPVList n | RVGList n | RLVList n
-       | RStat n | RStatVFS n
-       | RHashtable n
-       | RDirentList n ->
+       | RStringList n | RStruct (n, _) | RStructList (n, _)
+       | RHashtable n ->
           check_arg_ret_name n
-       | RIntBool (n,m) ->
-          check_arg_ret_name n;
-          check_arg_ret_name m
       );
       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
   ) all_functions;
@@ -3259,46 +3315,21 @@ I<The caller must free the returned string after use>.\n\n"
             pr "This function returns a NULL-terminated array of strings
 (like L<environ(3)>), or NULL if there was an error.
 I<The caller must free the strings and the array after use>.\n\n"
-        | RIntBool _ ->
-            pr "This function returns a C<struct guestfs_int_bool *>,
+        | RStruct (_, typ) ->
+            pr "This function returns a C<struct guestfs_%s *>,
 or NULL if there was an error.
-I<The caller must call C<guestfs_free_int_bool> after use>.\n\n"
-        | RPVList _ ->
-            pr "This function returns a C<struct guestfs_lvm_pv_list *>
+I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
+        | RStructList (_, typ) ->
+            pr "This function returns a C<struct guestfs_%s_list *>
 (see E<lt>guestfs-structs.hE<gt>),
 or NULL if there was an error.
-I<The caller must call C<guestfs_free_lvm_pv_list> after use>.\n\n"
-        | RVGList _ ->
-            pr "This function returns a C<struct guestfs_lvm_vg_list *>
-(see E<lt>guestfs-structs.hE<gt>),
-or NULL if there was an error.
-I<The caller must call C<guestfs_free_lvm_vg_list> after use>.\n\n"
-        | RLVList _ ->
-            pr "This function returns a C<struct guestfs_lvm_lv_list *>
-(see E<lt>guestfs-structs.hE<gt>),
-or NULL if there was an error.
-I<The caller must call C<guestfs_free_lvm_lv_list> after use>.\n\n"
-        | RStat _ ->
-            pr "This function returns a C<struct guestfs_stat *>
-(see L<stat(2)> and E<lt>guestfs-structs.hE<gt>),
-or NULL if there was an error.
-I<The caller must call C<free> after use>.\n\n"
-        | RStatVFS _ ->
-            pr "This function returns a C<struct guestfs_statvfs *>
-(see L<statvfs(2)> and E<lt>guestfs-structs.hE<gt>),
-or NULL if there was an error.
-I<The caller must call C<free> after use>.\n\n"
+I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
         | RHashtable _ ->
             pr "This function returns a NULL-terminated array of
 strings, or NULL if there was an error.
 The array of strings will always have length C<2n+1>, where
 C<n> keys and values alternate, followed by the trailing NULL entry.
 I<The caller must free the strings and the array after use>.\n\n"
-        | RDirentList _ ->
-            pr "This function returns a C<struct guestfs_dirent_list *>
-(see E<lt>guestfs-structs.hE<gt>),
-or NULL if there was an error.
-I<The caller must call C<guestfs_free_dirent_list> after use>.\n\n"
        );
        if List.mem ProtocolLimitWarning flags then
          pr "%s\n\n" protocol_limit_warning;
@@ -3308,68 +3339,39 @@ I<The caller must call C<guestfs_free_dirent_list> after use>.\n\n"
   ) all_functions_sorted
 
 and generate_structs_pod () =
-  (* LVM structs documentation. *)
+  (* Structs documentation. *)
   List.iter (
     fun (typ, cols) ->
-      pr "=head2 guestfs_lvm_%s\n" typ;
+      pr "=head2 guestfs_%s\n" typ;
       pr "\n";
-      pr " struct guestfs_lvm_%s {\n" typ;
+      pr " struct guestfs_%s {\n" typ;
       List.iter (
        function
-       | name, `String -> pr "  char *%s;\n" name
-       | name, `UUID ->
-           pr "  /* The next field is NOT nul-terminated, be careful when printing it: */\n";
-           pr "  char %s[32];\n" name
-       | name, `Bytes -> pr "  uint64_t %s;\n" name
-       | name, `Int -> pr "  int64_t %s;\n" name
-       | name, `OptPercent ->
-           pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
-           pr "  float %s;\n" name
+       | name, FChar -> pr "   char %s;\n" name
+       | name, FUInt32 -> pr "   uint32_t %s;\n" name
+       | name, FInt32 -> pr "   int32_t %s;\n" name
+       | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
+       | name, FInt64 -> pr "   int64_t %s;\n" name
+       | name, FString -> pr "   char *%s;\n" name
+       | name, FUUID ->
+           pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
+           pr "   char %s[32];\n" name
+       | name, FOptPercent ->
+           pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
+           pr "   float %s;\n" name
       ) cols;
+      pr " };\n";
       pr " \n";
-      pr " struct guestfs_lvm_%s_list {\n" typ;
+      pr " struct guestfs_%s_list {\n" typ;
       pr "   uint32_t len; /* Number of elements in list. */\n";
-      pr "   struct guestfs_lvm_%s *val; /* Elements. */\n" typ;
+      pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
       pr " };\n";
       pr " \n";
-      pr " void guestfs_free_lvm_%s_list (struct guestfs_free_lvm_%s_list *);\n"
+      pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
+      pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
        typ typ;
       pr "\n"
-  ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
-
-  (* Stat *)
-  List.iter (
-    fun (typ, cols) ->
-      pr "=head2 guestfs_%s\n" typ;
-      pr "\n";
-      pr " struct guestfs_%s {\n" typ;
-      List.iter (
-       function
-       | name, `Int -> pr "   int64_t %s;\n" name
-      ) cols;
-      pr " };\n";
-      pr "\n";
-  ) [ "stat", stat_cols; "statvfs", statvfs_cols ];
-
-  (* DirentList *)
-  pr "=head2 guestfs_dirent\n";
-  pr "\n";
-  pr " struct guestfs_dirent {\n";
-  List.iter (
-    function
-    | name, `String -> pr "   char *%s;\n" name
-    | name, `Int -> pr "   int64_t %s;\n" name
-    | name, `Char -> pr "   char %s;\n" name
-  ) dirent_cols;
-  pr " };\n";
-  pr "\n";
-  pr " struct guestfs_dirent_list {\n";
-  pr "   uint32_t len; /* Number of elements in list. */\n";
-  pr "   struct guestfs_dirent *val; /* Elements. */\n";
-  pr " };\n";
-  pr " \n";
-  pr " void guestfs_free_dirent_list (struct guestfs_free_dirent_list *);\n";
-  pr "\n"
+  ) structs
 
 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
@@ -3386,47 +3388,24 @@ and generate_xdr () =
   pr "typedef string str<>;\n";
   pr "\n";
 
-  (* LVM internal structures. *)
-  List.iter (
-    function
-    | typ, cols ->
-       pr "struct guestfs_lvm_int_%s {\n" typ;
-       List.iter (function
-                  | name, `String -> pr "  string %s<>;\n" name
-                  | name, `UUID -> pr "  opaque %s[32];\n" name
-                  | name, `Bytes -> pr "  hyper %s;\n" name
-                  | name, `Int -> pr "  hyper %s;\n" name
-                  | name, `OptPercent -> pr "  float %s;\n" name
-                 ) cols;
-       pr "};\n";
-       pr "\n";
-       pr "typedef struct guestfs_lvm_int_%s guestfs_lvm_int_%s_list<>;\n" typ typ;
-       pr "\n";
-  ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
-
-  (* Stat internal structures. *)
+  (* Internal structures. *)
   List.iter (
     function
     | typ, cols ->
        pr "struct guestfs_int_%s {\n" typ;
        List.iter (function
-                  | name, `Int -> pr "  hyper %s;\n" name
+                  | name, FChar -> pr "  char %s;\n" name
+                  | name, FString -> pr "  string %s<>;\n" name
+                  | name, FUUID -> pr "  opaque %s[32];\n" name
+                  | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
+                  | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
+                  | name, FOptPercent -> pr "  float %s;\n" name
                  ) cols;
        pr "};\n";
        pr "\n";
-  ) ["stat", stat_cols; "statvfs", statvfs_cols];
-
-  (* Dirent structures. *)
-  pr "struct guestfs_int_dirent {\n";
-  List.iter (function
-            | name, `Int -> pr "  hyper %s;\n" name
-            | name, `Char -> pr "  char %s;\n" name
-            | name, `String -> pr "  string %s<>;\n" name
-           ) dirent_cols;
-  pr "};\n";
-  pr "\n";
-  pr "typedef struct guestfs_int_dirent guestfs_int_dirent_list<>;\n";
-  pr "\n";
+       pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
+       pr "\n";
+  ) structs;
 
   List.iter (
     fun (shortname, style, _, _, _, _, _) ->
@@ -3471,39 +3450,18 @@ and generate_xdr () =
           pr "struct %s_ret {\n" name;
           pr "  str %s<>;\n" n;
           pr "};\n\n"
-       | RIntBool (n,m) ->
-          pr "struct %s_ret {\n" name;
-          pr "  int %s;\n" n;
-          pr "  bool %s;\n" m;
-          pr "};\n\n"
-       | RPVList n ->
-          pr "struct %s_ret {\n" name;
-          pr "  guestfs_lvm_int_pv_list %s;\n" n;
-          pr "};\n\n"
-       | RVGList n ->
-          pr "struct %s_ret {\n" name;
-          pr "  guestfs_lvm_int_vg_list %s;\n" n;
-          pr "};\n\n"
-       | RLVList n ->
-          pr "struct %s_ret {\n" name;
-          pr "  guestfs_lvm_int_lv_list %s;\n" n;
-          pr "};\n\n"
-       | RStat n ->
+       | RStruct (n, typ) ->
           pr "struct %s_ret {\n" name;
-          pr "  guestfs_int_stat %s;\n" n;
+          pr "  guestfs_int_%s %s;\n" typ n;
           pr "};\n\n"
-       | RStatVFS n ->
+       | RStructList (n, typ) ->
           pr "struct %s_ret {\n" name;
-          pr "  guestfs_int_statvfs %s;\n" n;
+          pr "  guestfs_int_%s_list %s;\n" typ n;
           pr "};\n\n"
        | RHashtable n ->
           pr "struct %s_ret {\n" name;
           pr "  str %s<>;\n" n;
           pr "};\n\n"
-       | RDirentList n ->
-          pr "struct %s_ret {\n" name;
-          pr "  guestfs_int_dirent_list %s;\n" n;
-          pr "};\n\n"
       );
   ) daemon_functions;
 
@@ -3591,63 +3549,32 @@ and generate_structs_h () =
    * must be identical to what rpcgen / the RFC defines.
    *)
 
-  (* guestfs_int_bool structure. *)
-  pr "struct guestfs_int_bool {\n";
-  pr "  int32_t i;\n";
-  pr "  int32_t b;\n";
-  pr "};\n";
-  pr "\n";
-
-  (* LVM public structures. *)
+  (* Public structures. *)
   List.iter (
-    function
-    | typ, cols ->
-       pr "struct guestfs_lvm_%s {\n" typ;
-       List.iter (
-         function
-         | name, `String -> pr "  char *%s;\n" name
-         | name, `UUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
-         | name, `Bytes -> pr "  uint64_t %s;\n" name
-         | name, `Int -> pr "  int64_t %s;\n" name
-         | name, `OptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
-       ) cols;
-       pr "};\n";
-       pr "\n";
-       pr "struct guestfs_lvm_%s_list {\n" typ;
-       pr "  uint32_t len;\n";
-       pr "  struct guestfs_lvm_%s *val;\n" typ;
-       pr "};\n";
-       pr "\n"
-  ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
-
-  (* Stat structures. *)
-  List.iter (
-    function
-    | typ, cols ->
-       pr "struct guestfs_%s {\n" typ;
-       List.iter (
-         function
-         | name, `Int -> pr "  int64_t %s;\n" name
-       ) cols;
-       pr "};\n";
-       pr "\n"
-  ) ["stat", stat_cols; "statvfs", statvfs_cols];
-
-  (* Dirent structures. *)
-  pr "struct guestfs_dirent {\n";
-  List.iter (
-    function
-    | name, `Int -> pr "  int64_t %s;\n" name
-    | name, `Char -> pr "  char %s;\n" name
-    | name, `String -> pr "  char *%s;\n" name
-  ) dirent_cols;
-  pr "};\n";
-  pr "\n";
-  pr "struct guestfs_dirent_list {\n";
-  pr "  uint32_t len;\n";
-  pr "  struct guestfs_dirent *val;\n";
-  pr "};\n";
-  pr "\n"
+    fun (typ, cols) ->
+      pr "struct guestfs_%s {\n" typ;
+      List.iter (
+       function
+       | name, FChar -> pr "  char %s;\n" name
+       | name, FString -> pr "  char *%s;\n" name
+       | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
+       | name, FUInt32 -> pr "  uint32_t %s;\n" name
+       | name, FInt32 -> pr "  int32_t %s;\n" name
+       | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
+       | name, FInt64 -> pr "  int64_t %s;\n" name
+       | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
+      ) cols;
+      pr "};\n";
+      pr "\n";
+      pr "struct guestfs_%s_list {\n" typ;
+      pr "  uint32_t len;\n";
+      pr "  struct guestfs_%s *val;\n" typ;
+      pr "};\n";
+      pr "\n";
+      pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
+      pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
+      pr "\n"
+  ) structs
 
 (* Generate the guestfs-actions.h file. *)
 and generate_actions_h () =
@@ -3752,11 +3679,8 @@ check_state (guestfs_h *g, const char *caller)
           failwithf "RConstString cannot be returned from a daemon function"
        | RInt _ | RInt64 _
        | RBool _ | RString _ | RStringList _
-       | RIntBool _
-       | RPVList _ | RVGList _ | RLVList _
-       | RStat _ | RStatVFS _
-       | RHashtable _
-       | RDirentList _ ->
+       | RStruct _ | RStructList _
+       | RHashtable _ ->
           pr "  struct %s_ret ret;\n" name
       );
       pr "};\n";
@@ -3796,11 +3720,8 @@ check_state (guestfs_h *g, const char *caller)
           failwithf "RConstString cannot be returned from a daemon function"
        | RInt _ | RInt64 _
        | RBool _ | RString _ | RStringList _
-       | RIntBool _
-       | RPVList _ | RVGList _ | RLVList _
-       | RStat _ | RStatVFS _
-       | RHashtable _
-       | RDirentList _ ->
+       | RStruct _ | RStructList _
+       | RHashtable _ ->
            pr "  if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
            pr "    error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
            pr "    return;\n";
@@ -3820,11 +3741,9 @@ check_state (guestfs_h *g, const char *caller)
        | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
        | RConstString _ ->
            failwithf "RConstString cannot be returned from a daemon function"
-       | RString _ | RStringList _ | RIntBool _
-       | RPVList _ | RVGList _ | RLVList _
-       | RStat _ | RStatVFS _
-       | RHashtable _
-       | RDirentList _ ->
+       | RString _ | RStringList _
+       | RStruct _ | RStructList _
+       | RHashtable _ ->
            "NULL" in
 
       pr "{\n";
@@ -3956,18 +3875,43 @@ check_state (guestfs_h *g, const char *caller)
             n n;
           pr "  ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
           pr "  return ctx.ret.%s.%s_val;\n" n n
-       | RIntBool _ ->
-          pr "  /* caller with free this */\n";
-          pr "  return safe_memdup (g, &ctx.ret, sizeof (ctx.ret));\n"
-       | RPVList n | RVGList n | RLVList n
-       | RStat n | RStatVFS n
-       | RDirentList n ->
+       | RStruct (n, _) ->
+          pr "  /* caller will free this */\n";
+          pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
+       | RStructList (n, _) ->
           pr "  /* caller will free this */\n";
           pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
       );
 
       pr "}\n\n"
-  ) daemon_functions
+  ) daemon_functions;
+
+  (* Functions to free structures. *)
+  pr "/* Structure-freeing functions.  These rely on the fact that the\n";
+  pr " * structure format is identical to the XDR format.  See note in\n";
+  pr " * generator.ml.\n";
+  pr " */\n";
+  pr "\n";
+
+  List.iter (
+    fun (typ, _) ->
+      pr "void\n";
+      pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
+      pr "{\n";
+      pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
+      pr "  free (x);\n";
+      pr "}\n";
+      pr "\n";
+
+      pr "void\n";
+      pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
+      pr "{\n";
+      pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
+      pr "  free (x);\n";
+      pr "}\n";
+      pr "\n";
+
+  ) structs;
 
 (* Generate daemon/actions.h. *)
 and generate_daemon_actions_h () =
@@ -4016,13 +3960,8 @@ and generate_daemon_actions () =
            failwithf "RConstString cannot be returned from a daemon function"
        | RString _ -> pr "  char *r;\n"; "NULL"
        | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
-       | RIntBool _ -> pr "  guestfs_%s_ret *r;\n" name; "NULL"
-       | RPVList _ -> pr "  guestfs_lvm_int_pv_list *r;\n"; "NULL"
-       | RVGList _ -> pr "  guestfs_lvm_int_vg_list *r;\n"; "NULL"
-       | RLVList _ -> pr "  guestfs_lvm_int_lv_list *r;\n"; "NULL"
-       | RStat _ -> pr "  guestfs_int_stat *r;\n"; "NULL"
-       | RStatVFS _ -> pr "  guestfs_int_statvfs *r;\n"; "NULL"
-       | RDirentList _ -> pr "  guestfs_int_dirent_list *r;\n"; "NULL" in
+       | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
+       | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL" in
 
       (match snd style with
        | [] -> ()
@@ -4118,13 +4057,14 @@ and generate_daemon_actions () =
            pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
              name;
            pr "  free_strings (r);\n"
-       | RIntBool _ ->
-           pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) r);\n"
+       | RStruct (n, _) ->
+           pr "  struct guestfs_%s_ret ret;\n" name;
+           pr "  ret.%s = *r;\n" n;
+           pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
              name;
-           pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) r);\n" name
-       | RPVList n | RVGList n | RLVList n
-       | RStat n | RStatVFS n
-       | RDirentList n ->
+           pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
+             name
+       | RStructList (n, _) ->
            pr "  struct guestfs_%s_ret ret;\n" name;
            pr "  ret.%s = *r;\n" n;
            pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
@@ -4175,7 +4115,7 @@ and generate_daemon_actions () =
          typ (String.concat "," (List.map fst cols));
        pr "\n";
 
-       pr "static int lvm_tokenize_%s (char *str, struct guestfs_lvm_int_%s *r)\n" typ typ;
+       pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
        pr "{\n";
        pr "  char *tok, *p, *next;\n";
        pr "  int i, j;\n";
@@ -4203,13 +4143,13 @@ and generate_daemon_actions () =
            pr "  if (*p) next = p+1; else next = NULL;\n";
            pr "  *p = '\\0';\n";
            (match coltype with
-            | `String ->
+            | FString ->
                 pr "  r->%s = strdup (tok);\n" name;
                 pr "  if (r->%s == NULL) {\n" name;
                 pr "    perror (\"strdup\");\n";
                 pr "    return -1;\n";
                 pr "  }\n"
-            | `UUID ->
+            | FUUID ->
                 pr "  for (i = j = 0; i < 32; ++j) {\n";
                 pr "    if (tok[j] == '\\0') {\n";
                 pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
@@ -4217,23 +4157,25 @@ and generate_daemon_actions () =
                 pr "    } else if (tok[j] != '-')\n";
                 pr "      r->%s[i++] = tok[j];\n" name;
                 pr "  }\n";
-            | `Bytes ->
+            | FBytes ->
                 pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
                 pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
                 pr "    return -1;\n";
                 pr "  }\n";
-            | `Int ->
+            | FInt64 ->
                 pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
                 pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
                 pr "    return -1;\n";
                 pr "  }\n";
-            | `OptPercent ->
+            | FOptPercent ->
                 pr "  if (tok[0] == '\\0')\n";
                 pr "    r->%s = -1;\n" name;
                 pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
                 pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
                 pr "    return -1;\n";
                 pr "  }\n";
+            | FInt32 | FUInt32 | FUInt64 | FChar ->
+                assert false (* can never be an LVM column *)
            );
            pr "  tok = next;\n";
        ) cols;
@@ -4246,13 +4188,13 @@ and generate_daemon_actions () =
        pr "}\n";
        pr "\n";
 
-       pr "guestfs_lvm_int_%s_list *\n" typ;
+       pr "guestfs_int_lvm_%s_list *\n" typ;
        pr "parse_command_line_%ss (void)\n" typ;
        pr "{\n";
        pr "  char *out, *err;\n";
        pr "  char *p, *pend;\n";
        pr "  int r, i;\n";
-       pr "  guestfs_lvm_int_%s_list *ret;\n" typ;
+       pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
        pr "  void *newp;\n";
        pr "\n";
        pr "  ret = malloc (sizeof *ret);\n";
@@ -4261,8 +4203,8 @@ and generate_daemon_actions () =
        pr "    return NULL;\n";
        pr "  }\n";
        pr "\n";
-       pr "  ret->guestfs_lvm_int_%s_list_len = 0;\n" typ;
-       pr "  ret->guestfs_lvm_int_%s_list_val = NULL;\n" typ;
+       pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
+       pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
        pr "\n";
        pr "  r = command (&out, &err,\n";
        pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
@@ -4297,22 +4239,22 @@ and generate_daemon_actions () =
        pr "    }\n";
        pr "\n";
        pr "    /* Allocate some space to store this next entry. */\n";
-       pr "    newp = realloc (ret->guestfs_lvm_int_%s_list_val,\n" typ;
-       pr "                sizeof (guestfs_lvm_int_%s) * (i+1));\n" typ;
+       pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
+       pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
        pr "    if (newp == NULL) {\n";
        pr "      reply_with_perror (\"realloc\");\n";
-       pr "      free (ret->guestfs_lvm_int_%s_list_val);\n" typ;
+       pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
        pr "      free (ret);\n";
        pr "      free (out);\n";
        pr "      return NULL;\n";
        pr "    }\n";
-       pr "    ret->guestfs_lvm_int_%s_list_val = newp;\n" typ;
+       pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
        pr "\n";
        pr "    /* Tokenize the next entry. */\n";
-       pr "    r = lvm_tokenize_%s (p, &ret->guestfs_lvm_int_%s_list_val[i]);\n" typ typ;
+       pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
        pr "    if (r == -1) {\n";
        pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
-        pr "      free (ret->guestfs_lvm_int_%s_list_val);\n" typ;
+        pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
         pr "      free (ret);\n";
        pr "      free (out);\n";
        pr "      return NULL;\n";
@@ -4322,13 +4264,13 @@ and generate_daemon_actions () =
        pr "    p = pend;\n";
        pr "  }\n";
        pr "\n";
-       pr "  ret->guestfs_lvm_int_%s_list_len = i;\n" typ;
+       pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
        pr "\n";
        pr "  free (out);\n";
        pr "  return ret;\n";
        pr "}\n"
 
-  ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
+  ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
 
 (* Generate a list of function names, for debugging in the daemon.. *)
 and generate_daemon_names () =
@@ -4686,7 +4628,7 @@ and generate_one_test_body name i test_name init test =
       List.iter (generate_test_command_call test_name) seq
   | TestOutput (seq, expected) ->
       pr "  /* TestOutput for %s (%d) */\n" name i;
-      pr "  char expected[] = \"%s\";\n" (c_quote expected);
+      pr "  const char *expected = \"%s\";\n" (c_quote expected);
       let seq, last = get_seq_last seq in
       let test () =
        pr "    if (strcmp (r, expected) != 0) {\n";
@@ -4708,7 +4650,7 @@ and generate_one_test_body name i test_name init test =
            pr "      return -1;\n";
            pr "    }\n";
             pr "    {\n";
-            pr "      char expected[] = \"%s\";\n" (c_quote str);
+            pr "      const char *expected = \"%s\";\n" (c_quote str);
            pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
            pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
            pr "        return -1;\n";
@@ -4736,7 +4678,7 @@ and generate_one_test_body name i test_name init test =
            pr "      return -1;\n";
            pr "    }\n";
             pr "    {\n";
-            pr "      char expected[] = \"%s\";\n" (c_quote str);
+            pr "      const char *expected = \"%s\";\n" (c_quote str);
            pr "      r[%d][5] = 's';\n" i;
            pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
            pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
@@ -4882,7 +4824,7 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
        | OptString n, "NULL" -> ()
        | String n, arg
        | OptString n, arg ->
-           pr "    char %s[] = \"%s\";\n" n (c_quote arg);
+           pr "    const char *%s = \"%s\";\n" n (c_quote arg);
        | Int _, _
        | Bool _, _
        | FileIn _, _ | FileOut _, _ -> ()
@@ -4890,9 +4832,9 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
            let strs = string_split " " arg in
            iteri (
              fun i str ->
-                pr "    char %s_%d[] = \"%s\";\n" n i (c_quote str);
+                pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
            ) strs;
-           pr "    char *%s[] = {\n" n;
+           pr "    const char *%s[] = {\n" n;
            iteri (
              fun i _ -> pr "      %s_%d,\n" n i
            ) strs;
@@ -4910,20 +4852,10 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
            pr "    char **r;\n";
            pr "    int i;\n";
            "NULL"
-       | RIntBool _ ->
-           pr "    struct guestfs_int_bool *r;\n"; "NULL"
-       | RPVList _ ->
-           pr "    struct guestfs_lvm_pv_list *r;\n"; "NULL"
-       | RVGList _ ->
-           pr "    struct guestfs_lvm_vg_list *r;\n"; "NULL"
-       | RLVList _ ->
-           pr "    struct guestfs_lvm_lv_list *r;\n"; "NULL"
-       | RStat _ ->
-           pr "    struct guestfs_stat *r;\n"; "NULL"
-       | RStatVFS _ ->
-           pr "    struct guestfs_statvfs *r;\n"; "NULL"
-       | RDirentList _ ->
-           pr "    struct guestfs_dirent_list *r;\n"; "NULL" in
+       | RStruct (_, typ) ->
+           pr "    struct guestfs_%s *r;\n" typ; "NULL"
+       | RStructList (_, typ) ->
+           pr "    struct guestfs_%s_list *r;\n" typ; "NULL" in
 
       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
       pr "    r = guestfs_%s (g" name;
@@ -4969,18 +4901,10 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
           pr "    for (i = 0; r[i] != NULL; ++i)\n";
           pr "      free (r[i]);\n";
           pr "    free (r);\n"
-       | RIntBool _ ->
-          pr "    guestfs_free_int_bool (r);\n"
-       | RPVList _ ->
-          pr "    guestfs_free_lvm_pv_list (r);\n"
-       | RVGList _ ->
-          pr "    guestfs_free_lvm_vg_list (r);\n"
-       | RLVList _ ->
-          pr "    guestfs_free_lvm_lv_list (r);\n"
-       | RStat _ | RStatVFS _ ->
-          pr "    free (r);\n"
-       | RDirentList _ ->
-          pr "    guestfs_free_dirent_list (r);\n"
+       | RStruct (_, typ) ->
+          pr "    guestfs_free_%s (r);\n" typ
+       | RStructList (_, typ) ->
+          pr "    guestfs_free_%s_list (r);\n" typ
       );
 
       pr "  }\n"
@@ -5082,82 +5006,47 @@ and generate_fish_cmds () =
   pr "}\n";
   pr "\n";
 
-  (* print_{pv,vg,lv}_list functions *)
-  List.iter (
-    function
-    | typ, cols ->
-       pr "static void print_%s (struct guestfs_lvm_%s *%s)\n" typ typ typ;
-       pr "{\n";
-       pr "  int i;\n";
-       pr "\n";
-       List.iter (
-         function
-         | name, `String ->
-             pr "  printf (\"%s: %%s\\n\", %s->%s);\n" name typ name
-         | name, `UUID ->
-             pr "  printf (\"%s: \");\n" name;
-             pr "  for (i = 0; i < 32; ++i)\n";
-             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
-             pr "  printf (\"\\n\");\n"
-         | name, `Bytes ->
-             pr "  printf (\"%s: %%\" PRIu64 \"\\n\", %s->%s);\n" name typ name
-         | name, `Int ->
-             pr "  printf (\"%s: %%\" PRIi64 \"\\n\", %s->%s);\n" name typ name
-         | name, `OptPercent ->
-             pr "  if (%s->%s >= 0) printf (\"%s: %%g %%%%\\n\", %s->%s);\n"
-               typ name name typ name;
-             pr "  else printf (\"%s: \\n\");\n" name
-       ) cols;
-       pr "}\n";
-       pr "\n";
-       pr "static void print_%s_list (struct guestfs_lvm_%s_list *%ss)\n"
-         typ typ typ;
-       pr "{\n";
-       pr "  int i;\n";
-       pr "\n";
-       pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
-       pr "    print_%s (&%ss->val[i]);\n" typ typ;
-       pr "}\n";
-       pr "\n";
-  ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
-
-  (* print_{stat,statvfs} functions *)
-  List.iter (
-    function
-    | typ, cols ->
-       pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
-       pr "{\n";
-       List.iter (
-         function
-         | name, `Int ->
-             pr "  printf (\"%s: %%\" PRIi64 \"\\n\", %s->%s);\n" name typ name
-       ) cols;
-       pr "}\n";
-       pr "\n";
-  ) ["stat", stat_cols; "statvfs", statvfs_cols];
-
-  (* print_dirent_list function *)
-  pr "static void print_dirent (struct guestfs_dirent *dirent)\n";
-  pr "{\n";
+  (* print_* functions *)
   List.iter (
-    function
-    | name, `String ->
-       pr "  printf (\"%s: %%s\\n\", dirent->%s);\n" name name
-    | name, `Int ->
-       pr "  printf (\"%s: %%\" PRIi64 \"\\n\", dirent->%s);\n" name name
-    | name, `Char ->
-       pr "  printf (\"%s: %%c\\n\", dirent->%s);\n" name name
-  ) dirent_cols;
-  pr "}\n";
-  pr "\n";
-  pr "static void print_dirent_list (struct guestfs_dirent_list *dirents)\n";
-  pr "{\n";
-  pr "  int i;\n";
-  pr "\n";
-  pr "  for (i = 0; i < dirents->len; ++i)\n";
-  pr "    print_dirent (&dirents->val[i]);\n";
-  pr "}\n";
-  pr "\n";
+    fun (typ, cols) ->
+      pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
+      pr "{\n";
+      List.iter (
+       function
+       | name, FString ->
+           pr "  printf (\"%s: %%s\\n\", %s->%s);\n" name typ name
+       | name, FUUID ->
+           pr "  printf (\"%s: \");\n" name;
+           pr "  for (int i = 0; i < 32; ++i)\n";
+           pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
+           pr "  printf (\"\\n\");\n"
+       | name, (FUInt64|FBytes) ->
+           pr "  printf (\"%s: %%\" PRIu64 \"\\n\", %s->%s);\n" name typ name
+       | name, FInt64 ->
+           pr "  printf (\"%s: %%\" PRIi64 \"\\n\", %s->%s);\n" name typ name
+       | name, FUInt32 ->
+           pr "  printf (\"%s: %%\" PRIu32 \"\\n\", %s->%s);\n" name typ name
+       | name, FInt32 ->
+           pr "  printf (\"%s: %%\" PRIi32 \"\\n\", %s->%s);\n" name typ name
+       | name, FChar ->
+           pr "  printf (\"%s: %%c\\n\", %s->%s);\n" name typ name
+       | name, FOptPercent ->
+           pr "  if (%s->%s >= 0) printf (\"%s: %%g %%%%\\n\", %s->%s);\n"
+             typ name name typ name;
+           pr "  else printf (\"%s: \\n\");\n" name
+      ) cols;
+      pr "}\n";
+      pr "\n";
+      pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
+       typ typ typ;
+      pr "{\n";
+      pr "  int i;\n";
+      pr "\n";
+      pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
+      pr "    print_%s (&%ss->val[i]);\n" typ typ;
+      pr "}\n";
+      pr "\n";
+  ) structs;
 
   (* run_<action> actions *)
   List.iter (
@@ -5172,13 +5061,8 @@ and generate_fish_cmds () =
        | RConstString _ -> pr "  const char *r;\n"
        | RString _ -> pr "  char *r;\n"
        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
-       | RIntBool _ -> pr "  struct guestfs_int_bool *r;\n"
-       | RPVList _ -> pr "  struct guestfs_lvm_pv_list *r;\n"
-       | RVGList _ -> pr "  struct guestfs_lvm_vg_list *r;\n"
-       | RLVList _ -> pr "  struct guestfs_lvm_lv_list *r;\n"
-       | RStat _ -> pr "  struct guestfs_stat *r;\n"
-       | RStatVFS _ -> pr "  struct guestfs_statvfs *r;\n"
-       | RDirentList _ -> pr "  struct guestfs_dirent_list *r;\n"
+       | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
+       | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
       );
       List.iter (
        function
@@ -5257,47 +5141,21 @@ and generate_fish_cmds () =
           pr "  print_strings (r);\n";
           pr "  free_strings (r);\n";
           pr "  return 0;\n"
-       | RIntBool _ ->
-          pr "  if (r == NULL) return -1;\n";
-          pr "  printf (\"%%d, %%s\\n\", r->i,\n";
-          pr "    r->b ? \"true\" : \"false\");\n";
-          pr "  guestfs_free_int_bool (r);\n";
-          pr "  return 0;\n"
-       | RPVList _ ->
+       | RStruct (_, typ) ->
           pr "  if (r == NULL) return -1;\n";
-          pr "  print_pv_list (r);\n";
-          pr "  guestfs_free_lvm_pv_list (r);\n";
+          pr "  print_%s (r);\n" typ;
+          pr "  guestfs_free_%s (r);\n" typ;
           pr "  return 0;\n"
-       | RVGList _ ->
+       | RStructList (_, typ) ->
           pr "  if (r == NULL) return -1;\n";
-          pr "  print_vg_list (r);\n";
-          pr "  guestfs_free_lvm_vg_list (r);\n";
-          pr "  return 0;\n"
-       | RLVList _ ->
-          pr "  if (r == NULL) return -1;\n";
-          pr "  print_lv_list (r);\n";
-          pr "  guestfs_free_lvm_lv_list (r);\n";
-          pr "  return 0;\n"
-       | RStat _ ->
-          pr "  if (r == NULL) return -1;\n";
-          pr "  print_stat (r);\n";
-          pr "  free (r);\n";
-          pr "  return 0;\n"
-       | RStatVFS _ ->
-          pr "  if (r == NULL) return -1;\n";
-          pr "  print_statvfs (r);\n";
-          pr "  free (r);\n";
+          pr "  print_%s_list (r);\n" typ;
+          pr "  guestfs_free_%s_list (r);\n" typ;
           pr "  return 0;\n"
        | RHashtable _ ->
           pr "  if (r == NULL) return -1;\n";
           pr "  print_table (r);\n";
           pr "  free_strings (r);\n";
           pr "  return 0;\n"
-       | RDirentList _ ->
-          pr "  if (r == NULL) return -1;\n";
-          pr "  print_dirent_list (r);\n";
-          pr "  guestfs_free_dirent_list (r);\n";
-          pr "  return 0;\n"
       );
       pr "}\n";
       pr "\n"
@@ -5490,27 +5348,12 @@ and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
    | RConstString _ -> pr "const char *"
    | RString _ -> pr "char *"
    | RStringList _ | RHashtable _ -> pr "char **"
-   | RIntBool _ ->
-       if not in_daemon then pr "struct guestfs_int_bool *"
-       else pr "guestfs_%s_ret *" name
-   | RPVList _ ->
-       if not in_daemon then pr "struct guestfs_lvm_pv_list *"
-       else pr "guestfs_lvm_int_pv_list *"
-   | RVGList _ ->
-       if not in_daemon then pr "struct guestfs_lvm_vg_list *"
-       else pr "guestfs_lvm_int_vg_list *"
-   | RLVList _ ->
-       if not in_daemon then pr "struct guestfs_lvm_lv_list *"
-       else pr "guestfs_lvm_int_lv_list *"
-   | RStat _ ->
-       if not in_daemon then pr "struct guestfs_stat *"
-       else pr "guestfs_int_stat *"
-   | RStatVFS _ ->
-       if not in_daemon then pr "struct guestfs_statvfs *"
-       else pr "guestfs_int_statvfs *"
-   | RDirentList _ ->
-       if not in_daemon then pr "struct guestfs_dirent_list *"
-       else pr "guestfs_int_dirent_list *"
+   | RStruct (_, typ) ->
+       if not in_daemon then pr "struct guestfs_%s *" typ
+       else pr "guestfs_int_%s *" typ
+   | RStructList (_, typ) ->
+       if not in_daemon then pr "struct guestfs_%s_list *" typ
+       else pr "guestfs_int_%s_list *" typ
   );
   pr "%s%s (" prefix name;
   if handle = None && List.length (snd style) = 0 then
@@ -5588,11 +5431,7 @@ val close : t -> unit
     provide predictable cleanup. *)
 
 ";
-  generate_ocaml_lvm_structure_decls ();
-
-  generate_ocaml_stat_structure_decls ();
-
-  generate_ocaml_dirent_structure_decls ();
+  generate_ocaml_structure_decls ();
 
   (* The actions. *)
   List.iter (
@@ -5617,11 +5456,7 @@ let () =
 
 ";
 
-  generate_ocaml_lvm_structure_decls ();
-
-  generate_ocaml_stat_structure_decls ();
-
-  generate_ocaml_dirent_structure_decls ();
+  generate_ocaml_structure_decls ();
 
   (* The actions. *)
   List.iter (
@@ -5679,14 +5514,14 @@ copy_table (char * const * argv)
 
 ";
 
-  (* LVM struct copy functions. *)
+  (* Struct copy functions. *)
   List.iter (
     fun (typ, cols) ->
       let has_optpercent_col =
-       List.exists (function (_, `OptPercent) -> true | _ -> false) cols in
+       List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
 
       pr "static CAMLprim value\n";
-      pr "copy_lvm_%s (const struct guestfs_lvm_%s *%s)\n" typ typ typ;
+      pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
       pr "{\n";
       pr "  CAMLparam0 ();\n";
       if has_optpercent_col then
@@ -5698,21 +5533,24 @@ copy_table (char * const * argv)
       iteri (
        fun i col ->
          (match col with
-          | name, `String ->
+          | name, FString ->
               pr "  v = caml_copy_string (%s->%s);\n" typ name
-          | name, `UUID ->
+          | name, FUUID ->
               pr "  v = caml_alloc_string (32);\n";
               pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
-          | name, `Bytes
-          | name, `Int ->
+          | name, (FBytes|FInt64|FUInt64) ->
               pr "  v = caml_copy_int64 (%s->%s);\n" typ name
-          | name, `OptPercent ->
+          | name, (FInt32|FUInt32) ->
+              pr "  v = caml_copy_int32 (%s->%s);\n" typ name
+          | name, FOptPercent ->
               pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
               pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
               pr "    v = caml_alloc (1, 0);\n";
               pr "    Store_field (v, 0, v2);\n";
               pr "  } else /* None */\n";
               pr "    v = Val_int (0);\n";
+          | name, FChar ->
+              pr "  v = Val_int (%s->%s);\n" typ name
          );
          pr "  Store_field (rv, %d, v);\n" i
       ) cols;
@@ -5721,7 +5559,7 @@ copy_table (char * const * argv)
       pr "\n";
 
       pr "static CAMLprim value\n";
-      pr "copy_lvm_%s_list (const struct guestfs_lvm_%s_list *%ss)\n"
+      pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n"
        typ typ typ;
       pr "{\n";
       pr "  CAMLparam0 ();\n";
@@ -5733,81 +5571,14 @@ copy_table (char * const * argv)
       pr "  else {\n";
       pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
       pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
-      pr "      v = copy_lvm_%s (&%ss->val[i]);\n" typ typ;
+      pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
       pr "      caml_modify (&Field (rv, i), v);\n";
       pr "    }\n";
       pr "    CAMLreturn (rv);\n";
       pr "  }\n";
       pr "}\n";
       pr "\n";
-  ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
-
-  (* Stat copy functions. *)
-  List.iter (
-    fun (typ, cols) ->
-      pr "static CAMLprim value\n";
-      pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
-      pr "{\n";
-      pr "  CAMLparam0 ();\n";
-      pr "  CAMLlocal2 (rv, v);\n";
-      pr "\n";
-      pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
-      iteri (
-       fun i col ->
-         (match col with
-          | name, `Int ->
-              pr "  v = caml_copy_int64 (%s->%s);\n" typ name
-         );
-         pr "  Store_field (rv, %d, v);\n" i
-      ) cols;
-      pr "  CAMLreturn (rv);\n";
-      pr "}\n";
-      pr "\n";
-  ) ["stat", stat_cols; "statvfs", statvfs_cols];
-
-  (* Dirent copy functions. *)
-  pr "static CAMLprim value\n";
-  pr "copy_dirent (const struct guestfs_dirent *dirent)\n";
-  pr "{\n";
-  pr "  CAMLparam0 ();\n";
-  pr "  CAMLlocal2 (rv, v);\n";
-  pr "\n";
-  pr "  rv = caml_alloc (%d, 0);\n" (List.length dirent_cols);
-  iteri (
-    fun i col ->
-      (match col with
-       | name, `String ->
-          pr "  v = caml_copy_string (dirent->%s);\n" name
-       | name, `Int ->
-          pr "  v = caml_copy_int64 (dirent->%s);\n" name
-       | name, `Char ->
-          pr "  v = Val_int (dirent->%s);\n" name
-      );
-      pr "  Store_field (rv, %d, v);\n" i
-  ) dirent_cols;
-  pr "  CAMLreturn (rv);\n";
-  pr "}\n";
-  pr "\n";
-
-  pr "static CAMLprim value\n";
-  pr "copy_dirent_list (const struct guestfs_dirent_list *dirents)\n";
-  pr "{\n";
-  pr "  CAMLparam0 ();\n";
-  pr "  CAMLlocal2 (rv, v);\n";
-  pr "  int i;\n";
-  pr "\n";
-  pr "  if (dirents->len == 0)\n";
-  pr "    CAMLreturn (Atom (0));\n";
-  pr "  else {\n";
-  pr "    rv = caml_alloc (dirents->len, 0);\n";
-  pr "    for (i = 0; i < dirents->len; ++i) {\n";
-  pr "      v = copy_dirent (&dirents->val[i]);\n";
-  pr "      caml_modify (&Field (rv, i), v);\n";
-  pr "    }\n";
-  pr "    CAMLreturn (rv);\n";
-  pr "  }\n";
-  pr "}\n";
-  pr "\n";
+  ) structs;
 
   (* The wrappers. *)
   List.iter (
@@ -5868,24 +5639,14 @@ copy_table (char * const * argv)
            pr "  int i;\n";
            pr "  char **r;\n";
            "NULL"
-       | RIntBool _ ->
-           pr "  struct guestfs_int_bool *r;\n"; "NULL"
-       | RPVList _ ->
-           pr "  struct guestfs_lvm_pv_list *r;\n"; "NULL"
-       | RVGList _ ->
-           pr "  struct guestfs_lvm_vg_list *r;\n"; "NULL"
-       | RLVList _ ->
-           pr "  struct guestfs_lvm_lv_list *r;\n"; "NULL"
-       | RStat _ ->
-           pr "  struct guestfs_stat *r;\n"; "NULL"
-       | RStatVFS _ ->
-           pr "  struct guestfs_statvfs *r;\n"; "NULL"
+       | RStruct (_, typ) ->
+           pr "  struct guestfs_%s *r;\n" typ; "NULL"
+       | RStructList (_, typ) ->
+           pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
        | RHashtable _ ->
            pr "  int i;\n";
            pr "  char **r;\n";
-           "NULL"
-       | RDirentList _ ->
-           pr "  struct guestfs_dirent_list *r;\n"; "NULL" in
+           "NULL" in
       pr "\n";
 
       pr "  caml_enter_blocking_section ();\n";
@@ -5919,33 +5680,16 @@ copy_table (char * const * argv)
           pr "  rv = caml_copy_string_array ((const char **) r);\n";
           pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
           pr "  free (r);\n"
-       | RIntBool _ ->
-          pr "  rv = caml_alloc (2, 0);\n";
-          pr "  Store_field (rv, 0, Val_int (r->i));\n";
-          pr "  Store_field (rv, 1, Val_bool (r->b));\n";
-          pr "  guestfs_free_int_bool (r);\n";
-       | RPVList _ ->
-          pr "  rv = copy_lvm_pv_list (r);\n";
-          pr "  guestfs_free_lvm_pv_list (r);\n";
-       | RVGList _ ->
-          pr "  rv = copy_lvm_vg_list (r);\n";
-          pr "  guestfs_free_lvm_vg_list (r);\n";
-       | RLVList _ ->
-          pr "  rv = copy_lvm_lv_list (r);\n";
-          pr "  guestfs_free_lvm_lv_list (r);\n";
-       | RStat _ ->
-          pr "  rv = copy_stat (r);\n";
-          pr "  free (r);\n";
-       | RStatVFS _ ->
-          pr "  rv = copy_statvfs (r);\n";
-          pr "  free (r);\n";
+       | RStruct (_, typ) ->
+          pr "  rv = copy_%s (r);\n" typ;
+          pr "  guestfs_free_%s (r);\n" typ;
+       | RStructList (_, typ) ->
+          pr "  rv = copy_%s_list (r);\n" typ;
+          pr "  guestfs_free_%s_list (r);\n" typ;
        | RHashtable _ ->
           pr "  rv = copy_table (r);\n";
           pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
           pr "  free (r);\n";
-       | RDirentList _ ->
-          pr "  rv = copy_dirent_list (r);\n";
-          pr "  guestfs_free_dirent_list (r);\n";
       );
 
       pr "  CAMLreturn (rv);\n";
@@ -5964,44 +5708,22 @@ copy_table (char * const * argv)
       )
   ) all_functions
 
-and generate_ocaml_lvm_structure_decls () =
-  List.iter (
-    fun (typ, cols) ->
-      pr "type lvm_%s = {\n" typ;
-      List.iter (
-       function
-       | name, `String -> pr "  %s : string;\n" name
-       | name, `UUID -> pr "  %s : string;\n" name
-       | name, `Bytes -> pr "  %s : int64;\n" name
-       | name, `Int -> pr "  %s : int64;\n" name
-       | name, `OptPercent -> pr "  %s : float option;\n" name
-      ) cols;
-      pr "}\n";
-      pr "\n"
-  ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
-
-and generate_ocaml_stat_structure_decls () =
+and generate_ocaml_structure_decls () =
   List.iter (
     fun (typ, cols) ->
       pr "type %s = {\n" typ;
       List.iter (
        function
-       | name, `Int -> pr "  %s : int64;\n" name
+       | name, FString -> pr "  %s : string;\n" name
+       | name, FUUID -> pr "  %s : string;\n" name
+       | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
+       | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
+       | name, FChar -> pr "  %s : char;\n" name
+       | name, FOptPercent -> pr "  %s : float option;\n" name
       ) cols;
       pr "}\n";
       pr "\n"
-  ) ["stat", stat_cols; "statvfs", statvfs_cols]
-
-and generate_ocaml_dirent_structure_decls () =
-  pr "type dirent = {\n";
-  List.iter (
-    function
-    | name, `Int -> pr "  %s : int64;\n" name
-    | name, `Char -> pr "  %s : char;\n" name
-    | name, `String -> pr "  %s : string;\n" name
-  ) dirent_cols;
-  pr "}\n";
-  pr "\n"
+  ) structs
 
 and generate_ocaml_prototype ?(is_external = false) name style =
   if is_external then pr "external " else pr "val ";
@@ -6022,14 +5744,9 @@ and generate_ocaml_prototype ?(is_external = false) name style =
    | RConstString _ -> pr "string"
    | RString _ -> pr "string"
    | RStringList _ -> pr "string array"
-   | RIntBool _ -> pr "int * bool"
-   | RPVList _ -> pr "lvm_pv array"
-   | RVGList _ -> pr "lvm_vg array"
-   | RLVList _ -> pr "lvm_lv array"
-   | RStat _ -> pr "stat"
-   | RStatVFS _ -> pr "statvfs"
+   | RStruct (_, typ) -> pr "%s" typ
+   | RStructList (_, typ) -> pr "%s array" typ
    | RHashtable _ -> pr "(string * string) list"
-   | RDirentList _ -> pr "dirent array"
   );
   if is_external then (
     pr " = ";
@@ -6143,11 +5860,8 @@ DESTROY (g)
        | RConstString _ -> pr "SV *\n"
        | RString _ -> pr "SV *\n"
        | RStringList _
-       | RIntBool _
-       | RPVList _ | RVGList _ | RLVList _
-       | RStat _ | RStatVFS _
-       | RHashtable _
-       | RDirentList _ ->
+       | RStruct _ | RStructList _
+       | RHashtable _ ->
           pr "void\n" (* all lists returned implictly on the stack *)
       );
       (* Call and arguments. *)
@@ -6263,42 +5977,20 @@ DESTROY (g)
           pr "        free (%s[i]);\n" n;
           pr "      }\n";
           pr "      free (%s);\n" n;
-       | RIntBool _ ->
-          pr "PREINIT:\n";
-          pr "      struct guestfs_int_bool *r;\n";
-          pr " PPCODE:\n";
-          pr "      r = guestfs_%s " name;
-          generate_call_args ~handle:"g" (snd style);
-          pr ";\n";
-          do_cleanups ();
-          pr "      if (r == NULL)\n";
-          pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
-          pr "      EXTEND (SP, 2);\n";
-          pr "      PUSHs (sv_2mortal (newSViv (r->i)));\n";
-          pr "      PUSHs (sv_2mortal (newSViv (r->b)));\n";
-          pr "      guestfs_free_int_bool (r);\n";
-       | RPVList n ->
-          generate_perl_lvm_code "pv" pv_cols name style n do_cleanups
-       | RVGList n ->
-          generate_perl_lvm_code "vg" vg_cols name style n do_cleanups
-       | RLVList n ->
-          generate_perl_lvm_code "lv" lv_cols name style n do_cleanups
-       | RStat n ->
-          generate_perl_stat_code "stat" stat_cols name style n do_cleanups
-       | RStatVFS n ->
-          generate_perl_stat_code
-            "statvfs" statvfs_cols name style n do_cleanups
-       | RDirentList n ->
-          generate_perl_dirent_code
-            "dirent" dirent_cols name style n do_cleanups
+       | RStruct (n, typ) ->
+          let cols = cols_of_struct typ in
+          generate_perl_struct_code typ cols name style n do_cleanups
+       | RStructList (n, typ) ->
+          let cols = cols_of_struct typ in
+          generate_perl_struct_list_code typ cols name style n do_cleanups
       );
 
       pr "\n"
   ) all_functions
 
-and generate_perl_lvm_code typ cols name style n do_cleanups =
+and generate_perl_struct_list_code typ cols name style n do_cleanups =
   pr "PREINIT:\n";
-  pr "      struct guestfs_lvm_%s_list *%s;\n" typ n;
+  pr "      struct guestfs_%s_list *%s;\n" typ n;
   pr "      int i;\n";
   pr "      HV *hv;\n";
   pr " PPCODE:\n";
@@ -6313,27 +6005,33 @@ and generate_perl_lvm_code typ cols name style n do_cleanups =
   pr "        hv = newHV ();\n";
   List.iter (
     function
-    | name, `String ->
+    | name, FString ->
        pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
          name (String.length name) n name
-    | name, `UUID ->
+    | name, FUUID ->
        pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
          name (String.length name) n name
-    | name, `Bytes ->
+    | name, (FBytes|FUInt64) ->
        pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
          name (String.length name) n name
-    | name, `Int ->
+    | name, FInt64 ->
        pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
          name (String.length name) n name
-    | name, `OptPercent ->
+    | name, (FInt32|FUInt32) ->
+       pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
+         name (String.length name) n name
+    | name, FChar ->
+       pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
+         name (String.length name) n name
+    | name, FOptPercent ->
        pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
          name (String.length name) n name
   ) cols;
   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
   pr "      }\n";
-  pr "      guestfs_free_lvm_%s_list (%s);\n" typ n
+  pr "      guestfs_free_%s_list (%s);\n" typ n
 
-and generate_perl_stat_code typ cols name style n do_cleanups =
+and generate_perl_struct_code typ cols name style n do_cleanups =
   pr "PREINIT:\n";
   pr "      struct guestfs_%s *%s;\n" typ n;
   pr " PPCODE:\n";
@@ -6346,42 +6044,30 @@ and generate_perl_stat_code typ cols name style n do_cleanups =
   pr "      EXTEND (SP, %d);\n" (List.length cols);
   List.iter (
     function
-    | name, `Int ->
-       pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n" n name
+    | name, FString ->
+       pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
+         n name
+    | name, FUUID ->
+       pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
+         n name
+    | name, (FBytes|FUInt64) ->
+       pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
+         n name
+    | name, FInt64 ->
+       pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
+         n name
+    | name, (FInt32|FUInt32) ->
+       pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
+         n name
+    | name, FChar ->
+       pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
+         n name
+    | name, FOptPercent ->
+       pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
+         n name
   ) cols;
   pr "      free (%s);\n" n
 
-and generate_perl_dirent_code typ cols name style n do_cleanups =
-  pr "PREINIT:\n";
-  pr "      struct guestfs_%s_list *%s;\n" typ n;
-  pr "      int i;\n";
-  pr "      HV *hv;\n";
-  pr " PPCODE:\n";
-  pr "      %s = guestfs_%s " n name;
-  generate_call_args ~handle:"g" (snd style);
-  pr ";\n";
-  do_cleanups ();
-  pr "      if (%s == NULL)\n" n;
-  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";
-  List.iter (
-    function
-    | name, `String ->
-       pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
-         name (String.length name) n name
-    | name, `Int ->
-       pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
-         name (String.length name) n name
-    | name, `Char ->
-       pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
-         name (String.length name) n name
-  ) cols;
-  pr "        PUSHs (newRV (sv_2mortal ((SV *) hv)));\n";
-  pr "      }\n";
-  pr "      guestfs_free_%s_list (%s);\n" typ n
-
 (* Generate Sys/Guestfs.pm. *)
 and generate_perl_pm () =
   generate_header HashStyle LGPLv2;
@@ -6396,7 +6082,7 @@ Sys::Guestfs - Perl bindings for libguestfs
 =head1 SYNOPSIS
 
  use Sys::Guestfs;
+
  my $h = Sys::Guestfs->new ();
  $h->add_drive ('guest.img');
  $h->launch ();
@@ -6511,15 +6197,10 @@ and generate_perl_prototype name style =
    | RInt64 n
    | RConstString n
    | RString n -> pr "$%s = " n
-   | RIntBool (n, m) -> pr "($%s, $%s) = " n m
-   | RStringList n
-   | RPVList n
-   | RVGList n
-   | RLVList n
-   | RDirentList n -> pr "@%s = " n
-   | RStat n
-   | RStatVFS n
+   | RStruct (n,_)
    | RHashtable n -> pr "%%%s = " n
+   | RStringList n
+   | RStructList (n,_) -> pr "@%s = " n
   );
   pr "$h->%s (" name;
   let comma = ref false in
@@ -6676,34 +6357,42 @@ py_guestfs_close (PyObject *self, PyObject *args)
 
 ";
 
-  (* LVM structures, turned into Python dictionaries. *)
+  (* 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 "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
       pr "{\n";
       pr "  PyObject *dict;\n";
       pr "\n";
       pr "  dict = PyDict_New ();\n";
       List.iter (
        function
-       | name, `String ->
+       | name, FString ->
            pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
            pr "                        PyString_FromString (%s->%s));\n"
              typ name
-       | name, `UUID ->
+       | name, FUUID ->
            pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
            pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
              typ name
-       | name, `Bytes ->
+       | name, (FBytes|FUInt64) ->
            pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
            pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
              typ name
-       | name, `Int ->
+       | name, FInt64 ->
            pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
            pr "                        PyLong_FromLongLong (%s->%s));\n"
              typ name
-       | name, `OptPercent ->
+       | name, FUInt32 ->
+           pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
+           pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
+             typ name
+       | name, FInt32 ->
+           pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
+           pr "                        PyLong_FromLong (%s->%s));\n"
+             typ name
+       | name, FOptPercent ->
            pr "  if (%s->%s >= 0)\n" typ name;
            pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
            pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
@@ -6712,81 +6401,27 @@ py_guestfs_close (PyObject *self, PyObject *args)
            pr "    Py_INCREF (Py_None);\n";
            pr "    PyDict_SetItemString (dict, \"%s\", Py_None);" name;
            pr "  }\n"
+       | name, FChar ->
+           pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
+           pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
       ) 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 "put_%s_list (struct guestfs_%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 "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
       pr "  return list;\n";
       pr "};\n";
       pr "\n"
-  ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
-
-  (* Stat structures, turned into Python dictionaries. *)
-  List.iter (
-    fun (typ, cols) ->
-      pr "static PyObject *\n";
-      pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
-      pr "{\n";
-      pr "  PyObject *dict;\n";
-      pr "\n";
-      pr "  dict = PyDict_New ();\n";
-      List.iter (
-       function
-       | name, `Int ->
-           pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
-           pr "                        PyLong_FromLongLong (%s->%s));\n"
-             typ name
-      ) cols;
-      pr "  return dict;\n";
-      pr "};\n";
-      pr "\n";
-  ) ["stat", stat_cols; "statvfs", statvfs_cols];
-
-  (* Dirent structures, turned into Python dictionaries. *)
-  pr "static PyObject *\n";
-  pr "put_dirent (struct guestfs_dirent *dirent)\n";
-  pr "{\n";
-  pr "  PyObject *dict;\n";
-  pr "\n";
-  pr "  dict = PyDict_New ();\n";
-  List.iter (
-    function
-    | name, `Int ->
-       pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
-       pr "                        PyLong_FromLongLong (dirent->%s));\n" name
-    | name, `Char ->
-       pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
-       pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
-    | name, `String ->
-       pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
-       pr "                        PyString_FromString (dirent->%s));\n" name
-  ) dirent_cols;
-  pr "  return dict;\n";
-  pr "};\n";
-  pr "\n";
-
-  pr "static PyObject *\n";
-  pr "put_dirent_list (struct guestfs_dirent_list *dirents)\n";
-  pr "{\n";
-  pr "  PyObject *list;\n";
-  pr "  int i;\n";
-  pr "\n";
-  pr "  list = PyList_New (dirents->len);\n";
-  pr "  for (i = 0; i < dirents->len; ++i)\n";
-  pr "    PyList_SetItem (list, i, put_dirent (&dirents->val[i]));\n";
-  pr "  return list;\n";
-  pr "};\n";
-  pr "\n";
+  ) structs;
 
   (* Python wrapper functions. *)
   List.iter (
@@ -6806,13 +6441,9 @@ py_guestfs_close (PyObject *self, PyObject *args)
        | 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"
-       | RDirentList n -> pr "  struct guestfs_dirent_list *r;\n"; "NULL" in
+       | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
+       | RStructList (_, typ) ->
+           pr "  struct guestfs_%s_list *r;\n" typ; "NULL" in
 
       List.iter (
        function
@@ -6893,32 +6524,15 @@ py_guestfs_close (PyObject *self, PyObject *args)
        | 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"
-       | RStat n ->
-          pr "  py_r = put_stat (r);\n";
-          pr "  free (r);\n"
-       | RStatVFS n ->
-          pr "  py_r = put_statvfs (r);\n";
-          pr "  free (r);\n"
+       | RStruct (_, typ) ->
+          pr "  py_r = put_%s (r);\n" typ;
+          pr "  guestfs_free_%s (r);\n" typ
+       | RStructList (_, typ) ->
+          pr "  py_r = put_%s_list (r);\n" typ;
+          pr "  guestfs_free_%s_list (r);\n" typ
        | RHashtable n ->
           pr "  py_r = put_table (r);\n";
           pr "  free_strings (r);\n"
-       | RDirentList n ->
-          pr "  py_r = put_dirent_list (r);\n";
-          pr "  guestfs_free_dirent_list (r);\n"
       );
 
       pr "  return py_r;\n";
@@ -7033,22 +6647,12 @@ class GuestFS:
          | RString _ -> doc
          | RStringList _ ->
              doc ^ "\n\nThis function returns a list of strings."
-         | RIntBool _ ->
-             doc ^ "\n\nThis function returns a tuple (int, bool).\n"
-         | RPVList _ ->
-             doc ^ "\n\nThis function returns a list of PVs.  Each PV is represented as a dictionary."
-         | RVGList _ ->
-             doc ^ "\n\nThis function returns a list of VGs.  Each VG is represented as a dictionary."
-         | RLVList _ ->
-             doc ^ "\n\nThis function returns a list of LVs.  Each LV is represented as a dictionary."
-         | RStat _ ->
-             doc ^ "\n\nThis function returns a dictionary, with keys matching the various fields in the stat structure."
-         | RStatVFS _ ->
-             doc ^ "\n\nThis function returns a dictionary, with keys matching the various fields in the statvfs structure."
+         | RStruct (_, typ) ->
+             doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
+         | RStructList (_, typ) ->
+             doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
          | RHashtable _ ->
-             doc ^ "\n\nThis function returns a dictionary."
-         | RDirentList _ ->
-             doc ^ "\n\nThis function returns a list of directory entries.  Each directory entry is represented as a dictionary." in
+             doc ^ "\n\nThis function returns a dictionary." in
        let doc =
          if List.mem ProtocolLimitWarning flags then
            doc ^ "\n\n" ^ protocol_limit_warning
@@ -7218,13 +6822,9 @@ static VALUE ruby_guestfs_close (VALUE gv)
        | 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"
-       | RDirentList n -> pr "  struct guestfs_dirent_list *r;\n"; "NULL" in
+       | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
+       | RStructList (_, typ) ->
+           pr "  struct guestfs_%s_list *r;\n" typ; "NULL" in
       pr "\n";
 
       pr "  r = guestfs_%s " name;
@@ -7265,36 +6865,12 @@ static VALUE ruby_guestfs_close (VALUE gv)
           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"
+       | RStruct (_, typ) ->
+          let cols = cols_of_struct typ in
+          generate_ruby_struct_code typ cols
+       | RStructList (_, typ) ->
+          let cols = cols_of_struct typ in
+          generate_ruby_struct_list_code typ cols
        | RHashtable _ ->
           pr "  VALUE rv = rb_hash_new ();\n";
           pr "  int i;\n";
@@ -7305,8 +6881,6 @@ static VALUE ruby_guestfs_close (VALUE gv)
           pr "  }\n";
           pr "  free (r);\n";
           pr "  return rv;\n"
-       | RDirentList n ->
-          generate_ruby_dirent_code "dirent" dirent_cols
       );
 
       pr "}\n";
@@ -7334,41 +6908,55 @@ void Init__guestfs ()
 
   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";
+(* Ruby code to return a struct. *)
+and generate_ruby_struct_code typ cols =
+  pr "  VALUE rv = 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
+    | name, FString ->
+       pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
+    | name, FUUID ->
+       pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
+    | name, (FBytes|FUInt64) ->
+       pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
+    | name, FInt64 ->
+       pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
+    | name, FUInt32 ->
+       pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
+    | name, FInt32 ->
+       pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
+    | name, FOptPercent ->
+       pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
+    | name, FChar -> (* XXX wrong? *)
+       pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
   ) cols;
-  pr "    rb_ary_push (rv, hv);\n";
-  pr "  }\n";
-  pr "  guestfs_free_lvm_%s_list (r);\n" typ;
+  pr "  guestfs_free_%s (r);\n" typ;
   pr "  return rv;\n"
 
-(* Ruby code to return a dirent struct list. *)
-and generate_ruby_dirent_code typ cols =
+(* Ruby code to return a struct list. *)
+and generate_ruby_struct_list_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, (`Char|`Int) ->
-       pr "    rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
+    | name, FString ->
+       pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
+    | name, FUUID ->
+       pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
+    | name, (FBytes|FUInt64) ->
+       pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
+    | name, FInt64 ->
+       pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
+    | name, FUInt32 ->
+       pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
+    | name, FInt32 ->
+       pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
+    | name, FOptPercent ->
+       pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
+    | name, FChar -> (* XXX wrong? *)
+       pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
   ) cols;
   pr "    rb_ary_push (rv, hv);\n";
   pr "  }\n";
@@ -7507,14 +7095,13 @@ and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
    | RBool _ -> pr "boolean ";
    | RConstString _ | RString _ -> pr "String ";
    | RStringList _ -> pr "String[] ";
-   | RIntBool _ -> pr "IntBool ";
-   | RPVList _ -> pr "PV[] ";
-   | RVGList _ -> pr "VG[] ";
-   | RLVList _ -> pr "LV[] ";
-   | RStat _ -> pr "Stat ";
-   | RStatVFS _ -> pr "StatVFS ";
+   | RStruct (_, typ) ->
+       let name = java_name_of_struct typ in
+       pr "%s " name;
+   | RStructList (_, typ) ->
+       let name = java_name_of_struct typ in
+       pr "%s[] " name;
    | RHashtable _ -> pr "HashMap<String,String> ";
-   | RDirentList _ -> pr "Dirent[] ";
   );
 
   if native then pr "_%s " name else pr "%s " name;
@@ -7549,7 +7136,7 @@ and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
   pr "    throws LibGuestFSException";
   if semicolon then pr ";"
 
-and generate_java_struct typ cols =
+and generate_java_struct jtyp cols =
   generate_header CStyle LGPLv2;
 
   pr "\
@@ -7562,16 +7149,16 @@ package com.redhat.et.libguestfs;
  * @see GuestFS
  */
 public class %s {
-" typ typ;
+" jtyp jtyp;
 
   List.iter (
     function
-    | name, `String
-    | name, `UUID -> pr "  public String %s;\n" name
-    | name, `Bytes
-    | name, `Int -> pr "  public long %s;\n" name
-    | name, `Char -> pr "  public char %s;\n" name
-    | name, `OptPercent ->
+    | name, FString
+    | name, FUUID -> pr "  public String %s;\n" name
+    | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
+    | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
+    | name, FChar -> pr "  public char %s;\n" name
+    | name, FOptPercent ->
        pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
        pr "  public float %s;\n" name
   ) cols;
@@ -7635,9 +7222,9 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
        | RInt64 _ -> pr "jlong ";
        | RBool _ -> pr "jboolean ";
        | RConstString _ | RString _ -> pr "jstring ";
-       | RIntBool _ | RStat _ | RStatVFS _ | RHashtable _ ->
+       | RStruct _ | RHashtable _ ->
           pr "jobject ";
-       | RStringList _ | RPVList _ | RVGList _ | RLVList _ | RDirentList _ ->
+       | RStringList _ | RStructList _ ->
           pr "jobjectArray ";
       );
       pr "JNICALL\n";
@@ -7678,46 +7265,18 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
            pr "  jclass cl;\n";
            pr "  jstring jstr;\n";
            pr "  char **r;\n"; "NULL", "NULL"
-       | RIntBool _ ->
+       | RStruct (_, typ) ->
            pr "  jobject jr;\n";
            pr "  jclass cl;\n";
            pr "  jfieldID fl;\n";
-           pr "  struct guestfs_int_bool *r;\n"; "NULL", "NULL"
-       | RStat _ ->
-           pr "  jobject jr;\n";
-           pr "  jclass cl;\n";
-           pr "  jfieldID fl;\n";
-           pr "  struct guestfs_stat *r;\n"; "NULL", "NULL"
-       | RStatVFS _ ->
-           pr "  jobject jr;\n";
-           pr "  jclass cl;\n";
-           pr "  jfieldID fl;\n";
-           pr "  struct guestfs_statvfs *r;\n"; "NULL", "NULL"
-       | RPVList _ ->
-           pr "  jobjectArray jr;\n";
-           pr "  jclass cl;\n";
-           pr "  jfieldID fl;\n";
-           pr "  jobject jfl;\n";
-           pr "  struct guestfs_lvm_pv_list *r;\n"; "NULL", "NULL"
-       | RVGList _ ->
-           pr "  jobjectArray jr;\n";
-           pr "  jclass cl;\n";
-           pr "  jfieldID fl;\n";
-           pr "  jobject jfl;\n";
-           pr "  struct guestfs_lvm_vg_list *r;\n"; "NULL", "NULL"
-       | RLVList _ ->
+           pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
+       | RStructList (_, typ) ->
            pr "  jobjectArray jr;\n";
            pr "  jclass cl;\n";
            pr "  jfieldID fl;\n";
            pr "  jobject jfl;\n";
-           pr "  struct guestfs_lvm_lv_list *r;\n"; "NULL", "NULL"
-       | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
-       | RDirentList _ ->
-           pr "  jobjectArray jr;\n";
-           pr "  jclass cl;\n";
-           pr "  jfieldID fl;\n";
-           pr "  jobject jfl;\n";
-           pr "  struct guestfs_dirent_list *r;\n"; "NULL", "NULL" in
+           pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
+       | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL" in
       List.iter (
        function
        | String n
@@ -7735,11 +7294,9 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
 
       let needs_i =
        (match fst style with
-        | RStringList _ | RPVList _ | RVGList _ | RLVList _
-        | RDirentList _ -> true
+        | RStringList _ | RStructList _ -> true
         | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
-        | RString _ | RIntBool _ | RStat _ | RStatVFS _
-        | RHashtable _ -> false) ||
+        | RString _ | RStruct _ | RHashtable _ -> false) ||
        List.exists (function StringList _ -> true | _ -> false) (snd style) in
       if needs_i then
        pr "  int i;\n";
@@ -7827,68 +7384,67 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
           pr "  }\n";
           pr "  free (r);\n";
           pr "  return jr;\n"
-       | RIntBool _ ->
-          pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/IntBool\");\n";
-          pr "  jr = (*env)->AllocObject (env, cl);\n";
-          pr "  fl = (*env)->GetFieldID (env, cl, \"i\", \"I\");\n";
-          pr "  (*env)->SetIntField (env, jr, fl, r->i);\n";
-          pr "  fl = (*env)->GetFieldID (env, cl, \"i\", \"Z\");\n";
-          pr "  (*env)->SetBooleanField (env, jr, fl, r->b);\n";
-          pr "  guestfs_free_int_bool (r);\n";
-          pr "  return jr;\n"
-       | RStat _ ->
-          pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/Stat\");\n";
-          pr "  jr = (*env)->AllocObject (env, cl);\n";
-          List.iter (
-            function
-            | name, `Int ->
-                pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n"
-                  name;
-                pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
-          ) stat_cols;
-          pr "  free (r);\n";
-          pr "  return jr;\n"
-       | RStatVFS _ ->
-          pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/StatVFS\");\n";
-          pr "  jr = (*env)->AllocObject (env, cl);\n";
-          List.iter (
-            function
-            | name, `Int ->
-                pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n"
-                  name;
-                pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
-          ) statvfs_cols;
-          pr "  free (r);\n";
-          pr "  return jr;\n"
-       | RPVList _ ->
-          generate_java_lvm_return "pv" "PV" pv_cols
-       | RVGList _ ->
-          generate_java_lvm_return "vg" "VG" vg_cols
-       | RLVList _ ->
-          generate_java_lvm_return "lv" "LV" lv_cols
+       | RStruct (_, typ) ->
+          let jtyp = java_name_of_struct typ in
+          let cols = cols_of_struct typ in
+          generate_java_struct_return typ jtyp cols
+       | RStructList (_, typ) ->
+          let jtyp = java_name_of_struct typ in
+          let cols = cols_of_struct typ in
+          generate_java_struct_list_return typ jtyp cols
        | RHashtable _ ->
           (* XXX *)
           pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
           pr "  return NULL;\n"
-       | RDirentList _ ->
-          generate_java_dirent_return "dirent" "Dirent" dirent_cols
       );
 
       pr "}\n";
       pr "\n"
   ) all_functions
 
-and generate_java_lvm_return typ jtyp cols =
+and generate_java_struct_return typ jtyp cols =
+  pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
+  pr "  jr = (*env)->AllocObject (env, cl);\n";
+  List.iter (
+    function
+    | name, FString ->
+       pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
+       pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
+    | name, FUUID ->
+       pr "  {\n";
+       pr "    char s[33];\n";
+       pr "    memcpy (s, r->%s, 32);\n" name;
+       pr "    s[32] = 0;\n";
+       pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
+       pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
+       pr "  }\n";
+    | name, (FBytes|FUInt64|FInt64) ->
+       pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
+       pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
+    | name, (FUInt32|FInt32) ->
+       pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
+       pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
+    | name, FOptPercent ->
+       pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
+       pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
+    | name, FChar ->
+       pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
+       pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
+  ) cols;
+  pr "  free (r);\n";
+  pr "  return jr;\n"
+
+and generate_java_struct_list_return typ jtyp cols =
   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
   pr "  for (i = 0; i < r->len; ++i) {\n";
   pr "    jfl = (*env)->AllocObject (env, cl);\n";
   List.iter (
     function
-    | name, `String ->
+    | name, FString ->
        pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
        pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
-    | name, `UUID ->
+    | name, FUUID ->
        pr "    {\n";
        pr "      char s[33];\n";
        pr "      memcpy (s, r->val[i].%s, 32);\n" name;
@@ -7896,30 +7452,17 @@ and generate_java_lvm_return typ jtyp cols =
        pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
        pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
        pr "    }\n";
-    | name, (`Bytes|`Int) ->
+    | name, (FBytes|FUInt64|FInt64) ->
        pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
        pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
-    | name, `OptPercent ->
+    | name, (FUInt32|FInt32) ->
+       pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
+       pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
+    | name, FOptPercent ->
        pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
        pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
-  ) cols;
-  pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
-  pr "  }\n";
-  pr "  guestfs_free_lvm_%s_list (r);\n" typ;
-  pr "  return jr;\n"
-
-and generate_java_dirent_return typ jtyp cols =
-  pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
-  pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
-  pr "  for (i = 0; i < r->len; ++i) {\n";
-  pr "    jfl = (*env)->AllocObject (env, cl);\n";
-  List.iter (
-    function
-    | name, `String ->
-       pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
-       pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
-    | name, (`Char|`Int) ->
-       pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
+    | name, FChar ->
+       pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
        pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
   ) cols;
   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
@@ -7942,14 +7485,9 @@ and generate_haskell_hs () =
     | RConstString _, _
     | RString _, _
     | RStringList _, _
-    | RIntBool _, _
-    | RPVList _, _
-    | RVGList _, _
-    | RLVList _, _
-    | RStat _, _
-    | RStatVFS _, _
-    | RHashtable _, _
-    | RDirentList _, _ -> false in
+    | RStruct _, _
+    | RStructList _, _
+    | RHashtable _, _ -> false in
 
   pr "\
 {-# INCLUDE <guestfs.h> #-}
@@ -8058,9 +7596,8 @@ last_error h = do
             pr "    then do\n";
             pr "      err <- last_error h\n";
             pr "      fail err\n";
-        | RConstString _ | RString _ | RStringList _ | RIntBool _
-        | RPVList _ | RVGList _ | RLVList _ | RStat _ | RStatVFS _
-        | RHashtable _ | RDirentList _ ->
+        | RConstString _ | RString _ | RStringList _ | RStruct _
+        | RStructList _ | RHashtable _ ->
             pr "  if (r == nullPtr)\n";
             pr "    then do\n";
             pr "      err <- last_error h\n";
@@ -8078,14 +7615,9 @@ last_error h = do
         | RConstString _
         | RString _
         | RStringList _
-        | RIntBool _
-        | RPVList _
-        | RVGList _
-        | RLVList _
-        | RStat _
-        | RStatVFS _
-        | RHashtable _
-        | RDirentList _ ->
+        | RStruct _
+        | RStructList _
+        | RHashtable _ ->
             pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
        );
        pr "\n";
@@ -8120,14 +7652,13 @@ and generate_haskell_prototype ~handle ?(hs = false) style =
    | RConstString _ -> pr "%s" string
    | RString _ -> pr "%s" string
    | RStringList _ -> pr "[%s]" string
-   | RIntBool _ -> pr "IntBool"
-   | RPVList _ -> pr "[PV]"
-   | RVGList _ -> pr "[VG]"
-   | RLVList _ -> pr "[LV]"
-   | RStat _ -> pr "Stat"
-   | RStatVFS _ -> pr "StatVFS"
+   | RStruct (_, typ) ->
+       let name = java_name_of_struct typ in
+       pr "%s" name
+   | RStructList (_, typ) ->
+       let name = java_name_of_struct typ in
+       pr "[%s]" name
    | RHashtable _ -> pr "Hashtable"
-   | RDirentList _ -> pr "[Dirent]"
   );
   pr ")"
 
@@ -8144,6 +7675,8 @@ and generate_bindtests () =
 #include \"guestfs_protocol.h\"
 
 #define error guestfs_error
+#define safe_calloc guestfs_safe_calloc
+#define safe_malloc guestfs_safe_malloc
 
 static void
 print_strings (char * const* const argv)
@@ -8219,84 +7752,36 @@ print_strings (char * const* const argv)
             pr "  char **strs;\n";
             pr "  int n, i;\n";
             pr "  sscanf (val, \"%%d\", &n);\n";
-            pr "  strs = malloc ((n+1) * sizeof (char *));\n";
+            pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
             pr "  for (i = 0; i < n; ++i) {\n";
-            pr "    strs[i] = malloc (16);\n";
+            pr "    strs[i] = safe_malloc (g, 16);\n";
             pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
             pr "  }\n";
             pr "  strs[n] = NULL;\n";
             pr "  return strs;\n"
-        | RIntBool _ ->
-            pr "  struct guestfs_int_bool *r;\n";
-            pr "  r = malloc (sizeof (struct guestfs_int_bool));\n";
-            pr "  sscanf (val, \"%%\" SCNi32, &r->i);\n";
-            pr "  r->b = 0;\n";
+        | RStruct (_, typ) ->
+            pr "  struct guestfs_%s *r;\n" typ;
+            pr "  r = safe_calloc (g, sizeof *r, 1);\n";
             pr "  return r;\n"
-        | RPVList _ ->
-            pr "  struct guestfs_lvm_pv_list *r;\n";
-            pr "  int i;\n";
-            pr "  r = malloc (sizeof (struct guestfs_lvm_pv_list));\n";
+        | RStructList (_, typ) ->
+            pr "  struct guestfs_%s_list *r;\n" typ;
+            pr "  r = safe_calloc (g, sizeof *r, 1);\n";
             pr "  sscanf (val, \"%%d\", &r->len);\n";
-            pr "  r->val = calloc (r->len, sizeof (struct guestfs_lvm_pv));\n";
-            pr "  for (i = 0; i < r->len; ++i) {\n";
-            pr "    r->val[i].pv_name = malloc (16);\n";
-            pr "    snprintf (r->val[i].pv_name, 16, \"%%d\", i);\n";
-            pr "  }\n";
-            pr "  return r;\n"
-        | RVGList _ ->
-            pr "  struct guestfs_lvm_vg_list *r;\n";
-            pr "  int i;\n";
-            pr "  r = malloc (sizeof (struct guestfs_lvm_vg_list));\n";
-            pr "  sscanf (val, \"%%d\", &r->len);\n";
-            pr "  r->val = calloc (r->len, sizeof (struct guestfs_lvm_vg));\n";
-            pr "  for (i = 0; i < r->len; ++i) {\n";
-            pr "    r->val[i].vg_name = malloc (16);\n";
-            pr "    snprintf (r->val[i].vg_name, 16, \"%%d\", i);\n";
-            pr "  }\n";
-            pr "  return r;\n"
-        | RLVList _ ->
-            pr "  struct guestfs_lvm_lv_list *r;\n";
-            pr "  int i;\n";
-            pr "  r = malloc (sizeof (struct guestfs_lvm_lv_list));\n";
-            pr "  sscanf (val, \"%%d\", &r->len);\n";
-            pr "  r->val = calloc (r->len, sizeof (struct guestfs_lvm_lv));\n";
-            pr "  for (i = 0; i < r->len; ++i) {\n";
-            pr "    r->val[i].lv_name = malloc (16);\n";
-            pr "    snprintf (r->val[i].lv_name, 16, \"%%d\", i);\n";
-            pr "  }\n";
-            pr "  return r;\n"
-        | RStat _ ->
-            pr "  struct guestfs_stat *r;\n";
-            pr "  r = calloc (1, sizeof (*r));\n";
-            pr "  sscanf (val, \"%%\" SCNi64, &r->dev);\n";
-            pr "  return r;\n"
-        | RStatVFS _ ->
-            pr "  struct guestfs_statvfs *r;\n";
-            pr "  r = calloc (1, sizeof (*r));\n";
-            pr "  sscanf (val, \"%%\" SCNi64, &r->bsize);\n";
+            pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
             pr "  return r;\n"
         | RHashtable _ ->
             pr "  char **strs;\n";
             pr "  int n, i;\n";
             pr "  sscanf (val, \"%%d\", &n);\n";
-            pr "  strs = malloc ((n*2+1) * sizeof (char *));\n";
+            pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
             pr "  for (i = 0; i < n; ++i) {\n";
-            pr "    strs[i*2] = malloc (16);\n";
-            pr "    strs[i*2+1] = malloc (16);\n";
+            pr "    strs[i*2] = safe_malloc (g, 16);\n";
+            pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
             pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
             pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
             pr "  }\n";
             pr "  strs[n*2] = NULL;\n";
             pr "  return strs;\n"
-        | RDirentList _ ->
-            pr "  struct guestfs_dirent_list *r;\n";
-            pr "  int i;\n";
-            pr "  r = malloc (sizeof (struct guestfs_dirent_list));\n";
-            pr "  sscanf (val, \"%%d\", &r->len);\n";
-            pr "  r->val = calloc (r->len, sizeof (struct guestfs_dirent));\n";
-            pr "  for (i = 0; i < r->len; ++i)\n";
-            pr "    r->val[i].ino = i;\n";
-            pr "  return r;\n"
        );
        pr "}\n";
        pr "\n"
@@ -8310,10 +7795,9 @@ print_strings (char * const* const argv)
         | RErr | RInt _ | RInt64 _ | RBool _ ->
             pr "  return -1;\n"
         | RConstString _
-        | RString _ | RStringList _ | RIntBool _
-        | RPVList _ | RVGList _ | RLVList _ | RStat _ | RStatVFS _
-        | RHashtable _
-        | RDirentList _ ->
+        | RString _ | RStringList _ | RStruct _
+        | RStructList _
+        | RHashtable _ ->
             pr "  return NULL;\n"
        );
        pr "}\n";
@@ -8605,7 +8089,7 @@ let output_to filename =
 let () =
   check_functions ();
 
-  if not (Sys.file_exists "configure.ac") then (
+  if not (Sys.file_exists "config.status") then (
     eprintf "\
 You are probably running this from the wrong directory.
 Run it from the top source directory using the command
@@ -8722,29 +8206,14 @@ Run it from the top source directory using the command
   generate_java_java ();
   close ();
 
-  let close = output_to "java/com/redhat/et/libguestfs/PV.java" in
-  generate_java_struct "PV" pv_cols;
-  close ();
-
-  let close = output_to "java/com/redhat/et/libguestfs/VG.java" in
-  generate_java_struct "VG" vg_cols;
-  close ();
-
-  let close = output_to "java/com/redhat/et/libguestfs/LV.java" in
-  generate_java_struct "LV" lv_cols;
-  close ();
-
-  let close = output_to "java/com/redhat/et/libguestfs/Stat.java" in
-  generate_java_struct "Stat" stat_cols;
-  close ();
-
-  let close = output_to "java/com/redhat/et/libguestfs/StatVFS.java" in
-  generate_java_struct "StatVFS" statvfs_cols;
-  close ();
-
-  let close = output_to "java/com/redhat/et/libguestfs/Dirent.java" in
-  generate_java_struct "Dirent" dirent_cols;
-  close ();
+  List.iter (
+    fun (typ, jtyp) ->
+      let cols = cols_of_struct typ in
+      let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
+      let close = output_to filename in
+      generate_java_struct jtyp cols;
+      close ();
+  ) java_structs;
 
   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
   generate_java_c ();
index c3bce0b..66ab12a 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stddef.h>
 #include <unistd.h>
 #include <ctype.h>
 #include <string.h>
@@ -453,6 +454,42 @@ guestfs_safe_malloc (guestfs_h *g, size_t nbytes)
   return ptr;
 }
 
+/* Return 1 if an array of N objects, each of size S, cannot exist due
+   to size arithmetic overflow.  S must be positive and N must be
+   nonnegative.  This is a macro, not an inline function, so that it
+   works correctly even when SIZE_MAX < N.
+
+   By gnulib convention, SIZE_MAX represents overflow in size
+   calculations, so the conservative dividend to use here is
+   SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
+   However, malloc (SIZE_MAX) fails on all known hosts where
+   sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
+   exactly-SIZE_MAX allocations on such hosts; this avoids a test and
+   branch when S is known to be 1.  */
+# define xalloc_oversized(n, s) \
+    ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
+
+/* Technically we should add an autoconf test for this, testing for the desired
+   functionality, like what's done in gnulib, but for now, this is fine.  */
+#define HAVE_GNU_CALLOC (__GLIBC__ >= 2)
+
+/* Allocate zeroed memory for N elements of S bytes, with error
+   checking.  S must be nonzero.  */
+void *
+guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s)
+{
+  /* From gnulib's calloc function in xmalloc.c.  */
+  void *p;
+  /* Test for overflow, since some calloc implementations don't have
+     proper overflow checks.  But omit overflow and size-zero tests if
+     HAVE_GNU_CALLOC, since GNU calloc catches overflow and never
+     returns NULL if successful.  */
+  if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s))
+      || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
+    g->abort_cb ();
+  return p;
+}
+
 void *
 guestfs_safe_realloc (guestfs_h *g, void *ptr, int nbytes)
 {
@@ -630,6 +667,17 @@ guestfs_get_memsize (guestfs_h *g)
   return g->memsize;
 }
 
+int
+guestfs_get_pid (guestfs_h *g)
+{
+  if (g->pid > 0)
+    return g->pid;
+  else {
+    error (g, "get_pid: no qemu subprocess");
+    return -1;
+  }
+}
+
 /* Add a string to the current command line. */
 static void
 incr_cmdline_size (guestfs_h *g)
@@ -1442,44 +1490,6 @@ guestfs_end_busy (guestfs_h *g)
   return 0;
 }
 
-/* Structure-freeing functions.  These rely on the fact that the
- * structure format is identical to the XDR format.  See note in
- * generator.ml.
- */
-void
-guestfs_free_int_bool (struct guestfs_int_bool *x)
-{
-  free (x);
-}
-
-void
-guestfs_free_lvm_pv_list (struct guestfs_lvm_pv_list *x)
-{
-  xdr_free ((xdrproc_t) xdr_guestfs_lvm_int_pv_list, (char *) x);
-  free (x);
-}
-
-void
-guestfs_free_lvm_vg_list (struct guestfs_lvm_vg_list *x)
-{
-  xdr_free ((xdrproc_t) xdr_guestfs_lvm_int_vg_list, (char *) x);
-  free (x);
-}
-
-void
-guestfs_free_lvm_lv_list (struct guestfs_lvm_lv_list *x)
-{
-  xdr_free ((xdrproc_t) xdr_guestfs_lvm_int_lv_list, (char *) x);
-  free (x);
-}
-
-void
-guestfs_free_dirent_list (struct guestfs_dirent_list *x)
-{
-  xdr_free ((xdrproc_t) xdr_guestfs_int_dirent_list, (char *) x);
-  free (x);
-}
-
 /* We don't know if stdout_event or sock_read_event will be the
  * first to receive EOF if the qemu process dies.  This function
  * has the common cleanup code for both.
@@ -2239,6 +2249,10 @@ guestfs__receive_file_sync (guestfs_h *g, const char *filename)
   char fbuf[4];
   uint32_t flag = GUESTFS_CANCEL_FLAG;
 
+  if (g->verbose)
+    fprintf (stderr, "%s: waiting for daemon to acknowledge cancellation\n",
+            __func__);
+
   xdrmem_create (&xdr, fbuf, sizeof fbuf, XDR_ENCODE);
   xdr_uint32_t (&xdr, &flag);
   xdr_destroy (&xdr);
index 201d60c..f2e108b 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs
- * Copyright (C) 2009 Red Hat Inc. 
+ * 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
@@ -52,13 +52,6 @@ extern guestfs_abort_cb guestfs_get_out_of_memory_handler (guestfs_h *g);
 #include <guestfs-structs.h>
 #include <guestfs-actions.h>
 
-/* Free up return values. */
-extern void guestfs_free_int_bool (struct guestfs_int_bool *);
-extern void guestfs_free_lvm_pv_list (struct guestfs_lvm_pv_list *);
-extern void guestfs_free_lvm_vg_list (struct guestfs_lvm_vg_list *);
-extern void guestfs_free_lvm_lv_list (struct guestfs_lvm_lv_list *);
-extern void guestfs_free_dirent_list (struct guestfs_dirent_list *);
-
 /* Low-level event API. */
 typedef void (*guestfs_send_cb) (guestfs_h *g, void *data);
 typedef void (*guestfs_reply_cb) (guestfs_h *g, void *data, XDR *xdr);
@@ -77,6 +70,7 @@ extern void guestfs_error (guestfs_h *g, const char *fs, ...)
 extern void guestfs_perrorf (guestfs_h *g, const char *fs, ...)
   __attribute__((format (printf,2,3)));
 extern void *guestfs_safe_malloc (guestfs_h *g, size_t nbytes);
+extern void *guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s);
 extern void *guestfs_safe_realloc (guestfs_h *g, void *ptr, int nbytes);
 extern char *guestfs_safe_strdup (guestfs_h *g, const char *str);
 extern void *guestfs_safe_memdup (guestfs_h *g, void *ptr, size_t size);