+ guestfs_add_drive_opts (g, filename,
+ GUESTFS_ADD_DRIVE_OPTS_FORMAT, "qcow2",
+ GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,
+ -1);
+
+and so forth. Don't forget the terminating C<-1> otherwise
+Bad Things will happen!
+
+=head2 USING va_list FOR OPTIONAL ARGUMENTS
+
+The second variant has the same name with the suffix C<_va>, which
+works the same way but takes a C<va_list>. See the C manual for
+details. For the example function, this is declared:
+
+ int guestfs_add_drive_opts_va (guestfs_h *g, const char *filename,
+ va_list args);
+
+=head2 CONSTRUCTING OPTIONAL ARGUMENTS
+
+The third variant is useful where you need to construct these
+calls. You pass in a structure where you fill in the optional
+fields. The structure has a bitmask as the first element which
+you must set to indicate which fields you have filled in. For
+our example function the structure and call are declared:
+
+ struct guestfs_add_drive_opts_argv {
+ uint64_t bitmask;
+ int readonly;
+ const char *format;
+ /* ... */
+ };
+ int guestfs_add_drive_opts_argv (guestfs_h *g, const char *filename,
+ const struct guestfs_add_drive_opts_argv *optargs);
+
+You could call it like this:
+
+ struct guestfs_add_drive_opts_argv optargs = {
+ .bitmask = GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK |
+ GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK,
+ .readonly = 1,
+ .format = "qcow2"
+ };
+
+ guestfs_add_drive_opts_argv (g, filename, &optargs);
+
+Notes:
+
+=over 4
+
+=item *
+
+The C<_BITMASK> suffix on each option name when specifying the
+bitmask.
+
+=item *
+
+You do not need to fill in all fields of the structure.
+
+=item *
+
+There must be a one-to-one correspondence between fields of the
+structure that are filled in, and bits set in the bitmask.
+
+=back
+
+=head2 OPTIONAL ARGUMENTS IN OTHER LANGUAGES
+
+In other languages, optional arguments are expressed in the
+way that is natural for that language. We refer you to the
+language-specific documentation for more details on that.
+
+For guestfish, see L<guestfish(1)/OPTIONAL ARGUMENTS>.
+
+=head2 SETTING CALLBACKS TO HANDLE EVENTS
+
+B<Note:> This section documents the generic event mechanism introduced
+in libguestfs 1.10, which you should use in new code if possible. The
+old functions C<guestfs_set_log_message_callback>,
+C<guestfs_set_subprocess_quit_callback>,
+C<guestfs_set_launch_done_callback>, C<guestfs_set_close_callback> and
+C<guestfs_set_progress_callback> are no longer documented in this
+manual page. Because of the ABI guarantee, the old functions continue
+to work.
+
+Handles generate events when certain things happen, such as log
+messages being generated, progress messages during long-running
+operations, or the handle being closed. The API calls described below
+let you register a callback to be called when events happen. You can
+register multiple callbacks (for the same, different or overlapping
+sets of events), and individually remove callbacks. If callbacks are
+not removed, then they remain in force until the handle is closed.
+
+In the current implementation, events are only generated
+synchronously: that means that events (and hence callbacks) can only
+happen while you are in the middle of making another libguestfs call.
+The callback is called in the same thread.
+
+Events may contain a payload, usually nothing (void), an array of 64
+bit unsigned integers, or a message buffer. Payloads are discussed
+later on.
+
+=head3 CLASSES OF EVENTS
+
+=over 4
+
+=item GUESTFS_EVENT_CLOSE
+(payload type: void)
+
+The callback function will be called while the handle is being closed
+(synchronously from L</guestfs_close>).
+
+Note that libguestfs installs an L<atexit(3)> handler to try to clean
+up handles that are open when the program exits. This means that this
+callback might be called indirectly from L<exit(3)>, which can cause
+unexpected problems in higher-level languages (eg. if your HLL
+interpreter has already been cleaned up by the time this is called,
+and if your callback then jumps into some HLL function).
+
+If no callback is registered: the handle is closed without any
+callback being invoked.
+
+=item GUESTFS_EVENT_SUBPROCESS_QUIT
+(payload type: void)
+
+The callback function will be called when the child process quits,
+either asynchronously or if killed by L</guestfs_kill_subprocess>.
+(This corresponds to a transition from any state to the CONFIG state).
+
+If no callback is registered: the event is ignored.
+
+=item GUESTFS_EVENT_LAUNCH_DONE
+(payload type: void)
+
+The callback function will be called when the child process becomes
+ready first time after it has been launched. (This corresponds to a
+transition from LAUNCHING to the READY state).
+
+If no callback is registered: the event is ignored.
+
+=item GUESTFS_EVENT_PROGRESS
+(payload type: array of 4 x uint64_t)
+
+Some long-running operations can generate progress messages. If
+this callback is registered, then it will be called each time a
+progress message is generated (usually two seconds after the
+operation started, and three times per second thereafter until
+it completes, although the frequency may change in future versions).
+
+The callback receives in the payload four unsigned 64 bit numbers
+which are (in order): C<proc_nr>, C<serial>, C<position>, C<total>.
+
+The units of C<total> are not defined, although for some
+operations C<total> may relate in some way to the amount of
+data to be transferred (eg. in bytes or megabytes), and
+C<position> may be the portion which has been transferred.
+
+The only defined and stable parts of the API are:
+
+=over 4
+
+=item *
+
+The callback can display to the user some type of progress bar or
+indicator which shows the ratio of C<position>:C<total>.
+
+=item *
+
+0 E<lt>= C<position> E<lt>= C<total>
+
+=item *
+
+If any progress notification is sent during a call, then a final
+progress notification is always sent when C<position> = C<total>
+(I<unless> the call fails with an error).
+
+This is to simplify caller code, so callers can easily set the
+progress indicator to "100%" at the end of the operation, without
+requiring special code to detect this case.
+
+=item *
+
+For some calls we are unable to estimate the progress of the call, but
+we can still generate progress messages to indicate activity. This is
+known as "pulse mode", and is directly supported by certain progress
+bar implementations (eg. GtkProgressBar).
+
+For these calls, zero or more progress messages are generated with
+C<position = 0> and C<total = 1>, followed by a final message with
+C<position = total = 1>.
+
+As noted above, if the call fails with an error then the final message
+may not be generated.
+
+=back
+
+The callback also receives the procedure number (C<proc_nr>) and
+serial number (C<serial>) of the call. These are only useful for
+debugging protocol issues, and the callback can normally ignore them.
+The callback may want to print these numbers in error messages or
+debugging messages.
+
+If no callback is registered: progress messages are discarded.
+
+=item GUESTFS_EVENT_APPLIANCE
+(payload type: message buffer)
+
+The callback function is called whenever a log message is generated by
+qemu, the appliance kernel, guestfsd (daemon), or utility programs.
+
+If the verbose flag (L</guestfs_set_verbose>) is set before launch
+(L</guestfs_launch>) then additional debug messages are generated.
+
+If no callback is registered: the messages are discarded unless the
+verbose flag is set in which case they are sent to stderr. You can
+override the printing of verbose messages to stderr by setting up a
+callback.
+
+=item GUESTFS_EVENT_LIBRARY
+(payload type: message buffer)
+
+The callback function is called whenever a log message is generated by
+the library part of libguestfs.
+
+If the verbose flag (L</guestfs_set_verbose>) is set then additional
+debug messages are generated.
+
+If no callback is registered: the messages are discarded unless the
+verbose flag is set in which case they are sent to stderr. You can
+override the printing of verbose messages to stderr by setting up a
+callback.
+
+=item GUESTFS_EVENT_TRACE
+(payload type: message buffer)
+
+The callback function is called whenever a trace message is generated.
+This only applies if the trace flag (L</guestfs_set_trace>) is set.
+
+If no callback is registered: the messages are sent to stderr. You
+can override the printing of trace messages to stderr by setting up a
+callback.
+
+=item GUESTFS_EVENT_ENTER
+(payload type: function name)
+
+The callback function is called whenever a libguestfs function
+is entered.
+
+The payload is a string which contains the name of the function
+that we are entering (not including C<guestfs_> prefix).
+
+Note that libguestfs functions can call themselves, so you may
+see many events from a single call. A few libguestfs functions
+do not generate this event.
+
+If no callback is registered: the event is ignored.
+
+=back
+
+=head3 guestfs_set_event_callback
+
+ int guestfs_set_event_callback (guestfs_h *g,
+ guestfs_event_callback cb,
+ uint64_t event_bitmask,
+ int flags,
+ void *opaque);
+
+This function registers a callback (C<cb>) for all event classes
+in the C<event_bitmask>.
+
+For example, to register for all log message events, you could call
+this function with the bitmask
+C<GUESTFS_EVENT_APPLIANCE|GUESTFS_EVENT_LIBRARY>. To register a
+single callback for all possible classes of events, use
+C<GUESTFS_EVENT_ALL>.
+
+C<flags> should always be passed as 0.
+
+C<opaque> is an opaque pointer which is passed to the callback. You
+can use it for any purpose.
+
+The return value is the event handle (an integer) which you can use to
+delete the callback (see below).
+
+If there is an error, this function returns C<-1>, and sets the error
+in the handle in the usual way (see L</guestfs_last_error> etc.)
+
+Callbacks remain in effect until they are deleted, or until the handle
+is closed.
+
+In the case where multiple callbacks are registered for a particular
+event class, all of the callbacks are called. The order in which
+multiple callbacks are called is not defined.
+
+=head3 guestfs_delete_event_callback
+
+ void guestfs_delete_event_callback (guestfs_h *g, int event_handle);
+
+Delete a callback that was previously registered. C<event_handle>
+should be the integer that was returned by a previous call to
+C<guestfs_set_event_callback> on the same handle.
+
+=head3 guestfs_event_callback
+
+ typedef void (*guestfs_event_callback) (
+ guestfs_h *g,
+ void *opaque,
+ uint64_t event,
+ int event_handle,
+ int flags,
+ const char *buf, size_t buf_len,
+ const uint64_t *array, size_t array_len);
+
+This is the type of the event callback function that you have to
+provide.
+
+The basic parameters are: the handle (C<g>), the opaque user pointer
+(C<opaque>), the event class (eg. C<GUESTFS_EVENT_PROGRESS>), the
+event handle, and C<flags> which in the current API you should ignore.
+
+The remaining parameters contain the event payload (if any). Each
+event may contain a payload, which usually relates to the event class,
+but for future proofing your code should be written to handle any
+payload for any event class.
+
+C<buf> and C<buf_len> contain a message buffer (if C<buf_len == 0>,
+then there is no message buffer). Note that this message buffer can
+contain arbitrary 8 bit data, including NUL bytes.
+
+C<array> and C<array_len> is an array of 64 bit unsigned integers. At
+the moment this is only used for progress messages.
+
+=head3 EXAMPLE: CAPTURING LOG MESSAGES
+
+One motivation for the generic event API was to allow GUI programs to
+capture debug and other messages. In libguestfs E<le> 1.8 these were
+sent unconditionally to C<stderr>.
+
+Events associated with log messages are: C<GUESTFS_EVENT_LIBRARY>,
+C<GUESTFS_EVENT_APPLIANCE> and C<GUESTFS_EVENT_TRACE>. (Note that
+error messages are not events; you must capture error messages
+separately).
+
+Programs have to set up a callback to capture the classes of events of
+interest:
+
+ int eh =
+ guestfs_set_event_callback
+ (g, message_callback,
+ GUESTFS_EVENT_LIBRARY|GUESTFS_EVENT_APPLIANCE|
+ GUESTFS_EVENT_TRACE,
+ 0, NULL) == -1)
+ if (eh == -1) {
+ // handle error in the usual way
+ }
+
+The callback can then direct messages to the appropriate place. In
+this example, messages are directed to syslog:
+
+ static void
+ message_callback (
+ guestfs_h *g,
+ void *opaque,
+ uint64_t event,
+ int event_handle,
+ int flags,
+ const char *buf, size_t buf_len,
+ const uint64_t *array, size_t array_len)
+ {
+ const int priority = LOG_USER|LOG_INFO;
+ if (buf_len > 0)
+ syslog (priority, "event 0x%lx: %s", event, buf);
+ }
+
+=head1 CANCELLING LONG TRANSFERS
+
+Some operations can be cancelled by the caller while they are in
+progress. Currently only operations that involve uploading or
+downloading data can be cancelled (technically: operations that have
+C<FileIn> or C<FileOut> parameters in the generator).
+
+=head2 guestfs_user_cancel
+
+ void guestfs_user_cancel (guestfs_h *g);
+
+C<guestfs_user_cancel> cancels the current upload or download
+operation.
+
+Unlike most other libguestfs calls, this function is signal safe and
+thread safe. You can call it from a signal handler or from another
+thread, without needing to do any locking.
+
+The transfer that was in progress (if there is one) will stop shortly
+afterwards, and will return an error. The errno (see
+L</guestfs_last_errno>) is set to C<EINTR>, so you can test for this
+to find out if the operation was cancelled or failed because of
+another error.
+
+No cleanup is performed: for example, if a file was being uploaded
+then after cancellation there may be a partially uploaded file. It is
+the caller's responsibility to clean up if necessary.
+
+There are two common places that you might call C<guestfs_user_cancel>.
+
+In an interactive text-based program, you might call it from a
+C<SIGINT> signal handler so that pressing C<^C> cancels the current
+operation. (You also need to call L</guestfs_set_pgroup> so that
+child processes don't receive the C<^C> signal).
+
+In a graphical program, when the main thread is displaying a progress
+bar with a cancel button, wire up the cancel button to call this
+function.
+
+=head1 PRIVATE DATA AREA
+
+You can attach named pieces of private data to the libguestfs handle,
+fetch them by name, and walk over them, for the lifetime of the
+handle. This is called the private data area and is only available
+from the C API.
+
+To attach a named piece of data, use the following call:
+
+ void guestfs_set_private (guestfs_h *g, const char *key, void *data);
+
+C<key> is the name to associate with this data, and C<data> is an
+arbitrary pointer (which can be C<NULL>). Any previous item with the
+same key is overwritten.
+
+You can use any C<key> you want, but your key should I<not> start with
+an underscore character. Keys beginning with an underscore character
+are reserved for internal libguestfs purposes (eg. for implementing
+language bindings). It is recommended that you prefix the key with
+some unique string to avoid collisions with other users.
+
+To retrieve the pointer, use:
+
+ void *guestfs_get_private (guestfs_h *g, const char *key);
+
+This function returns C<NULL> if either no data is found associated
+with C<key>, or if the user previously set the C<key>'s C<data>
+pointer to C<NULL>.
+
+Libguestfs does not try to look at or interpret the C<data> pointer in
+any way. As far as libguestfs is concerned, it need not be a valid
+pointer at all. In particular, libguestfs does I<not> try to free the
+data when the handle is closed. If the data must be freed, then the
+caller must either free it before calling L</guestfs_close> or must
+set up a close callback to do it (see L</GUESTFS_EVENT_CLOSE>).
+
+To walk over all entries, use these two functions:
+
+ void *guestfs_first_private (guestfs_h *g, const char **key_rtn);
+
+ void *guestfs_next_private (guestfs_h *g, const char **key_rtn);
+
+C<guestfs_first_private> returns the first key, pointer pair ("first"
+does not have any particular meaning -- keys are not returned in any
+defined order). A pointer to the key is returned in C<*key_rtn> and
+the corresponding data pointer is returned from the function. C<NULL>
+is returned if there are no keys stored in the handle.
+
+C<guestfs_next_private> returns the next key, pointer pair. The
+return value of this function is also C<NULL> is there are no further
+entries to return.
+
+Notes about walking over entries:
+
+=over 4
+
+=item *
+
+You must not call C<guestfs_set_private> while walking over the
+entries.
+
+=item *
+
+The handle maintains an internal iterator which is reset when you call
+C<guestfs_first_private>. This internal iterator is invalidated when
+you call C<guestfs_set_private>.
+
+=item *
+
+If you have set the data pointer associated with a key to C<NULL>, ie:
+
+ guestfs_set_private (g, key, NULL);
+
+then that C<key> is not returned when walking.
+
+=item *
+
+C<*key_rtn> is only valid until the next call to
+C<guestfs_first_private>, C<guestfs_next_private> or
+C<guestfs_set_private>.
+
+=back
+
+The following example code shows how to print all keys and data
+pointers that are associated with the handle C<g>:
+
+ const char *key;
+ void *data = guestfs_first_private (g, &key);
+ while (data != NULL)
+ {
+ printf ("key = %s, data = %p\n", key, data);
+ data = guestfs_next_private (g, &key);
+ }
+
+More commonly you are only interested in keys that begin with an
+application-specific prefix C<foo_>. Modify the loop like so:
+
+ const char *key;
+ void *data = guestfs_first_private (g, &key);
+ while (data != NULL)
+ {
+ if (strncmp (key, "foo_", strlen ("foo_")) == 0)
+ printf ("key = %s, data = %p\n", key, data);
+ data = guestfs_next_private (g, &key);
+ }
+
+If you need to modify keys while walking, then you have to jump back
+to the beginning of the loop. For example, to delete all keys
+prefixed with C<foo_>:
+
+ const char *key;
+ void *data;
+ again:
+ data = guestfs_first_private (g, &key);
+ while (data != NULL)
+ {
+ if (strncmp (key, "foo_", strlen ("foo_")) == 0)
+ {
+ guestfs_set_private (g, key, NULL);
+ /* note that 'key' pointer is now invalid, and so is
+ the internal iterator */
+ goto again;
+ }
+ data = guestfs_next_private (g, &key);
+ }
+
+Note that the above loop is guaranteed to terminate because the keys
+are being deleted, but other manipulations of keys within the loop
+might not terminate unless you also maintain an indication of which
+keys have been visited.
+
+=begin html
+
+<!-- old anchor for the next section -->
+<a name="state_machine_and_low_level_event_api"/>
+
+=end html
+
+=head1 ARCHITECTURE
+
+Internally, libguestfs is implemented by running an appliance (a
+special type of small virtual machine) using L<qemu(1)>. Qemu runs as
+a child process of the main program.
+
+ ___________________
+ / \
+ | main program |
+ | |
+ | | child process / appliance
+ | | __________________________
+ | | / qemu \
+ +-------------------+ RPC | +-----------------+ |
+ | libguestfs <--------------------> guestfsd | |
+ | | | +-----------------+ |
+ \___________________/ | | Linux kernel | |
+ | +--^--------------+ |
+ \_________|________________/
+ |
+ _______v______
+ / \
+ | Device or |
+ | disk image |
+ \______________/
+
+The library, linked to the main program, creates the child process and
+hence the appliance in the L</guestfs_launch> function.
+
+Inside the appliance is a Linux kernel and a complete stack of
+userspace tools (such as LVM and ext2 programs) and a small
+controlling daemon called L</guestfsd>. The library talks to
+L</guestfsd> using remote procedure calls (RPC). There is a mostly
+one-to-one correspondence between libguestfs API calls and RPC calls
+to the daemon. Lastly the disk image(s) are attached to the qemu
+process which translates device access by the appliance's Linux kernel
+into accesses to the image.
+
+A common misunderstanding is that the appliance "is" the virtual