+You may think the above is an awful lot of hassle, and it is.
+There are other ways outside of the C linking system to ensure
+that this kind of incompatibility never arises, such as using
+package versioning:
+
+ Requires: libguestfs >= 1.0.80
+
+=head1 CALLS WITH OPTIONAL ARGUMENTS
+
+A recent feature of the API is the introduction of calls which take
+optional arguments. In C these are declared 3 ways. The main way is
+as a call which takes variable arguments (ie. C<...>), as in this
+example:
+
+ int guestfs_add_drive_opts (guestfs_h *g, const char *filename, ...);
+
+Call this with a list of optional arguments, terminated by C<-1>.
+So to call with no optional arguments specified:
+
+ guestfs_add_drive_opts (g, filename, -1);
+
+With a single optional argument:
+
+ guestfs_add_drive_opts (g, filename,
+ GUESTFS_ADD_DRIVE_OPTS_FORMAT, "qcow2",
+ -1);
+
+With two:
+
+ 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.
+
+=head1 SYSTEMTAP
+
+The libguestfs C library can be probed using systemtap or DTrace.
+This is true of any library, not just libguestfs. However libguestfs
+also contains static markers to help in probing internal operations.
+
+You can list all the static markers by doing:
+
+ stap -l 'process("/usr/lib*/libguestfs.so.0")
+ .provider("guestfs").mark("*")'
+
+B<Note:> These static markers are I<not> part of the stable API and
+may change in future versions.
+
+=head2 SYSTEMTAP SCRIPT EXAMPLE
+
+This script contains examples of displaying both the static markers
+and some ordinary C entry points:
+
+ global last;
+
+ function display_time () {
+ now = gettimeofday_us ();
+ delta = 0;
+ if (last > 0)
+ delta = now - last;
+ last = now;
+
+ printf ("%d (+%d):", now, delta);
+ }
+
+ probe begin {
+ last = 0;
+ printf ("ready\n");
+ }
+
+ /* Display all calls to static markers. */
+ probe process("/usr/lib*/libguestfs.so.0")
+ .provider("guestfs").mark("*") ? {
+ display_time();
+ printf ("\t%s %s\n", $$name, $$parms);
+ }
+
+ /* Display all calls to guestfs_mkfs* functions. */
+ probe process("/usr/lib*/libguestfs.so.0")
+ .function("guestfs_mkfs*") ? {
+ display_time();
+ printf ("\t%s %s\n", probefunc(), $$parms);
+ }
+
+The script above can be saved to C<test.stap> and run using the
+L<stap(1)> program. Note that you either have to be root, or you have
+to add yourself to several special stap groups. Consult the systemtap
+documentation for more information.
+
+ # stap /tmp/test.stap
+ ready
+
+In another terminal, run a guestfish command such as this:
+
+ guestfish -N fs
+
+In the first terminal, stap trace output similar to this is shown:
+
+ 1318248056692655 (+0): launch_start
+ 1318248056692850 (+195): launch_build_appliance_start
+ 1318248056818285 (+125435): launch_build_appliance_end
+ 1318248056838059 (+19774): launch_run_qemu
+ 1318248061071167 (+4233108): launch_end
+ 1318248061280324 (+209157): guestfs_mkfs g=0x1024ab0 fstype=0x46116f device=0x1024e60
+
+=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
+machine. Although the disk image you are attached to might also be
+used by some virtual machine, libguestfs doesn't know or care about
+this. (But you will care if both libguestfs's qemu process and your
+virtual machine are trying to update the disk image at the same time,
+since these usually results in massive disk corruption).
+
+=head1 STATE MACHINE
+
+libguestfs uses a state machine to model the child process:
+
+ |
+ guestfs_create
+ |
+ |
+ ____V_____
+ / \
+ | CONFIG |
+ \__________/
+ ^ ^ ^ \
+ / | \ \ guestfs_launch
+ / | _\__V______
+ / | / \
+ / | | LAUNCHING |
+ / | \___________/
+ / | /
+ / | guestfs_launch
+ / | /
+ ______ / __|____V
+ / \ ------> / \
+ | BUSY | | READY |
+ \______/ <------ \________/
+
+The normal transitions are (1) CONFIG (when the handle is created, but
+there is no child process), (2) LAUNCHING (when the child process is
+booting up), (3) alternating between READY and BUSY as commands are
+issued to, and carried out by, the child process.
+
+The guest may be killed by L</guestfs_kill_subprocess>, or may die
+asynchronously at any time (eg. due to some internal error), and that
+causes the state to transition back to CONFIG.
+
+Configuration commands for qemu such as L</guestfs_add_drive> can only
+be issued when in the CONFIG state.
+
+The API offers one call that goes from CONFIG through LAUNCHING to
+READY. L</guestfs_launch> blocks until the child process is READY to
+accept commands (or until some failure or timeout).
+L</guestfs_launch> internally moves the state from CONFIG to LAUNCHING
+while it is running.
+
+API actions such as L</guestfs_mount> can only be issued when in the
+READY state. These API calls block waiting for the command to be
+carried out (ie. the state to transition to BUSY and then back to
+READY). There are no non-blocking versions, and no way to issue more
+than one command per handle at the same time.
+
+Finally, the child process sends asynchronous messages back to the
+main program, such as kernel log messages. You can register a
+callback to receive these messages.
+
+=head1 INTERNALS
+
+=head2 APPLIANCE BOOT PROCESS
+
+This process has evolved and continues to evolve. The description
+here corresponds only to the current version of libguestfs and is
+provided for information only.
+
+In order to follow the stages involved below, enable libguestfs
+debugging (set the environment variable C<LIBGUESTFS_DEBUG=1>).
+
+=over 4
+
+=item Create the appliance
+
+C<febootstrap-supermin-helper> is invoked to create the kernel, a
+small initrd and the appliance.
+
+The appliance is cached in C</var/tmp/.guestfs-E<lt>UIDE<gt>> (or in
+another directory if C<TMPDIR> is set).
+
+For a complete description of how the appliance is created and cached,
+read the L<febootstrap(8)> and L<febootstrap-supermin-helper(8)> man
+pages.
+
+=item Start qemu and boot the kernel
+
+qemu is invoked to boot the kernel.
+
+=item Run the initrd
+
+C<febootstrap-supermin-helper> builds a small initrd. The initrd is
+not the appliance. The purpose of the initrd is to load enough kernel
+modules in order that the appliance itself can be mounted and started.
+
+The initrd is a cpio archive called
+C</var/tmp/.guestfs-E<lt>UIDE<gt>/initrd>.
+
+When the initrd has started you will see messages showing that kernel
+modules are being loaded, similar to this:
+
+ febootstrap: ext2 mini initrd starting up
+ febootstrap: mounting /sys
+ febootstrap: internal insmod libcrc32c.ko
+ febootstrap: internal insmod crc32c-intel.ko
+
+=item Find and mount the appliance device
+
+The appliance is a sparse file containing an ext2 filesystem which
+contains a familiar (although reduced in size) Linux operating system.
+It would normally be called C</var/tmp/.guestfs-E<lt>UIDE<gt>/root>.
+
+The regular disks being inspected by libguestfs are the first
+devices exposed by qemu (eg. as C</dev/vda>).
+
+The last disk added to qemu is the appliance itself (eg. C</dev/vdb>
+if there was only one regular disk).
+
+Thus the final job of the initrd is to locate the appliance disk,
+mount it, and switch root into the appliance, and run C</init> from
+the appliance.
+
+If this works successfully you will see messages such as:
+
+ febootstrap: picked /sys/block/vdb/dev as root device
+ febootstrap: creating /dev/root as block special 252:16
+ febootstrap: mounting new root on /root
+ febootstrap: chroot
+ Starting /init script ...
+
+Note that C<Starting /init script ...> indicates that the appliance's
+init script is now running.
+
+=item Initialize the appliance
+
+The appliance itself now initializes itself. This involves starting
+certain processes like C<udev>, possibly printing some debug
+information, and finally running the daemon (C<guestfsd>).
+
+=item The daemon
+
+Finally the daemon (C<guestfsd>) runs inside the appliance. If it
+runs you should see:
+
+ verbose daemon enabled
+
+The daemon expects to see a named virtio-serial port exposed by qemu
+and connected on the other end to the library.
+
+The daemon connects to this port (and hence to the library) and sends
+a four byte message C<GUESTFS_LAUNCH_FLAG>, which initiates the
+communication protocol (see below).
+
+=back
+
+=head2 COMMUNICATION PROTOCOL
+
+Don't rely on using this protocol directly. This section documents
+how it currently works, but it may change at any time.
+
+The protocol used to talk between the library and the daemon running
+inside the qemu virtual machine is a simple RPC mechanism built on top
+of XDR (RFC 1014, RFC 1832, RFC 4506).
+
+The detailed format of structures is in C<src/guestfs_protocol.x>
+(note: this file is automatically generated).
+
+There are two broad cases, ordinary functions that don't have any
+C<FileIn> and C<FileOut> parameters, which are handled with very
+simple request/reply messages. Then there are functions that have any
+C<FileIn> or C<FileOut> parameters, which use the same request and
+reply messages, but they may also be followed by files sent using a
+chunked encoding.
+
+=head3 ORDINARY FUNCTIONS (NO FILEIN/FILEOUT PARAMS)
+
+For ordinary functions, the request message is:
+
+ total length (header + arguments,
+ but not including the length word itself)
+ struct guestfs_message_header (encoded as XDR)
+ struct guestfs_<foo>_args (encoded as XDR)
+
+The total length field allows the daemon to allocate a fixed size
+buffer into which it slurps the rest of the message. As a result, the
+total length is limited to C<GUESTFS_MESSAGE_MAX> bytes (currently
+4MB), which means the effective size of any request is limited to
+somewhere under this size.
+
+Note also that many functions don't take any arguments, in which case
+the C<guestfs_I<foo>_args> is completely omitted.
+
+The header contains the procedure number (C<guestfs_proc>) which is
+how the receiver knows what type of args structure to expect, or none
+at all.
+
+For functions that take optional arguments, the optional arguments are
+encoded in the C<guestfs_I<foo>_args> structure in the same way as
+ordinary arguments. A bitmask in the header indicates which optional
+arguments are meaningful. The bitmask is also checked to see if it
+contains bits set which the daemon does not know about (eg. if more
+optional arguments were added in a later version of the library), and
+this causes the call to be rejected.
+
+The reply message for ordinary functions is:
+
+ total length (header + ret,
+ but not including the length word itself)
+ struct guestfs_message_header (encoded as XDR)
+ struct guestfs_<foo>_ret (encoded as XDR)
+
+As above the C<guestfs_I<foo>_ret> structure may be completely omitted
+for functions that return no formal return values.
+
+As above the total length of the reply is limited to
+C<GUESTFS_MESSAGE_MAX>.
+
+In the case of an error, a flag is set in the header, and the reply
+message is slightly changed:
+
+ total length (header + error,
+ but not including the length word itself)
+ struct guestfs_message_header (encoded as XDR)
+ struct guestfs_message_error (encoded as XDR)
+
+The C<guestfs_message_error> structure contains the error message as a
+string.
+
+=head3 FUNCTIONS THAT HAVE FILEIN PARAMETERS
+
+A C<FileIn> parameter indicates that we transfer a file I<into> the
+guest. The normal request message is sent (see above). However this
+is followed by a sequence of file chunks.
+
+ total length (header + arguments,
+ but not including the length word itself,
+ and not including the chunks)
+ struct guestfs_message_header (encoded as XDR)
+ struct guestfs_<foo>_args (encoded as XDR)
+ sequence of chunks for FileIn param #0
+ sequence of chunks for FileIn param #1 etc.
+
+The "sequence of chunks" is:
+
+ length of chunk (not including length word itself)
+ struct guestfs_chunk (encoded as XDR)
+ length of chunk
+ struct guestfs_chunk (encoded as XDR)
+ ...
+ length of chunk
+ struct guestfs_chunk (with data.data_len == 0)
+
+The final chunk has the C<data_len> field set to zero. Additionally a
+flag is set in the final chunk to indicate either successful
+completion or early cancellation.
+
+At time of writing there are no functions that have more than one
+FileIn parameter. However this is (theoretically) supported, by
+sending the sequence of chunks for each FileIn parameter one after
+another (from left to right).
+
+Both the library (sender) I<and> the daemon (receiver) may cancel the
+transfer. The library does this by sending a chunk with a special
+flag set to indicate cancellation. When the daemon sees this, it
+cancels the whole RPC, does I<not> send any reply, and goes back to
+reading the next request.
+
+The daemon may also cancel. It does this by writing a special word
+C<GUESTFS_CANCEL_FLAG> to the socket. The library listens for this
+during the transfer, and if it gets it, it will cancel the transfer
+(it sends a cancel chunk). The special word is chosen so that even if
+cancellation happens right at the end of the transfer (after the
+library has finished writing and has started listening for the reply),
+the "spurious" cancel flag will not be confused with the reply
+message.
+
+This protocol allows the transfer of arbitrary sized files (no 32 bit
+limit), and also files where the size is not known in advance
+(eg. from pipes or sockets). However the chunks are rather small
+(C<GUESTFS_MAX_CHUNK_SIZE>), so that neither the library nor the
+daemon need to keep much in memory.
+
+=head3 FUNCTIONS THAT HAVE FILEOUT PARAMETERS
+
+The protocol for FileOut parameters is exactly the same as for FileIn
+parameters, but with the roles of daemon and library reversed.