Rewrite of main loop impl, start of FileIn/FileOut support.
authorRichard Jones <rjones@redhat.com>
Sat, 18 Apr 2009 12:17:12 +0000 (13:17 +0100)
committerRichard Jones <rjones@redhat.com>
Sat, 18 Apr 2009 12:17:12 +0000 (13:17 +0100)
17 files changed:
daemon/Makefile.am
daemon/daemon.h
daemon/upload.c [new file with mode: 0644]
fish/cmds.c
guestfish-actions.pod
guestfs-actions.pod
guestfs.pod
perl/lib/Sys/Guestfs.pm
python/guestfs-py.c
python/guestfs.py
src/generator.ml
src/guestfs-actions.c
src/guestfs.c
src/guestfs.h
src/guestfs_protocol.c
src/guestfs_protocol.h
src/guestfs_protocol.x

index 75de066..1c1609d 100644 (file)
@@ -36,6 +36,7 @@ guestfsd_SOURCES = \
        stubs.c \
        sync.c \
        tune2fs.c \
        stubs.c \
        sync.c \
        tune2fs.c \
+       upload.c \
        ../src/guestfs_protocol.h \
        ../src/guestfs_protocol.c
 
        ../src/guestfs_protocol.h \
        ../src/guestfs_protocol.c
 
index 27d86c9..ca71265 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "../src/guestfs_protocol.h"
 
 
 #include "../src/guestfs_protocol.h"
 
-/* in guestfsd.c */
+/*-- in guestfsd.c --*/
 extern int xwrite (int sock, const void *buf, size_t len);
 extern int xread (int sock, void *buf, size_t len);
 
 extern int xwrite (int sock, const void *buf, size_t len);
 extern int xread (int sock, void *buf, size_t len);
 
@@ -44,25 +44,37 @@ extern int command (char **stdoutput, char **stderror, const char *name, ...);
 extern int commandv (char **stdoutput, char **stderror,
                     char * const* const argv);
 
 extern int commandv (char **stdoutput, char **stderror,
                     char * const* const argv);
 
-/* in proto.c */
+/*-- in proto.c --*/
 extern int proc_nr;
 extern int serial;
 
 extern int proc_nr;
 extern int serial;
 
-/* in mount.c */
+/*-- in mount.c --*/
 extern int root_mounted;
 
 extern int root_mounted;
 
-/* in stubs.c (auto-generated) */
+/*-- 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 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);
 
-/* in proto.c */
+/*-- in proto.c --*/
 extern void main_loop (int sock);
 extern void main_loop (int sock);
+
+/* ordinary daemon functions use these to indicate errors */
 extern void reply_with_error (const char *fs, ...);
 extern void reply_with_perror (const char *fs, ...);
 extern void reply_with_error (const char *fs, ...);
 extern void reply_with_perror (const char *fs, ...);
+
+/* daemon functions that return files (FileOut) should call
+ * reply, then send_file for each FileOut parameter.
+ */
+#if 0
+extern void send_file ();
+#endif
+
+/* only call this if there is a FileOut parameter */
 extern void reply (xdrproc_t xdrp, char *ret);
 
 extern void reply (xdrproc_t xdrp, char *ret);
 
+/* Helper for functions that need a root filesystem mounted. */
 #define NEED_ROOT(errcode)                                             \
   do {                                                                 \
     if (!root_mounted) {                                               \
 #define NEED_ROOT(errcode)                                             \
   do {                                                                 \
     if (!root_mounted) {                                               \
@@ -72,6 +84,7 @@ extern void reply (xdrproc_t xdrp, char *ret);
   }                                                                    \
   while (0)
 
   }                                                                    \
   while (0)
 
+/* Helper for functions that need an argument ("path") that is absolute. */
 #define ABS_PATH(path,errcode)                                         \
   do {                                                                 \
     if ((path)[0] != '/') {                                            \
 #define ABS_PATH(path,errcode)                                         \
   do {                                                                 \
     if ((path)[0] != '/') {                                            \
@@ -80,6 +93,7 @@ extern void reply (xdrproc_t xdrp, char *ret);
     }                                                                  \
   } while (0)
 
     }                                                                  \
   } while (0)
 
+/* Helper for functions that need an argument ("path") that is a device. */
 #define IS_DEVICE(path,errcode)                                                \
   do {                                                                 \
     struct stat statbuf;                                               \
 #define IS_DEVICE(path,errcode)                                                \
   do {                                                                 \
     struct stat statbuf;                                               \
@@ -104,6 +118,7 @@ extern void reply (xdrproc_t xdrp, char *ret);
 #define CHROOT_OUT \
   do { int old_errno = errno; chroot ("."); errno = old_errno; } while (0)
 
 #define CHROOT_OUT \
   do { int old_errno = errno; chroot ("."); errno = old_errno; } while (0)
 
+/* Marks functions which are not implemented. */
 #define XXX_NOT_IMPL(errcode)                                          \
   do {                                                                 \
     reply_with_error ("%s: function not implemented", __func__);       \
 #define XXX_NOT_IMPL(errcode)                                          \
   do {                                                                 \
     reply_with_error ("%s: function not implemented", __func__);       \
diff --git a/daemon/upload.c b/daemon/upload.c
new file mode 100644 (file)
index 0000000..d2feb02
--- /dev/null
@@ -0,0 +1,40 @@
+/* libguestfs - the guestfsd daemon
+ * 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.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "../src/guestfs_protocol.h"
+#include "daemon.h"
+#include "actions.h"
+
+int
+do_upload (const char *remote_filename)
+{
+  XXX_NOT_IMPL (-1);
+}
+
+int
+do_download (const char *remote_filename)
+{
+  XXX_NOT_IMPL (-1);
+}
index 8ee72d2..c197ece 100644 (file)
@@ -155,7 +155,7 @@ void display_command (const char *cmd)
     pod2text ("touch - update file timestamps or create a new file", " touch <path>\n\nTouch acts like the L<touch(1)> command.  It can be used to\nupdate the timestamps on a file, or, if the file does not exist,\nto create a new zero-length file.");
   else
   if (strcasecmp (cmd, "cat") == 0)
     pod2text ("touch - update file timestamps or create a new file", " touch <path>\n\nTouch acts like the L<touch(1)> command.  It can be used to\nupdate the timestamps on a file, or, if the file does not exist,\nto create a new zero-length file.");
   else
   if (strcasecmp (cmd, "cat") == 0)
-    pod2text ("cat - list the contents of a file", " cat <path>\n\nReturn the contents of the file named C<path>.\n\nNote that this function cannot correctly handle binary files\n(specifically, files containing C<\\0> character which is treated\nas end of string).  For those you need to use the C<read_file>\nfunction which has a more complex interface.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB.  To transfer large files you should use\nFTP.");
+    pod2text ("cat - list the contents of a file", " cat <path>\n\nReturn the contents of the file named C<path>.\n\nNote that this function cannot correctly handle binary files\n(specifically, files containing C<\\0> character which is treated\nas end of string).  For those you need to use the C<download>\nfunction which has a more complex interface.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB.  To transfer large files you should use\nFTP.");
   else
   if (strcasecmp (cmd, "ll") == 0)
     pod2text ("ll - list the files in a directory (long format)", " ll <directory>\n\nList the files in C<directory> (relative to the root directory,\nthere is no cwd) in the format of 'ls -la'.\n\nThis command is mostly useful for interactive sessions.  It\nis I<not> intended that you try to parse the output string.");
   else
   if (strcasecmp (cmd, "ll") == 0)
     pod2text ("ll - list the files in a directory (long format)", " ll <directory>\n\nList the files in C<directory> (relative to the root directory,\nthere is no cwd) in the format of 'ls -la'.\n\nThis command is mostly useful for interactive sessions.  It\nis I<not> intended that you try to parse the output string.");
index d4c0401..116878d 100644 (file)
@@ -289,7 +289,7 @@ Return the contents of the file named C<path>.
 
 Note that this function cannot correctly handle binary files
 (specifically, files containing C<\0> character which is treated
 
 Note that this function cannot correctly handle binary files
 (specifically, files containing C<\0> character which is treated
-as end of string).  For those you need to use the C<read_file>
+as end of string).  For those you need to use the C<download>
 function which has a more complex interface.
 
 Because of the message protocol, there is a transfer limit 
 function which has a more complex interface.
 
 Because of the message protocol, there is a transfer limit 
index cb2415c..520425c 100644 (file)
@@ -378,7 +378,7 @@ Return the contents of the file named C<path>.
 
 Note that this function cannot correctly handle binary files
 (specifically, files containing C<\0> character which is treated
 
 Note that this function cannot correctly handle binary files
 (specifically, files containing C<\0> character which is treated
-as end of string).  For those you need to use the C<guestfs_read_file>
+as end of string).  For those you need to use the C<guestfs_download>
 function which has a more complex interface.
 
 This function returns a string, or NULL on error.
 function which has a more complex interface.
 
 This function returns a string, or NULL on error.
index 6c01600..cce7b90 100644 (file)
@@ -86,9 +86,8 @@ C<guestfs_h> is the opaque type representing a connection handle.
 Create a handle by calling C<guestfs_create>.  Call C<guestfs_close>
 to free the handle and release all resources used.
 
 Create a handle by calling C<guestfs_create>.  Call C<guestfs_close>
 to free the handle and release all resources used.
 
-Handles and operations on handles are not thread safe.  However you
-can use a separate handle for each thread (but not on the same disk
-image).
+For information on using multiple handles and threads, see the section
+MULTIPLE HANDLES AND MULTIPLE THREADS below.
 
 =head2 guestfs_create
 
 
 =head2 guestfs_create
 
@@ -312,34 +311,21 @@ this function with C<cb> set to C<NULL>.
 
 =head2 NON-BLOCKING ACTIONS
 
 
 =head2 NON-BLOCKING ACTIONS
 
-XXX NOT IMPLEMENTED YET XXX
+XXX This section was documented in previous versions but never
+implemented in a way which matched the documentation.  For now I have
+removed the documentation, pending a working implementation.  See also
+C<src/guestfs-actions.c> in the source.
 
 
-C<guestfs_set_reply_callback> is the most interesting callback to
-play with, since it allows you to perform actions without blocking.
 
 
-For example:
+=head2 guestfs_set_send_callback
 
 
- do_it ()
- {
-   start_call ();
-   guestfs_main_loop_run (); /* --> blocks, then calls my_cb */
- }
+ typedef void (*guestfs_send_cb) (guestfs_h *g, void *opaque);
+ void guestfs_set_send_callback (guestfs_h *handle,
+                                 guestfs_send_cb cb,
+                                 void *opaque);
 
 
- start_call ()
- {
-   guestfs_set_reply_callback (handle, my_cb, data);
-   guestfs_nb_[action] (handle, [other parameters ...]);
-   /* returns immediately */
- }
- my_cb (guestfs_h *handle, void *data, XDR *xdr)
- {
-   retval = guestfs_nb_[action]_r (handle, xdr);
-   /* ... */
- }
-
-There are C<guestfs_nb_*> and C<guestfs_nb_*_r> functions
-corresponding to every C<guestfs_*> action in the high-level API.
+The callback function C<cb> will be called whenever a message
+which is queued for sending, has been sent.
 
 =head2 guestfs_set_reply_callback
 
 
 =head2 guestfs_set_reply_callback
 
@@ -400,9 +386,10 @@ non-blocking wait for the child process to finish booting up.
 
 =head2 EVENT MAIN LOOP
 
 
 =head2 EVENT MAIN LOOP
 
-To use the low-level event API, you have to provide an event "main
-loop".  You can write your own, but if you don't want to write one,
-two are provided for you:
+To use the low-level event API and/or to use handles from multiple
+threads, you have to provide an event "main loop".  You can write your
+own, but if you don't want to write one, two types are provided for
+you:
 
 =over 4
 
 
 =over 4
 
@@ -410,8 +397,8 @@ two are provided for you:
 
 A simple main loop that is implemented using L<select(2)>.
 
 
 A simple main loop that is implemented using L<select(2)>.
 
-This is the default main loop unless you call C<guestfs_set_main_loop>
-or C<guestfs_glib_set_main_loop>.
+This is the default main loop for new guestfs handles, unless you
+call C<guestfs_set_main_loop> after a handle is created.
 
 =item libguestfs-glib
 
 
 =item libguestfs-glib
 
@@ -421,67 +408,83 @@ without hanging during long or slow operations.
 
 =back
 
 
 =back
 
-=head2 guestfs_set_main_loop
+=head2 MULTIPLE HANDLES AND MULTIPLE THREADS
+
+The support for multiple handles and multiple threads is modelled
+after glib (although doesn't require glib, if you use the select-based
+main loop).
+
+L<http://library.gnome.org/devel/glib/unstable/glib-The-Main-Event-Loop.html>
+
+You will need to create one main loop for each thread that wants to
+use libguestfs.  Each guestfs handle should be confined to one thread.
+If you try to pass guestfs handles between threads, you will get
+undefined results.
+
+If you only want to use guestfs handles from one thread in your
+program, but your program has other threads doing other things, then
+you don't need to do anything special.
 
 
- void guestfs_set_main_loop (guestfs_main_loop *);
+=head2 SINGLE THREAD CASE
 
 
-This call sets the current main loop to the list of callbacks
-contained in the C<guestfs_main_loop> structure.
+In the single thread case, there is a single select-based main loop
+created for you.  All guestfs handles will use this main loop to
+execute high level API actions.
 
 
-Only one main loop implementation can be used by libguestfs, so
-calling this replaces the previous one.  (So this is something that
-has to be done by the main program, but only the main program "knows"
-that it is a GTK+ program or whatever).
+=head2 MULTIPLE THREADS CASE
+
+In the multiple threads case, you will need to create a main loop for
+each thread that wants to use libguestfs.
+
+To create main loops for other threads, use
+C<guestfs_create_main_loop> or C<guestfs_glib_create_main_loop>.
+
+Then you will need to attach each handle to the thread-specific main
+loop by calling:
+
+ handle = guestfs_create ();
+ guestfs_set_main_loop (handle, main_loop_of_current_thread);
+
+=head2 guestfs_set_main_loop
 
 
-You should call this early in the main program, certainly before
-calling C<guestfs_create>.
+ void guestfs_set_main_loop (guestfs_h *handle,
+                             guestfs_main_loop *main_loop);
 
 
-=head2 guestfs_glib_set_main_loop
+Sets the main loop used by high level API actions for this handle.  By
+default, the select-based main loop is used (see
+C<guestfs_get_default_main_loop>).
 
 
- void guestfs_glib_set_main_loop (GMainLoop *);
+You only need to use this in multi-threaded programs, where multiple
+threads want to use libguestfs.  Create a main loop for each thread,
+then call this function.
 
 
-This helper calls C<guestfs_set_main_loop> with the correct callbacks
-for integrating with the GLib main loop.
+You cannot pass guestfs handles between threads.
 
 
-The libguestfs-glib main loop is contained in a separate library, so
-that libguestfs doesn't depend on the whole of GLib:
+=head2 guestfs_get_main_loop
 
 
- #include <glib.h>
- #include <guestfs-glib.h>
+ guestfs_main_loop *guestfs_get_main_loop (guestfs_h *handle);
 
 
- main ()
- {
-   GMainLoop *loop =
-     g_main_loop_new (g_main_context_default (), 1);
-   ...
-   guestfs_glib_set_main_loop (loop);
-   ...
-   g_main_loop_run (loop);
- }
+Return the main loop used by C<handle>.
 
 
-To use this main loop you must link with C<-lguestfs-glib>.  (See also
-the GLib and GTK+ documentation).
+=head2 guestfs_get_default_main_loop
 
 
-=head2 guestfs_main_loop_run
+ guestfs_main_loop *guestfs_get_default_main_loop (void);
 
 
- void guestfs_main_loop_run (void);
+Return the default select-based main loop.
 
 
-This calls the main loop.
+=head2 guestfs_create_main_loop
 
 
-For some types of main loop you may want or prefer to call another
-function, eg. C<g_main_loop_run>, or the main loop may already be
-invoked by another part of your program.  In those cases, ignore this
-call.
+ guestfs_main_loop *guestfs_create_main_loop (void);
 
 
-=head2 guestfs_main_loop_quit
+This creates a select-based main loop.  You should create one main
+loop for each additional thread that needs to use libguestfs.
 
 
- void guestfs_main_loop_quit (void);
+=head2 guestfs_free_main_loop
 
 
-This instructs the main loop to quit.  In other words,
-C<guestfs_main_loop_run> will return.
+ void guestfs_free_main_loop (guestfs_main_loop *);
 
 
-For some types of main loop you may want or prefer to call another
-function, eg. C<g_main_loop_quit>.  In those cases, ignore this call.
+Free the select-based main loop which was previously allocated with
+C<guestfs_create_main_loop>.
 
 =head2 WRITING A CUSTOM MAIN LOOP
 
 
 =head2 WRITING A CUSTOM MAIN LOOP
 
index a351d57..28d2b0f 100644 (file)
@@ -330,7 +330,7 @@ Return the contents of the file named C<path>.
 
 Note that this function cannot correctly handle binary files
 (specifically, files containing C<\0> character which is treated
 
 Note that this function cannot correctly handle binary files
 (specifically, files containing C<\0> character which is treated
-as end of string).  For those you need to use the C<$h-E<gt>read_file>
+as end of string).  For those you need to use the C<$h-E<gt>download>
 function which has a more complex interface.
 
 Because of the message protocol, there is a transfer limit 
 function which has a more complex interface.
 
 Because of the message protocol, there is a transfer limit 
index c8df178..09d4270 100644 (file)
@@ -103,7 +103,6 @@ put_table (char * const * const argv)
 
   list = PyList_New (argc >> 1);
   for (i = 0; i < argc; i += 2) {
 
   list = PyList_New (argc >> 1);
   for (i = 0; i < argc; i += 2) {
-    PyObject *item;
     item = PyTuple_New (2);
     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
     item = PyTuple_New (2);
     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
index 9739fa5..0a4c396 100644 (file)
@@ -236,7 +236,7 @@ class GuestFS:
         Note that this function cannot correctly handle binary
         files (specifically, files containing "\\0" character
         which is treated as end of string). For those you need
         Note that this function cannot correctly handle binary
         files (specifically, files containing "\\0" character
         which is treated as end of string). For those you need
-        to use the "g.read_file" function which has a more
+        to use the "g.download" function which has a more
         complex interface.
         
         Because of the message protocol, there is a transfer
         complex interface.
         
         Because of the message protocol, there is a transfer
index c0a4740..77bcc47 100755 (executable)
@@ -98,6 +98,16 @@ and argt =
   | StringList of string(* list of strings (each string cannot be NULL) *)
   | Bool of string     (* boolean *)
   | Int of string      (* int (smallish ints, signed, <= 31 bits) *)
   | StringList of string(* list of strings (each string cannot be NULL) *)
   | Bool of string     (* boolean *)
   | Int of string      (* int (smallish ints, signed, <= 31 bits) *)
+    (* These are treated as filenames (simple string parameters) in
+     * the C API and bindings.  But in the RPC protocol, we transfer
+     * the actual file content up to or down from the daemon.
+     * FileIn: local machine -> daemon (in request)
+     * FileOut: daemon -> local machine (in reply)
+     * In guestfish (only), the special name "-" means read from
+     * stdin or write to stdout.
+     *)
+  | FileIn of string
+  | FileOut of string
 
 type flags =
   | ProtocolLimitWarning  (* display warning about protocol size limits *)
 
 type flags =
   | ProtocolLimitWarning  (* display warning about protocol size limits *)
@@ -384,7 +394,7 @@ Return the contents of the file named C<path>.
 
 Note that this function cannot correctly handle binary files
 (specifically, files containing C<\\0> character which is treated
 
 Note that this function cannot correctly handle binary files
 (specifically, files containing C<\\0> character which is treated
-as end of string).  For those you need to use the C<guestfs_read_file>
+as end of string).  For those you need to use the C<guestfs_download>
 function which has a more complex interface.");
 
   ("ll", (RString "listing", [String "directory"]), 5, [],
 function which has a more complex interface.");
 
   ("ll", (RString "listing", [String "directory"]), 5, [],
@@ -1198,6 +1208,30 @@ Reread the partition table on C<device>.
 
 This uses the L<blockdev(8)> command.");
 
 
 This uses the L<blockdev(8)> command.");
 
+(*
+  ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
+   [],
+   "upload a file from the local machine",
+   "\
+Upload local file C<filename> to C<remotefilename> on the
+filesystem.
+
+C<filename> can also be a named pipe.
+
+See also C<guestfs_upload>.");
+
+  ("download", (RErr, [String "remotefilename"; FileOut "filename"]), 67, [],
+   [],
+   "download a file to the local machine",
+   "\
+Download file C<remotefilename> and save it as C<filename>
+on the local machine.
+
+C<filename> can also be a named pipe.
+
+See also C<guestfs_download>, C<guestfs_cat>.");
+*)
+
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
@@ -1410,7 +1444,8 @@ let mapi f xs =
   loop 0 xs
 
 let name_of_argt = function
   loop 0 xs
 
 let name_of_argt = function
-  | String n | OptString n | StringList n | Bool n | Int n -> n
+  | String n | OptString n | StringList n | Bool n | Int n
+  | FileIn n | FileOut n -> n
 
 let seq_of_test = function
   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
 
 let seq_of_test = function
   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
@@ -1765,6 +1800,7 @@ and generate_xdr () =
             | StringList n -> pr "  str %s<>;\n" n
             | Bool n -> pr "  bool %s;\n" n
             | Int n -> pr "  int %s;\n" n
             | StringList n -> pr "  str %s<>;\n" n
             | Bool n -> pr "  bool %s;\n" n
             | Int n -> pr "  int %s;\n" n
+            | FileIn _ | FileOut _ -> ()
           ) args;
           pr "};\n\n"
       );
           ) args;
           pr "};\n\n"
       );
@@ -1830,7 +1866,7 @@ and generate_xdr () =
     fun (shortname, _, proc_nr, _, _, _, _) ->
       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
   ) daemon_functions;
     fun (shortname, _, proc_nr, _, _, _, _) ->
       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
   ) daemon_functions;
-  pr "  GUESTFS_PROC_dummy\n"; (* so we don't have a "hanging comma" *)
+  pr "  GUESTFS_PROC_NR_PROCS\n";
   pr "};\n";
   pr "\n";
 
   pr "};\n";
   pr "\n";
 
@@ -1864,6 +1900,19 @@ struct guestfs_message_error {
   string error<GUESTFS_ERROR_LEN>;   /* error message */
 };
 
   string error<GUESTFS_ERROR_LEN>;   /* error message */
 };
 
+/* For normal requests and replies (not involving any FileIn or
+ * FileOut parameters), the protocol is:
+ *
+ * For requests:
+ *   total length (header + args, but not including length word itself)
+ *   header
+ *   guestfs_foo_args struct
+ * For replies:
+ *   total length (as above)
+ *   header
+ *   guestfs_foo_ret struct
+ */
+
 struct guestfs_message_header {
   unsigned prog;                     /* GUESTFS_PROGRAM */
   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
 struct guestfs_message_header {
   unsigned prog;                     /* GUESTFS_PROGRAM */
   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
@@ -1872,6 +1921,31 @@ struct guestfs_message_header {
   unsigned serial;                   /* message serial number */
   guestfs_message_status status;
 };
   unsigned serial;                   /* message serial number */
   guestfs_message_status status;
 };
+
+/* Chunked encoding used to transfer files, for FileIn and FileOut
+ * parameters.
+ *
+ * For requests which have >= 1 FileIn parameter:
+ *   length of header + args (but not length word itself, and not chunks)
+ *   header
+ *   guestfs_foo_args struct
+ *   sequence of chunks for FileIn param #0
+ *   sequence of chunks for FileIn param #1 etc
+ *
+ * For replies which have >= 1 FileOut parameter:
+ *   length of header + ret (but not length word itself, and not chunks)
+ *   header
+ *   guestfs_foo_ret struct
+ *   sequence of chunks for FileOut param #0
+ *   sequence of chunks for FileOut param #1 etc
+ */
+const GUESTFS_MAX_CHUNK_SIZE = 8192;
+
+struct guestfs_chunk {
+  int cancel;                       /* if non-zero, transfer is cancelled */
+  /* data size is 0 bytes if the transfer has finished successfully */
+  opaque data<GUESTFS_MAX_CHUNK_SIZE>;
+};
 "
 
 (* Generate the guestfs-structs.h file. *)
 "
 
 (* Generate the guestfs-structs.h file. *)
@@ -1953,9 +2027,14 @@ and generate_client_actions () =
     fun (shortname, style, _, _, _, _, _) ->
       let name = "guestfs_" ^ shortname in
 
     fun (shortname, style, _, _, _, _, _) ->
       let name = "guestfs_" ^ shortname in
 
-      (* Generate the return value struct. *)
-      pr "struct %s_rv {\n" shortname;
-      pr "  int cb_done;  /* flag to indicate callback was called */\n";
+      (* Generate the state struct which stores the high-level
+       * state between callback functions.  The callback(s) are:
+       *   <name>_cb_header_sent      header was sent
+       *   <name>_cb_file_sent        FileIn file was sent
+       *   <name>_cb_reply_received   reply received
+       *)
+      pr "struct %s_state {\n" shortname;
+      pr "  int cb_done;\n";
       pr "  struct guestfs_message_header hdr;\n";
       pr "  struct guestfs_message_error err;\n";
       (match fst style with
       pr "  struct guestfs_message_header hdr;\n";
       pr "  struct guestfs_message_error err;\n";
       (match fst style with
@@ -1970,19 +2049,20 @@ and generate_client_actions () =
        | RHashtable _ ->
           pr "  struct %s_ret ret;\n" name
       );
        | RHashtable _ ->
           pr "  struct %s_ret ret;\n" name
       );
-      pr "};\n\n";
+      pr "};\n";
+      pr "\n";
 
       (* Generate the callback function. *)
       pr "static void %s_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
       pr "{\n";
 
       (* Generate the callback function. *)
       pr "static void %s_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
       pr "{\n";
-      pr "  struct %s_rv *rv = (struct %s_rv *) data;\n" shortname shortname;
+      pr "  struct %s_state *state = (struct %s_state *) data;\n" shortname shortname;
       pr "\n";
       pr "\n";
-      pr "  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {\n";
+      pr "  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {\n";
       pr "    error (g, \"%s: failed to parse reply header\");\n" name;
       pr "    return;\n";
       pr "  }\n";
       pr "    error (g, \"%s: failed to parse reply header\");\n" name;
       pr "    return;\n";
       pr "  }\n";
-      pr "  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {\n";
-      pr "    if (!xdr_guestfs_message_error (xdr, &rv->err)) {\n";
+      pr "  if (state->hdr.status == GUESTFS_STATUS_ERROR) {\n";
+      pr "    if (!xdr_guestfs_message_error (xdr, &state->err)) {\n";
       pr "      error (g, \"%s: failed to parse reply error\");\n" name;
       pr "      return;\n";
       pr "    }\n";
       pr "      error (g, \"%s: failed to parse reply error\");\n" name;
       pr "      return;\n";
       pr "    }\n";
@@ -1999,15 +2079,15 @@ and generate_client_actions () =
        | RPVList _ | RVGList _ | RLVList _
        | RStat _ | RStatVFS _
        | RHashtable _ ->
        | RPVList _ | RVGList _ | RLVList _
        | RStat _ | RStatVFS _
        | RHashtable _ ->
-           pr "  if (!xdr_%s_ret (xdr, &rv->ret)) {\n" name;
+           pr "  if (!xdr_%s_ret (xdr, &state->ret)) {\n" name;
            pr "    error (g, \"%s: failed to parse reply\");\n" name;
            pr "    return;\n";
            pr "  }\n";
       );
 
       pr " done:\n";
            pr "    error (g, \"%s: failed to parse reply\");\n" name;
            pr "    return;\n";
            pr "  }\n";
       );
 
       pr " done:\n";
-      pr "  rv->cb_done = 1;\n";
-      pr "  main_loop.main_loop_quit (g);\n";
+      pr "  state->cb_done = 1;\n";
+      pr "  g->main_loop->main_loop_quit (g->main_loop, g);\n";
       pr "}\n\n";
 
       (* Generate the action stub. *)
       pr "}\n\n";
 
       (* Generate the action stub. *)
@@ -2032,19 +2112,26 @@ and generate_client_actions () =
        | _ -> pr "  struct %s_args args;\n" name
       );
 
        | _ -> pr "  struct %s_args args;\n" name
       );
 
-      pr "  struct %s_rv rv;\n" shortname;
+      pr "  struct %s_state state;\n" shortname;
       pr "  int serial;\n";
       pr "\n";
       pr "  if (g->state != READY) {\n";
       pr "  int serial;\n";
       pr "\n";
       pr "  if (g->state != READY) {\n";
-      pr "    error (g, \"%s called from the wrong state, %%d != READY\",\n"
-       name;
-      pr "      g->state);\n";
+      pr "    if (g->state == CONFIG)\n";
+      pr "      error (g, \"%%s: call launch() before using this function\",\n";
+      pr "        \"%s\");\n" name;
+      pr "    else if (g->state == LAUNCHING)\n";
+      pr "      error (g, \"%%s: call wait_ready() before using this function\",\n";
+      pr "        \"%s\");\n" name;
+      pr "    else\n";
+      pr "      error (g, \"%%s called from the wrong state, %%d != READY\",\n";
+      pr "        \"%s\", g->state);\n" name;
       pr "    return %s;\n" error_code;
       pr "  }\n";
       pr "\n";
       pr "    return %s;\n" error_code;
       pr "  }\n";
       pr "\n";
-      pr "  memset (&rv, 0, sizeof rv);\n";
+      pr "  memset (&state, 0, sizeof state);\n";
       pr "\n";
 
       pr "\n";
 
+      (* Dispatch the main header and arguments. *)
       (match snd style with
        | [] ->
           pr "  serial = dispatch (g, GUESTFS_PROC_%s, NULL, NULL);\n"
       (match snd style with
        | [] ->
           pr "  serial = dispatch (g, GUESTFS_PROC_%s, NULL, NULL);\n"
@@ -2063,6 +2150,7 @@ and generate_client_actions () =
                 pr "  args.%s = %s;\n" n n
             | Int n ->
                 pr "  args.%s = %s;\n" n n
                 pr "  args.%s = %s;\n" n n
             | Int n ->
                 pr "  args.%s = %s;\n" n n
+            | FileIn _ | FileOut _ -> ()
           ) args;
           pr "  serial = dispatch (g, GUESTFS_PROC_%s,\n"
             (String.uppercase shortname);
           ) args;
           pr "  serial = dispatch (g, GUESTFS_PROC_%s,\n"
             (String.uppercase shortname);
@@ -2073,52 +2161,73 @@ and generate_client_actions () =
       pr "    return %s;\n" error_code;
       pr "\n";
 
       pr "    return %s;\n" error_code;
       pr "\n";
 
-      pr "  rv.cb_done = 0;\n";
+      (* Send any additional files requested. *)
+      List.iter (
+       function
+       | FileIn n ->
+           pr "  if (send_file (g, %s) == -1)\n" n;
+           pr "    return %s;\n" error_code;
+           pr "\n";
+       | _ -> ()
+      ) (snd style);
+
+      (* Wait for the reply from the remote end. *)
+      pr "  state.cb_done = 0;\n";
       pr "  g->reply_cb_internal = %s_cb;\n" shortname;
       pr "  g->reply_cb_internal = %s_cb;\n" shortname;
-      pr "  g->reply_cb_internal_data = &rv;\n";
-      pr "  main_loop.main_loop_run (g);\n";
+      pr "  g->reply_cb_internal_data = &state;\n";
+      pr "  (void) g->main_loop->main_loop_run (g->main_loop, g);\n";
       pr "  g->reply_cb_internal = NULL;\n";
       pr "  g->reply_cb_internal_data = NULL;\n";
       pr "  g->reply_cb_internal = NULL;\n";
       pr "  g->reply_cb_internal_data = NULL;\n";
-      pr "  if (!rv.cb_done) {\n";
+      pr "  if (!state.cb_done) {\n";
       pr "    error (g, \"%s failed, see earlier error messages\");\n" name;
       pr "    return %s;\n" error_code;
       pr "  }\n";
       pr "\n";
 
       pr "    error (g, \"%s failed, see earlier error messages\");\n" name;
       pr "    return %s;\n" error_code;
       pr "  }\n";
       pr "\n";
 
-      pr "  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_%s, serial) == -1)\n"
+      pr "  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_%s, serial) == -1)\n"
        (String.uppercase shortname);
       pr "    return %s;\n" error_code;
       pr "\n";
 
        (String.uppercase shortname);
       pr "    return %s;\n" error_code;
       pr "\n";
 
-      pr "  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {\n";
-      pr "    error (g, \"%%s\", rv.err.error);\n";
+      pr "  if (state.hdr.status == GUESTFS_STATUS_ERROR) {\n";
+      pr "    error (g, \"%%s\", state.err.error);\n";
       pr "    return %s;\n" error_code;
       pr "  }\n";
       pr "\n";
 
       pr "    return %s;\n" error_code;
       pr "  }\n";
       pr "\n";
 
+      (* Expecting to receive further files (FileOut)? *)
+      List.iter (
+       function
+       | FileOut n ->
+           pr "  if (receive_file (g, %s) == -1)\n" n;
+           pr "    return %s;\n" error_code;
+           pr "\n";
+       | _ -> ()
+      ) (snd style);
+
       (match fst style with
        | RErr -> pr "  return 0;\n"
        | RInt n | RInt64 n | RBool n ->
       (match fst style with
        | RErr -> pr "  return 0;\n"
        | RInt n | RInt64 n | RBool n ->
-          pr "  return rv.ret.%s;\n" n
+          pr "  return state.ret.%s;\n" n
        | RConstString _ ->
           failwithf "RConstString cannot be returned from a daemon function"
        | RString n ->
        | RConstString _ ->
           failwithf "RConstString cannot be returned from a daemon function"
        | RString n ->
-          pr "  return rv.ret.%s; /* caller will free */\n" n
+          pr "  return state.ret.%s; /* caller will free */\n" n
        | RStringList n | RHashtable n ->
           pr "  /* caller will free this, but we need to add a NULL entry */\n";
        | RStringList n | RHashtable n ->
           pr "  /* caller will free this, but we need to add a NULL entry */\n";
-          pr "  rv.ret.%s.%s_val =" n n;
-          pr "    safe_realloc (g, rv.ret.%s.%s_val,\n" n n;
-          pr "                  sizeof (char *) * (rv.ret.%s.%s_len + 1));\n"
+          pr "  state.ret.%s.%s_val =" n n;
+          pr "    safe_realloc (g, state.ret.%s.%s_val,\n" n n;
+          pr "                  sizeof (char *) * (state.ret.%s.%s_len + 1));\n"
             n n;
             n n;
-          pr "  rv.ret.%s.%s_val[rv.ret.%s.%s_len] = NULL;\n" n n n n;
-          pr "  return rv.ret.%s.%s_val;\n" n n
+          pr "  state.ret.%s.%s_val[state.ret.%s.%s_len] = NULL;\n" n n n n;
+          pr "  return state.ret.%s.%s_val;\n" n n
        | RIntBool _ ->
           pr "  /* caller with free this */\n";
        | RIntBool _ ->
           pr "  /* caller with free this */\n";
-          pr "  return safe_memdup (g, &rv.ret, sizeof (rv.ret));\n"
+          pr "  return safe_memdup (g, &state.ret, sizeof (state.ret));\n"
        | RPVList n | RVGList n | RLVList n
        | RStat n | RStatVFS n ->
           pr "  /* caller will free this */\n";
        | RPVList n | RVGList n | RLVList n
        | RStat n | RStatVFS n ->
           pr "  /* caller will free this */\n";
-          pr "  return safe_memdup (g, &rv.ret.%s, sizeof (rv.ret.%s));\n" n n
+          pr "  return safe_memdup (g, &state.ret.%s, sizeof (state.ret.%s));\n" n n
       );
 
       pr "}\n\n"
       );
 
       pr "}\n\n"
@@ -2189,6 +2298,7 @@ and generate_daemon_actions () =
             | StringList n -> pr "  char **%s;\n" n
             | Bool n -> pr "  int %s;\n" n
             | Int n -> pr "  int %s;\n" n
             | StringList n -> pr "  char **%s;\n" n
             | Bool n -> pr "  int %s;\n" n
             | Int n -> pr "  int %s;\n" n
+            | FileIn _ | FileOut _ -> ()
           ) args
       );
       pr "\n";
           ) args
       );
       pr "\n";
@@ -2212,12 +2322,19 @@ and generate_daemon_actions () =
                 pr "  %s = args.%s.%s_val;\n" n n n
             | Bool n -> pr "  %s = args.%s;\n" n n
             | Int n -> pr "  %s = args.%s;\n" n n
                 pr "  %s = args.%s.%s_val;\n" n n n
             | Bool n -> pr "  %s = args.%s;\n" n n
             | Int n -> pr "  %s = args.%s;\n" n n
+            | FileIn _ | FileOut _ -> ()
           ) args;
           pr "\n"
       );
 
           ) args;
           pr "\n"
       );
 
+      (* Don't want to call the impl with any FileIn or FileOut
+       * parameters, since these go "outside" the RPC protocol.
+       *)
+      let argsnofile =
+       List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
+         (snd style) in
       pr "  r = do_%s " name;
       pr "  r = do_%s " name;
-      generate_call_args style;
+      generate_call_args argsnofile;
       pr ";\n";
 
       pr "  if (r == %s)\n" error_code;
       pr ";\n";
 
       pr "  if (r == %s)\n" error_code;
@@ -2225,34 +2342,48 @@ and generate_daemon_actions () =
       pr "    goto done;\n";
       pr "\n";
 
       pr "    goto done;\n";
       pr "\n";
 
-      (match fst style with
-       | RErr -> pr "  reply (NULL, NULL);\n"
-       | RInt n | RInt64 n | RBool 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
-       | RConstString _ ->
-          failwithf "RConstString cannot be returned from a daemon function"
-       | RString 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 "  free (r);\n"
-       | RStringList n | RHashtable n ->
-          pr "  struct guestfs_%s_ret ret;\n" name;
-          pr "  ret.%s.%s_len = count_strings (r);\n" n n;
-          pr "  ret.%s.%s_val = r;\n" n n;
-          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" name;
-          pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) r);\n" name
-       | RPVList n | RVGList n | RLVList n
-       | RStat n | RStatVFS 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 *) &ret);\n" name
+      (* If there are any FileOut parameters, then the impl must
+       * send its own reply.
+       *)
+      let no_reply =
+       List.exists (function FileOut _ -> true | _ -> false) (snd style) in
+      if no_reply then
+       pr "  /* do_%s has already sent a reply */\n" name
+      else (
+       match fst style with
+       | RErr -> pr "  reply (NULL, NULL);\n"
+       | RInt n | RInt64 n | RBool 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
+       | RConstString _ ->
+           failwithf "RConstString cannot be returned from a daemon function"
+       | RString 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 "  free (r);\n"
+       | RStringList n | RHashtable n ->
+           pr "  struct guestfs_%s_ret ret;\n" name;
+           pr "  ret.%s.%s_len = count_strings (r);\n" n n;
+           pr "  ret.%s.%s_val = r;\n" n n;
+           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"
+             name;
+           pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) r);\n" name
+       | RPVList n | RVGList n | RLVList n
+       | RStat n | RStatVFS 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 *) &ret);\n"
+             name
       );
 
       (* Free the args. *)
       );
 
       (* Free the args. *)
@@ -2890,6 +3021,7 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
        | OptString _, _
        | Int _, _
        | Bool _, _ -> ()
        | OptString _, _
        | Int _, _
        | Bool _, _ -> ()
+       | FileIn _, _ | FileOut _, _ -> ()
        | StringList n, arg ->
            pr "    char *%s[] = {\n" n;
            let strs = string_split " " arg in
        | StringList n, arg ->
            pr "    char *%s[] = {\n" n;
            let strs = string_split " " arg in
@@ -2929,7 +3061,9 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
       (* Generate the parameters. *)
       List.iter (
        function
       (* Generate the parameters. *)
       List.iter (
        function
-       | String _, arg -> pr ", \"%s\"" (c_quote arg)
+       | String _, arg
+       | FileIn _, arg | FileOut _, arg ->
+           pr ", \"%s\"" (c_quote arg)
        | OptString _, arg ->
            if arg = "NULL" then pr ", NULL" else pr ", \"%s\"" (c_quote arg)
        | StringList n, _ ->
        | OptString _, arg ->
            if arg = "NULL" then pr ", NULL" else pr ", \"%s\"" (c_quote arg)
        | StringList n, _ ->
@@ -3151,7 +3285,9 @@ and generate_fish_cmds () =
       List.iter (
        function
        | String n
       List.iter (
        function
        | String n
-       | OptString n -> pr "  const char *%s;\n" n
+       | OptString n
+       | FileIn n
+       | FileOut n -> pr "  const char *%s;\n" n
        | StringList n -> pr "  char **%s;\n" n
        | Bool n -> pr "  int %s;\n" n
        | Int n -> pr "  int %s;\n" n
        | StringList n -> pr "  char **%s;\n" n
        | Bool n -> pr "  int %s;\n" n
        | Int n -> pr "  int %s;\n" n
@@ -3172,6 +3308,12 @@ and generate_fish_cmds () =
          | OptString name ->
              pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
                name i i
          | OptString name ->
              pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
                name i i
+         | FileIn name ->
+             pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
+               name i i
+         | FileOut name ->
+             pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
+               name i i
          | StringList name ->
              pr "  %s = parse_string_list (argv[%d]);\n" name i
          | Bool name ->
          | StringList name ->
              pr "  %s = parse_string_list (argv[%d]);\n" name i
          | Bool name ->
@@ -3185,7 +3327,7 @@ and generate_fish_cmds () =
        try find_map (function FishAction n -> Some n | _ -> None) flags
        with Not_found -> sprintf "guestfs_%s" name in
       pr "  r = %s " fn;
        try find_map (function FishAction n -> Some n | _ -> None) flags
        with Not_found -> sprintf "guestfs_%s" name in
       pr "  r = %s " fn;
-      generate_call_args ~handle:"g" style;
+      generate_call_args ~handle:"g" (snd style);
       pr ";\n";
 
       (* Check return value for errors and display command results. *)
       pr ";\n";
 
       (* Check return value for errors and display command results. *)
@@ -3394,11 +3536,16 @@ and generate_fish_actions_pod () =
        | StringList n -> pr " %s,..." n
        | Bool _ -> pr " true|false"
        | Int n -> pr " %s" n
        | StringList n -> pr " %s,..." n
        | Bool _ -> pr " true|false"
        | Int n -> pr " %s" n
+       | FileIn n | FileOut n -> pr " (%s|-)" n
       ) (snd style);
       pr "\n";
       pr "\n";
       pr "%s\n\n" longdesc;
 
       ) (snd style);
       pr "\n";
       pr "\n";
       pr "%s\n\n" longdesc;
 
+      if List.exists (function FileIn _ | FileOut _ -> true
+                     | _ -> false) (snd style) then
+       pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
+
       if List.mem ProtocolLimitWarning flags then
        pr "%s\n\n" protocol_limit_warning;
 
       if List.mem ProtocolLimitWarning flags then
        pr "%s\n\n" protocol_limit_warning;
 
@@ -3457,11 +3604,14 @@ and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
     in
     List.iter (
       function
     in
     List.iter (
       function
-      | String n -> next (); pr "const char *%s" n
+      | String n
       | OptString n -> next (); pr "const char *%s" n
       | StringList n -> next (); pr "char * const* const %s" n
       | Bool n -> next (); pr "int %s" n
       | Int n -> next (); pr "int %s" n
       | OptString n -> next (); pr "const char *%s" n
       | StringList n -> next (); pr "char * const* const %s" n
       | Bool n -> next (); pr "int %s" n
       | Int n -> next (); pr "int %s" n
+      | FileIn n
+      | FileOut n ->
+         if not in_daemon then (next (); pr "const char *%s" n)
     ) (snd style);
   );
   pr ")";
     ) (snd style);
   );
   pr ")";
@@ -3469,7 +3619,7 @@ and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
   if newline then pr "\n"
 
 (* Generate C call arguments, eg "(handle, foo, bar)" *)
   if newline then pr "\n"
 
 (* Generate C call arguments, eg "(handle, foo, bar)" *)
-and generate_call_args ?handle style =
+and generate_call_args ?handle args =
   pr "(";
   let comma = ref false in
   (match handle with
   pr "(";
   let comma = ref false in
   (match handle with
@@ -3480,13 +3630,8 @@ and generate_call_args ?handle style =
     fun arg ->
       if !comma then pr ", ";
       comma := true;
     fun arg ->
       if !comma then pr ", ";
       comma := true;
-      match arg with
-      | String n
-      | OptString n
-      | StringList n
-      | Bool n
-      | Int n -> pr "%s" n
-  ) (snd style);
+      pr "%s" (name_of_argt arg)
+  ) args;
   pr ")"
 
 (* Generate the OCaml bindings interface. *)
   pr ")"
 
 (* Generate the OCaml bindings interface. *)
@@ -3715,7 +3860,9 @@ copy_table (char * const * argv)
 
       List.iter (
        function
 
       List.iter (
        function
-       | String n ->
+       | String n
+       | FileIn n
+       | FileOut n ->
            pr "  const char *%s = String_val (%sv);\n" n n
        | OptString n ->
            pr "  const char *%s =\n" n;
            pr "  const char *%s = String_val (%sv);\n" n n
        | OptString n ->
            pr "  const char *%s =\n" n;
@@ -3760,7 +3907,7 @@ copy_table (char * const * argv)
 
       pr "  caml_enter_blocking_section ();\n";
       pr "  r = guestfs_%s " name;
 
       pr "  caml_enter_blocking_section ();\n";
       pr "  r = guestfs_%s " name;
-      generate_call_args ~handle:"g" style;
+      generate_call_args ~handle:"g" (snd style);
       pr ";\n";
       pr "  caml_leave_blocking_section ();\n";
 
       pr ";\n";
       pr "  caml_leave_blocking_section ();\n";
 
@@ -3768,7 +3915,7 @@ copy_table (char * const * argv)
        function
        | StringList n ->
            pr "  ocaml_guestfs_free_strings (%s);\n" n;
        function
        | StringList n ->
            pr "  ocaml_guestfs_free_strings (%s);\n" n;
-       | String _ | OptString _ | Bool _ | Int _ -> ()
+       | String _ | OptString _ | Bool _ | Int _ | FileIn _ | FileOut _ -> ()
       ) (snd style);
 
       pr "  if (r == %s)\n" error_code;
       ) (snd style);
 
       pr "  if (r == %s)\n" error_code;
@@ -3864,7 +4011,7 @@ and generate_ocaml_prototype ?(is_external = false) name style =
   pr "%s : t -> " name;
   List.iter (
     function
   pr "%s : t -> " name;
   List.iter (
     function
-    | String _ -> pr "string -> "
+    | String _ | FileIn _ | FileOut _ -> pr "string -> "
     | OptString _ -> pr "string option -> "
     | StringList _ -> pr "string array -> "
     | Bool _ -> pr "bool -> "
     | OptString _ -> pr "string option -> "
     | StringList _ -> pr "string array -> "
     | Bool _ -> pr "bool -> "
@@ -4003,12 +4150,12 @@ DESTROY (g)
       );
       (* Call and arguments. *)
       pr "%s " name;
       );
       (* Call and arguments. *)
       pr "%s " name;
-      generate_call_args ~handle:"g" style;
+      generate_call_args ~handle:"g" (snd style);
       pr "\n";
       pr "      guestfs_h *g;\n";
       List.iter (
        function
       pr "\n";
       pr "      guestfs_h *g;\n";
       List.iter (
        function
-       | String n -> pr "      char *%s;\n" n
+       | String n | FileIn n | FileOut n -> pr "      char *%s;\n" n
        | OptString n -> pr "      char *%s;\n" n
        | StringList n -> pr "      char **%s;\n" n
        | Bool n -> pr "      int %s;\n" n
        | OptString n -> pr "      char *%s;\n" n
        | StringList n -> pr "      char **%s;\n" n
        | Bool n -> pr "      int %s;\n" n
@@ -4018,10 +4165,8 @@ DESTROY (g)
       let do_cleanups () =
        List.iter (
          function
       let do_cleanups () =
        List.iter (
          function
-         | String _
-         | OptString _
-         | Bool _
-         | Int _ -> ()
+         | String _ | OptString _ | Bool _ | Int _
+         | FileIn _ | FileOut _ -> ()
          | StringList n -> pr "      free (%s);\n" n
        ) (snd style)
       in
          | StringList n -> pr "      free (%s);\n" n
        ) (snd style)
       in
@@ -4033,7 +4178,7 @@ DESTROY (g)
           pr "      int r;\n";
           pr " PPCODE:\n";
           pr "      r = guestfs_%s " name;
           pr "      int r;\n";
           pr " PPCODE:\n";
           pr "      r = guestfs_%s " name;
-          generate_call_args ~handle:"g" style;
+          generate_call_args ~handle:"g" (snd style);
           pr ";\n";
           do_cleanups ();
           pr "      if (r == -1)\n";
           pr ";\n";
           do_cleanups ();
           pr "      if (r == -1)\n";
@@ -4044,7 +4189,7 @@ DESTROY (g)
           pr "      int %s;\n" n;
           pr "   CODE:\n";
           pr "      %s = guestfs_%s " n name;
           pr "      int %s;\n" n;
           pr "   CODE:\n";
           pr "      %s = guestfs_%s " n name;
-          generate_call_args ~handle:"g" style;
+          generate_call_args ~handle:"g" (snd style);
           pr ";\n";
           do_cleanups ();
           pr "      if (%s == -1)\n" n;
           pr ";\n";
           do_cleanups ();
           pr "      if (%s == -1)\n" n;
@@ -4057,7 +4202,7 @@ DESTROY (g)
           pr "      int64_t %s;\n" n;
           pr "   CODE:\n";
           pr "      %s = guestfs_%s " n name;
           pr "      int64_t %s;\n" n;
           pr "   CODE:\n";
           pr "      %s = guestfs_%s " n name;
-          generate_call_args ~handle:"g" style;
+          generate_call_args ~handle:"g" (snd style);
           pr ";\n";
           do_cleanups ();
           pr "      if (%s == -1)\n" n;
           pr ";\n";
           do_cleanups ();
           pr "      if (%s == -1)\n" n;
@@ -4070,7 +4215,7 @@ DESTROY (g)
           pr "      const char *%s;\n" n;
           pr "   CODE:\n";
           pr "      %s = guestfs_%s " n name;
           pr "      const char *%s;\n" n;
           pr "   CODE:\n";
           pr "      %s = guestfs_%s " n name;
-          generate_call_args ~handle:"g" style;
+          generate_call_args ~handle:"g" (snd style);
           pr ";\n";
           do_cleanups ();
           pr "      if (%s == NULL)\n" n;
           pr ";\n";
           do_cleanups ();
           pr "      if (%s == NULL)\n" n;
@@ -4083,7 +4228,7 @@ DESTROY (g)
           pr "      char *%s;\n" n;
           pr "   CODE:\n";
           pr "      %s = guestfs_%s " n name;
           pr "      char *%s;\n" n;
           pr "   CODE:\n";
           pr "      %s = guestfs_%s " n name;
-          generate_call_args ~handle:"g" style;
+          generate_call_args ~handle:"g" (snd style);
           pr ";\n";
           do_cleanups ();
           pr "      if (%s == NULL)\n" n;
           pr ";\n";
           do_cleanups ();
           pr "      if (%s == NULL)\n" n;
@@ -4098,7 +4243,7 @@ DESTROY (g)
           pr "      int i, n;\n";
           pr " PPCODE:\n";
           pr "      %s = guestfs_%s " n name;
           pr "      int i, n;\n";
           pr " PPCODE:\n";
           pr "      %s = guestfs_%s " n name;
-          generate_call_args ~handle:"g" style;
+          generate_call_args ~handle:"g" (snd style);
           pr ";\n";
           do_cleanups ();
           pr "      if (%s == NULL)\n" n;
           pr ";\n";
           do_cleanups ();
           pr "      if (%s == NULL)\n" n;
@@ -4115,7 +4260,7 @@ DESTROY (g)
           pr "      struct guestfs_int_bool *r;\n";
           pr " PPCODE:\n";
           pr "      r = guestfs_%s " name;
           pr "      struct guestfs_int_bool *r;\n";
           pr " PPCODE:\n";
           pr "      r = guestfs_%s " name;
-          generate_call_args ~handle:"g" style;
+          generate_call_args ~handle:"g" (snd style);
           pr ";\n";
           do_cleanups ();
           pr "      if (r == NULL)\n";
           pr ";\n";
           do_cleanups ();
           pr "      if (r == NULL)\n";
@@ -4147,7 +4292,7 @@ and generate_perl_lvm_code typ cols name style n do_cleanups =
   pr "      HV *hv;\n";
   pr " PPCODE:\n";
   pr "      %s = guestfs_%s " n name;
   pr "      HV *hv;\n";
   pr " PPCODE:\n";
   pr "      %s = guestfs_%s " n name;
-  generate_call_args ~handle:"g" style;
+  generate_call_args ~handle:"g" (snd style);
   pr ";\n";
   do_cleanups ();
   pr "      if (%s == NULL)\n" n;
   pr ";\n";
   do_cleanups ();
   pr "      if (%s == NULL)\n" n;
@@ -4182,7 +4327,7 @@ and generate_perl_stat_code typ cols name style n do_cleanups =
   pr "      struct guestfs_%s *%s;\n" typ n;
   pr " PPCODE:\n";
   pr "      %s = guestfs_%s " n name;
   pr "      struct guestfs_%s *%s;\n" typ n;
   pr " PPCODE:\n";
   pr "      %s = guestfs_%s " n name;
-  generate_call_args ~handle:"g" style;
+  generate_call_args ~handle:"g" (snd style);
   pr ";\n";
   do_cleanups ();
   pr "      if (%s == NULL)\n" n;
   pr ";\n";
   do_cleanups ();
   pr "      if (%s == NULL)\n" n;
@@ -4338,7 +4483,7 @@ and generate_perl_prototype name style =
       if !comma then pr ", ";
       comma := true;
       match arg with
       if !comma then pr ", ";
       comma := true;
       match arg with
-      | String n | OptString n | Bool n | Int n ->
+      | String n | OptString n | Bool n | Int n | FileIn n | FileOut n ->
          pr "$%s" n
       | StringList n ->
          pr "\\@%s" n
          pr "$%s" n
       | StringList n ->
          pr "\\@%s" n
@@ -4434,7 +4579,6 @@ put_table (char * const * const argv)
 
   list = PyList_New (argc >> 1);
   for (i = 0; i < argc; i += 2) {
 
   list = PyList_New (argc >> 1);
   for (i = 0; i < argc; i += 2) {
-    PyObject *item;
     item = PyTuple_New (2);
     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
     item = PyTuple_New (2);
     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
@@ -4590,7 +4734,7 @@ py_guestfs_close (PyObject *self, PyObject *args)
 
       List.iter (
        function
 
       List.iter (
        function
-       | String n -> pr "  const char *%s;\n" n
+       | String n | FileIn n | FileOut n -> pr "  const char *%s;\n" n
        | OptString n -> pr "  const char *%s;\n" n
        | StringList n ->
            pr "  PyObject *py_%s;\n" n;
        | OptString n -> pr "  const char *%s;\n" n
        | StringList n ->
            pr "  PyObject *py_%s;\n" n;
@@ -4605,7 +4749,7 @@ py_guestfs_close (PyObject *self, PyObject *args)
       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
       List.iter (
        function
       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
       List.iter (
        function
-       | String _ -> pr "s"
+       | String _ | FileIn _ | FileOut _ -> pr "s"
        | OptString _ -> pr "z"
        | StringList _ -> pr "O"
        | Bool _ -> pr "i" (* XXX Python has booleans? *)
        | OptString _ -> pr "z"
        | StringList _ -> pr "O"
        | Bool _ -> pr "i" (* XXX Python has booleans? *)
@@ -4615,7 +4759,7 @@ py_guestfs_close (PyObject *self, PyObject *args)
       pr "                         &py_g";
       List.iter (
        function
       pr "                         &py_g";
       List.iter (
        function
-       | String n -> pr ", &%s" n
+       | String n | FileIn n | FileOut n -> pr ", &%s" n
        | OptString n -> pr ", &%s" n
        | StringList n -> pr ", &py_%s" n
        | Bool n -> pr ", &%s" n
        | OptString n -> pr ", &%s" n
        | StringList n -> pr ", &py_%s" n
        | Bool n -> pr ", &%s" n
@@ -4628,7 +4772,7 @@ py_guestfs_close (PyObject *self, PyObject *args)
       pr "  g = get_handle (py_g);\n";
       List.iter (
        function
       pr "  g = get_handle (py_g);\n";
       List.iter (
        function
-       | String _ | OptString _ | Bool _ | Int _ -> ()
+       | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
        | StringList n ->
            pr "  %s = get_string_list (py_%s);\n" n n;
            pr "  if (!%s) return NULL;\n" n
        | StringList n ->
            pr "  %s = get_string_list (py_%s);\n" n n;
            pr "  if (!%s) return NULL;\n" n
@@ -4637,12 +4781,12 @@ py_guestfs_close (PyObject *self, PyObject *args)
       pr "\n";
 
       pr "  r = guestfs_%s " name;
       pr "\n";
 
       pr "  r = guestfs_%s " name;
-      generate_call_args ~handle:"g" style;
+      generate_call_args ~handle:"g" (snd style);
       pr ";\n";
 
       List.iter (
        function
       pr ";\n";
 
       List.iter (
        function
-       | String _ | OptString _ | Bool _ | Int _ -> ()
+       | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
        | StringList n ->
            pr "  free (%s);\n" n
       ) (snd style);
        | StringList n ->
            pr "  free (%s);\n" n
       ) (snd style);
@@ -4826,11 +4970,11 @@ class GuestFS:
       let doc = String.concat "\n        " doc in
 
       pr "    def %s " name;
       let doc = String.concat "\n        " doc in
 
       pr "    def %s " name;
-      generate_call_args ~handle:"self" style;
+      generate_call_args ~handle:"self" (snd style);
       pr ":\n";
       pr "        u\"\"\"%s\"\"\"\n" doc;
       pr "        return libguestfsmod.%s " name;
       pr ":\n";
       pr "        u\"\"\"%s\"\"\"\n" doc;
       pr "        return libguestfsmod.%s " name;
-      generate_call_args ~handle:"self._o" style;
+      generate_call_args ~handle:"self._o" (snd style);
       pr "\n";
       pr "\n";
   ) all_functions
       pr "\n";
       pr "\n";
   ) all_functions
@@ -4932,7 +5076,7 @@ static VALUE ruby_guestfs_close (VALUE gv)
 
       List.iter (
        function
 
       List.iter (
        function
-       | String n ->
+       | String n | FileIn n | FileOut n ->
            pr "  const char *%s = StringValueCStr (%sv);\n" n n;
            pr "  if (!%s)\n" n;
            pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
            pr "  const char *%s = StringValueCStr (%sv);\n" n n;
            pr "  if (!%s)\n" n;
            pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
@@ -4972,12 +5116,12 @@ static VALUE ruby_guestfs_close (VALUE gv)
       pr "\n";
 
       pr "  r = guestfs_%s " name;
       pr "\n";
 
       pr "  r = guestfs_%s " name;
-      generate_call_args ~handle:"g" style;
+      generate_call_args ~handle:"g" (snd style);
       pr ";\n";
 
       List.iter (
        function
       pr ";\n";
 
       List.iter (
        function
-       | String _ | OptString _ | Bool _ | Int _ -> ()
+       | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
        | StringList n ->
            pr "  free (%s);\n" n
       ) (snd style);
        | StringList n ->
            pr "  free (%s);\n" n
       ) (snd style);
index f516979..6f01f9f 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-struct mount_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct mount_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void mount_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void mount_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct mount_rv *rv = (struct mount_rv *) data;
+  struct mount_state *state = (struct mount_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_mount: failed to parse reply header");
     return;
   }
     error (g, "guestfs_mount: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_mount: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_mount: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_mount (guestfs_h *g,
 }
 
 int guestfs_mount (guestfs_h *g,
@@ -50,16 +50,23 @@ int guestfs_mount (guestfs_h *g,
                const char *mountpoint)
 {
   struct guestfs_mount_args args;
                const char *mountpoint)
 {
   struct guestfs_mount_args args;
-  struct mount_rv rv;
+  struct mount_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_mount called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_mount");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_mount");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_mount", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   args.mountpoint = (char *) mountpoint;
 
   args.device = (char *) device;
   args.mountpoint = (char *) mountpoint;
@@ -68,133 +75,147 @@ int guestfs_mount (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = mount_cb;
   g->reply_cb_internal = mount_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_mount failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_mount failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_MOUNT, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_MOUNT, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct sync_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct sync_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void sync_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void sync_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct sync_rv *rv = (struct sync_rv *) data;
+  struct sync_state *state = (struct sync_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_sync: failed to parse reply header");
     return;
   }
     error (g, "guestfs_sync: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_sync: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_sync: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_sync (guestfs_h *g)
 {
 }
 
 int guestfs_sync (guestfs_h *g)
 {
-  struct sync_rv rv;
+  struct sync_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_sync called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_sync");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_sync");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_sync", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_SYNC, NULL, NULL);
   if (serial == -1)
     return -1;
 
 
   serial = dispatch (g, GUESTFS_PROC_SYNC, NULL, NULL);
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = sync_cb;
   g->reply_cb_internal = sync_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_sync failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_sync failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_SYNC, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_SYNC, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct touch_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct touch_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void touch_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void touch_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct touch_rv *rv = (struct touch_rv *) data;
+  struct touch_state *state = (struct touch_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_touch: failed to parse reply header");
     return;
   }
     error (g, "guestfs_touch: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_touch: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_touch: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_touch (guestfs_h *g,
                const char *path)
 {
   struct guestfs_touch_args args;
 }
 
 int guestfs_touch (guestfs_h *g,
                const char *path)
 {
   struct guestfs_touch_args args;
-  struct touch_rv rv;
+  struct touch_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_touch called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_touch");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_touch");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_touch", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_TOUCH,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_TOUCH,
@@ -202,30 +223,30 @@ int guestfs_touch (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = touch_cb;
   g->reply_cb_internal = touch_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_touch failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_touch failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_TOUCH, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_TOUCH, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct cat_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct cat_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_cat_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_cat_ret ret;
@@ -233,42 +254,49 @@ struct cat_rv {
 
 static void cat_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void cat_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct cat_rv *rv = (struct cat_rv *) data;
+  struct cat_state *state = (struct cat_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_cat: failed to parse reply header");
     return;
   }
     error (g, "guestfs_cat: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_cat: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_cat: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_cat_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_cat_ret (xdr, &state->ret)) {
     error (g, "guestfs_cat: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_cat: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char *guestfs_cat (guestfs_h *g,
                const char *path)
 {
   struct guestfs_cat_args args;
 }
 
 char *guestfs_cat (guestfs_h *g,
                const char *path)
 {
   struct guestfs_cat_args args;
-  struct cat_rv rv;
+  struct cat_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_cat called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_cat");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_cat");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_cat", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_CAT,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_CAT,
@@ -276,30 +304,30 @@ char *guestfs_cat (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = cat_cb;
   g->reply_cb_internal = cat_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_cat failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_cat failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_CAT, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_CAT, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
     return NULL;
   }
 
-  return rv.ret.content; /* caller will free */
+  return state.ret.content; /* caller will free */
 }
 
 }
 
-struct ll_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct ll_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_ll_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_ll_ret ret;
@@ -307,42 +335,49 @@ struct ll_rv {
 
 static void ll_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void ll_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct ll_rv *rv = (struct ll_rv *) data;
+  struct ll_state *state = (struct ll_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_ll: failed to parse reply header");
     return;
   }
     error (g, "guestfs_ll: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_ll: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_ll: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_ll_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_ll_ret (xdr, &state->ret)) {
     error (g, "guestfs_ll: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_ll: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char *guestfs_ll (guestfs_h *g,
                const char *directory)
 {
   struct guestfs_ll_args args;
 }
 
 char *guestfs_ll (guestfs_h *g,
                const char *directory)
 {
   struct guestfs_ll_args args;
-  struct ll_rv rv;
+  struct ll_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_ll called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_ll");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_ll");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_ll", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.directory = (char *) directory;
   serial = dispatch (g, GUESTFS_PROC_LL,
 
   args.directory = (char *) directory;
   serial = dispatch (g, GUESTFS_PROC_LL,
@@ -350,30 +385,30 @@ char *guestfs_ll (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = ll_cb;
   g->reply_cb_internal = ll_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_ll failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_ll failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LL, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_LL, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
     return NULL;
   }
 
-  return rv.ret.listing; /* caller will free */
+  return state.ret.listing; /* caller will free */
 }
 
 }
 
-struct ls_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct ls_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_ls_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_ls_ret ret;
@@ -381,42 +416,49 @@ struct ls_rv {
 
 static void ls_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void ls_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct ls_rv *rv = (struct ls_rv *) data;
+  struct ls_state *state = (struct ls_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_ls: failed to parse reply header");
     return;
   }
     error (g, "guestfs_ls: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_ls: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_ls: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_ls_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_ls_ret (xdr, &state->ret)) {
     error (g, "guestfs_ls: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_ls: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_ls (guestfs_h *g,
                const char *directory)
 {
   struct guestfs_ls_args args;
 }
 
 char **guestfs_ls (guestfs_h *g,
                const char *directory)
 {
   struct guestfs_ls_args args;
-  struct ls_rv rv;
+  struct ls_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_ls called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_ls");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_ls");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_ls", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.directory = (char *) directory;
   serial = dispatch (g, GUESTFS_PROC_LS,
 
   args.directory = (char *) directory;
   serial = dispatch (g, GUESTFS_PROC_LS,
@@ -424,34 +466,34 @@ char **guestfs_ls (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = ls_cb;
   g->reply_cb_internal = ls_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_ls failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_ls failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_LS, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.listing.listing_val =    safe_realloc (g, rv.ret.listing.listing_val,
-                  sizeof (char *) * (rv.ret.listing.listing_len + 1));
-  rv.ret.listing.listing_val[rv.ret.listing.listing_len] = NULL;
-  return rv.ret.listing.listing_val;
+  state.ret.listing.listing_val =    safe_realloc (g, state.ret.listing.listing_val,
+                  sizeof (char *) * (state.ret.listing.listing_len + 1));
+  state.ret.listing.listing_val[state.ret.listing.listing_len] = NULL;
+  return state.ret.listing.listing_val;
 }
 
 }
 
-struct list_devices_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct list_devices_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_list_devices_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_list_devices_ret ret;
@@ -459,73 +501,80 @@ struct list_devices_rv {
 
 static void list_devices_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void list_devices_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct list_devices_rv *rv = (struct list_devices_rv *) data;
+  struct list_devices_state *state = (struct list_devices_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_list_devices: failed to parse reply header");
     return;
   }
     error (g, "guestfs_list_devices: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_list_devices: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_list_devices: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_list_devices_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_list_devices_ret (xdr, &state->ret)) {
     error (g, "guestfs_list_devices: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_list_devices: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_list_devices (guestfs_h *g)
 {
 }
 
 char **guestfs_list_devices (guestfs_h *g)
 {
-  struct list_devices_rv rv;
+  struct list_devices_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_list_devices called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_list_devices");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_list_devices");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_list_devices", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_LIST_DEVICES, NULL, NULL);
   if (serial == -1)
     return NULL;
 
 
   serial = dispatch (g, GUESTFS_PROC_LIST_DEVICES, NULL, NULL);
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = list_devices_cb;
   g->reply_cb_internal = list_devices_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_list_devices failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_list_devices failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LIST_DEVICES, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_LIST_DEVICES, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.devices.devices_val =    safe_realloc (g, rv.ret.devices.devices_val,
-                  sizeof (char *) * (rv.ret.devices.devices_len + 1));
-  rv.ret.devices.devices_val[rv.ret.devices.devices_len] = NULL;
-  return rv.ret.devices.devices_val;
+  state.ret.devices.devices_val =    safe_realloc (g, state.ret.devices.devices_val,
+                  sizeof (char *) * (state.ret.devices.devices_len + 1));
+  state.ret.devices.devices_val[state.ret.devices.devices_len] = NULL;
+  return state.ret.devices.devices_val;
 }
 
 }
 
-struct list_partitions_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct list_partitions_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_list_partitions_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_list_partitions_ret ret;
@@ -533,73 +582,80 @@ struct list_partitions_rv {
 
 static void list_partitions_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void list_partitions_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct list_partitions_rv *rv = (struct list_partitions_rv *) data;
+  struct list_partitions_state *state = (struct list_partitions_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_list_partitions: failed to parse reply header");
     return;
   }
     error (g, "guestfs_list_partitions: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_list_partitions: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_list_partitions: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_list_partitions_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_list_partitions_ret (xdr, &state->ret)) {
     error (g, "guestfs_list_partitions: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_list_partitions: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_list_partitions (guestfs_h *g)
 {
 }
 
 char **guestfs_list_partitions (guestfs_h *g)
 {
-  struct list_partitions_rv rv;
+  struct list_partitions_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_list_partitions called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_list_partitions");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_list_partitions");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_list_partitions", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_LIST_PARTITIONS, NULL, NULL);
   if (serial == -1)
     return NULL;
 
 
   serial = dispatch (g, GUESTFS_PROC_LIST_PARTITIONS, NULL, NULL);
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = list_partitions_cb;
   g->reply_cb_internal = list_partitions_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_list_partitions failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_list_partitions failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LIST_PARTITIONS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_LIST_PARTITIONS, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.partitions.partitions_val =    safe_realloc (g, rv.ret.partitions.partitions_val,
-                  sizeof (char *) * (rv.ret.partitions.partitions_len + 1));
-  rv.ret.partitions.partitions_val[rv.ret.partitions.partitions_len] = NULL;
-  return rv.ret.partitions.partitions_val;
+  state.ret.partitions.partitions_val =    safe_realloc (g, state.ret.partitions.partitions_val,
+                  sizeof (char *) * (state.ret.partitions.partitions_len + 1));
+  state.ret.partitions.partitions_val[state.ret.partitions.partitions_len] = NULL;
+  return state.ret.partitions.partitions_val;
 }
 
 }
 
-struct pvs_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct pvs_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_pvs_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_pvs_ret ret;
@@ -607,73 +663,80 @@ struct pvs_rv {
 
 static void pvs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void pvs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct pvs_rv *rv = (struct pvs_rv *) data;
+  struct pvs_state *state = (struct pvs_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_pvs: failed to parse reply header");
     return;
   }
     error (g, "guestfs_pvs: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_pvs: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_pvs: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_pvs_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_pvs_ret (xdr, &state->ret)) {
     error (g, "guestfs_pvs: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_pvs: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_pvs (guestfs_h *g)
 {
 }
 
 char **guestfs_pvs (guestfs_h *g)
 {
-  struct pvs_rv rv;
+  struct pvs_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_pvs called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_pvs");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_pvs");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_pvs", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_PVS, NULL, NULL);
   if (serial == -1)
     return NULL;
 
 
   serial = dispatch (g, GUESTFS_PROC_PVS, NULL, NULL);
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = pvs_cb;
   g->reply_cb_internal = pvs_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_pvs failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_pvs failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_PVS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_PVS, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.physvols.physvols_val =    safe_realloc (g, rv.ret.physvols.physvols_val,
-                  sizeof (char *) * (rv.ret.physvols.physvols_len + 1));
-  rv.ret.physvols.physvols_val[rv.ret.physvols.physvols_len] = NULL;
-  return rv.ret.physvols.physvols_val;
+  state.ret.physvols.physvols_val =    safe_realloc (g, state.ret.physvols.physvols_val,
+                  sizeof (char *) * (state.ret.physvols.physvols_len + 1));
+  state.ret.physvols.physvols_val[state.ret.physvols.physvols_len] = NULL;
+  return state.ret.physvols.physvols_val;
 }
 
 }
 
-struct vgs_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct vgs_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_vgs_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_vgs_ret ret;
@@ -681,73 +744,80 @@ struct vgs_rv {
 
 static void vgs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void vgs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct vgs_rv *rv = (struct vgs_rv *) data;
+  struct vgs_state *state = (struct vgs_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_vgs: failed to parse reply header");
     return;
   }
     error (g, "guestfs_vgs: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_vgs: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_vgs: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_vgs_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_vgs_ret (xdr, &state->ret)) {
     error (g, "guestfs_vgs: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_vgs: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_vgs (guestfs_h *g)
 {
 }
 
 char **guestfs_vgs (guestfs_h *g)
 {
-  struct vgs_rv rv;
+  struct vgs_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_vgs called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_vgs");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_vgs");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_vgs", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_VGS, NULL, NULL);
   if (serial == -1)
     return NULL;
 
 
   serial = dispatch (g, GUESTFS_PROC_VGS, NULL, NULL);
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = vgs_cb;
   g->reply_cb_internal = vgs_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_vgs failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_vgs failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_VGS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_VGS, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.volgroups.volgroups_val =    safe_realloc (g, rv.ret.volgroups.volgroups_val,
-                  sizeof (char *) * (rv.ret.volgroups.volgroups_len + 1));
-  rv.ret.volgroups.volgroups_val[rv.ret.volgroups.volgroups_len] = NULL;
-  return rv.ret.volgroups.volgroups_val;
+  state.ret.volgroups.volgroups_val =    safe_realloc (g, state.ret.volgroups.volgroups_val,
+                  sizeof (char *) * (state.ret.volgroups.volgroups_len + 1));
+  state.ret.volgroups.volgroups_val[state.ret.volgroups.volgroups_len] = NULL;
+  return state.ret.volgroups.volgroups_val;
 }
 
 }
 
-struct lvs_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct lvs_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_lvs_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_lvs_ret ret;
@@ -755,73 +825,80 @@ struct lvs_rv {
 
 static void lvs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void lvs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct lvs_rv *rv = (struct lvs_rv *) data;
+  struct lvs_state *state = (struct lvs_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_lvs: failed to parse reply header");
     return;
   }
     error (g, "guestfs_lvs: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_lvs: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_lvs: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_lvs_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_lvs_ret (xdr, &state->ret)) {
     error (g, "guestfs_lvs: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_lvs: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_lvs (guestfs_h *g)
 {
 }
 
 char **guestfs_lvs (guestfs_h *g)
 {
-  struct lvs_rv rv;
+  struct lvs_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_lvs called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_lvs");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_lvs");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_lvs", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_LVS, NULL, NULL);
   if (serial == -1)
     return NULL;
 
 
   serial = dispatch (g, GUESTFS_PROC_LVS, NULL, NULL);
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = lvs_cb;
   g->reply_cb_internal = lvs_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_lvs failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_lvs failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LVS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_LVS, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.logvols.logvols_val =    safe_realloc (g, rv.ret.logvols.logvols_val,
-                  sizeof (char *) * (rv.ret.logvols.logvols_len + 1));
-  rv.ret.logvols.logvols_val[rv.ret.logvols.logvols_len] = NULL;
-  return rv.ret.logvols.logvols_val;
+  state.ret.logvols.logvols_val =    safe_realloc (g, state.ret.logvols.logvols_val,
+                  sizeof (char *) * (state.ret.logvols.logvols_len + 1));
+  state.ret.logvols.logvols_val[state.ret.logvols.logvols_len] = NULL;
+  return state.ret.logvols.logvols_val;
 }
 
 }
 
-struct pvs_full_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct pvs_full_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_pvs_full_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_pvs_full_ret ret;
@@ -829,70 +906,77 @@ struct pvs_full_rv {
 
 static void pvs_full_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void pvs_full_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct pvs_full_rv *rv = (struct pvs_full_rv *) data;
+  struct pvs_full_state *state = (struct pvs_full_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_pvs_full: failed to parse reply header");
     return;
   }
     error (g, "guestfs_pvs_full: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_pvs_full: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_pvs_full: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_pvs_full_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_pvs_full_ret (xdr, &state->ret)) {
     error (g, "guestfs_pvs_full: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_pvs_full: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *g)
 {
 }
 
 struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *g)
 {
-  struct pvs_full_rv rv;
+  struct pvs_full_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_pvs_full called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_pvs_full");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_pvs_full");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_pvs_full", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_PVS_FULL, NULL, NULL);
   if (serial == -1)
     return NULL;
 
 
   serial = dispatch (g, GUESTFS_PROC_PVS_FULL, NULL, NULL);
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = pvs_full_cb;
   g->reply_cb_internal = pvs_full_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_pvs_full failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_pvs_full failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_PVS_FULL, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_PVS_FULL, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this */
     return NULL;
   }
 
   /* caller will free this */
-  return safe_memdup (g, &rv.ret.physvols, sizeof (rv.ret.physvols));
+  return safe_memdup (g, &state.ret.physvols, sizeof (state.ret.physvols));
 }
 
 }
 
-struct vgs_full_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct vgs_full_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_vgs_full_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_vgs_full_ret ret;
@@ -900,70 +984,77 @@ struct vgs_full_rv {
 
 static void vgs_full_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void vgs_full_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct vgs_full_rv *rv = (struct vgs_full_rv *) data;
+  struct vgs_full_state *state = (struct vgs_full_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_vgs_full: failed to parse reply header");
     return;
   }
     error (g, "guestfs_vgs_full: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_vgs_full: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_vgs_full: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_vgs_full_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_vgs_full_ret (xdr, &state->ret)) {
     error (g, "guestfs_vgs_full: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_vgs_full: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *g)
 {
 }
 
 struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *g)
 {
-  struct vgs_full_rv rv;
+  struct vgs_full_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_vgs_full called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_vgs_full");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_vgs_full");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_vgs_full", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_VGS_FULL, NULL, NULL);
   if (serial == -1)
     return NULL;
 
 
   serial = dispatch (g, GUESTFS_PROC_VGS_FULL, NULL, NULL);
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = vgs_full_cb;
   g->reply_cb_internal = vgs_full_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_vgs_full failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_vgs_full failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_VGS_FULL, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_VGS_FULL, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this */
     return NULL;
   }
 
   /* caller will free this */
-  return safe_memdup (g, &rv.ret.volgroups, sizeof (rv.ret.volgroups));
+  return safe_memdup (g, &state.ret.volgroups, sizeof (state.ret.volgroups));
 }
 
 }
 
-struct lvs_full_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct lvs_full_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_lvs_full_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_lvs_full_ret ret;
@@ -971,70 +1062,77 @@ struct lvs_full_rv {
 
 static void lvs_full_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void lvs_full_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct lvs_full_rv *rv = (struct lvs_full_rv *) data;
+  struct lvs_full_state *state = (struct lvs_full_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_lvs_full: failed to parse reply header");
     return;
   }
     error (g, "guestfs_lvs_full: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_lvs_full: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_lvs_full: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_lvs_full_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_lvs_full_ret (xdr, &state->ret)) {
     error (g, "guestfs_lvs_full: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_lvs_full: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *g)
 {
 }
 
 struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *g)
 {
-  struct lvs_full_rv rv;
+  struct lvs_full_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_lvs_full called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_lvs_full");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_lvs_full");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_lvs_full", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_LVS_FULL, NULL, NULL);
   if (serial == -1)
     return NULL;
 
 
   serial = dispatch (g, GUESTFS_PROC_LVS_FULL, NULL, NULL);
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = lvs_full_cb;
   g->reply_cb_internal = lvs_full_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_lvs_full failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_lvs_full failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LVS_FULL, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_LVS_FULL, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this */
     return NULL;
   }
 
   /* caller will free this */
-  return safe_memdup (g, &rv.ret.logvols, sizeof (rv.ret.logvols));
+  return safe_memdup (g, &state.ret.logvols, sizeof (state.ret.logvols));
 }
 
 }
 
-struct read_lines_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct read_lines_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_read_lines_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_read_lines_ret ret;
@@ -1042,42 +1140,49 @@ struct read_lines_rv {
 
 static void read_lines_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void read_lines_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct read_lines_rv *rv = (struct read_lines_rv *) data;
+  struct read_lines_state *state = (struct read_lines_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_read_lines: failed to parse reply header");
     return;
   }
     error (g, "guestfs_read_lines: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_read_lines: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_read_lines: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_read_lines_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_read_lines_ret (xdr, &state->ret)) {
     error (g, "guestfs_read_lines: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_read_lines: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_read_lines (guestfs_h *g,
                const char *path)
 {
   struct guestfs_read_lines_args args;
 }
 
 char **guestfs_read_lines (guestfs_h *g,
                const char *path)
 {
   struct guestfs_read_lines_args args;
-  struct read_lines_rv rv;
+  struct read_lines_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_read_lines called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_read_lines");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_read_lines");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_read_lines", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_READ_LINES,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_READ_LINES,
@@ -1085,56 +1190,56 @@ char **guestfs_read_lines (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = read_lines_cb;
   g->reply_cb_internal = read_lines_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_read_lines failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_read_lines failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_READ_LINES, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_READ_LINES, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.lines.lines_val =    safe_realloc (g, rv.ret.lines.lines_val,
-                  sizeof (char *) * (rv.ret.lines.lines_len + 1));
-  rv.ret.lines.lines_val[rv.ret.lines.lines_len] = NULL;
-  return rv.ret.lines.lines_val;
+  state.ret.lines.lines_val =    safe_realloc (g, state.ret.lines.lines_val,
+                  sizeof (char *) * (state.ret.lines.lines_len + 1));
+  state.ret.lines.lines_val[state.ret.lines.lines_len] = NULL;
+  return state.ret.lines.lines_val;
 }
 
 }
 
-struct aug_init_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_init_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_init_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_init_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_init_rv *rv = (struct aug_init_rv *) data;
+  struct aug_init_state *state = (struct aug_init_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_init: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_init: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_init: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_aug_init: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_aug_init (guestfs_h *g,
 }
 
 int guestfs_aug_init (guestfs_h *g,
@@ -1142,16 +1247,23 @@ int guestfs_aug_init (guestfs_h *g,
                int flags)
 {
   struct guestfs_aug_init_args args;
                int flags)
 {
   struct guestfs_aug_init_args args;
-  struct aug_init_rv rv;
+  struct aug_init_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_init called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_init");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_init");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_init", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.root = (char *) root;
   args.flags = flags;
 
   args.root = (char *) root;
   args.flags = flags;
@@ -1160,95 +1272,102 @@ int guestfs_aug_init (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_init_cb;
   g->reply_cb_internal = aug_init_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_init failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_aug_init failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_INIT, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_INIT, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct aug_close_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_close_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_close_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_close_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_close_rv *rv = (struct aug_close_rv *) data;
+  struct aug_close_state *state = (struct aug_close_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_close: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_close: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_close: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_aug_close: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_aug_close (guestfs_h *g)
 {
 }
 
 int guestfs_aug_close (guestfs_h *g)
 {
-  struct aug_close_rv rv;
+  struct aug_close_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_close called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_close");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_close");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_close", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_AUG_CLOSE, NULL, NULL);
   if (serial == -1)
     return -1;
 
 
   serial = dispatch (g, GUESTFS_PROC_AUG_CLOSE, NULL, NULL);
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_close_cb;
   g->reply_cb_internal = aug_close_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_close failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_aug_close failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_CLOSE, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_CLOSE, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct aug_defvar_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_defvar_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_defvar_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_defvar_ret ret;
@@ -1256,26 +1375,26 @@ struct aug_defvar_rv {
 
 static void aug_defvar_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void aug_defvar_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_defvar_rv *rv = (struct aug_defvar_rv *) data;
+  struct aug_defvar_state *state = (struct aug_defvar_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_defvar: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_defvar: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_defvar: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_aug_defvar: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_aug_defvar_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_aug_defvar_ret (xdr, &state->ret)) {
     error (g, "guestfs_aug_defvar: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_aug_defvar: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_aug_defvar (guestfs_h *g,
 }
 
 int guestfs_aug_defvar (guestfs_h *g,
@@ -1283,16 +1402,23 @@ int guestfs_aug_defvar (guestfs_h *g,
                const char *expr)
 {
   struct guestfs_aug_defvar_args args;
                const char *expr)
 {
   struct guestfs_aug_defvar_args args;
-  struct aug_defvar_rv rv;
+  struct aug_defvar_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_defvar called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_defvar");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_defvar");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_defvar", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.name = (char *) name;
   args.expr = expr ? (char **) &expr : NULL;
 
   args.name = (char *) name;
   args.expr = expr ? (char **) &expr : NULL;
@@ -1301,30 +1427,30 @@ int guestfs_aug_defvar (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_defvar_cb;
   g->reply_cb_internal = aug_defvar_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_defvar failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_aug_defvar failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_DEFVAR, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_DEFVAR, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
-  return rv.ret.nrnodes;
+  return state.ret.nrnodes;
 }
 
 }
 
-struct aug_defnode_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_defnode_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_defnode_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_defnode_ret ret;
@@ -1332,26 +1458,26 @@ struct aug_defnode_rv {
 
 static void aug_defnode_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void aug_defnode_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_defnode_rv *rv = (struct aug_defnode_rv *) data;
+  struct aug_defnode_state *state = (struct aug_defnode_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_defnode: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_defnode: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_defnode: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_aug_defnode: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_aug_defnode_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_aug_defnode_ret (xdr, &state->ret)) {
     error (g, "guestfs_aug_defnode: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_aug_defnode: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g,
 }
 
 struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g,
@@ -1360,16 +1486,23 @@ struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g,
                const char *val)
 {
   struct guestfs_aug_defnode_args args;
                const char *val)
 {
   struct guestfs_aug_defnode_args args;
-  struct aug_defnode_rv rv;
+  struct aug_defnode_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_defnode called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_defnode");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_defnode");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_defnode", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.name = (char *) name;
   args.expr = (char *) expr;
 
   args.name = (char *) name;
   args.expr = (char *) expr;
@@ -1379,31 +1512,31 @@ struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_defnode_cb;
   g->reply_cb_internal = aug_defnode_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_defnode failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_aug_defnode failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_DEFNODE, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_DEFNODE, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller with free this */
     return NULL;
   }
 
   /* caller with free this */
-  return safe_memdup (g, &rv.ret, sizeof (rv.ret));
+  return safe_memdup (g, &state.ret, sizeof (state.ret));
 }
 
 }
 
-struct aug_get_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_get_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_get_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_get_ret ret;
@@ -1411,42 +1544,49 @@ struct aug_get_rv {
 
 static void aug_get_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void aug_get_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_get_rv *rv = (struct aug_get_rv *) data;
+  struct aug_get_state *state = (struct aug_get_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_get: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_get: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_get: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_aug_get: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_aug_get_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_aug_get_ret (xdr, &state->ret)) {
     error (g, "guestfs_aug_get: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_aug_get: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char *guestfs_aug_get (guestfs_h *g,
                const char *path)
 {
   struct guestfs_aug_get_args args;
 }
 
 char *guestfs_aug_get (guestfs_h *g,
                const char *path)
 {
   struct guestfs_aug_get_args args;
-  struct aug_get_rv rv;
+  struct aug_get_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_get called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_get");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_get");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_get", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_AUG_GET,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_AUG_GET,
@@ -1454,52 +1594,52 @@ char *guestfs_aug_get (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_get_cb;
   g->reply_cb_internal = aug_get_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_get failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_aug_get failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_GET, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_GET, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
     return NULL;
   }
 
-  return rv.ret.val; /* caller will free */
+  return state.ret.val; /* caller will free */
 }
 
 }
 
-struct aug_set_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_set_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_set_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_set_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_set_rv *rv = (struct aug_set_rv *) data;
+  struct aug_set_state *state = (struct aug_set_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_set: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_set: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_set: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_aug_set: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_aug_set (guestfs_h *g,
 }
 
 int guestfs_aug_set (guestfs_h *g,
@@ -1507,16 +1647,23 @@ int guestfs_aug_set (guestfs_h *g,
                const char *val)
 {
   struct guestfs_aug_set_args args;
                const char *val)
 {
   struct guestfs_aug_set_args args;
-  struct aug_set_rv rv;
+  struct aug_set_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_set called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_set");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_set");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_set", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   args.val = (char *) val;
 
   args.path = (char *) path;
   args.val = (char *) val;
@@ -1525,52 +1672,52 @@ int guestfs_aug_set (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_set_cb;
   g->reply_cb_internal = aug_set_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_set failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_aug_set failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_SET, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_SET, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct aug_insert_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_insert_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_insert_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_insert_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_insert_rv *rv = (struct aug_insert_rv *) data;
+  struct aug_insert_state *state = (struct aug_insert_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_insert: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_insert: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_insert: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_aug_insert: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_aug_insert (guestfs_h *g,
 }
 
 int guestfs_aug_insert (guestfs_h *g,
@@ -1579,16 +1726,23 @@ int guestfs_aug_insert (guestfs_h *g,
                int before)
 {
   struct guestfs_aug_insert_args args;
                int before)
 {
   struct guestfs_aug_insert_args args;
-  struct aug_insert_rv rv;
+  struct aug_insert_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_insert called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_insert");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_insert");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_insert", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   args.label = (char *) label;
 
   args.path = (char *) path;
   args.label = (char *) label;
@@ -1598,30 +1752,30 @@ int guestfs_aug_insert (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_insert_cb;
   g->reply_cb_internal = aug_insert_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_insert failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_aug_insert failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_INSERT, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_INSERT, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct aug_rm_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_rm_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_rm_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_rm_ret ret;
@@ -1629,42 +1783,49 @@ struct aug_rm_rv {
 
 static void aug_rm_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void aug_rm_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_rm_rv *rv = (struct aug_rm_rv *) data;
+  struct aug_rm_state *state = (struct aug_rm_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_rm: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_rm: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_rm: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_aug_rm: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_aug_rm_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_aug_rm_ret (xdr, &state->ret)) {
     error (g, "guestfs_aug_rm: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_aug_rm: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_aug_rm (guestfs_h *g,
                const char *path)
 {
   struct guestfs_aug_rm_args args;
 }
 
 int guestfs_aug_rm (guestfs_h *g,
                const char *path)
 {
   struct guestfs_aug_rm_args args;
-  struct aug_rm_rv rv;
+  struct aug_rm_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_rm called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_rm");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_rm");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_rm", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_AUG_RM,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_AUG_RM,
@@ -1672,52 +1833,52 @@ int guestfs_aug_rm (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_rm_cb;
   g->reply_cb_internal = aug_rm_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_rm failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_aug_rm failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_RM, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_RM, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
-  return rv.ret.nrnodes;
+  return state.ret.nrnodes;
 }
 
 }
 
-struct aug_mv_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_mv_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_mv_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_mv_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_mv_rv *rv = (struct aug_mv_rv *) data;
+  struct aug_mv_state *state = (struct aug_mv_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_mv: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_mv: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_mv: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_aug_mv: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_aug_mv (guestfs_h *g,
 }
 
 int guestfs_aug_mv (guestfs_h *g,
@@ -1725,16 +1886,23 @@ int guestfs_aug_mv (guestfs_h *g,
                const char *dest)
 {
   struct guestfs_aug_mv_args args;
                const char *dest)
 {
   struct guestfs_aug_mv_args args;
-  struct aug_mv_rv rv;
+  struct aug_mv_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_mv called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_mv");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_mv");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_mv", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.src = (char *) src;
   args.dest = (char *) dest;
 
   args.src = (char *) src;
   args.dest = (char *) dest;
@@ -1743,30 +1911,30 @@ int guestfs_aug_mv (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_mv_cb;
   g->reply_cb_internal = aug_mv_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_mv failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_aug_mv failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_MV, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_MV, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct aug_match_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_match_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_match_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_match_ret ret;
@@ -1774,42 +1942,49 @@ struct aug_match_rv {
 
 static void aug_match_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void aug_match_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_match_rv *rv = (struct aug_match_rv *) data;
+  struct aug_match_state *state = (struct aug_match_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_match: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_match: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_match: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_aug_match: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_aug_match_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_aug_match_ret (xdr, &state->ret)) {
     error (g, "guestfs_aug_match: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_aug_match: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_aug_match (guestfs_h *g,
                const char *path)
 {
   struct guestfs_aug_match_args args;
 }
 
 char **guestfs_aug_match (guestfs_h *g,
                const char *path)
 {
   struct guestfs_aug_match_args args;
-  struct aug_match_rv rv;
+  struct aug_match_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_match called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_match");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_match");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_match", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_AUG_MATCH,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_AUG_MATCH,
@@ -1817,164 +1992,178 @@ char **guestfs_aug_match (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_match_cb;
   g->reply_cb_internal = aug_match_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_match failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_aug_match failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_MATCH, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_MATCH, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.matches.matches_val =    safe_realloc (g, rv.ret.matches.matches_val,
-                  sizeof (char *) * (rv.ret.matches.matches_len + 1));
-  rv.ret.matches.matches_val[rv.ret.matches.matches_len] = NULL;
-  return rv.ret.matches.matches_val;
+  state.ret.matches.matches_val =    safe_realloc (g, state.ret.matches.matches_val,
+                  sizeof (char *) * (state.ret.matches.matches_len + 1));
+  state.ret.matches.matches_val[state.ret.matches.matches_len] = NULL;
+  return state.ret.matches.matches_val;
 }
 
 }
 
-struct aug_save_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_save_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_save_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_save_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_save_rv *rv = (struct aug_save_rv *) data;
+  struct aug_save_state *state = (struct aug_save_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_save: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_save: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_save: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_aug_save: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_aug_save (guestfs_h *g)
 {
 }
 
 int guestfs_aug_save (guestfs_h *g)
 {
-  struct aug_save_rv rv;
+  struct aug_save_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_save called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_save");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_save");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_save", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_AUG_SAVE, NULL, NULL);
   if (serial == -1)
     return -1;
 
 
   serial = dispatch (g, GUESTFS_PROC_AUG_SAVE, NULL, NULL);
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_save_cb;
   g->reply_cb_internal = aug_save_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_save failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_aug_save failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_SAVE, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_SAVE, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct aug_load_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_load_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_load_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void aug_load_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_load_rv *rv = (struct aug_load_rv *) data;
+  struct aug_load_state *state = (struct aug_load_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_load: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_load: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_load: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_aug_load: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_aug_load (guestfs_h *g)
 {
 }
 
 int guestfs_aug_load (guestfs_h *g)
 {
-  struct aug_load_rv rv;
+  struct aug_load_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_load called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_load");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_load");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_load", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_AUG_LOAD, NULL, NULL);
   if (serial == -1)
     return -1;
 
 
   serial = dispatch (g, GUESTFS_PROC_AUG_LOAD, NULL, NULL);
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_load_cb;
   g->reply_cb_internal = aug_load_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_load failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_aug_load failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_LOAD, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_LOAD, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct aug_ls_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct aug_ls_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_ls_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_aug_ls_ret ret;
@@ -1982,42 +2171,49 @@ struct aug_ls_rv {
 
 static void aug_ls_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void aug_ls_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct aug_ls_rv *rv = (struct aug_ls_rv *) data;
+  struct aug_ls_state *state = (struct aug_ls_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_aug_ls: failed to parse reply header");
     return;
   }
     error (g, "guestfs_aug_ls: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_aug_ls: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_aug_ls: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_aug_ls_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_aug_ls_ret (xdr, &state->ret)) {
     error (g, "guestfs_aug_ls: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_aug_ls: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_aug_ls (guestfs_h *g,
                const char *path)
 {
   struct guestfs_aug_ls_args args;
 }
 
 char **guestfs_aug_ls (guestfs_h *g,
                const char *path)
 {
   struct guestfs_aug_ls_args args;
-  struct aug_ls_rv rv;
+  struct aug_ls_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_aug_ls called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_aug_ls");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_aug_ls");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_aug_ls", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_AUG_LS,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_AUG_LS,
@@ -2025,72 +2221,79 @@ char **guestfs_aug_ls (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = aug_ls_cb;
   g->reply_cb_internal = aug_ls_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_aug_ls failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_aug_ls failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_LS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_AUG_LS, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.matches.matches_val =    safe_realloc (g, rv.ret.matches.matches_val,
-                  sizeof (char *) * (rv.ret.matches.matches_len + 1));
-  rv.ret.matches.matches_val[rv.ret.matches.matches_len] = NULL;
-  return rv.ret.matches.matches_val;
+  state.ret.matches.matches_val =    safe_realloc (g, state.ret.matches.matches_val,
+                  sizeof (char *) * (state.ret.matches.matches_len + 1));
+  state.ret.matches.matches_val[state.ret.matches.matches_len] = NULL;
+  return state.ret.matches.matches_val;
 }
 
 }
 
-struct rm_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct rm_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void rm_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void rm_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct rm_rv *rv = (struct rm_rv *) data;
+  struct rm_state *state = (struct rm_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_rm: failed to parse reply header");
     return;
   }
     error (g, "guestfs_rm: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_rm: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_rm: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_rm (guestfs_h *g,
                const char *path)
 {
   struct guestfs_rm_args args;
 }
 
 int guestfs_rm (guestfs_h *g,
                const char *path)
 {
   struct guestfs_rm_args args;
-  struct rm_rv rv;
+  struct rm_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_rm called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_rm");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_rm");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_rm", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_RM,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_RM,
@@ -2098,68 +2301,75 @@ int guestfs_rm (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = rm_cb;
   g->reply_cb_internal = rm_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_rm failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_rm failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_RM, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_RM, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct rmdir_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct rmdir_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void rmdir_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void rmdir_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct rmdir_rv *rv = (struct rmdir_rv *) data;
+  struct rmdir_state *state = (struct rmdir_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_rmdir: failed to parse reply header");
     return;
   }
     error (g, "guestfs_rmdir: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_rmdir: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_rmdir: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_rmdir (guestfs_h *g,
                const char *path)
 {
   struct guestfs_rmdir_args args;
 }
 
 int guestfs_rmdir (guestfs_h *g,
                const char *path)
 {
   struct guestfs_rmdir_args args;
-  struct rmdir_rv rv;
+  struct rmdir_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_rmdir called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_rmdir");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_rmdir");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_rmdir", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_RMDIR,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_RMDIR,
@@ -2167,68 +2377,75 @@ int guestfs_rmdir (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = rmdir_cb;
   g->reply_cb_internal = rmdir_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_rmdir failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_rmdir failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_RMDIR, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_RMDIR, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct rm_rf_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct rm_rf_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void rm_rf_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void rm_rf_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct rm_rf_rv *rv = (struct rm_rf_rv *) data;
+  struct rm_rf_state *state = (struct rm_rf_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_rm_rf: failed to parse reply header");
     return;
   }
     error (g, "guestfs_rm_rf: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_rm_rf: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_rm_rf: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_rm_rf (guestfs_h *g,
                const char *path)
 {
   struct guestfs_rm_rf_args args;
 }
 
 int guestfs_rm_rf (guestfs_h *g,
                const char *path)
 {
   struct guestfs_rm_rf_args args;
-  struct rm_rf_rv rv;
+  struct rm_rf_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_rm_rf called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_rm_rf");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_rm_rf");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_rm_rf", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_RM_RF,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_RM_RF,
@@ -2236,68 +2453,75 @@ int guestfs_rm_rf (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = rm_rf_cb;
   g->reply_cb_internal = rm_rf_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_rm_rf failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_rm_rf failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_RM_RF, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_RM_RF, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct mkdir_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct mkdir_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void mkdir_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void mkdir_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct mkdir_rv *rv = (struct mkdir_rv *) data;
+  struct mkdir_state *state = (struct mkdir_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_mkdir: failed to parse reply header");
     return;
   }
     error (g, "guestfs_mkdir: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_mkdir: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_mkdir: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_mkdir (guestfs_h *g,
                const char *path)
 {
   struct guestfs_mkdir_args args;
 }
 
 int guestfs_mkdir (guestfs_h *g,
                const char *path)
 {
   struct guestfs_mkdir_args args;
-  struct mkdir_rv rv;
+  struct mkdir_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_mkdir called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_mkdir");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_mkdir");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_mkdir", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_MKDIR,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_MKDIR,
@@ -2305,68 +2529,75 @@ int guestfs_mkdir (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = mkdir_cb;
   g->reply_cb_internal = mkdir_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_mkdir failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_mkdir failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_MKDIR, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_MKDIR, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct mkdir_p_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct mkdir_p_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void mkdir_p_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void mkdir_p_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct mkdir_p_rv *rv = (struct mkdir_p_rv *) data;
+  struct mkdir_p_state *state = (struct mkdir_p_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_mkdir_p: failed to parse reply header");
     return;
   }
     error (g, "guestfs_mkdir_p: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_mkdir_p: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_mkdir_p: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_mkdir_p (guestfs_h *g,
                const char *path)
 {
   struct guestfs_mkdir_p_args args;
 }
 
 int guestfs_mkdir_p (guestfs_h *g,
                const char *path)
 {
   struct guestfs_mkdir_p_args args;
-  struct mkdir_p_rv rv;
+  struct mkdir_p_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_mkdir_p called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_mkdir_p");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_mkdir_p");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_mkdir_p", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_MKDIR_P,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_MKDIR_P,
@@ -2374,52 +2605,52 @@ int guestfs_mkdir_p (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = mkdir_p_cb;
   g->reply_cb_internal = mkdir_p_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_mkdir_p failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_mkdir_p failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_MKDIR_P, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_MKDIR_P, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct chmod_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct chmod_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void chmod_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void chmod_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct chmod_rv *rv = (struct chmod_rv *) data;
+  struct chmod_state *state = (struct chmod_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_chmod: failed to parse reply header");
     return;
   }
     error (g, "guestfs_chmod: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_chmod: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_chmod: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_chmod (guestfs_h *g,
 }
 
 int guestfs_chmod (guestfs_h *g,
@@ -2427,16 +2658,23 @@ int guestfs_chmod (guestfs_h *g,
                const char *path)
 {
   struct guestfs_chmod_args args;
                const char *path)
 {
   struct guestfs_chmod_args args;
-  struct chmod_rv rv;
+  struct chmod_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_chmod called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_chmod");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_chmod");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_chmod", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.mode = mode;
   args.path = (char *) path;
 
   args.mode = mode;
   args.path = (char *) path;
@@ -2445,52 +2683,52 @@ int guestfs_chmod (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = chmod_cb;
   g->reply_cb_internal = chmod_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_chmod failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_chmod failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_CHMOD, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_CHMOD, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct chown_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct chown_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void chown_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void chown_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct chown_rv *rv = (struct chown_rv *) data;
+  struct chown_state *state = (struct chown_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_chown: failed to parse reply header");
     return;
   }
     error (g, "guestfs_chown: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_chown: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_chown: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_chown (guestfs_h *g,
 }
 
 int guestfs_chown (guestfs_h *g,
@@ -2499,16 +2737,23 @@ int guestfs_chown (guestfs_h *g,
                const char *path)
 {
   struct guestfs_chown_args args;
                const char *path)
 {
   struct guestfs_chown_args args;
-  struct chown_rv rv;
+  struct chown_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_chown called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_chown");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_chown");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_chown", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.owner = owner;
   args.group = group;
 
   args.owner = owner;
   args.group = group;
@@ -2518,30 +2763,30 @@ int guestfs_chown (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = chown_cb;
   g->reply_cb_internal = chown_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_chown failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_chown failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_CHOWN, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_CHOWN, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct exists_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct exists_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_exists_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_exists_ret ret;
@@ -2549,42 +2794,49 @@ struct exists_rv {
 
 static void exists_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void exists_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct exists_rv *rv = (struct exists_rv *) data;
+  struct exists_state *state = (struct exists_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_exists: failed to parse reply header");
     return;
   }
     error (g, "guestfs_exists: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_exists: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_exists: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_exists_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_exists_ret (xdr, &state->ret)) {
     error (g, "guestfs_exists: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_exists: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_exists (guestfs_h *g,
                const char *path)
 {
   struct guestfs_exists_args args;
 }
 
 int guestfs_exists (guestfs_h *g,
                const char *path)
 {
   struct guestfs_exists_args args;
-  struct exists_rv rv;
+  struct exists_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_exists called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_exists");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_exists");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_exists", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_EXISTS,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_EXISTS,
@@ -2592,30 +2844,30 @@ int guestfs_exists (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = exists_cb;
   g->reply_cb_internal = exists_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_exists failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_exists failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_EXISTS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_EXISTS, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
-  return rv.ret.existsflag;
+  return state.ret.existsflag;
 }
 
 }
 
-struct is_file_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct is_file_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_is_file_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_is_file_ret ret;
@@ -2623,42 +2875,49 @@ struct is_file_rv {
 
 static void is_file_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void is_file_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct is_file_rv *rv = (struct is_file_rv *) data;
+  struct is_file_state *state = (struct is_file_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_is_file: failed to parse reply header");
     return;
   }
     error (g, "guestfs_is_file: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_is_file: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_is_file: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_is_file_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_is_file_ret (xdr, &state->ret)) {
     error (g, "guestfs_is_file: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_is_file: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_is_file (guestfs_h *g,
                const char *path)
 {
   struct guestfs_is_file_args args;
 }
 
 int guestfs_is_file (guestfs_h *g,
                const char *path)
 {
   struct guestfs_is_file_args args;
-  struct is_file_rv rv;
+  struct is_file_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_is_file called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_is_file");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_is_file");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_is_file", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_IS_FILE,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_IS_FILE,
@@ -2666,30 +2925,30 @@ int guestfs_is_file (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = is_file_cb;
   g->reply_cb_internal = is_file_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_is_file failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_is_file failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_IS_FILE, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_IS_FILE, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
-  return rv.ret.fileflag;
+  return state.ret.fileflag;
 }
 
 }
 
-struct is_dir_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct is_dir_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_is_dir_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_is_dir_ret ret;
@@ -2697,42 +2956,49 @@ struct is_dir_rv {
 
 static void is_dir_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void is_dir_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct is_dir_rv *rv = (struct is_dir_rv *) data;
+  struct is_dir_state *state = (struct is_dir_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_is_dir: failed to parse reply header");
     return;
   }
     error (g, "guestfs_is_dir: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_is_dir: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_is_dir: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_is_dir_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_is_dir_ret (xdr, &state->ret)) {
     error (g, "guestfs_is_dir: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_is_dir: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_is_dir (guestfs_h *g,
                const char *path)
 {
   struct guestfs_is_dir_args args;
 }
 
 int guestfs_is_dir (guestfs_h *g,
                const char *path)
 {
   struct guestfs_is_dir_args args;
-  struct is_dir_rv rv;
+  struct is_dir_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_is_dir called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_is_dir");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_is_dir");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_is_dir", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_IS_DIR,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_IS_DIR,
@@ -2740,68 +3006,75 @@ int guestfs_is_dir (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = is_dir_cb;
   g->reply_cb_internal = is_dir_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_is_dir failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_is_dir failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_IS_DIR, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_IS_DIR, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
-  return rv.ret.dirflag;
+  return state.ret.dirflag;
 }
 
 }
 
-struct pvcreate_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct pvcreate_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void pvcreate_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void pvcreate_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct pvcreate_rv *rv = (struct pvcreate_rv *) data;
+  struct pvcreate_state *state = (struct pvcreate_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_pvcreate: failed to parse reply header");
     return;
   }
     error (g, "guestfs_pvcreate: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_pvcreate: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_pvcreate: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_pvcreate (guestfs_h *g,
                const char *device)
 {
   struct guestfs_pvcreate_args args;
 }
 
 int guestfs_pvcreate (guestfs_h *g,
                const char *device)
 {
   struct guestfs_pvcreate_args args;
-  struct pvcreate_rv rv;
+  struct pvcreate_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_pvcreate called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_pvcreate");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_pvcreate");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_pvcreate", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_PVCREATE,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_PVCREATE,
@@ -2809,52 +3082,52 @@ int guestfs_pvcreate (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = pvcreate_cb;
   g->reply_cb_internal = pvcreate_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_pvcreate failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_pvcreate failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_PVCREATE, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_PVCREATE, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct vgcreate_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct vgcreate_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void vgcreate_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void vgcreate_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct vgcreate_rv *rv = (struct vgcreate_rv *) data;
+  struct vgcreate_state *state = (struct vgcreate_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_vgcreate: failed to parse reply header");
     return;
   }
     error (g, "guestfs_vgcreate: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_vgcreate: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_vgcreate: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_vgcreate (guestfs_h *g,
 }
 
 int guestfs_vgcreate (guestfs_h *g,
@@ -2862,16 +3135,23 @@ int guestfs_vgcreate (guestfs_h *g,
                char * const* const physvols)
 {
   struct guestfs_vgcreate_args args;
                char * const* const physvols)
 {
   struct guestfs_vgcreate_args args;
-  struct vgcreate_rv rv;
+  struct vgcreate_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_vgcreate called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_vgcreate");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_vgcreate");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_vgcreate", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.volgroup = (char *) volgroup;
   args.physvols.physvols_val = (char **) physvols;
 
   args.volgroup = (char *) volgroup;
   args.physvols.physvols_val = (char **) physvols;
@@ -2881,52 +3161,52 @@ int guestfs_vgcreate (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = vgcreate_cb;
   g->reply_cb_internal = vgcreate_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_vgcreate failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_vgcreate failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_VGCREATE, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_VGCREATE, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct lvcreate_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct lvcreate_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void lvcreate_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void lvcreate_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct lvcreate_rv *rv = (struct lvcreate_rv *) data;
+  struct lvcreate_state *state = (struct lvcreate_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_lvcreate: failed to parse reply header");
     return;
   }
     error (g, "guestfs_lvcreate: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_lvcreate: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_lvcreate: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_lvcreate (guestfs_h *g,
 }
 
 int guestfs_lvcreate (guestfs_h *g,
@@ -2935,16 +3215,23 @@ int guestfs_lvcreate (guestfs_h *g,
                int mbytes)
 {
   struct guestfs_lvcreate_args args;
                int mbytes)
 {
   struct guestfs_lvcreate_args args;
-  struct lvcreate_rv rv;
+  struct lvcreate_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_lvcreate called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_lvcreate");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_lvcreate");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_lvcreate", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.logvol = (char *) logvol;
   args.volgroup = (char *) volgroup;
 
   args.logvol = (char *) logvol;
   args.volgroup = (char *) volgroup;
@@ -2954,52 +3241,52 @@ int guestfs_lvcreate (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = lvcreate_cb;
   g->reply_cb_internal = lvcreate_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_lvcreate failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_lvcreate failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LVCREATE, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_LVCREATE, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct mkfs_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct mkfs_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void mkfs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void mkfs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct mkfs_rv *rv = (struct mkfs_rv *) data;
+  struct mkfs_state *state = (struct mkfs_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_mkfs: failed to parse reply header");
     return;
   }
     error (g, "guestfs_mkfs: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_mkfs: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_mkfs: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_mkfs (guestfs_h *g,
 }
 
 int guestfs_mkfs (guestfs_h *g,
@@ -3007,16 +3294,23 @@ int guestfs_mkfs (guestfs_h *g,
                const char *device)
 {
   struct guestfs_mkfs_args args;
                const char *device)
 {
   struct guestfs_mkfs_args args;
-  struct mkfs_rv rv;
+  struct mkfs_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_mkfs called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_mkfs");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_mkfs");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_mkfs", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.fstype = (char *) fstype;
   args.device = (char *) device;
 
   args.fstype = (char *) fstype;
   args.device = (char *) device;
@@ -3025,52 +3319,52 @@ int guestfs_mkfs (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = mkfs_cb;
   g->reply_cb_internal = mkfs_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_mkfs failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_mkfs failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_MKFS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_MKFS, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct sfdisk_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct sfdisk_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void sfdisk_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void sfdisk_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct sfdisk_rv *rv = (struct sfdisk_rv *) data;
+  struct sfdisk_state *state = (struct sfdisk_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_sfdisk: failed to parse reply header");
     return;
   }
     error (g, "guestfs_sfdisk: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_sfdisk: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_sfdisk: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_sfdisk (guestfs_h *g,
 }
 
 int guestfs_sfdisk (guestfs_h *g,
@@ -3081,16 +3375,23 @@ int guestfs_sfdisk (guestfs_h *g,
                char * const* const lines)
 {
   struct guestfs_sfdisk_args args;
                char * const* const lines)
 {
   struct guestfs_sfdisk_args args;
-  struct sfdisk_rv rv;
+  struct sfdisk_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_sfdisk called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_sfdisk");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_sfdisk");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_sfdisk", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   args.cyls = cyls;
 
   args.device = (char *) device;
   args.cyls = cyls;
@@ -3103,52 +3404,52 @@ int guestfs_sfdisk (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = sfdisk_cb;
   g->reply_cb_internal = sfdisk_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_sfdisk failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_sfdisk failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_SFDISK, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_SFDISK, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct write_file_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct write_file_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void write_file_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void write_file_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct write_file_rv *rv = (struct write_file_rv *) data;
+  struct write_file_state *state = (struct write_file_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_write_file: failed to parse reply header");
     return;
   }
     error (g, "guestfs_write_file: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_write_file: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_write_file: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_write_file (guestfs_h *g,
 }
 
 int guestfs_write_file (guestfs_h *g,
@@ -3157,16 +3458,23 @@ int guestfs_write_file (guestfs_h *g,
                int size)
 {
   struct guestfs_write_file_args args;
                int size)
 {
   struct guestfs_write_file_args args;
-  struct write_file_rv rv;
+  struct write_file_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_write_file called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_write_file");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_write_file");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_write_file", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   args.content = (char *) content;
 
   args.path = (char *) path;
   args.content = (char *) content;
@@ -3176,68 +3484,75 @@ int guestfs_write_file (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = write_file_cb;
   g->reply_cb_internal = write_file_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_write_file failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_write_file failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_WRITE_FILE, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_WRITE_FILE, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct umount_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct umount_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void umount_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void umount_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct umount_rv *rv = (struct umount_rv *) data;
+  struct umount_state *state = (struct umount_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_umount: failed to parse reply header");
     return;
   }
     error (g, "guestfs_umount: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_umount: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_umount: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_umount (guestfs_h *g,
                const char *pathordevice)
 {
   struct guestfs_umount_args args;
 }
 
 int guestfs_umount (guestfs_h *g,
                const char *pathordevice)
 {
   struct guestfs_umount_args args;
-  struct umount_rv rv;
+  struct umount_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_umount called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_umount");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_umount");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_umount", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.pathordevice = (char *) pathordevice;
   serial = dispatch (g, GUESTFS_PROC_UMOUNT,
 
   args.pathordevice = (char *) pathordevice;
   serial = dispatch (g, GUESTFS_PROC_UMOUNT,
@@ -3245,30 +3560,30 @@ int guestfs_umount (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = umount_cb;
   g->reply_cb_internal = umount_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_umount failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_umount failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_UMOUNT, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_UMOUNT, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct mounts_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct mounts_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_mounts_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_mounts_ret ret;
@@ -3276,203 +3591,224 @@ struct mounts_rv {
 
 static void mounts_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void mounts_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct mounts_rv *rv = (struct mounts_rv *) data;
+  struct mounts_state *state = (struct mounts_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_mounts: failed to parse reply header");
     return;
   }
     error (g, "guestfs_mounts: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_mounts: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_mounts: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_mounts_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_mounts_ret (xdr, &state->ret)) {
     error (g, "guestfs_mounts: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_mounts: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_mounts (guestfs_h *g)
 {
 }
 
 char **guestfs_mounts (guestfs_h *g)
 {
-  struct mounts_rv rv;
+  struct mounts_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_mounts called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_mounts");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_mounts");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_mounts", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_MOUNTS, NULL, NULL);
   if (serial == -1)
     return NULL;
 
 
   serial = dispatch (g, GUESTFS_PROC_MOUNTS, NULL, NULL);
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = mounts_cb;
   g->reply_cb_internal = mounts_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_mounts failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_mounts failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_MOUNTS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_MOUNTS, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.devices.devices_val =    safe_realloc (g, rv.ret.devices.devices_val,
-                  sizeof (char *) * (rv.ret.devices.devices_len + 1));
-  rv.ret.devices.devices_val[rv.ret.devices.devices_len] = NULL;
-  return rv.ret.devices.devices_val;
+  state.ret.devices.devices_val =    safe_realloc (g, state.ret.devices.devices_val,
+                  sizeof (char *) * (state.ret.devices.devices_len + 1));
+  state.ret.devices.devices_val[state.ret.devices.devices_len] = NULL;
+  return state.ret.devices.devices_val;
 }
 
 }
 
-struct umount_all_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct umount_all_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void umount_all_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void umount_all_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct umount_all_rv *rv = (struct umount_all_rv *) data;
+  struct umount_all_state *state = (struct umount_all_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_umount_all: failed to parse reply header");
     return;
   }
     error (g, "guestfs_umount_all: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_umount_all: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_umount_all: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_umount_all (guestfs_h *g)
 {
 }
 
 int guestfs_umount_all (guestfs_h *g)
 {
-  struct umount_all_rv rv;
+  struct umount_all_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_umount_all called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_umount_all");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_umount_all");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_umount_all", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_UMOUNT_ALL, NULL, NULL);
   if (serial == -1)
     return -1;
 
 
   serial = dispatch (g, GUESTFS_PROC_UMOUNT_ALL, NULL, NULL);
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = umount_all_cb;
   g->reply_cb_internal = umount_all_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_umount_all failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_umount_all failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_UMOUNT_ALL, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_UMOUNT_ALL, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct lvm_remove_all_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct lvm_remove_all_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void lvm_remove_all_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void lvm_remove_all_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct lvm_remove_all_rv *rv = (struct lvm_remove_all_rv *) data;
+  struct lvm_remove_all_state *state = (struct lvm_remove_all_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_lvm_remove_all: failed to parse reply header");
     return;
   }
     error (g, "guestfs_lvm_remove_all: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_lvm_remove_all: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_lvm_remove_all: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_lvm_remove_all (guestfs_h *g)
 {
 }
 
 int guestfs_lvm_remove_all (guestfs_h *g)
 {
-  struct lvm_remove_all_rv rv;
+  struct lvm_remove_all_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_lvm_remove_all called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_lvm_remove_all");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_lvm_remove_all");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_lvm_remove_all", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   serial = dispatch (g, GUESTFS_PROC_LVM_REMOVE_ALL, NULL, NULL);
   if (serial == -1)
     return -1;
 
 
   serial = dispatch (g, GUESTFS_PROC_LVM_REMOVE_ALL, NULL, NULL);
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = lvm_remove_all_cb;
   g->reply_cb_internal = lvm_remove_all_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_lvm_remove_all failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_lvm_remove_all failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LVM_REMOVE_ALL, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_LVM_REMOVE_ALL, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct file_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct file_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_file_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_file_ret ret;
@@ -3480,42 +3816,49 @@ struct file_rv {
 
 static void file_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void file_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct file_rv *rv = (struct file_rv *) data;
+  struct file_state *state = (struct file_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_file: failed to parse reply header");
     return;
   }
     error (g, "guestfs_file: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_file: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_file: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_file_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_file_ret (xdr, &state->ret)) {
     error (g, "guestfs_file: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_file: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char *guestfs_file (guestfs_h *g,
                const char *path)
 {
   struct guestfs_file_args args;
 }
 
 char *guestfs_file (guestfs_h *g,
                const char *path)
 {
   struct guestfs_file_args args;
-  struct file_rv rv;
+  struct file_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_file called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_file");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_file");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_file", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_FILE,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_FILE,
@@ -3523,30 +3866,30 @@ char *guestfs_file (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = file_cb;
   g->reply_cb_internal = file_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_file failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_file failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_FILE, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_FILE, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
     return NULL;
   }
 
-  return rv.ret.description; /* caller will free */
+  return state.ret.description; /* caller will free */
 }
 
 }
 
-struct command_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct command_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_command_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_command_ret ret;
@@ -3554,42 +3897,49 @@ struct command_rv {
 
 static void command_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void command_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct command_rv *rv = (struct command_rv *) data;
+  struct command_state *state = (struct command_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_command: failed to parse reply header");
     return;
   }
     error (g, "guestfs_command: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_command: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_command: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_command_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_command_ret (xdr, &state->ret)) {
     error (g, "guestfs_command: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_command: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char *guestfs_command (guestfs_h *g,
                char * const* const arguments)
 {
   struct guestfs_command_args args;
 }
 
 char *guestfs_command (guestfs_h *g,
                char * const* const arguments)
 {
   struct guestfs_command_args args;
-  struct command_rv rv;
+  struct command_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_command called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_command");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_command");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_command", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.arguments.arguments_val = (char **) arguments;
   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
 
   args.arguments.arguments_val = (char **) arguments;
   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
@@ -3598,30 +3948,30 @@ char *guestfs_command (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = command_cb;
   g->reply_cb_internal = command_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_command failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_command failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_COMMAND, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_COMMAND, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
     return NULL;
   }
 
-  return rv.ret.output; /* caller will free */
+  return state.ret.output; /* caller will free */
 }
 
 }
 
-struct command_lines_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct command_lines_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_command_lines_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_command_lines_ret ret;
@@ -3629,42 +3979,49 @@ struct command_lines_rv {
 
 static void command_lines_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void command_lines_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct command_lines_rv *rv = (struct command_lines_rv *) data;
+  struct command_lines_state *state = (struct command_lines_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_command_lines: failed to parse reply header");
     return;
   }
     error (g, "guestfs_command_lines: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_command_lines: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_command_lines: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_command_lines_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_command_lines_ret (xdr, &state->ret)) {
     error (g, "guestfs_command_lines: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_command_lines: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_command_lines (guestfs_h *g,
                char * const* const arguments)
 {
   struct guestfs_command_lines_args args;
 }
 
 char **guestfs_command_lines (guestfs_h *g,
                char * const* const arguments)
 {
   struct guestfs_command_lines_args args;
-  struct command_lines_rv rv;
+  struct command_lines_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_command_lines called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_command_lines");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_command_lines");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_command_lines", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.arguments.arguments_val = (char **) arguments;
   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
 
   args.arguments.arguments_val = (char **) arguments;
   for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ;
@@ -3673,34 +4030,34 @@ char **guestfs_command_lines (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = command_lines_cb;
   g->reply_cb_internal = command_lines_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_command_lines failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_command_lines failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_COMMAND_LINES, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_COMMAND_LINES, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.lines.lines_val =    safe_realloc (g, rv.ret.lines.lines_val,
-                  sizeof (char *) * (rv.ret.lines.lines_len + 1));
-  rv.ret.lines.lines_val[rv.ret.lines.lines_len] = NULL;
-  return rv.ret.lines.lines_val;
+  state.ret.lines.lines_val =    safe_realloc (g, state.ret.lines.lines_val,
+                  sizeof (char *) * (state.ret.lines.lines_len + 1));
+  state.ret.lines.lines_val[state.ret.lines.lines_len] = NULL;
+  return state.ret.lines.lines_val;
 }
 
 }
 
-struct stat_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct stat_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_stat_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_stat_ret ret;
@@ -3708,42 +4065,49 @@ struct stat_rv {
 
 static void stat_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void stat_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct stat_rv *rv = (struct stat_rv *) data;
+  struct stat_state *state = (struct stat_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_stat: failed to parse reply header");
     return;
   }
     error (g, "guestfs_stat: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_stat: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_stat: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_stat_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_stat_ret (xdr, &state->ret)) {
     error (g, "guestfs_stat: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_stat: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 struct guestfs_stat *guestfs_stat (guestfs_h *g,
                const char *path)
 {
   struct guestfs_stat_args args;
 }
 
 struct guestfs_stat *guestfs_stat (guestfs_h *g,
                const char *path)
 {
   struct guestfs_stat_args args;
-  struct stat_rv rv;
+  struct stat_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_stat called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_stat");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_stat");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_stat", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_STAT,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_STAT,
@@ -3751,31 +4115,31 @@ struct guestfs_stat *guestfs_stat (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = stat_cb;
   g->reply_cb_internal = stat_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_stat failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_stat failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_STAT, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_STAT, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this */
     return NULL;
   }
 
   /* caller will free this */
-  return safe_memdup (g, &rv.ret.statbuf, sizeof (rv.ret.statbuf));
+  return safe_memdup (g, &state.ret.statbuf, sizeof (state.ret.statbuf));
 }
 
 }
 
-struct lstat_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct lstat_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_lstat_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_lstat_ret ret;
@@ -3783,42 +4147,49 @@ struct lstat_rv {
 
 static void lstat_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void lstat_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct lstat_rv *rv = (struct lstat_rv *) data;
+  struct lstat_state *state = (struct lstat_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_lstat: failed to parse reply header");
     return;
   }
     error (g, "guestfs_lstat: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_lstat: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_lstat: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_lstat_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_lstat_ret (xdr, &state->ret)) {
     error (g, "guestfs_lstat: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_lstat: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 struct guestfs_stat *guestfs_lstat (guestfs_h *g,
                const char *path)
 {
   struct guestfs_lstat_args args;
 }
 
 struct guestfs_stat *guestfs_lstat (guestfs_h *g,
                const char *path)
 {
   struct guestfs_lstat_args args;
-  struct lstat_rv rv;
+  struct lstat_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_lstat called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_lstat");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_lstat");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_lstat", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_LSTAT,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_LSTAT,
@@ -3826,31 +4197,31 @@ struct guestfs_stat *guestfs_lstat (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = lstat_cb;
   g->reply_cb_internal = lstat_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_lstat failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_lstat failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LSTAT, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_LSTAT, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this */
     return NULL;
   }
 
   /* caller will free this */
-  return safe_memdup (g, &rv.ret.statbuf, sizeof (rv.ret.statbuf));
+  return safe_memdup (g, &state.ret.statbuf, sizeof (state.ret.statbuf));
 }
 
 }
 
-struct statvfs_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct statvfs_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_statvfs_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_statvfs_ret ret;
@@ -3858,42 +4229,49 @@ struct statvfs_rv {
 
 static void statvfs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void statvfs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct statvfs_rv *rv = (struct statvfs_rv *) data;
+  struct statvfs_state *state = (struct statvfs_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_statvfs: failed to parse reply header");
     return;
   }
     error (g, "guestfs_statvfs: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_statvfs: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_statvfs: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_statvfs_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_statvfs_ret (xdr, &state->ret)) {
     error (g, "guestfs_statvfs: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_statvfs: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 struct guestfs_statvfs *guestfs_statvfs (guestfs_h *g,
                const char *path)
 {
   struct guestfs_statvfs_args args;
 }
 
 struct guestfs_statvfs *guestfs_statvfs (guestfs_h *g,
                const char *path)
 {
   struct guestfs_statvfs_args args;
-  struct statvfs_rv rv;
+  struct statvfs_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_statvfs called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_statvfs");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_statvfs");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_statvfs", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_STATVFS,
 
   args.path = (char *) path;
   serial = dispatch (g, GUESTFS_PROC_STATVFS,
@@ -3901,31 +4279,31 @@ struct guestfs_statvfs *guestfs_statvfs (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = statvfs_cb;
   g->reply_cb_internal = statvfs_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_statvfs failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_statvfs failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_STATVFS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_STATVFS, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this */
     return NULL;
   }
 
   /* caller will free this */
-  return safe_memdup (g, &rv.ret.statbuf, sizeof (rv.ret.statbuf));
+  return safe_memdup (g, &state.ret.statbuf, sizeof (state.ret.statbuf));
 }
 
 }
 
-struct tune2fs_l_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct tune2fs_l_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_tune2fs_l_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_tune2fs_l_ret ret;
@@ -3933,42 +4311,49 @@ struct tune2fs_l_rv {
 
 static void tune2fs_l_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void tune2fs_l_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct tune2fs_l_rv *rv = (struct tune2fs_l_rv *) data;
+  struct tune2fs_l_state *state = (struct tune2fs_l_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_tune2fs_l: failed to parse reply header");
     return;
   }
     error (g, "guestfs_tune2fs_l: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_tune2fs_l: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_tune2fs_l: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_tune2fs_l_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_tune2fs_l_ret (xdr, &state->ret)) {
     error (g, "guestfs_tune2fs_l: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_tune2fs_l: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 char **guestfs_tune2fs_l (guestfs_h *g,
                const char *device)
 {
   struct guestfs_tune2fs_l_args args;
 }
 
 char **guestfs_tune2fs_l (guestfs_h *g,
                const char *device)
 {
   struct guestfs_tune2fs_l_args args;
-  struct tune2fs_l_rv rv;
+  struct tune2fs_l_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_tune2fs_l called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_tune2fs_l");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_tune2fs_l");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_tune2fs_l", g->state);
     return NULL;
   }
 
     return NULL;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_TUNE2FS_L,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_TUNE2FS_L,
@@ -3976,72 +4361,79 @@ char **guestfs_tune2fs_l (guestfs_h *g,
   if (serial == -1)
     return NULL;
 
   if (serial == -1)
     return NULL;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = tune2fs_l_cb;
   g->reply_cb_internal = tune2fs_l_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_tune2fs_l failed, see earlier error messages");
     return NULL;
   }
 
     error (g, "guestfs_tune2fs_l failed, see earlier error messages");
     return NULL;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_TUNE2FS_L, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_TUNE2FS_L, serial) == -1)
     return NULL;
 
     return NULL;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
     return NULL;
   }
 
   /* caller will free this, but we need to add a NULL entry */
-  rv.ret.superblock.superblock_val =    safe_realloc (g, rv.ret.superblock.superblock_val,
-                  sizeof (char *) * (rv.ret.superblock.superblock_len + 1));
-  rv.ret.superblock.superblock_val[rv.ret.superblock.superblock_len] = NULL;
-  return rv.ret.superblock.superblock_val;
+  state.ret.superblock.superblock_val =    safe_realloc (g, state.ret.superblock.superblock_val,
+                  sizeof (char *) * (state.ret.superblock.superblock_len + 1));
+  state.ret.superblock.superblock_val[state.ret.superblock.superblock_len] = NULL;
+  return state.ret.superblock.superblock_val;
 }
 
 }
 
-struct blockdev_setro_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct blockdev_setro_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void blockdev_setro_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void blockdev_setro_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct blockdev_setro_rv *rv = (struct blockdev_setro_rv *) data;
+  struct blockdev_setro_state *state = (struct blockdev_setro_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_blockdev_setro: failed to parse reply header");
     return;
   }
     error (g, "guestfs_blockdev_setro: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_blockdev_setro: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_blockdev_setro: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_blockdev_setro (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_setro_args args;
 }
 
 int guestfs_blockdev_setro (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_setro_args args;
-  struct blockdev_setro_rv rv;
+  struct blockdev_setro_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_blockdev_setro called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_blockdev_setro");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_blockdev_setro");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_blockdev_setro", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_SETRO,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_SETRO,
@@ -4049,68 +4441,75 @@ int guestfs_blockdev_setro (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = blockdev_setro_cb;
   g->reply_cb_internal = blockdev_setro_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_blockdev_setro failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_blockdev_setro failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_BLOCKDEV_SETRO, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_BLOCKDEV_SETRO, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct blockdev_setrw_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct blockdev_setrw_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void blockdev_setrw_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void blockdev_setrw_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct blockdev_setrw_rv *rv = (struct blockdev_setrw_rv *) data;
+  struct blockdev_setrw_state *state = (struct blockdev_setrw_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_blockdev_setrw: failed to parse reply header");
     return;
   }
     error (g, "guestfs_blockdev_setrw: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_blockdev_setrw: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_blockdev_setrw: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_blockdev_setrw (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_setrw_args args;
 }
 
 int guestfs_blockdev_setrw (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_setrw_args args;
-  struct blockdev_setrw_rv rv;
+  struct blockdev_setrw_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_blockdev_setrw called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_blockdev_setrw");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_blockdev_setrw");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_blockdev_setrw", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_SETRW,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_SETRW,
@@ -4118,30 +4517,30 @@ int guestfs_blockdev_setrw (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = blockdev_setrw_cb;
   g->reply_cb_internal = blockdev_setrw_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_blockdev_setrw failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_blockdev_setrw failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_BLOCKDEV_SETRW, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_BLOCKDEV_SETRW, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct blockdev_getro_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct blockdev_getro_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_blockdev_getro_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_blockdev_getro_ret ret;
@@ -4149,42 +4548,49 @@ struct blockdev_getro_rv {
 
 static void blockdev_getro_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void blockdev_getro_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct blockdev_getro_rv *rv = (struct blockdev_getro_rv *) data;
+  struct blockdev_getro_state *state = (struct blockdev_getro_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_blockdev_getro: failed to parse reply header");
     return;
   }
     error (g, "guestfs_blockdev_getro: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_blockdev_getro: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_blockdev_getro: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_blockdev_getro_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_blockdev_getro_ret (xdr, &state->ret)) {
     error (g, "guestfs_blockdev_getro: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_blockdev_getro: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_blockdev_getro (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_getro_args args;
 }
 
 int guestfs_blockdev_getro (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_getro_args args;
-  struct blockdev_getro_rv rv;
+  struct blockdev_getro_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_blockdev_getro called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_blockdev_getro");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_blockdev_getro");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_blockdev_getro", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_GETRO,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_GETRO,
@@ -4192,30 +4598,30 @@ int guestfs_blockdev_getro (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = blockdev_getro_cb;
   g->reply_cb_internal = blockdev_getro_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_blockdev_getro failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_blockdev_getro failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_BLOCKDEV_GETRO, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_BLOCKDEV_GETRO, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
-  return rv.ret.ro;
+  return state.ret.ro;
 }
 
 }
 
-struct blockdev_getss_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct blockdev_getss_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_blockdev_getss_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_blockdev_getss_ret ret;
@@ -4223,42 +4629,49 @@ struct blockdev_getss_rv {
 
 static void blockdev_getss_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void blockdev_getss_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct blockdev_getss_rv *rv = (struct blockdev_getss_rv *) data;
+  struct blockdev_getss_state *state = (struct blockdev_getss_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_blockdev_getss: failed to parse reply header");
     return;
   }
     error (g, "guestfs_blockdev_getss: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_blockdev_getss: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_blockdev_getss: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_blockdev_getss_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_blockdev_getss_ret (xdr, &state->ret)) {
     error (g, "guestfs_blockdev_getss: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_blockdev_getss: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_blockdev_getss (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_getss_args args;
 }
 
 int guestfs_blockdev_getss (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_getss_args args;
-  struct blockdev_getss_rv rv;
+  struct blockdev_getss_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_blockdev_getss called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_blockdev_getss");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_blockdev_getss");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_blockdev_getss", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_GETSS,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_GETSS,
@@ -4266,30 +4679,30 @@ int guestfs_blockdev_getss (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = blockdev_getss_cb;
   g->reply_cb_internal = blockdev_getss_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_blockdev_getss failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_blockdev_getss failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_BLOCKDEV_GETSS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_BLOCKDEV_GETSS, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
-  return rv.ret.sectorsize;
+  return state.ret.sectorsize;
 }
 
 }
 
-struct blockdev_getbsz_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct blockdev_getbsz_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_blockdev_getbsz_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_blockdev_getbsz_ret ret;
@@ -4297,42 +4710,49 @@ struct blockdev_getbsz_rv {
 
 static void blockdev_getbsz_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void blockdev_getbsz_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct blockdev_getbsz_rv *rv = (struct blockdev_getbsz_rv *) data;
+  struct blockdev_getbsz_state *state = (struct blockdev_getbsz_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_blockdev_getbsz: failed to parse reply header");
     return;
   }
     error (g, "guestfs_blockdev_getbsz: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_blockdev_getbsz: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_blockdev_getbsz: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_blockdev_getbsz_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_blockdev_getbsz_ret (xdr, &state->ret)) {
     error (g, "guestfs_blockdev_getbsz: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_blockdev_getbsz: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_blockdev_getbsz (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_getbsz_args args;
 }
 
 int guestfs_blockdev_getbsz (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_getbsz_args args;
-  struct blockdev_getbsz_rv rv;
+  struct blockdev_getbsz_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_blockdev_getbsz called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_blockdev_getbsz");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_blockdev_getbsz");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_blockdev_getbsz", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_GETBSZ,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_GETBSZ,
@@ -4340,52 +4760,52 @@ int guestfs_blockdev_getbsz (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = blockdev_getbsz_cb;
   g->reply_cb_internal = blockdev_getbsz_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_blockdev_getbsz failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_blockdev_getbsz failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_BLOCKDEV_GETBSZ, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_BLOCKDEV_GETBSZ, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
-  return rv.ret.blocksize;
+  return state.ret.blocksize;
 }
 
 }
 
-struct blockdev_setbsz_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct blockdev_setbsz_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void blockdev_setbsz_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void blockdev_setbsz_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct blockdev_setbsz_rv *rv = (struct blockdev_setbsz_rv *) data;
+  struct blockdev_setbsz_state *state = (struct blockdev_setbsz_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_blockdev_setbsz: failed to parse reply header");
     return;
   }
     error (g, "guestfs_blockdev_setbsz: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_blockdev_setbsz: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_blockdev_setbsz: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_blockdev_setbsz (guestfs_h *g,
 }
 
 int guestfs_blockdev_setbsz (guestfs_h *g,
@@ -4393,16 +4813,23 @@ int guestfs_blockdev_setbsz (guestfs_h *g,
                int blocksize)
 {
   struct guestfs_blockdev_setbsz_args args;
                int blocksize)
 {
   struct guestfs_blockdev_setbsz_args args;
-  struct blockdev_setbsz_rv rv;
+  struct blockdev_setbsz_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_blockdev_setbsz called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_blockdev_setbsz");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_blockdev_setbsz");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_blockdev_setbsz", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   args.blocksize = blocksize;
 
   args.device = (char *) device;
   args.blocksize = blocksize;
@@ -4411,30 +4838,30 @@ int guestfs_blockdev_setbsz (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = blockdev_setbsz_cb;
   g->reply_cb_internal = blockdev_setbsz_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_blockdev_setbsz failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_blockdev_setbsz failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_BLOCKDEV_SETBSZ, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_BLOCKDEV_SETBSZ, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct blockdev_getsz_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct blockdev_getsz_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_blockdev_getsz_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_blockdev_getsz_ret ret;
@@ -4442,42 +4869,49 @@ struct blockdev_getsz_rv {
 
 static void blockdev_getsz_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void blockdev_getsz_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct blockdev_getsz_rv *rv = (struct blockdev_getsz_rv *) data;
+  struct blockdev_getsz_state *state = (struct blockdev_getsz_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_blockdev_getsz: failed to parse reply header");
     return;
   }
     error (g, "guestfs_blockdev_getsz: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_blockdev_getsz: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_blockdev_getsz: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_blockdev_getsz_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_blockdev_getsz_ret (xdr, &state->ret)) {
     error (g, "guestfs_blockdev_getsz: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_blockdev_getsz: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int64_t guestfs_blockdev_getsz (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_getsz_args args;
 }
 
 int64_t guestfs_blockdev_getsz (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_getsz_args args;
-  struct blockdev_getsz_rv rv;
+  struct blockdev_getsz_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_blockdev_getsz called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_blockdev_getsz");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_blockdev_getsz");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_blockdev_getsz", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_GETSZ,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_GETSZ,
@@ -4485,30 +4919,30 @@ int64_t guestfs_blockdev_getsz (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = blockdev_getsz_cb;
   g->reply_cb_internal = blockdev_getsz_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_blockdev_getsz failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_blockdev_getsz failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_BLOCKDEV_GETSZ, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_BLOCKDEV_GETSZ, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
-  return rv.ret.sizeinsectors;
+  return state.ret.sizeinsectors;
 }
 
 }
 
-struct blockdev_getsize64_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct blockdev_getsize64_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_blockdev_getsize64_ret ret;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
   struct guestfs_blockdev_getsize64_ret ret;
@@ -4516,42 +4950,49 @@ struct blockdev_getsize64_rv {
 
 static void blockdev_getsize64_cb (guestfs_h *g, void *data, XDR *xdr)
 {
 
 static void blockdev_getsize64_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct blockdev_getsize64_rv *rv = (struct blockdev_getsize64_rv *) data;
+  struct blockdev_getsize64_state *state = (struct blockdev_getsize64_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_blockdev_getsize64: failed to parse reply header");
     return;
   }
     error (g, "guestfs_blockdev_getsize64: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_blockdev_getsize64: failed to parse reply error");
       return;
     }
     goto done;
   }
       error (g, "guestfs_blockdev_getsize64: failed to parse reply error");
       return;
     }
     goto done;
   }
-  if (!xdr_guestfs_blockdev_getsize64_ret (xdr, &rv->ret)) {
+  if (!xdr_guestfs_blockdev_getsize64_ret (xdr, &state->ret)) {
     error (g, "guestfs_blockdev_getsize64: failed to parse reply");
     return;
   }
  done:
     error (g, "guestfs_blockdev_getsize64: failed to parse reply");
     return;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int64_t guestfs_blockdev_getsize64 (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_getsize64_args args;
 }
 
 int64_t guestfs_blockdev_getsize64 (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_getsize64_args args;
-  struct blockdev_getsize64_rv rv;
+  struct blockdev_getsize64_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_blockdev_getsize64 called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_blockdev_getsize64");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_blockdev_getsize64");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_blockdev_getsize64", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_GETSIZE64,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_GETSIZE64,
@@ -4559,68 +5000,75 @@ int64_t guestfs_blockdev_getsize64 (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = blockdev_getsize64_cb;
   g->reply_cb_internal = blockdev_getsize64_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_blockdev_getsize64 failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_blockdev_getsize64 failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_BLOCKDEV_GETSIZE64, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_BLOCKDEV_GETSIZE64, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
-  return rv.ret.sizeinbytes;
+  return state.ret.sizeinbytes;
 }
 
 }
 
-struct blockdev_flushbufs_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct blockdev_flushbufs_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void blockdev_flushbufs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void blockdev_flushbufs_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct blockdev_flushbufs_rv *rv = (struct blockdev_flushbufs_rv *) data;
+  struct blockdev_flushbufs_state *state = (struct blockdev_flushbufs_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_blockdev_flushbufs: failed to parse reply header");
     return;
   }
     error (g, "guestfs_blockdev_flushbufs: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_blockdev_flushbufs: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_blockdev_flushbufs: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_blockdev_flushbufs (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_flushbufs_args args;
 }
 
 int guestfs_blockdev_flushbufs (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_flushbufs_args args;
-  struct blockdev_flushbufs_rv rv;
+  struct blockdev_flushbufs_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_blockdev_flushbufs called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_blockdev_flushbufs");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_blockdev_flushbufs");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_blockdev_flushbufs", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS,
@@ -4628,68 +5076,75 @@ int guestfs_blockdev_flushbufs (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = blockdev_flushbufs_cb;
   g->reply_cb_internal = blockdev_flushbufs_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_blockdev_flushbufs failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_blockdev_flushbufs failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
   return 0;
 }
 
     return -1;
   }
 
   return 0;
 }
 
-struct blockdev_rereadpt_rv {
-  int cb_done;  /* flag to indicate callback was called */
+struct blockdev_rereadpt_state {
+  int cb_done;
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void blockdev_rereadpt_cb (guestfs_h *g, void *data, XDR *xdr)
 {
   struct guestfs_message_header hdr;
   struct guestfs_message_error err;
 };
 
 static void blockdev_rereadpt_cb (guestfs_h *g, void *data, XDR *xdr)
 {
-  struct blockdev_rereadpt_rv *rv = (struct blockdev_rereadpt_rv *) data;
+  struct blockdev_rereadpt_state *state = (struct blockdev_rereadpt_state *) data;
 
 
-  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+  if (!xdr_guestfs_message_header (xdr, &state->hdr)) {
     error (g, "guestfs_blockdev_rereadpt: failed to parse reply header");
     return;
   }
     error (g, "guestfs_blockdev_rereadpt: failed to parse reply header");
     return;
   }
-  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
-    if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+  if (state->hdr.status == GUESTFS_STATUS_ERROR) {
+    if (!xdr_guestfs_message_error (xdr, &state->err)) {
       error (g, "guestfs_blockdev_rereadpt: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
       error (g, "guestfs_blockdev_rereadpt: failed to parse reply error");
       return;
     }
     goto done;
   }
  done:
-  rv->cb_done = 1;
-  main_loop.main_loop_quit (g);
+  state->cb_done = 1;
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int guestfs_blockdev_rereadpt (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_rereadpt_args args;
 }
 
 int guestfs_blockdev_rereadpt (guestfs_h *g,
                const char *device)
 {
   struct guestfs_blockdev_rereadpt_args args;
-  struct blockdev_rereadpt_rv rv;
+  struct blockdev_rereadpt_state state;
   int serial;
 
   if (g->state != READY) {
   int serial;
 
   if (g->state != READY) {
-    error (g, "guestfs_blockdev_rereadpt called from the wrong state, %d != READY",
-      g->state);
+    if (g->state == CONFIG)
+      error (g, "%s: call launch() before using this function",
+        "guestfs_blockdev_rereadpt");
+    else if (g->state == LAUNCHING)
+      error (g, "%s: call wait_ready() before using this function",
+        "guestfs_blockdev_rereadpt");
+    else
+      error (g, "%s called from the wrong state, %d != READY",
+        "guestfs_blockdev_rereadpt", g->state);
     return -1;
   }
 
     return -1;
   }
 
-  memset (&rv, 0, sizeof rv);
+  memset (&state, 0, sizeof state);
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_REREADPT,
 
   args.device = (char *) device;
   serial = dispatch (g, GUESTFS_PROC_BLOCKDEV_REREADPT,
@@ -4697,22 +5152,22 @@ int guestfs_blockdev_rereadpt (guestfs_h *g,
   if (serial == -1)
     return -1;
 
   if (serial == -1)
     return -1;
 
-  rv.cb_done = 0;
+  state.cb_done = 0;
   g->reply_cb_internal = blockdev_rereadpt_cb;
   g->reply_cb_internal = blockdev_rereadpt_cb;
-  g->reply_cb_internal_data = &rv;
-  main_loop.main_loop_run (g);
+  g->reply_cb_internal_data = &state;
+  (void) g->main_loop->main_loop_run (g->main_loop, g);
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
   g->reply_cb_internal = NULL;
   g->reply_cb_internal_data = NULL;
-  if (!rv.cb_done) {
+  if (!state.cb_done) {
     error (g, "guestfs_blockdev_rereadpt failed, see earlier error messages");
     return -1;
   }
 
     error (g, "guestfs_blockdev_rereadpt failed, see earlier error messages");
     return -1;
   }
 
-  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_BLOCKDEV_REREADPT, serial) == -1)
+  if (check_reply_header (g, &state.hdr, GUESTFS_PROC_BLOCKDEV_REREADPT, serial) == -1)
     return -1;
 
     return -1;
 
-  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
-    error (g, "%s", rv.err.error);
+  if (state.hdr.status == GUESTFS_STATUS_ERROR) {
+    error (g, "%s", state.err.error);
     return -1;
   }
 
     return -1;
   }
 
index e104633..6c49e90 100644 (file)
@@ -64,35 +64,71 @@ static char *safe_strdup (guestfs_h *g, const char *str);
 static void *safe_memdup (guestfs_h *g, void *ptr, size_t size);
 
 static void default_error_cb (guestfs_h *g, void *data, const char *msg);
 static void *safe_memdup (guestfs_h *g, void *ptr, size_t size);
 
 static void default_error_cb (guestfs_h *g, void *data, const char *msg);
-static void stdout_event (void *data, int watch, int fd, int events);
-static void sock_read_event (void *data, int watch, int fd, int events);
-static void sock_write_event (void *data, int watch, int fd, int events);
+static void stdout_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events);
+static void sock_read_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events);
+static void sock_write_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events);
 
 static void close_handles (void);
 
 
 static void close_handles (void);
 
-static int select_add_handle (guestfs_h *g, int fd, int events, guestfs_handle_event_cb cb, void *data);
-static int select_remove_handle (guestfs_h *g, int watch);
-static int select_add_timeout (guestfs_h *g, int interval, guestfs_handle_timeout_cb cb, void *data);
-static int select_remove_timeout (guestfs_h *g, int timer);
-static void select_main_loop_run (guestfs_h *g);
-static void select_main_loop_quit (guestfs_h *g);
+static int select_add_handle (guestfs_main_loop *ml, guestfs_h *g, int fd, int events, guestfs_handle_event_cb cb, void *data);
+static int select_remove_handle (guestfs_main_loop *ml, guestfs_h *g, int watch);
+static int select_add_timeout (guestfs_main_loop *ml, guestfs_h *g, int interval, guestfs_handle_timeout_cb cb, void *data);
+static int select_remove_timeout (guestfs_main_loop *ml, guestfs_h *g, int timer);
+static int select_main_loop_run (guestfs_main_loop *ml, guestfs_h *g);
+static int select_main_loop_quit (guestfs_main_loop *ml, guestfs_h *g);
 
 
-#define UNIX_PATH_MAX 108
+/* Default select-based main loop. */
+struct select_handle_cb_data {
+  guestfs_handle_event_cb cb;
+  guestfs_h *g;
+  void *data;
+};
 
 
-/* Also in guestfsd.c */
-#define VMCHANNEL_PORT 6666
-#define VMCHANNEL_ADDR "10.0.2.4"
+struct select_main_loop {
+  /* NB. These fields must be the same as in struct guestfs_main_loop: */
+  guestfs_add_handle_cb add_handle;
+  guestfs_remove_handle_cb remove_handle;
+  guestfs_add_timeout_cb add_timeout;
+  guestfs_remove_timeout_cb remove_timeout;
+  guestfs_main_loop_run_cb main_loop_run;
+  guestfs_main_loop_quit_cb main_loop_quit;
+
+  /* Additional private data: */
+  int is_running;
+
+  fd_set rset;
+  fd_set wset;
+  fd_set xset;
+
+  int max_fd;
+  int nr_fds;
+  struct select_handle_cb_data *handle_cb_data;
+};
 
 
-/* Current main loop. */
-static guestfs_main_loop main_loop = {
+/* Default main loop. */
+static struct select_main_loop default_main_loop = {
   .add_handle = select_add_handle,
   .remove_handle = select_remove_handle,
   .add_timeout = select_add_timeout,
   .remove_timeout = select_remove_timeout,
   .main_loop_run = select_main_loop_run,
   .main_loop_quit = select_main_loop_quit,
   .add_handle = select_add_handle,
   .remove_handle = select_remove_handle,
   .add_timeout = select_add_timeout,
   .remove_timeout = select_remove_timeout,
   .main_loop_run = select_main_loop_run,
   .main_loop_quit = select_main_loop_quit,
+
+  /* XXX hopefully .rset, .wset, .xset are initialized to the empty
+   * set by the normal action of everything being initialized to zero.
+   */
+  .is_running = 0,
+  .max_fd = -1,
+  .nr_fds = 0,
+  .handle_cb_data = NULL,
 };
 
 };
 
+#define UNIX_PATH_MAX 108
+
+/* Also in guestfsd.c */
+#define VMCHANNEL_PORT 6666
+#define VMCHANNEL_ADDR "10.0.2.4"
+
 /* GuestFS handle and connection. */
 enum state { CONFIG, LAUNCHING, READY, BUSY, NO_HANDLE };
 
 /* GuestFS handle and connection. */
 enum state { CONFIG, LAUNCHING, READY, BUSY, NO_HANDLE };
 
@@ -127,6 +163,8 @@ struct guestfs_h
   guestfs_abort_cb           abort_cb;
   guestfs_error_handler_cb   error_cb;
   void *                     error_cb_data;
   guestfs_abort_cb           abort_cb;
   guestfs_error_handler_cb   error_cb;
   void *                     error_cb_data;
+  guestfs_send_cb            send_cb;
+  void *                     send_cb_data;
   guestfs_reply_cb           reply_cb;
   void *                     reply_cb_data;
   guestfs_log_message_cb     log_message_cb;
   guestfs_reply_cb           reply_cb;
   void *                     reply_cb_data;
   guestfs_log_message_cb     log_message_cb;
@@ -136,15 +174,21 @@ struct guestfs_h
   guestfs_launch_done_cb     launch_done_cb;
   void *                     launch_done_cb_data;
 
   guestfs_launch_done_cb     launch_done_cb;
   void *                     launch_done_cb_data;
 
-  /* These callbacks are called before reply_cb and launch_done_cb,
-   * and are used to implement the high-level API without needing to
-   * interfere with callbacks that the user might have set.
+  /* These callbacks are called before send_cb, reply_cb and
+   * launch_done_cb, and are used to implement the high-level
+   * API without needing to interfere with callbacks that the
+   * user might have set.
    */
    */
+  guestfs_send_cb            send_cb_internal;
+  void *                     send_cb_internal_data;
   guestfs_reply_cb           reply_cb_internal;
   void *                     reply_cb_internal_data;
   guestfs_launch_done_cb     launch_done_cb_internal;
   void *                     launch_done_cb_internal_data;
 
   guestfs_reply_cb           reply_cb_internal;
   void *                     reply_cb_internal_data;
   guestfs_launch_done_cb     launch_done_cb_internal;
   void *                     launch_done_cb_internal_data;
 
+  /* Main loop used by this handle. */
+  guestfs_main_loop *main_loop;
+
   /* Messages sent and received from the daemon. */
   char *msg_in;
   int msg_in_size, msg_in_allocated;
   /* Messages sent and received from the daemon. */
   char *msg_in;
   int msg_in_size, msg_in_allocated;
@@ -187,6 +231,8 @@ guestfs_create (void)
   g->path = str != NULL ? str : GUESTFS_DEFAULT_PATH;
   /* XXX We should probably make QEMU configurable as well. */
 
   g->path = str != NULL ? str : GUESTFS_DEFAULT_PATH;
   /* XXX We should probably make QEMU configurable as well. */
 
+  g->main_loop = (guestfs_main_loop *) &default_main_loop;
+
   /* Start with large serial numbers so they are easy to spot
    * inside the protocol.
    */
   /* Start with large serial numbers so they are easy to spot
    * inside the protocol.
    */
@@ -780,18 +826,18 @@ guestfs_launch (guestfs_h *g)
   g->msg_out_pos = 0;
 
   g->stdout_watch =
   g->msg_out_pos = 0;
 
   g->stdout_watch =
-    main_loop.add_handle (g, g->fd[1],
-                         GUESTFS_HANDLE_READABLE,
-                         stdout_event, g);
+    g->main_loop->add_handle (g->main_loop, g, g->fd[1],
+                             GUESTFS_HANDLE_READABLE,
+                             stdout_event, NULL);
   if (g->stdout_watch == -1) {
     error (g, "could not watch qemu stdout");
     goto cleanup3;
   }
 
   g->sock_watch =
   if (g->stdout_watch == -1) {
     error (g, "could not watch qemu stdout");
     goto cleanup3;
   }
 
   g->sock_watch =
-    main_loop.add_handle (g, g->sock,
-                         GUESTFS_HANDLE_READABLE,
-                         sock_read_event, g);
+    g->main_loop->add_handle (g->main_loop, g, g->sock,
+                             GUESTFS_HANDLE_READABLE,
+                             sock_read_event, NULL);
   if (g->sock_watch == -1) {
     error (g, "could not watch daemon communications socket");
     goto cleanup3;
   if (g->sock_watch == -1) {
     error (g, "could not watch daemon communications socket");
     goto cleanup3;
@@ -802,9 +848,9 @@ guestfs_launch (guestfs_h *g)
 
  cleanup3:
   if (g->stdout_watch >= 0)
 
  cleanup3:
   if (g->stdout_watch >= 0)
-    main_loop.remove_handle (g, g->stdout_watch);
+    g->main_loop->remove_handle (g->main_loop, g, g->stdout_watch);
   if (g->sock_watch >= 0)
   if (g->sock_watch >= 0)
-    main_loop.remove_handle (g, g->sock_watch);
+    g->main_loop->remove_handle (g->main_loop, g, g->sock_watch);
 
  cleanup2:
   close (g->sock);
 
  cleanup2:
   close (g->sock);
@@ -831,14 +877,17 @@ guestfs_launch (guestfs_h *g)
 static void
 finish_wait_ready (guestfs_h *g, void *vp)
 {
 static void
 finish_wait_ready (guestfs_h *g, void *vp)
 {
+  if (g->verbose)
+    fprintf (stderr, "finish_wait_ready called, %p, vp = %p\n", g, vp);
+
   *((int *)vp) = 1;
   *((int *)vp) = 1;
-  main_loop.main_loop_quit (g);
+  g->main_loop->main_loop_quit (g->main_loop, g);
 }
 
 int
 guestfs_wait_ready (guestfs_h *g)
 {
 }
 
 int
 guestfs_wait_ready (guestfs_h *g)
 {
-  int r = 0;
+  int finished = 0, r;
 
   if (g->state == READY) return 0;
 
 
   if (g->state == READY) return 0;
 
@@ -853,12 +902,14 @@ guestfs_wait_ready (guestfs_h *g)
   }
 
   g->launch_done_cb_internal = finish_wait_ready;
   }
 
   g->launch_done_cb_internal = finish_wait_ready;
-  g->launch_done_cb_internal_data = &r;
-  main_loop.main_loop_run (g);
+  g->launch_done_cb_internal_data = &finished;
+  r = g->main_loop->main_loop_run (g->main_loop, g);
   g->launch_done_cb_internal = NULL;
   g->launch_done_cb_internal_data = NULL;
 
   g->launch_done_cb_internal = NULL;
   g->launch_done_cb_internal_data = NULL;
 
-  if (r != 1) {
+  if (r == -1) return -1;
+
+  if (finished != 1) {
     error (g, "guestfs_wait_ready failed, see earlier error messages");
     return -1;
   }
     error (g, "guestfs_wait_ready failed, see earlier error messages");
     return -1;
   }
@@ -897,9 +948,9 @@ guestfs_kill_subprocess (guestfs_h *g)
  * we see kernel messages here too.
  */
 static void
  * we see kernel messages here too.
  */
 static void
-stdout_event (void *data, int watch, int fd, int events)
+stdout_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data,
+             int watch, int fd, int events)
 {
 {
-  guestfs_h *g = (guestfs_h *) data;
   char buf[4096];
   int n;
 
   char buf[4096];
   int n;
 
@@ -923,9 +974,9 @@ stdout_event (void *data, int watch, int fd, int events)
     /*kill (g->pid, SIGTERM);*/
     waitpid (g->pid, NULL, 0);
     if (g->stdout_watch >= 0)
     /*kill (g->pid, SIGTERM);*/
     waitpid (g->pid, NULL, 0);
     if (g->stdout_watch >= 0)
-      main_loop.remove_handle (g, g->stdout_watch);
+      g->main_loop->remove_handle (g->main_loop, g, g->stdout_watch);
     if (g->sock_watch >= 0)
     if (g->sock_watch >= 0)
-      main_loop.remove_handle (g, g->sock_watch);
+      g->main_loop->remove_handle (g->main_loop, g, g->sock_watch);
     close (g->fd[0]);
     close (g->fd[1]);
     close (g->sock);
     close (g->fd[0]);
     close (g->fd[1]);
     close (g->sock);
@@ -961,9 +1012,9 @@ stdout_event (void *data, int watch, int fd, int events)
  * guestfsd (daemon inside the guest) communication socket.
  */
 static void
  * guestfsd (daemon inside the guest) communication socket.
  */
 static void
-sock_read_event (void *data, int watch, int fd, int events)
+sock_read_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data,
+                int watch, int fd, int events)
 {
 {
-  guestfs_h *g = (guestfs_h *) data;
   XDR xdr;
   unsigned len;
   int n;
   XDR xdr;
   unsigned len;
   int n;
@@ -1098,9 +1149,9 @@ sock_read_event (void *data, int watch, int fd, int events)
  * guestfsd (daemon inside the guest) communication socket.
  */
 static void
  * guestfsd (daemon inside the guest) communication socket.
  */
 static void
-sock_write_event (void *data, int watch, int fd, int events)
+sock_write_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data,
+                 int watch, int fd, int events)
 {
 {
-  guestfs_h *g = (guestfs_h *) data;
   int n;
 
   if (g->verbose)
   int n;
 
   if (g->verbose)
@@ -1145,14 +1196,14 @@ sock_write_event (void *data, int watch, int fd, int events)
   free (g->msg_out);
   g->msg_out_pos = g->msg_out_size = 0;
 
   free (g->msg_out);
   g->msg_out_pos = g->msg_out_size = 0;
 
-  if (main_loop.remove_handle (g, g->sock_watch) == -1) {
+  if (g->main_loop->remove_handle (g->main_loop, g, g->sock_watch) == -1) {
     error (g, "remove_handle failed in sock_write_event");
     return;
   }
   g->sock_watch =
     error (g, "remove_handle failed in sock_write_event");
     return;
   }
   g->sock_watch =
-    main_loop.add_handle (g, g->sock,
-                         GUESTFS_HANDLE_READABLE,
-                         sock_read_event, g);
+    g->main_loop->add_handle (g->main_loop, g, g->sock,
+                             GUESTFS_HANDLE_READABLE,
+                             sock_read_event, NULL);
   if (g->sock_watch == -1) {
     error (g, "add_handle failed in sock_write_event");
     return;
   if (g->sock_watch == -1) {
     error (g, "add_handle failed in sock_write_event");
     return;
@@ -1220,14 +1271,14 @@ dispatch (guestfs_h *g, int proc_nr, xdrproc_t xdrp, char *args)
   memcpy (g->msg_out + 4, buffer, len);
 
   /* Change the handle to sock_write_event. */
   memcpy (g->msg_out + 4, buffer, len);
 
   /* Change the handle to sock_write_event. */
-  if (main_loop.remove_handle (g, g->sock_watch) == -1) {
+  if (g->main_loop->remove_handle (g->main_loop, g, g->sock_watch) == -1) {
     error (g, "remove_handle failed in dispatch");
     goto cleanup1;
   }
   g->sock_watch =
     error (g, "remove_handle failed in dispatch");
     goto cleanup1;
   }
   g->sock_watch =
-    main_loop.add_handle (g, g->sock,
-                         GUESTFS_HANDLE_WRITABLE,
-                         sock_write_event, g);
+    g->main_loop->add_handle (g->main_loop, g, g->sock,
+                             GUESTFS_HANDLE_WRITABLE,
+                             sock_write_event, NULL);
   if (g->sock_watch == -1) {
     error (g, "add_handle failed in dispatch");
     goto cleanup1;
   if (g->sock_watch == -1) {
     error (g, "add_handle failed in dispatch");
     goto cleanup1;
@@ -1243,6 +1294,139 @@ dispatch (guestfs_h *g, int proc_nr, xdrproc_t xdrp, char *args)
   return -1;
 }
 
   return -1;
 }
 
+#if 0
+static int cancel = 0; /* XXX Implement file cancellation. */
+
+static int
+send_file (guestfs_h *g, const char *filename)
+{
+  char buf[GUESTFS_MAX_CHUNK_SIZE];
+  int fd, r;
+
+  fd = open (filename, O_RDONLY);
+  if (fd == -1) {
+    perrorf (g, "open: %s", filename);
+    send_file_cancellation (g);
+    /* Daemon sees cancellation and won't reply, so caller can
+     * just return here.
+     */
+    return -1;
+  }
+
+  /* Send file in chunked encoding. */
+  while (!cancel && (r = read (fd, buf, sizeof buf)) > 0) {
+    if (send_file_data (g, buf, r) == -1)
+      return -1;
+  }
+
+  if (cancel) {
+    send_file_cancellation (g);
+    return -1;
+  }
+
+  if (r == -1) {
+    perrorf (g, "read: %s", filename);
+    send_file_cancellation (g);
+    return -1;
+  }
+
+  /* End of file, but before we send that, we need to close
+   * the file and check for errors.
+   */
+  if (close (fd) == -1) {
+    perrorf (g, "close: %s", filename);
+    send_file_cancellation (g);
+    return -1;
+  }
+
+  return send_file_complete (g);
+}
+
+/* Send a chunk, cancellation or end of file, wait for it to go. */
+static int
+send_file_chunk (guestfs_h *g, int cancel, const char *buf, size_t len)
+{
+  void *data;
+  guestfs_chunk chunk;
+  XDR xdr;
+
+  if (g->state != BUSY) {
+    error (g, "send_file_chunk: state %d != READY", g->state);
+    return -1;
+  }
+
+  /* Serialize the chunk. */
+  chunk.cancel = cancel;
+  chunk.data.data_len = len;
+  chunk.data.data_val = (char *) buf;
+
+  data = safe_malloc (g, GUESTFS_MAX_CHUNK_SIZE + 48);
+  xdrmem_create (&xdr, data, GUESTFS_MAX_CHUNK_SIZE + 48, XDR_ENCODE);
+  if (xdr_guestfs_chunk (&xdr, &chunk)) {
+    error (g, "xdr_guestfs_chunk failed");
+    free (data);
+    return -1;
+  }
+
+  chunkdatalen = xdr_getpos (&xdr);
+  xdr_destroy (&xdr);
+
+  len = xdr_getpos (&xdr);
+  xdr_destroy (&xdr);
+
+  data = safe_realloc (g, data, len);
+  g->msg_out = data;
+  g->msg_out_size = len;
+  g->msg_out_pos = 0;
+
+  /* Change the handle to sock_write_event. */
+  if (g->main_loop->remove_handle (g->main_loop, g, g->sock_watch) == -1) {
+    error (g, "remove_handle failed in dispatch");
+    goto cleanup1;
+  }
+  g->sock_watch =
+    g->main_loop->add_handle (g->main_loop, g, g->sock,
+                             GUESTFS_HANDLE_WRITABLE,
+                             sock_write_event, NULL);
+  if (g->sock_watch == -1) {
+    error (g, "add_handle failed in dispatch");
+    goto cleanup1;
+  }
+
+  return 0;
+
+ cleanup1:
+  free (g->msg_out);
+  g->msg_out = NULL;
+  g->msg_out_size = 0;
+  g->state = READY;
+  return -1;
+}
+
+/* Send a chunk of file data. */
+static int
+send_file_data (guestfs_h *g, const char *buf, size_t len)
+{
+  return send_file_chunk (g, 0, buf, len);
+}
+
+/* Send a cancellation message. */
+static int
+send_file_cancellation (guestfs_h *g)
+{
+  char buf[1];
+  return send_file_chunk (g, 1, buf, 0);
+}
+
+/* Send a file complete chunk. */
+static int
+send_file_complete (guestfs_h *g)
+{
+  char buf[0];
+  return send_file_chunk (g, 0, buf, 0);
+}
+#endif
+
 /* Check the return message from a call for validity. */
 static int
 check_reply_header (guestfs_h *g,
 /* Check the return message from a call for validity. */
 static int
 check_reply_header (guestfs_h *g,
@@ -1313,36 +1497,11 @@ guestfs_free_lvm_lv_list (struct guestfs_lvm_lv_list *x)
 
 /* This is the default main loop implementation, using select(2). */
 
 
 /* This is the default main loop implementation, using select(2). */
 
-struct handle_cb_data {
-  guestfs_handle_event_cb cb;
-  void *data;
-};
-
-static fd_set rset;
-static fd_set wset;
-static fd_set xset;
-static int select_init_done = 0;
-static int max_fd = -1;
-static int nr_fds = 0;
-static struct handle_cb_data *handle_cb_data = NULL;
-
-static void
-select_init (void)
-{
-  if (!select_init_done) {
-    FD_ZERO (&rset);
-    FD_ZERO (&wset);
-    FD_ZERO (&xset);
-
-    select_init_done = 1;
-  }
-}
-
 static int
 static int
-select_add_handle (guestfs_h *g, int fd, int events,
+select_add_handle (guestfs_main_loop *mlv, guestfs_h *g, int fd, int events,
                   guestfs_handle_event_cb cb, void *data)
 {
                   guestfs_handle_event_cb cb, void *data)
 {
-  select_init ();
+  struct select_main_loop *ml = (struct select_main_loop *) mlv;
 
   if (fd < 0 || fd >= FD_SETSIZE) {
     error (g, "fd %d is out of range", fd);
 
   if (fd < 0 || fd >= FD_SETSIZE) {
     error (g, "fd %d is out of range", fd);
@@ -1362,7 +1521,9 @@ select_add_handle (guestfs_h *g, int fd, int events,
     return -1;
   }
 
     return -1;
   }
 
-  if (FD_ISSET (fd, &rset) || FD_ISSET (fd, &wset) || FD_ISSET (fd, &xset)) {
+  if (FD_ISSET (fd, &ml->rset) ||
+      FD_ISSET (fd, &ml->wset) ||
+      FD_ISSET (fd, &ml->xset)) {
     error (g, "fd %d is already registered", fd);
     return -1;
   }
     error (g, "fd %d is already registered", fd);
     return -1;
   }
@@ -1373,102 +1534,111 @@ select_add_handle (guestfs_h *g, int fd, int events,
   }
 
   if ((events & GUESTFS_HANDLE_READABLE))
   }
 
   if ((events & GUESTFS_HANDLE_READABLE))
-    FD_SET (fd, &rset);
+    FD_SET (fd, &ml->rset);
   if ((events & GUESTFS_HANDLE_WRITABLE))
   if ((events & GUESTFS_HANDLE_WRITABLE))
-    FD_SET (fd, &wset);
+    FD_SET (fd, &ml->wset);
   if ((events & GUESTFS_HANDLE_HANGUP) || (events & GUESTFS_HANDLE_ERROR))
   if ((events & GUESTFS_HANDLE_HANGUP) || (events & GUESTFS_HANDLE_ERROR))
-    FD_SET (fd, &xset);
+    FD_SET (fd, &ml->xset);
 
 
-  if (fd > max_fd) {
-    max_fd = fd;
-    handle_cb_data = safe_realloc (g, handle_cb_data,
-                                  sizeof (struct handle_cb_data) * (max_fd+1));
+  if (fd > ml->max_fd) {
+    ml->max_fd = fd;
+    ml->handle_cb_data =
+      safe_realloc (g, ml->handle_cb_data,
+                   sizeof (struct select_handle_cb_data) * (ml->max_fd+1));
   }
   }
-  handle_cb_data[fd].cb = cb;
-  handle_cb_data[fd].data = data;
+  ml->handle_cb_data[fd].cb = cb;
+  ml->handle_cb_data[fd].g = g;
+  ml->handle_cb_data[fd].data = data;
 
 
-  nr_fds++;
+  ml->nr_fds++;
 
   /* Any integer >= 0 can be the handle, and this is as good as any ... */
   return fd;
 }
 
 static int
 
   /* Any integer >= 0 can be the handle, and this is as good as any ... */
   return fd;
 }
 
 static int
-select_remove_handle (guestfs_h *g, int fd)
+select_remove_handle (guestfs_main_loop *mlv, guestfs_h *g, int fd)
 {
 {
-  select_init ();
+  struct select_main_loop *ml = (struct select_main_loop *) mlv;
 
   if (fd < 0 || fd >= FD_SETSIZE) {
     error (g, "fd %d is out of range", fd);
     return -1;
   }
 
 
   if (fd < 0 || fd >= FD_SETSIZE) {
     error (g, "fd %d is out of range", fd);
     return -1;
   }
 
-  if (!FD_ISSET (fd, &rset) && !FD_ISSET (fd, &wset) && !FD_ISSET (fd, &xset)) {
+  if (!FD_ISSET (fd, &ml->rset) &&
+      !FD_ISSET (fd, &ml->wset) &&
+      !FD_ISSET (fd, &ml->xset)) {
     error (g, "fd %d was not registered", fd);
     return -1;
   }
 
     error (g, "fd %d was not registered", fd);
     return -1;
   }
 
-  FD_CLR (fd, &rset);
-  FD_CLR (fd, &wset);
-  FD_CLR (fd, &xset);
+  FD_CLR (fd, &ml->rset);
+  FD_CLR (fd, &ml->wset);
+  FD_CLR (fd, &ml->xset);
 
 
-  if (fd == max_fd) {
-    max_fd--;
-    handle_cb_data = safe_realloc (g, handle_cb_data,
-                                  sizeof (struct handle_cb_data) * (max_fd+1));
+  if (fd == ml->max_fd) {
+    ml->max_fd--;
+    ml->handle_cb_data =
+      safe_realloc (g, ml->handle_cb_data,
+                   sizeof (struct select_handle_cb_data) * (ml->max_fd+1));
   }
 
   }
 
-  nr_fds--;
+  ml->nr_fds--;
 
   return 0;
 }
 
 static int
 
   return 0;
 }
 
 static int
-select_add_timeout (guestfs_h *g, int interval,
+select_add_timeout (guestfs_main_loop *mlv, guestfs_h *g, int interval,
                    guestfs_handle_timeout_cb cb, void *data)
 {
                    guestfs_handle_timeout_cb cb, void *data)
 {
-  select_init ();
+  //struct select_main_loop *ml = (struct select_main_loop *) mlv;
 
   abort ();                    /* XXX not implemented yet */
 }
 
 static int
 
   abort ();                    /* XXX not implemented yet */
 }
 
 static int
-select_remove_timeout (guestfs_h *g, int timer)
+select_remove_timeout (guestfs_main_loop *mlv, guestfs_h *g, int timer)
 {
 {
-  select_init ();
+  //struct select_main_loop *ml = (struct select_main_loop *) mlv;
 
   abort ();                    /* XXX not implemented yet */
 }
 
 
   abort ();                    /* XXX not implemented yet */
 }
 
-/* Note that main loops can be nested. */
-static int level = 0;
-
-static void
-select_main_loop_run (guestfs_h *g)
+/* The 'g' parameter is just used for error reporting.  Events
+ * for multiple handles can be dispatched by running the main
+ * loop.
+ */
+static int
+select_main_loop_run (guestfs_main_loop *mlv, guestfs_h *g)
 {
 {
-  int old_level, fd, r, events;
+  struct select_main_loop *ml = (struct select_main_loop *) mlv;
+  int fd, r, events;
   fd_set rset2, wset2, xset2;
 
   fd_set rset2, wset2, xset2;
 
-  select_init ();
+  if (ml->is_running) {
+    error (g, "select_main_loop_run: this cannot be called recursively");
+    return -1;
+  }
+
+  ml->is_running = 1;
 
 
-  old_level = level++;
-  while (level > old_level) {
-    if (nr_fds == 0) {
-      level = old_level;
+  while (ml->is_running) {
+    if (ml->nr_fds == 0)
       break;
       break;
-    }
 
 
-    rset2 = rset;
-    wset2 = wset;
-    xset2 = xset;
-    r = select (max_fd+1, &rset2, &wset2, &xset2, NULL);
+    rset2 = ml->rset;
+    wset2 = ml->wset;
+    xset2 = ml->xset;
+    r = select (ml->max_fd+1, &rset2, &wset2, &xset2, NULL);
     if (r == -1) {
       perrorf (g, "select");
     if (r == -1) {
       perrorf (g, "select");
-      level = old_level;
-      break;
+      ml->is_running = 0;
+      return -1;
     }
 
     }
 
-    for (fd = 0; r > 0 && fd <= max_fd; ++fd) {
+    for (fd = 0; r > 0 && fd <= ml->max_fd; ++fd) {
       events = 0;
       if (FD_ISSET (fd, &rset2))
        events |= GUESTFS_HANDLE_READABLE;
       events = 0;
       if (FD_ISSET (fd, &rset2))
        events |= GUESTFS_HANDLE_READABLE;
@@ -1478,22 +1648,28 @@ select_main_loop_run (guestfs_h *g)
        events |= GUESTFS_HANDLE_ERROR | GUESTFS_HANDLE_HANGUP;
       if (events) {
        r--;
        events |= GUESTFS_HANDLE_ERROR | GUESTFS_HANDLE_HANGUP;
       if (events) {
        r--;
-       handle_cb_data[fd].cb (handle_cb_data[fd].data,
-                              fd, fd, events);
+       ml->handle_cb_data[fd].cb ((guestfs_main_loop *) ml,
+                                  ml->handle_cb_data[fd].g,
+                                  ml->handle_cb_data[fd].data,
+                                  fd, fd, events);
       }
     }
   }
       }
     }
   }
+
+  ml->is_running = 0;
+  return 0;
 }
 
 }
 
-static void
-select_main_loop_quit (guestfs_h *g)
+static int
+select_main_loop_quit (guestfs_main_loop *mlv, guestfs_h *g)
 {
 {
-  select_init ();
+  struct select_main_loop *ml = (struct select_main_loop *) mlv;
 
 
-  if (level == 0) {
-    error (g, "cannot quit, we are not in a main loop");
-    return;
+  if (!ml->is_running) {
+    error (g, "cannot quit, we are not running in a main loop");
+    return -1;
   }
 
   }
 
-  level--;
+  ml->is_running = 0;
+  return 0;
 }
 }
index 3905554..bfa6b9c 100644 (file)
@@ -53,11 +53,13 @@ extern void guestfs_free_lvm_vg_list (struct guestfs_lvm_vg_list *);
 extern void guestfs_free_lvm_lv_list (struct guestfs_lvm_lv_list *);
 
 /* Low-level event API. */
 extern void guestfs_free_lvm_lv_list (struct guestfs_lvm_lv_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);
 typedef void (*guestfs_log_message_cb) (guestfs_h *g, void *data, char *buf, int len);
 typedef void (*guestfs_subprocess_quit_cb) (guestfs_h *g, void *data);
 typedef void (*guestfs_launch_done_cb) (guestfs_h *g, void *data);
 
 typedef void (*guestfs_reply_cb) (guestfs_h *g, void *data, XDR *xdr);
 typedef void (*guestfs_log_message_cb) (guestfs_h *g, void *data, char *buf, int len);
 typedef void (*guestfs_subprocess_quit_cb) (guestfs_h *g, void *data);
 typedef void (*guestfs_launch_done_cb) (guestfs_h *g, void *data);
 
+extern void guestfs_set_send_callback (guestfs_h *g, guestfs_send_cb cb, void *opaque);
 extern void guestfs_set_reply_callback (guestfs_h *g, guestfs_reply_cb cb, void *opaque);
 extern void guestfs_set_log_message_callback (guestfs_h *g, guestfs_log_message_cb cb, void *opaque);
 extern void guestfs_set_subprocess_quit_callback (guestfs_h *g, guestfs_subprocess_quit_cb cb, void *opaque);
 extern void guestfs_set_reply_callback (guestfs_h *g, guestfs_reply_cb cb, void *opaque);
 extern void guestfs_set_log_message_callback (guestfs_h *g, guestfs_log_message_cb cb, void *opaque);
 extern void guestfs_set_subprocess_quit_callback (guestfs_h *g, guestfs_subprocess_quit_cb cb, void *opaque);
@@ -69,15 +71,20 @@ extern void guestfs_set_launch_done_callback (guestfs_h *g, guestfs_launch_done_
 #define GUESTFS_HANDLE_HANGUP   0x4
 #define GUESTFS_HANDLE_ERROR    0x8
 
 #define GUESTFS_HANDLE_HANGUP   0x4
 #define GUESTFS_HANDLE_ERROR    0x8
 
-typedef void (*guestfs_handle_event_cb) (void *data, int watch, int fd, int events);
-typedef int (*guestfs_add_handle_cb) (guestfs_h *g, int fd, int events, guestfs_handle_event_cb cb, void *data);
-typedef int (*guestfs_remove_handle_cb) (guestfs_h *g, int watch);
-typedef void (*guestfs_handle_timeout_cb) (void *data, int timer);
-typedef int (*guestfs_add_timeout_cb) (guestfs_h *g, int interval, guestfs_handle_timeout_cb cb, void *data);
-typedef int (*guestfs_remove_timeout_cb) (guestfs_h *g, int timer);
-typedef void (*guestfs_main_loop_run_cb) (guestfs_h *g);
-typedef void (*guestfs_main_loop_quit_cb) (guestfs_h *g);
+struct guestfs_main_loop;
 
 
+typedef void (*guestfs_handle_event_cb) (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events);
+typedef int (*guestfs_add_handle_cb) (struct guestfs_main_loop *ml, guestfs_h *g, int fd, int events, guestfs_handle_event_cb cb, void *data);
+typedef int (*guestfs_remove_handle_cb) (struct guestfs_main_loop *ml, guestfs_h *g, int watch);
+typedef void (*guestfs_handle_timeout_cb) (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int timer);
+typedef int (*guestfs_add_timeout_cb) (struct guestfs_main_loop *ml, guestfs_h *g, int interval, guestfs_handle_timeout_cb cb, void *data);
+typedef int (*guestfs_remove_timeout_cb) (struct guestfs_main_loop *ml, guestfs_h *g, int timer);
+typedef int (*guestfs_main_loop_run_cb) (struct guestfs_main_loop *ml, guestfs_h *g);
+typedef int (*guestfs_main_loop_quit_cb) (struct guestfs_main_loop *ml, guestfs_h *g);
+
+/* This is the head of the main loop structure.  Concrete implementations
+ * use additional private data after this struct.
+ */
 struct guestfs_main_loop {
   guestfs_add_handle_cb add_handle;
   guestfs_remove_handle_cb remove_handle;
 struct guestfs_main_loop {
   guestfs_add_handle_cb add_handle;
   guestfs_remove_handle_cb remove_handle;
@@ -88,8 +95,11 @@ struct guestfs_main_loop {
 };
 typedef struct guestfs_main_loop guestfs_main_loop;
 
 };
 typedef struct guestfs_main_loop guestfs_main_loop;
 
-extern void guestfs_set_main_loop (guestfs_main_loop *);
-extern void guestfs_main_loop_run (void);
-extern void guestfs_main_loop_quit (void);
+extern void guestfs_set_main_loop (guestfs_h *handle, guestfs_main_loop *main_loop);
+extern guestfs_main_loop *guestfs_get_main_loop (guestfs_h *handle);
+extern guestfs_main_loop *guestfs_get_default_main_loop (void);
+
+extern guestfs_main_loop *guestfs_create_main_loop (void);
+extern void guestfs_free_main_loop (guestfs_main_loop *);
 
 #endif /* GUESTFS_H_ */
 
 #endif /* GUESTFS_H_ */
index eb90d75..86a338f 100644 (file)
@@ -1245,3 +1245,15 @@ xdr_guestfs_message_header (XDR *xdrs, guestfs_message_header *objp)
                 return FALSE;
        return TRUE;
 }
                 return FALSE;
        return TRUE;
 }
+
+bool_t
+xdr_guestfs_chunk (XDR *xdrs, guestfs_chunk *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_int (xdrs, &objp->cancel))
+                return FALSE;
+        if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, GUESTFS_MAX_CHUNK_SIZE))
+                return FALSE;
+       return TRUE;
+}
index 822d960..c1837f8 100644 (file)
@@ -682,7 +682,7 @@ enum guestfs_procedure {
        GUESTFS_PROC_BLOCKDEV_GETSIZE64 = 63,
        GUESTFS_PROC_BLOCKDEV_FLUSHBUFS = 64,
        GUESTFS_PROC_BLOCKDEV_REREADPT = 65,
        GUESTFS_PROC_BLOCKDEV_GETSIZE64 = 63,
        GUESTFS_PROC_BLOCKDEV_FLUSHBUFS = 64,
        GUESTFS_PROC_BLOCKDEV_REREADPT = 65,
-       GUESTFS_PROC_dummy = 65 + 1,
+       GUESTFS_PROC_NR_PROCS = 65 + 1,
 };
 typedef enum guestfs_procedure guestfs_procedure;
 #define GUESTFS_MESSAGE_MAX 4194304
 };
 typedef enum guestfs_procedure guestfs_procedure;
 #define GUESTFS_MESSAGE_MAX 4194304
@@ -716,6 +716,16 @@ struct guestfs_message_header {
        guestfs_message_status status;
 };
 typedef struct guestfs_message_header guestfs_message_header;
        guestfs_message_status status;
 };
 typedef struct guestfs_message_header guestfs_message_header;
+#define GUESTFS_MAX_CHUNK_SIZE 8192
+
+struct guestfs_chunk {
+       int cancel;
+       struct {
+               u_int data_len;
+               char *data_val;
+       } data;
+};
+typedef struct guestfs_chunk guestfs_chunk;
 
 /* the xdr functions */
 
 
 /* the xdr functions */
 
@@ -818,6 +828,7 @@ extern  bool_t xdr_guestfs_message_direction (XDR *, guestfs_message_direction*)
 extern  bool_t xdr_guestfs_message_status (XDR *, guestfs_message_status*);
 extern  bool_t xdr_guestfs_message_error (XDR *, guestfs_message_error*);
 extern  bool_t xdr_guestfs_message_header (XDR *, guestfs_message_header*);
 extern  bool_t xdr_guestfs_message_status (XDR *, guestfs_message_status*);
 extern  bool_t xdr_guestfs_message_error (XDR *, guestfs_message_error*);
 extern  bool_t xdr_guestfs_message_header (XDR *, guestfs_message_header*);
+extern  bool_t xdr_guestfs_chunk (XDR *, guestfs_chunk*);
 
 #else /* K&R C */
 extern bool_t xdr_str ();
 
 #else /* K&R C */
 extern bool_t xdr_str ();
@@ -918,6 +929,7 @@ extern bool_t xdr_guestfs_message_direction ();
 extern bool_t xdr_guestfs_message_status ();
 extern bool_t xdr_guestfs_message_error ();
 extern bool_t xdr_guestfs_message_header ();
 extern bool_t xdr_guestfs_message_status ();
 extern bool_t xdr_guestfs_message_error ();
 extern bool_t xdr_guestfs_message_header ();
+extern bool_t xdr_guestfs_chunk ();
 
 #endif /* K&R C */
 
 
 #endif /* K&R C */
 
index ba5d70c..d77bb5f 100644 (file)
@@ -541,7 +541,7 @@ enum guestfs_procedure {
   GUESTFS_PROC_BLOCKDEV_GETSIZE64 = 63,
   GUESTFS_PROC_BLOCKDEV_FLUSHBUFS = 64,
   GUESTFS_PROC_BLOCKDEV_REREADPT = 65,
   GUESTFS_PROC_BLOCKDEV_GETSIZE64 = 63,
   GUESTFS_PROC_BLOCKDEV_FLUSHBUFS = 64,
   GUESTFS_PROC_BLOCKDEV_REREADPT = 65,
-  GUESTFS_PROC_dummy
+  GUESTFS_PROC_NR_PROCS
 };
 
 const GUESTFS_MESSAGE_MAX = 4194304;
 };
 
 const GUESTFS_MESSAGE_MAX = 4194304;
@@ -565,6 +565,19 @@ struct guestfs_message_error {
   string error<GUESTFS_ERROR_LEN>;   /* error message */
 };
 
   string error<GUESTFS_ERROR_LEN>;   /* error message */
 };
 
+/* For normal requests and replies (not involving any FileIn or
+ * FileOut parameters), the protocol is:
+ *
+ * For requests:
+ *   total length (header + args, but not including length word itself)
+ *   header
+ *   guestfs_foo_args struct
+ * For replies:
+ *   total length (as above)
+ *   header
+ *   guestfs_foo_ret struct
+ */
+
 struct guestfs_message_header {
   unsigned prog;                     /* GUESTFS_PROGRAM */
   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
 struct guestfs_message_header {
   unsigned prog;                     /* GUESTFS_PROGRAM */
   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
@@ -573,3 +586,28 @@ struct guestfs_message_header {
   unsigned serial;                   /* message serial number */
   guestfs_message_status status;
 };
   unsigned serial;                   /* message serial number */
   guestfs_message_status status;
 };
+
+/* Chunked encoding used to transfer files, for FileIn and FileOut
+ * parameters.
+ *
+ * For requests which have >= 1 FileIn parameter:
+ *   length of header + args (but not length word itself, and not chunks)
+ *   header
+ *   guestfs_foo_args struct
+ *   sequence of chunks for FileIn param #0
+ *   sequence of chunks for FileIn param #1 etc
+ *
+ * For replies which have >= 1 FileOut parameter:
+ *   length of header + ret (but not length word itself, and not chunks)
+ *   header
+ *   guestfs_foo_ret struct
+ *   sequence of chunks for FileOut param #0
+ *   sequence of chunks for FileOut param #1 etc
+ */
+const GUESTFS_MAX_CHUNK_SIZE = 8192;
+
+struct guestfs_chunk {
+  int cancel;                       /* if non-zero, transfer is cancelled */
+  /* data size is 0 bytes if the transfer has finished successfully */
+  opaque data<GUESTFS_MAX_CHUNK_SIZE>;
+};