+#. type: verbatim
+#: ../src/guestfs.pod:1883
+#, no-wrap
+msgid ""
+" typedef void (*guestfs_event_callback) (\n"
+" guestfs_h *g,\n"
+" void *opaque,\n"
+" uint64_t event,\n"
+" int event_handle,\n"
+" int flags,\n"
+" const char *buf, size_t buf_len,\n"
+" const uint64_t *array, size_t array_len);\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1892
+msgid "This is the type of the event callback function that you have to provide."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1895
+msgid ""
+"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."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1899
+msgid ""
+"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."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1904
+msgid ""
+"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."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1908
+msgid ""
+"C<array> and C<array_len> is an array of 64 bit unsigned integers. At the "
+"moment this is only used for progress messages."
+msgstr ""
+
+#. type: =head3
+#: ../src/guestfs.pod:1911
+msgid "EXAMPLE: CAPTURING LOG MESSAGES"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1913
+msgid ""
+"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>."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1917
+msgid ""
+"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)."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1922
+msgid ""
+"Programs have to set up a callback to capture the classes of events of "
+"interest:"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:1925
+#, no-wrap
+msgid ""
+" int eh =\n"
+" guestfs_set_event_callback\n"
+" (g, message_callback,\n"
+" GUESTFS_EVENT_LIBRARY|GUESTFS_EVENT_APPLIANCE|\n"
+" GUESTFS_EVENT_TRACE,\n"
+" 0, NULL) == -1)\n"
+" if (eh == -1) {\n"
+" // handle error in the usual way\n"
+" }\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1935
+msgid ""
+"The callback can then direct messages to the appropriate place. In this "
+"example, messages are directed to syslog:"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:1938
+#, no-wrap
+msgid ""
+" static void\n"
+" message_callback (\n"
+" guestfs_h *g,\n"
+" void *opaque,\n"
+" uint64_t event,\n"
+" int event_handle,\n"
+" int flags,\n"
+" const char *buf, size_t buf_len,\n"
+" const uint64_t *array, size_t array_len)\n"
+" {\n"
+" const int priority = LOG_USER|LOG_INFO;\n"
+" if (buf_len > 0)\n"
+" syslog (priority, \"event 0x%lx: %s\", event, buf);\n"
+" }\n"
+"\n"
+msgstr ""
+
+#. type: =head1
+#: ../src/guestfs.pod:1953
+msgid "PRIVATE DATA AREA"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1955
+msgid ""
+"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."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1960
+msgid "To attach a named piece of data, use the following call:"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:1962
+#, no-wrap
+msgid ""
+" void guestfs_set_private (guestfs_h *g, const char *key, void *data);\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1964
+msgid ""
+"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 name is "
+"overwritten."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1968
+msgid ""
+"You can use any C<key> you want, but names beginning with an underscore "
+"character are reserved for internal libguestfs purposes (for implementing "
+"language bindings). It is recommended to prefix the name with some unique "
+"string to avoid collisions with other users."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1973
+msgid "To retrieve the pointer, use:"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:1975
+#, no-wrap
+msgid ""
+" void *guestfs_get_private (guestfs_h *g, const char *key);\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1977
+msgid ""
+"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>."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1981
+msgid ""
+"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>)."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1988
+msgid "To walk over all entries, use these two functions:"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:1990
+#, no-wrap
+msgid ""
+" void *guestfs_first_private (guestfs_h *g, const char **key_rtn);\n"
+"\n"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:1992
+#, no-wrap
+msgid ""
+" void *guestfs_next_private (guestfs_h *g, const char **key_rtn);\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:1994
+msgid ""
+"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."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2000
+msgid ""
+"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."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2004
+msgid "Notes about walking over entries:"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2010
+msgid "You must not call C<guestfs_set_private> while walking over the entries."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2015
+msgid ""
+"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>."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2021
+msgid "If you have set the data pointer associated with a key to C<NULL>, ie:"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:2023
+#, no-wrap
+msgid ""
+" guestfs_set_private (g, key, NULL);\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2025
+msgid "then that C<key> is not returned when walking."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2029
+msgid ""
+"C<*key_rtn> is only valid until the next call to C<guestfs_first_private>, "
+"C<guestfs_next_private> or C<guestfs_set_private>."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2035
+msgid ""
+"The following example code shows how to print all keys and data pointers "
+"that are associated with the handle C<g>:"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:2038
+#, no-wrap
+msgid ""
+" const char *key;\n"
+" void *data = guestfs_first_private (g, &key);\n"
+" while (data != NULL)\n"
+" {\n"
+" printf (\"key = %s, data = %p\\n\", key, data);\n"
+" data = guestfs_next_private (g, &key);\n"
+" }\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2046
+msgid ""
+"More commonly you are only interested in keys that begin with an "
+"application-specific prefix C<foo_>. Modify the loop like so:"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:2049
+#, no-wrap
+msgid ""
+" const char *key;\n"
+" void *data = guestfs_first_private (g, &key);\n"
+" while (data != NULL)\n"
+" {\n"
+" if (strncmp (key, \"foo_\", strlen (\"foo_\")) == 0)\n"
+" printf (\"key = %s, data = %p\\n\", key, data);\n"
+" data = guestfs_next_private (g, &key);\n"
+" }\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2058
+msgid ""
+"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_>:"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:2062
+#, no-wrap
+msgid ""
+" const char *key;\n"
+" void *data;\n"
+" again:\n"
+" data = guestfs_first_private (g, &key);\n"
+" while (data != NULL)\n"
+" {\n"
+" if (strncmp (key, \"foo_\", strlen (\"foo_\")) == 0)\n"
+" {\n"
+" guestfs_set_private (g, key, NULL);\n"
+" /* note that 'key' pointer is now invalid, and so is\n"
+" the internal iterator */\n"
+" goto again;\n"
+" }\n"
+" data = guestfs_next_private (g, &key);\n"
+" }\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2078
+msgid ""
+"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."
+msgstr ""
+
+#. type: =end
+#: ../src/guestfs.pod:2083 ../src/guestfs.pod:2088
+msgid "html"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2085
+msgid ""
+"<!-- old anchor for the next section --> <a "
+"name=\"state_machine_and_low_level_event_api\"/>"
+msgstr ""
+
+#. type: =head1
+#: ../src/guestfs.pod:2090
+msgid "ARCHITECTURE"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2092
+msgid ""
+"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."
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:2096
+#, no-wrap
+msgid ""
+" ___________________\n"
+" / \\\n"
+" | main program |\n"
+" | |\n"
+" | | child process / appliance\n"
+" | | __________________________\n"
+" | | / qemu \\\n"
+" +-------------------+ RPC | +-----------------+ |\n"
+" | libguestfs <--------------------> guestfsd | |\n"
+" | | | +-----------------+ |\n"
+" \\___________________/ | | Linux kernel | |\n"
+" | +--^--------------+ |\n"
+" \\_________|________________/\n"
+" |\n"
+" _______v______\n"
+" / \\\n"
+" | Device or |\n"
+" | disk image |\n"
+" \\______________/\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2116
+msgid ""
+"The library, linked to the main program, creates the child process and hence "
+"the appliance in the L</guestfs_launch> function."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2119
+msgid ""
+"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."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2128
+msgid ""
+"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)."
+msgstr ""
+
+#. type: =head1
+#: ../src/guestfs.pod:2135
+msgid "STATE MACHINE"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2137
+msgid "libguestfs uses a state machine to model the child process:"
+msgstr ""
+
+#. type: verbatim
+#: ../src/guestfs.pod:2139
+#, no-wrap
+msgid ""
+" |\n"
+" guestfs_create\n"
+" |\n"
+" |\n"
+" ____V_____\n"
+" / \\\n"
+" | CONFIG |\n"
+" \\__________/\n"
+" ^ ^ ^ \\\n"
+" / | \\ \\ guestfs_launch\n"
+" / | _\\__V______\n"
+" / | / \\\n"
+" / | | LAUNCHING |\n"
+" / | \\___________/\n"
+" / | /\n"
+" / | guestfs_launch\n"
+" / | /\n"
+" ______ / __|____V\n"
+" / \\ ------> / \\\n"
+" | BUSY | | READY |\n"
+" \\______/ <------ \\________/\n"
+"\n"
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2161
+msgid ""
+"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."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2166
+msgid ""
+"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."
+msgstr ""
+
+#. type: textblock
+#: ../src/guestfs.pod:2170