Copy some common C sources from libguestfs, trimmed to only what
virt-p2v needs.
---
Makefile.am | 1 +
libguestfs/README | 4 +
libguestfs/cleanups.c | 96 +++++++++++
libguestfs/cleanups.h | 74 +++++++++
libguestfs/guestfs-utils.c | 247 +++++++++++++++++++++++++++++
libguestfs/guestfs-utils.h | 85 ++++++++++
libguestfs/libxml2-cleanups.c | 94 +++++++++++
libguestfs/libxml2-writer-macros.h | 200 +++++++++++++++++++++++
8 files changed, 801 insertions(+)
create mode 100644 libguestfs/README
create mode 100644 libguestfs/cleanups.c
create mode 100644 libguestfs/cleanups.h
create mode 100644 libguestfs/guestfs-utils.c
create mode 100644 libguestfs/guestfs-utils.h
create mode 100644 libguestfs/libxml2-cleanups.c
create mode 100644 libguestfs/libxml2-writer-macros.h
diff --git a/Makefile.am b/Makefile.am
index 736b8fc..0d67dbf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,6 +38,7 @@ EXTRA_DIST = \
kiwi-config.sh \
kiwi-config.xml.in \
launch-virt-p2v \
+ libguestfs/README \
miniexpect/README \
p2v.ks.in \
p2v.service \
diff --git a/libguestfs/README b/libguestfs/README
new file mode 100644
index 0000000..fbf367b
--- /dev/null
+++ b/libguestfs/README
@@ -0,0 +1,4 @@
+This directory contains sources mostly copied from libguestfs.
+The sources were trimmed to contain only what is used by virt-p2v.
+
+Fixes ought to be sent also to libguestfs, to avoid diverging from libguestfs.
diff --git a/libguestfs/cleanups.c b/libguestfs/cleanups.c
new file mode 100644
index 0000000..dae75ee
--- /dev/null
+++ b/libguestfs/cleanups.c
@@ -0,0 +1,96 @@
+/* libguestfs
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * Libguestfs uses C<CLEANUP_*> macros to simplify temporary
+ * allocations. They are implemented using the
+ * C<__attribute__((cleanup))> feature of gcc and clang. Typical
+ * usage is:
+ *
+ * fn ()
+ * {
+ * CLEANUP_FREE char *str = NULL;
+ * str = safe_asprintf (g, "foo");
+ * // str is freed automatically when the function returns
+ * }
+ *
+ * There are a few catches to be aware of with the cleanup mechanism:
+ *
+ * =over 4
+ *
+ * =item *
+ *
+ * If a cleanup variable is not initialized, then you can end up
+ * calling L<free(3)> with an undefined value, resulting in the
+ * program crashing. For this reason, you should usually initialize
+ * every cleanup variable with something, eg. C<NULL>
+ *
+ * =item *
+ *
+ * Don't mark variables holding return values as cleanup variables.
+ *
+ * =item *
+ *
+ * The C<main()> function shouldn't use cleanup variables since it is
+ * normally exited by calling L<exit(3)>, and that doesn't call the
+ * cleanup handlers.
+ *
+ * =back
+ *
+ * The functions in this file are used internally by the C<CLEANUP_*>
+ * macros. Don't call them directly.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "guestfs-utils.h"
+
+/* Stdlib cleanups. */
+
+void
+guestfs_int_cleanup_free (void *ptr)
+{
+ free (* (void **) ptr);
+}
+
+void
+guestfs_int_cleanup_fclose (void *ptr)
+{
+ FILE *f = * (FILE **) ptr;
+
+ if (f)
+ fclose (f);
+}
+
+void
+guestfs_int_cleanup_pclose (void *ptr)
+{
+ FILE *f = * (FILE **) ptr;
+
+ if (f)
+ pclose (f);
+}
+
+void
+guestfs_int_cleanup_free_string_list (char ***ptr)
+{
+ guestfs_int_free_string_list (*ptr);
+}
diff --git a/libguestfs/cleanups.h b/libguestfs/cleanups.h
new file mode 100644
index 0000000..4defdef
--- /dev/null
+++ b/libguestfs/cleanups.h
@@ -0,0 +1,74 @@
+/* libguestfs
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef GUESTFS_CLEANUPS_H_
+#define GUESTFS_CLEANUPS_H_
+
+#ifdef HAVE_ATTRIBUTE_CLEANUP
+#define CLEANUP_FREE \
+ __attribute__((cleanup(guestfs_int_cleanup_free)))
+#define CLEANUP_FCLOSE \
+ __attribute__((cleanup(guestfs_int_cleanup_fclose)))
+#define CLEANUP_PCLOSE \
+ __attribute__((cleanup(guestfs_int_cleanup_pclose)))
+#define CLEANUP_FREE_STRING_LIST \
+ __attribute__((cleanup(guestfs_int_cleanup_free_string_list)))
+#define CLEANUP_XMLFREE \
+ __attribute__((cleanup(guestfs_int_cleanup_xmlFree)))
+#define CLEANUP_XMLBUFFERFREE \
+ __attribute__((cleanup(guestfs_int_cleanup_xmlBufferFree)))
+#define CLEANUP_XMLFREEDOC \
+ __attribute__((cleanup(guestfs_int_cleanup_xmlFreeDoc)))
+#define CLEANUP_XMLFREEURI \
+ __attribute__((cleanup(guestfs_int_cleanup_xmlFreeURI)))
+#define CLEANUP_XMLFREETEXTWRITER \
+ __attribute__((cleanup(guestfs_int_cleanup_xmlFreeTextWriter)))
+#define CLEANUP_XMLXPATHFREECONTEXT \
+ __attribute__((cleanup(guestfs_int_cleanup_xmlXPathFreeContext)))
+#define CLEANUP_XMLXPATHFREEOBJECT \
+ __attribute__((cleanup(guestfs_int_cleanup_xmlXPathFreeObject)))
+#else
+#define CLEANUP_FREE
+#define CLEANUP_FCLOSE
+#define CLEANUP_PCLOSE
+#define CLEANUP_FREE_STRING_LIST
+#define CLEANUP_XMLFREE
+#define CLEANUP_XMLBUFFERFREE
+#define CLEANUP_XMLFREEDOC
+#define CLEANUP_XMLFREEURI
+#define CLEANUP_XMLFREETEXTWRITER
+#define CLEANUP_XMLXPATHFREECONTEXT
+#define CLEANUP_XMLXPATHFREEOBJECT
+#endif
+
+/* These functions are used internally by the CLEANUP_* macros.
+ * Don't call them directly.
+ */
+extern void guestfs_int_cleanup_free (void *ptr);
+extern void guestfs_int_cleanup_fclose (void *ptr);
+extern void guestfs_int_cleanup_pclose (void *ptr);
+extern void guestfs_int_cleanup_free_string_list (char ***ptr);
+extern void guestfs_int_cleanup_xmlFree (void *ptr);
+extern void guestfs_int_cleanup_xmlBufferFree (void *ptr);
+extern void guestfs_int_cleanup_xmlFreeDoc (void *ptr);
+extern void guestfs_int_cleanup_xmlFreeURI (void *ptr);
+extern void guestfs_int_cleanup_xmlFreeTextWriter (void *ptr);
+extern void guestfs_int_cleanup_xmlXPathFreeContext (void *ptr);
+extern void guestfs_int_cleanup_xmlXPathFreeObject (void *ptr);
+
+#endif /* GUESTFS_CLEANUPS_H_ */
diff --git a/libguestfs/guestfs-utils.c b/libguestfs/guestfs-utils.c
new file mode 100644
index 0000000..505c9f6
--- /dev/null
+++ b/libguestfs/guestfs-utils.c
@@ -0,0 +1,247 @@
+/* libguestfs
+ * Copyright (C) 2009-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "guestfs-utils.h"
+
+void
+guestfs_int_free_string_list (char **argv)
+{
+ size_t i;
+
+ if (argv == NULL)
+ return;
+
+ for (i = 0; argv[i] != NULL; ++i)
+ free (argv[i]);
+ free (argv);
+}
+
+size_t
+guestfs_int_count_strings (char *const *argv)
+{
+ size_t r;
+
+ for (r = 0; argv[r]; ++r)
+ ;
+
+ return r;
+}
+
+char **
+guestfs_int_copy_string_list (char *const *argv)
+{
+ const size_t n = guestfs_int_count_strings (argv);
+ size_t i, j;
+ char **ret;
+
+ ret = malloc ((n+1) * sizeof (char *));
+ if (ret == NULL)
+ return NULL;
+ ret[n] = NULL;
+
+ for (i = 0; i < n; ++i) {
+ ret[i] = strdup (argv[i]);
+ if (ret[i] == NULL) {
+ for (j = 0; j < i; ++j)
+ free (ret[j]);
+ free (ret);
+ return NULL;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * Split string at separator character C<sep>, returning the list of
+ * strings. Returns C<NULL> on memory allocation failure.
+ *
+ * Note (assuming C<sep> is C<:>):
+ *
+ * =over 4
+ *
+ * =item C<str == NULL>
+ *
+ * aborts
+ *
+ * =item C<str == "">
+ *
+ * returns C<[]>
+ *
+ * =item C<str == "abc">
+ *
+ * returns C<["abc"]>
+ *
+ * =item C<str == ":">
+ *
+ * returns C<["", ""]>
+ *
+ * =back
+ */
+char **
+guestfs_int_split_string (char sep, const char *str)
+{
+ size_t i, n, c;
+ const size_t len = strlen (str);
+ char reject[2] = { sep, '\0' };
+ char **ret;
+
+ /* We have to handle the empty string case differently else the code
+ * below will return [""].
+ */
+ if (str[0] == '\0') {
+ ret = malloc (1 * sizeof (char *));
+ if (!ret)
+ return NULL;
+ ret[0] = NULL;
+ return ret;
+ }
+
+ for (n = i = 0; i < len; ++i)
+ if (str[i] == sep)
+ n++;
+
+ /* We always return a list of length 1 + (# separator characters).
+ * We also have to add a trailing NULL.
+ */
+ ret = malloc ((n+2) * sizeof (char *));
+ if (!ret)
+ return NULL;
+ ret[n+1] = NULL;
+
+ for (n = i = 0; i <= len; ++i, ++n) {
+ c = strcspn (&str[i], reject);
+ ret[n] = strndup (&str[i], c);
+ if (ret[n] == NULL) {
+ for (i = 0; i < n; ++i)
+ free (ret[i]);
+ free (ret);
+ return NULL;
+ }
+ i += c;
+ if (str[i] == '\0') /* end of string? */
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * Return a random string of characters.
+ *
+ * Notes:
+ *
+ * =over 4
+ *
+ * =item *
+ *
+ * The C<ret> buffer must have length C<len+1> in order to store the
+ * final C<\0> character.
+ *
+ * =item *
+ *
+ * There is about 5 bits of randomness per output character (so about
+ * C<5*len> bits of randomness in the resulting string).
+ *
+ * =back
+ */
+int
+guestfs_int_random_string (char *ret, size_t len)
+{
+ int fd;
+ size_t i;
+ unsigned char c;
+ int saved_errno;
+
+ fd = open ("/dev/urandom", O_RDONLY|O_CLOEXEC);
+ if (fd == -1)
+ return -1;
+
+ for (i = 0; i < len; ++i) {
+ if (read (fd, &c, 1) != 1) {
+ saved_errno = errno;
+ close (fd);
+ errno = saved_errno;
+ return -1;
+ }
+ /* Do not change this! */
+ ret[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[c % 36];
+ }
+ ret[len] = '\0';
+
+ if (close (fd) == -1)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * This turns a drive index (eg. C<27>) into a drive name
+ * (eg. C<"ab">).
+ *
+ * Drive indexes count from C<0>. The return buffer has to be large
+ * enough for the resulting string, and the returned pointer points to
+ * the *end* of the string.
+ *
+ *
L<https://rwmj.wordpress.com/2011/01/09/how-are-linux-drives-named-bey...
+ */
+char *
+guestfs_int_drive_name (size_t index, char *ret)
+{
+ if (index >= 26)
+ ret = guestfs_int_drive_name (index/26 - 1, ret);
+ index %= 26;
+ *ret++ = 'a' + index;
+ *ret = '\0';
+ return ret;
+}
+
+/**
+ * Similar to C<Tcl_GetBoolean>.
+ */
+int
+guestfs_int_is_true (const char *str)
+{
+ if (STREQ (str, "1") ||
+ STRCASEEQ (str, "true") ||
+ STRCASEEQ (str, "t") ||
+ STRCASEEQ (str, "yes") ||
+ STRCASEEQ (str, "y") ||
+ STRCASEEQ (str, "on"))
+ return 1;
+
+ if (STREQ (str, "0") ||
+ STRCASEEQ (str, "false") ||
+ STRCASEEQ (str, "f") ||
+ STRCASEEQ (str, "no") ||
+ STRCASEEQ (str, "n") ||
+ STRCASEEQ (str, "off"))
+ return 0;
+
+ return -1;
+}
diff --git a/libguestfs/guestfs-utils.h b/libguestfs/guestfs-utils.h
new file mode 100644
index 0000000..d5557a4
--- /dev/null
+++ b/libguestfs/guestfs-utils.h
@@ -0,0 +1,85 @@
+/* libguestfs
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef GUESTFS_UTILS_H_
+#define GUESTFS_UTILS_H_
+
+#include <string.h>
+
+#include "cleanups.h"
+
+#define _(str) dgettext(PACKAGE, (str))
+
+#define STREQ(a,b) (strcmp((a),(b)) == 0)
+#define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0)
+#define STRNEQ(a,b) (strcmp((a),(b)) != 0)
+#define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0)
+
+/* A simple (indeed, simplistic) way to build up short lists of
+ * arguments. Your code must define MAX_ARGS to a suitable "larger
+ * than could ever be needed" value. (If the value is exceeded then
+ * your code will abort). For more complex needs, use something else
+ * more suitable.
+ */
+#define ADD_ARG(argv,i,v) \
+ do { \
+ if ((i) >= MAX_ARGS) { \
+ fprintf (stderr, "%s: %d: internal error: exceeded MAX_ARGS (%zu) when
constructing the command line\n", __FILE__, __LINE__, (size_t) MAX_ARGS); \
+ abort (); \
+ } \
+ (argv)[(i)++] = (v); \
+ } while (0)
+
+extern void guestfs_int_free_string_list (char **);
+extern size_t guestfs_int_count_strings (char *const *);
+extern char **guestfs_int_copy_string_list (char *const *);
+extern char **guestfs_int_split_string (char sep, const char *);
+extern int guestfs_int_random_string (char *ret, size_t len);
+extern char *guestfs_int_drive_name (size_t index, char *ret);
+extern int guestfs_int_is_true (const char *str);
+
+/* ANSI colours. These are defined as macros so that we don't have to
+ * define the force_colour global variable in the library.
+ */
+#define ansi_green(fp) \
+ do { \
+ if (force_colour || isatty (fileno (fp))) \
+ fputs ("\033[0;32m", (fp)); \
+ } while (0)
+#define ansi_red(fp) \
+ do { \
+ if (force_colour || isatty (fileno (fp))) \
+ fputs ("\033[1;31m", (fp)); \
+ } while (0)
+#define ansi_blue(fp) \
+ do { \
+ if (force_colour || isatty (fileno (fp))) \
+ fputs ("\033[1;34m", (fp)); \
+ } while (0)
+#define ansi_magenta(fp) \
+ do { \
+ if (force_colour || isatty (fileno (fp))) \
+ fputs ("\033[1;35m", (fp)); \
+ } while (0)
+#define ansi_restore(fp) \
+ do { \
+ if (force_colour || isatty (fileno (fp))) \
+ fputs ("\033[0m", (fp)); \
+ } while (0)
+
+#endif /* GUESTFS_UTILS_H_ */
diff --git a/libguestfs/libxml2-cleanups.c b/libguestfs/libxml2-cleanups.c
new file mode 100644
index 0000000..829c620
--- /dev/null
+++ b/libguestfs/libxml2-cleanups.c
@@ -0,0 +1,94 @@
+/* libguestfs
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <libxml/uri.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xmlwriter.h>
+
+#include "cleanups.h"
+
+void
+guestfs_int_cleanup_xmlFree (void *ptr)
+{
+ xmlChar *buf = * (xmlChar **) ptr;
+
+ if (buf)
+ xmlFree (buf);
+}
+
+void
+guestfs_int_cleanup_xmlBufferFree (void *ptr)
+{
+ xmlBufferPtr xb = * (xmlBufferPtr *) ptr;
+
+ if (xb)
+ xmlBufferFree (xb);
+}
+
+void
+guestfs_int_cleanup_xmlFreeDoc (void *ptr)
+{
+ xmlDocPtr doc = * (xmlDocPtr *) ptr;
+
+ if (doc)
+ xmlFreeDoc (doc);
+}
+
+void
+guestfs_int_cleanup_xmlFreeURI (void *ptr)
+{
+ xmlURIPtr uri = * (xmlURIPtr *) ptr;
+
+ if (uri)
+ xmlFreeURI (uri);
+}
+
+void
+guestfs_int_cleanup_xmlFreeTextWriter (void *ptr)
+{
+ xmlTextWriterPtr xo = * (xmlTextWriterPtr *) ptr;
+
+ if (xo)
+ xmlFreeTextWriter (xo);
+}
+
+void
+guestfs_int_cleanup_xmlXPathFreeContext (void *ptr)
+{
+ xmlXPathContextPtr ctx = * (xmlXPathContextPtr *) ptr;
+
+ if (ctx)
+ xmlXPathFreeContext (ctx);
+}
+
+void
+guestfs_int_cleanup_xmlXPathFreeObject (void *ptr)
+{
+ xmlXPathObjectPtr obj = * (xmlXPathObjectPtr *) ptr;
+
+ if (obj)
+ xmlXPathFreeObject (obj);
+}
diff --git a/libguestfs/libxml2-writer-macros.h b/libguestfs/libxml2-writer-macros.h
new file mode 100644
index 0000000..66a7a8f
--- /dev/null
+++ b/libguestfs/libxml2-writer-macros.h
@@ -0,0 +1,200 @@
+/* libguestfs
+ * Copyright (C) 2009-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * These macros make it easier to write XML. To use them correctly
+ * you must be aware of these assumptions:
+ *
+ * =over 4
+ *
+ * =item *
+ *
+ * The C<xmlTextWriterPtr> is called C<xo>. It is used implicitly
+ * by all the macros.
+ *
+ * =item *
+ *
+ * On failure, a function called C<xml_error> is called which you must
+ * define (usually as a macro). You must use C<CLEANUP_*> macros in
+ * your functions if you want correct cleanup of local variables along
+ * the error path.
+ *
+ * =item *
+ *
+ * All the "bad" casting is hidden inside the macros.
+ *
+ * =back
+ */
+
+#ifndef GUESTFS_LIBXML2_WRITER_MACROS_H_
+#define GUESTFS_LIBXML2_WRITER_MACROS_H_
+
+#include <stdarg.h>
+
+/**
+ * To define an XML element use:
+ *
+ * start_element ("name") {
+ * ...
+ * } end_element ();
+ *
+ * which produces C<<< <name>...</name> >>>
+ */
+#define start_element(element) \
+ if (xmlTextWriterStartElement (xo, BAD_CAST (element)) == -1) { \
+ xml_error ("xmlTextWriterStartElement"); \
+ } \
+ do
+
+#define end_element() \
+ while (0); \
+ do { \
+ if (xmlTextWriterEndElement (xo) == -1) { \
+ xml_error ("xmlTextWriterEndElement"); \
+ } \
+ } while (0)
+
+/**
+ * To define an empty element:
+ *
+ * empty_element ("name");
+ *
+ * which produces C<<< <name/> >>>
+ */
+#define empty_element(element) \
+ do { start_element ((element)) {} end_element (); } while (0)
+
+/**
+ * To define a single element with no attributes containing some text:
+ *
+ * single_element ("name", text);
+ *
+ * which produces C<<< <name>text</name> >>>
+ */
+#define single_element(element,str) \
+ do { \
+ start_element ((element)) { \
+ string ((str)); \
+ } end_element (); \
+ } while (0)
+
+/**
+ * To define a single element with no attributes containing some text
+ * using a format string:
+ *
+ * single_element_format ("cores", "%d", nr_cores);
+ *
+ * which produces C<<< <cores>4</cores> >>>
+ */
+#define single_element_format(element,fs,...) \
+ do { \
+ start_element ((element)) { \
+ string_format ((fs), ##__VA_ARGS__); \
+ } end_element (); \
+ } while (0)
+
+/**
+ * To define an XML element with attributes, use:
+ *
+ * start_element ("name") {
+ * attribute ("foo", "bar");
+ * attribute_format ("count", "%d", count);
+ * ...
+ * } end_element ();
+ *
+ * which produces C<<< <name foo="bar"
count="123">...</name> >>>
+ */
+#define attribute(key,value) \
+ do { \
+ if (xmlTextWriterWriteAttribute (xo, BAD_CAST (key), \
+ BAD_CAST (value)) == -1) { \
+ xml_error ("xmlTextWriterWriteAttribute"); \
+ } \
+ } while (0)
+
+#define attribute_format(key,fs,...) \
+ do { \
+ if (xmlTextWriterWriteFormatAttribute (xo, BAD_CAST (key), \
+ fs, ##__VA_ARGS__) == -1) { \
+ xml_error ("xmlTextWriterWriteFormatAttribute"); \
+ } \
+ } while (0)
+
+/**
+ * C<attribute_ns (prefix, key, namespace_uri, value)> defines a
+ * namespaced attribute.
+ */
+#define attribute_ns(prefix,key,namespace_uri,value) \
+ do { \
+ if (xmlTextWriterWriteAttributeNS (xo, BAD_CAST (prefix), \
+ BAD_CAST (key), \
+ BAD_CAST (namespace_uri), \
+ BAD_CAST (value)) == -1) { \
+ xml_error ("xmlTextWriterWriteAttribute"); \
+ } \
+ } while (0)
+
+/**
+ * To define a verbatim string, use:
+ *
+ * string ("hello");
+ */
+#define string(str) \
+ do { \
+ if (xmlTextWriterWriteString (xo, BAD_CAST(str)) == -1) { \
+ xml_error ("xmlTextWriterWriteString"); \
+ } \
+ } while (0)
+
+/**
+ * To define a verbatim string using a format string, use:
+ *
+ * string ("%s, world", greeting);
+ */
+#define string_format(fs,...) \
+ do { \
+ if (xmlTextWriterWriteFormatString (xo, fs, ##__VA_ARGS__) == -1) { \
+ xml_error ("xmlTextWriterWriteFormatString"); \
+ } \
+ } while (0)
+
+/**
+ * To write a string encoded as base64:
+ *
+ * base64 (data, size);
+ */
+#define base64(data, size) \
+ do { \
+ if (xmlTextWriterWriteBase64 (xo, (data), 0, (size)) == -1) { \
+ xml_error ("xmlTextWriterWriteBase64"); \
+ } \
+ } while (0)
+
+/**
+ * To define a comment in the XML, use:
+ *
+ * comment ("number of items = %d", nr_items);
+ */
+#define comment(fs,...) \
+ do { \
+ if (xmlTextWriterWriteFormatComment (xo, fs, ##__VA_ARGS__) == -1) { \
+ xml_error ("xmlTextWriterWriteFormatComment"); \
+ } \
+ } while (0)
+
+#endif /* GUESTFS_LIBXML2_WRITER_MACROS_H_ */
--
2.21.0