+ if (!has_function)
+ printf ("this libguestfs.so does NOT have guestfs_dd function\n");
+ else {
+ printf ("this libguestfs.so has guestfs_dd function\n");
+ /* Now it's safe to call
+ guestfs_dd (g, "foo", "bar");
+ */
+ }
+ #else
+ printf ("guestfs_dd function was not found at compile time\n");
+ #endif
+ }
+
+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.
+
+ total length (header + ret,
+ but not including the length word itself,
+ and not including the chunks)
+ struct guestfs_message_header (encoded as XDR)
+ struct guestfs_<foo>_ret (encoded as XDR)
+ sequence of chunks for FileOut param #0
+ sequence of chunks for FileOut param #1 etc.
+
+=head3 INITIAL MESSAGE
+
+When the daemon launches it sends an initial word
+(C<GUESTFS_LAUNCH_FLAG>) which indicates that the guest and daemon is
+alive. This is what L</guestfs_launch> waits for.
+
+=head3 PROGRESS NOTIFICATION MESSAGES
+
+The daemon may send progress notification messages at any time. These
+are distinguished by the normal length word being replaced by
+C<GUESTFS_PROGRESS_FLAG>, followed by a fixed size progress message.
+
+The library turns them into progress callbacks (see
+L</GUESTFS_EVENT_PROGRESS>) if there is a callback registered, or
+discards them if not.
+
+The daemon self-limits the frequency of progress messages it sends
+(see C<daemon/proto.c:notify_progress>). Not all calls generate
+progress messages.
+
+=head1 LIBGUESTFS VERSION NUMBERS
+
+Since April 2010, libguestfs has started to make separate development
+and stable releases, along with corresponding branches in our git
+repository. These separate releases can be identified by version
+number:
+
+ even numbers for stable: 1.2.x, 1.4.x, ...
+ .-------- odd numbers for development: 1.3.x, 1.5.x, ...
+ |
+ v
+ 1 . 3 . 5
+ ^ ^
+ | |
+ | `-------- sub-version
+ |
+ `------ always '1' because we don't change the ABI
+
+Thus "1.3.5" is the 5th update to the development branch "1.3".
+
+As time passes we cherry pick fixes from the development branch and
+backport those into the stable branch, the effect being that the
+stable branch should get more stable and less buggy over time. So the
+stable releases are ideal for people who don't need new features but
+would just like the software to work.
+
+Our criteria for backporting changes are:
+
+=over 4
+
+=item *
+
+Documentation changes which don't affect any code are
+backported unless the documentation refers to a future feature
+which is not in stable.
+
+=item *
+
+Bug fixes which are not controversial, fix obvious problems, and
+have been well tested are backported.
+
+=item *
+
+Simple rearrangements of code which shouldn't affect how it works get
+backported. This is so that the code in the two branches doesn't get
+too far out of step, allowing us to backport future fixes more easily.
+
+=item *
+
+We I<don't> backport new features, new APIs, new tools etc, except in
+one exceptional case: the new feature is required in order to
+implement an important bug fix.
+
+=back
+
+A new stable branch starts when we think the new features in
+development are substantial and compelling enough over the current
+stable branch to warrant it. When that happens we create new stable
+and development versions 1.N.0 and 1.(N+1).0 [N is even]. The new
+dot-oh release won't necessarily be so stable at this point, but by
+backporting fixes from development, that branch will stabilize over
+time.
+
+=head1 EXTENDING LIBGUESTFS
+
+=head2 ADDING A NEW API ACTION
+
+Large amounts of boilerplate code in libguestfs (RPC, bindings,
+documentation) are generated, and this makes it easy to extend the
+libguestfs API.
+
+To add a new API action there are two changes:
+
+=over 4
+
+=item 1.
+
+You need to add a description of the call (name, parameters, return
+type, tests, documentation) to C<generator/generator_actions.ml>.
+
+There are two sorts of API action, depending on whether the call goes
+through to the daemon in the appliance, or is serviced entirely by the
+library (see L</ARCHITECTURE> above). L</guestfs_sync> is an example
+of the former, since the sync is done in the appliance.
+L</guestfs_set_trace> is an example of the latter, since a trace flag
+is maintained in the handle and all tracing is done on the library
+side.
+
+Most new actions are of the first type, and get added to the
+C<daemon_functions> list. Each function has a unique procedure number
+used in the RPC protocol which is assigned to that action when we
+publish libguestfs and cannot be reused. Take the latest procedure
+number and increment it.
+
+For library-only actions of the second type, add to the
+C<non_daemon_functions> list. Since these functions are serviced by
+the library and do not travel over the RPC mechanism to the daemon,
+these functions do not need a procedure number, and so the procedure
+number is set to C<-1>.
+
+=item 2.
+
+Implement the action (in C):
+
+For daemon actions, implement the function C<do_E<lt>nameE<gt>> in the
+C<daemon/> directory.
+
+For library actions, implement the function C<guestfs__E<lt>nameE<gt>>
+(note: double underscore) in the C<src/> directory.
+
+In either case, use another function as an example of what to do.
+
+=back
+
+After making these changes, use C<make> to compile.
+
+Note that you don't need to implement the RPC, language bindings,
+manual pages or anything else. It's all automatically generated from
+the OCaml description.
+
+=head2 ADDING TESTS FOR AN API ACTION
+
+You can supply zero or as many tests as you want per API call. The
+tests can either be added as part of the API description
+(C<generator/generator_actions.ml>), or in some rarer cases you may
+want to drop a script into C<regressions/>. Note that adding a script
+to C<regressions/> is slower, so if possible use the first method.
+
+The following describes the test environment used when you add an API
+test in C<generator_actions.ml>.
+
+The test environment has 4 block devices:
+
+=over 4
+
+=item C</dev/sda> 500MB
+
+General block device for testing.
+
+=item C</dev/sdb> 50MB
+
+C</dev/sdb1> is an ext2 filesystem used for testing
+filesystem write operations.
+
+=item C</dev/sdc> 10MB
+
+Used in a few tests where two block devices are needed.
+
+=item C</dev/sdd>
+
+ISO with fixed content (see C<images/test.iso>).
+
+=back
+
+To be able to run the tests in a reasonable amount of time, the
+libguestfs appliance and block devices are reused between tests. So
+don't try testing L</guestfs_kill_subprocess> :-x
+
+Each test starts with an initial scenario, selected using one of the
+C<Init*> expressions, described in C<generator/generator_types.ml>.
+These initialize the disks mentioned above in a particular way as
+documented in C<generator_types.ml>. You should not assume anything
+about the previous contents of other disks that are not initialized.
+
+You can add a prerequisite clause to any individual test. This is a
+run-time check, which, if it fails, causes the test to be skipped.
+Useful if testing a command which might not work on all variations of
+libguestfs builds. A test that has prerequisite of C<Always> means to
+run unconditionally.
+
+In addition, packagers can skip individual tests by setting
+environment variables before running C<make check>.
+
+ SKIP_TEST_<CMD>_<NUM>=1
+
+eg: C<SKIP_TEST_COMMAND_3=1> skips test #3 of L</guestfs_command>.
+
+or:
+
+ SKIP_TEST_<CMD>=1
+
+eg: C<SKIP_TEST_ZEROFREE=1> skips all L</guestfs_zerofree> tests.
+
+Packagers can run only certain tests by setting for example:
+
+ TEST_ONLY="vfs_type zerofree"
+
+See C<capitests/tests.c> for more details of how these environment
+variables work.
+
+=head2 DEBUGGING NEW API ACTIONS
+
+Test new actions work before submitting them.
+
+You can use guestfish to try out new commands.
+
+Debugging the daemon is a problem because it runs inside a minimal
+environment. However you can fprintf messages in the daemon to
+stderr, and they will show up if you use C<guestfish -v>.
+
+=head2 FORMATTING CODE AND OTHER CONVENTIONS
+
+Our C source code generally adheres to some basic code-formatting
+conventions. The existing code base is not totally consistent on this
+front, but we do prefer that contributed code be formatted similarly.
+In short, use spaces-not-TABs for indentation, use 2 spaces for each
+indentation level, and other than that, follow the K&R style.
+
+If you use Emacs, add the following to one of one of your start-up files
+(e.g., ~/.emacs), to help ensure that you get indentation right:
+
+ ;;; In libguestfs, indent with spaces everywhere (not TABs).
+ ;;; Exceptions: Makefile and ChangeLog modes.
+ (add-hook 'find-file-hook
+ '(lambda () (if (and buffer-file-name
+ (string-match "/libguestfs\\>"
+ (buffer-file-name))
+ (not (string-equal mode-name "Change Log"))
+ (not (string-equal mode-name "Makefile")))
+ (setq indent-tabs-mode nil))))
+
+ ;;; When editing C sources in libguestfs, use this style.
+ (defun libguestfs-c-mode ()
+ "C mode with adjusted defaults for use with libguestfs."
+ (interactive)
+ (c-set-style "K&R")
+ (setq c-indent-level 2)
+ (setq c-basic-offset 2))
+ (add-hook 'c-mode-hook
+ '(lambda () (if (string-match "/libguestfs\\>"
+ (buffer-file-name))
+ (libguestfs-c-mode))))