[Libguestfs] [PATCH v2 2/4] common/utils: Move libxml2 writer macros to a common header file.

Richard W.M. Jones rjones at redhat.com
Thu Oct 4 12:03:48 UTC 2018


In some places when generating XML output in C code we use some clever
macros:

  start_element ("memory") {
    attribute ("unit", "MiB");
    string ("%d", g->memsize);
  } end_element ();

This commit which is mostly refactoring moves the repeated definitions
of these macros into a common header file.

I also took this opportunity to change / clean up the macros:

 - The macros are now documented properly.

 - comment() and empty_element() macros are now available everywhere.

 - Error handling has been made generic.

 - Added do..while(0) around some of the macros to make them safe to
   use in all contexts.

 - Both string() and attribute() take a format string (previously
   there were string_format() and attribute_format() variants).

The last point causes the most churn since we must change the callers
to avoid format string security bugs.
---
 common/utils/Makefile.am             |   1 +
 common/utils/libxml2-writer-macros.h | 143 +++++++++++++++++++++++
 docs/C_SOURCE_FILES                  |   1 +
 lib/launch-libvirt.c                 | 169 +++++++++------------------
 p2v/physical-xml.c                   |  99 +++++-----------
 5 files changed, 225 insertions(+), 188 deletions(-)

diff --git a/common/utils/Makefile.am b/common/utils/Makefile.am
index 1fa98f992..4ff9efcbd 100644
--- a/common/utils/Makefile.am
+++ b/common/utils/Makefile.am
@@ -28,6 +28,7 @@ libutils_la_SOURCES = \
 	libxml2-cleanups.c \
 	libxml2-utils.c \
 	libxml2-utils.h \
+	libxml2-writer-macros.h \
 	utils.c
 libutils_la_CPPFLAGS = \
 	-DGUESTFS_WARN_DEPRECATED=1 \
diff --git a/common/utils/libxml2-writer-macros.h b/common/utils/libxml2-writer-macros.h
new file mode 100644
index 000000000..b5705645a
--- /dev/null
+++ b/common/utils/libxml2-writer-macros.h
@@ -0,0 +1,143 @@
+/* libguestfs
+ * Copyright (C) 2009-2018 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 an XML element with attributes, use:
+ *
+ *  start_element ("name") {
+ *    attribute ("foo", "bar");
+ *    attribute ("count", "%d", count);
+ *    ...
+ *  } end_element ();
+ *
+ * which produces C<<< <name foo="bar" count="123">...</name> >>>
+ */
+#define attribute(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");
+ *
+ * or:
+ *
+ *  string ("%s, world", greeting);
+ */
+#define string(fs,...)                                                  \
+  do {                                                                  \
+    if (xmlTextWriterWriteFormatString (xo, fs, ##__VA_ARGS__) == -1) { \
+      xml_error ("xmlTextWriterWriteFormatString");                     \
+    }                                                                   \
+  } 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_ */
diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES
index 1c262973c..7f1c60b30 100644
--- a/docs/C_SOURCE_FILES
+++ b/docs/C_SOURCE_FILES
@@ -62,6 +62,7 @@ common/utils/cleanups.h
 common/utils/gnulib-cleanups.c
 common/utils/guestfs-utils.h
 common/utils/libxml2-cleanups.c
+common/utils/libxml2-writer-macros.h
 common/utils/utils.c
 common/visit/visit.c
 common/visit/visit.h
diff --git a/lib/launch-libvirt.c b/lib/launch-libvirt.c
index 1a074fd6c..7b4b9f752 100644
--- a/lib/launch-libvirt.c
+++ b/lib/launch-libvirt.c
@@ -52,6 +52,16 @@
 #include "guestfs-internal.h"
 #include "guestfs_protocol.h"
 
+#include "libxml2-writer-macros.h"
+
+/* This macro is used by the macros in "libxml2-writer-macros.h"
+ * when an error occurs.
+ */
+#define xml_error(fn)                                                   \
+  perrorf (g, _("%s:%d: error constructing libvirt XML near call to \"%s\""), \
+	   __FILE__, __LINE__, (fn));                                   \
+  return -1;
+
 /* Fixes for Mac OS X */
 #ifndef SOCK_CLOEXEC
 # define SOCK_CLOEXEC O_CLOEXEC
@@ -909,79 +919,6 @@ static int construct_libvirt_xml_disk_source_hosts (guestfs_h *g, xmlTextWriterP
 static int construct_libvirt_xml_disk_source_seclabel (guestfs_h *g, const struct backend_libvirt_data *data, xmlTextWriterPtr xo);
 static int construct_libvirt_xml_appliance (guestfs_h *g, const struct libvirt_xml_params *params, xmlTextWriterPtr xo);
 
-/* These macros make it easier to write XML, but they also make a lot
- * of assumptions:
- *
- * - The xmlTextWriterPtr is called 'xo'.  It is used implicitly.
- *
- * - The guestfs handle is called 'g'.  It is used implicitly for errors.
- *
- * - It is safe to 'return -1' on failure.  This is OK provided you
- *   always use CLEANUP_* macros.
- *
- * - All the "bad" casting is hidden inside the macros.
- */
-
-/* <element */
-#define start_element(element)						\
-  if (xmlTextWriterStartElement (xo, BAD_CAST (element)) == -1) {	\
-    xml_error ("xmlTextWriterStartElement");				\
-    return -1;								\
-  }									\
-  do
-
-/* finish current </element> */
-#define end_element()				\
-  while (0);					\
-  do {						\
-    if (xmlTextWriterEndElement (xo) == -1) {	\
-      xml_error ("xmlTextWriterEndElement");	\
-      return -1;				\
-    }						\
-  } while (0)
-
-/* key=value attribute of the current element. */
-#define attribute(key,value)                                            \
-  if (xmlTextWriterWriteAttribute (xo, BAD_CAST (key), BAD_CAST (value)) == -1){ \
-    xml_error ("xmlTextWriterWriteAttribute");                          \
-    return -1;                                                          \
-  }
-
-/* key=value, but value is a printf-style format string. */
-#define attribute_format(key,fs,...)                                    \
-  if (xmlTextWriterWriteFormatAttribute (xo, BAD_CAST (key),            \
-                                         fs, ##__VA_ARGS__) == -1) {    \
-    xml_error ("xmlTextWriterWriteFormatAttribute");                    \
-    return -1;                                                          \
-  }
-
-/* attribute with namespace. */
-#define attribute_ns(prefix,key,namespace_uri,value)                    \
-  if (xmlTextWriterWriteAttributeNS (xo, BAD_CAST (prefix),             \
-                                     BAD_CAST (key), BAD_CAST (namespace_uri), \
-                                     BAD_CAST (value)) == -1) {         \
-    xml_error ("xmlTextWriterWriteAttribute");                          \
-    return -1;                                                          \
-  }
-
-/* A string, eg. within an element. */
-#define string(str)						\
-  if (xmlTextWriterWriteString (xo, BAD_CAST (str)) == -1) {	\
-    xml_error ("xmlTextWriterWriteString");			\
-    return -1;							\
-  }
-
-/* A string, using printf-style formatting. */
-#define string_format(fs,...)                                           \
-  if (xmlTextWriterWriteFormatString (xo, fs, ##__VA_ARGS__) == -1) {   \
-    xml_error ("xmlTextWriterWriteFormatString");                       \
-    return -1;                                                          \
-  }
-
-#define xml_error(fn)                                                   \
-  perrorf (g, _("%s:%d: error constructing libvirt XML near call to \"%s\""), \
-	   __FILE__, __LINE__, (fn));
-
 static xmlChar *
 construct_libvirt_xml (guestfs_h *g, const struct libvirt_xml_params *params)
 {
@@ -1040,7 +977,7 @@ construct_libvirt_xml_domain (guestfs_h *g,
                               xmlTextWriterPtr xo)
 {
   start_element ("domain") {
-    attribute ("type", params->data->is_kvm ? "kvm" : "qemu");
+    attribute ("type", "%s", params->data->is_kvm ? "kvm" : "qemu");
     attribute_ns ("xmlns", "qemu", NULL,
                   "http://libvirt.org/schemas/domain/qemu/1.0");
 
@@ -1070,7 +1007,7 @@ construct_libvirt_xml_name (guestfs_h *g,
                             xmlTextWriterPtr xo)
 {
   start_element ("name") {
-    string (params->data->name);
+    string ("%s", params->data->name);
   } end_element ();
 
   return 0;
@@ -1086,12 +1023,12 @@ construct_libvirt_xml_cpu (guestfs_h *g,
 
   start_element ("memory") {
     attribute ("unit", "MiB");
-    string_format ("%d", g->memsize);
+    string ("%d", g->memsize);
   } end_element ();
 
   start_element ("currentMemory") {
     attribute ("unit", "MiB");
-    string_format ("%d", g->memsize);
+    string ("%d", g->memsize);
   } end_element ();
 
   cpu_model = guestfs_int_get_cpu_model (params->data->is_kvm);
@@ -1105,14 +1042,14 @@ construct_libvirt_xml_cpu (guestfs_h *g,
       }
       else {
         start_element ("model") {
-          string (cpu_model);
+          string ("%s", cpu_model);
         } end_element ();
       }
     } end_element ();
   }
 
   start_element ("vcpu") {
-    string_format ("%d", g->smp);
+    string ("%d", g->smp);
   } end_element ();
 
   start_element ("clock") {
@@ -1162,7 +1099,7 @@ construct_libvirt_xml_boot (guestfs_h *g,
   start_element ("os") {
     start_element ("type") {
 #ifdef MACHINE_TYPE
-      attribute ("machine", MACHINE_TYPE);
+      attribute ("machine", "%s", MACHINE_TYPE);
 #endif
       string ("hvm");
     } end_element ();
@@ -1171,12 +1108,12 @@ construct_libvirt_xml_boot (guestfs_h *g,
       start_element ("loader") {
 	attribute ("readonly", "yes");
 	attribute ("type", "pflash");
-	string (params->data->uefi_code);
+	string ("%s", params->data->uefi_code);
       } end_element ();
 
       if (params->data->uefi_vars) {
 	start_element ("nvram") {
-	  string (params->data->uefi_vars);
+	  string ("%s", params->data->uefi_vars);
 	} end_element ();
       }
     }
@@ -1192,15 +1129,15 @@ construct_libvirt_xml_boot (guestfs_h *g,
 #endif
 
     start_element ("kernel") {
-      string (params->kernel);
+      string ("%s", params->kernel);
     } end_element ();
 
     start_element ("initrd") {
-      string (params->initrd);
+      string ("%s", params->initrd);
     } end_element ();
 
     start_element ("cmdline") {
-      string (cmdline);
+      string ("%s", cmdline);
     } end_element ();
 
 #if defined(__i386__) || defined(__x86_64__)
@@ -1252,10 +1189,10 @@ construct_libvirt_xml_seclabel (guestfs_h *g,
       attribute ("model", "selinux");
       attribute ("relabel", "yes");
       start_element ("label") {
-        string (params->data->selinux_label);
+        string ("%s", params->data->selinux_label);
       } end_element ();
       start_element ("imagelabel") {
-        string (params->data->selinux_imagelabel);
+        string ("%s", params->data->selinux_imagelabel);
       } end_element ();
     } end_element ();
   }
@@ -1292,7 +1229,7 @@ construct_libvirt_xml_devices (guestfs_h *g,
      */
     if (is_custom_hv (g)) {
       start_element ("emulator") {
-        string (g->hv);
+        string ("%s", g->hv);
       } end_element ();
     }
 #if defined(__arm__)
@@ -1301,7 +1238,7 @@ construct_libvirt_xml_devices (guestfs_h *g,
      */
     else {
       start_element ("emulator") {
-        string (QEMU);
+        string ("%s", QEMU);
       } end_element ();
     }
 #endif
@@ -1345,7 +1282,7 @@ construct_libvirt_xml_devices (guestfs_h *g,
       attribute ("type", "unix");
       start_element ("source") {
         attribute ("mode", "connect");
-        attribute ("path", params->data->console_path);
+        attribute ("path", "%s", params->data->console_path);
       } end_element ();
       start_element ("target") {
         attribute ("port", "0");
@@ -1359,7 +1296,7 @@ construct_libvirt_xml_devices (guestfs_h *g,
       attribute ("type", "unix");
       start_element ("source") {
         attribute ("mode", "connect");
-        attribute ("path", params->data->console_path);
+        attribute ("path", "%s", params->data->console_path);
       } end_element ();
       start_element ("target") {
 	attribute ("type", "sclp");
@@ -1373,7 +1310,7 @@ construct_libvirt_xml_devices (guestfs_h *g,
       attribute ("type", "unix");
       start_element ("source") {
         attribute ("mode", "connect");
-        attribute ("path", params->data->guestfsd_path);
+        attribute ("path", "%s", params->data->guestfsd_path);
       } end_element ();
       start_element ("target") {
         attribute ("type", "virtio");
@@ -1386,7 +1323,7 @@ construct_libvirt_xml_devices (guestfs_h *g,
       start_element ("interface") {
         attribute ("type", "bridge");
         start_element ("source") {
-          attribute ("bridge", params->data->network_bridge);
+          attribute ("bridge", "%s", params->data->network_bridge);
         } end_element ();
         start_element ("model") {
           attribute ("type", "virtio");
@@ -1440,7 +1377,7 @@ construct_libvirt_xml_disk (guestfs_h *g,
       attribute ("type", "file");
 
       start_element ("source") {
-        attribute ("file", drv->overlay);
+        attribute ("file", "%s", drv->overlay);
         if (construct_libvirt_xml_disk_source_seclabel (g, data, xo) == -1)
           return -1;
       } end_element ();
@@ -1480,7 +1417,7 @@ construct_libvirt_xml_disk (guestfs_h *g,
           attribute ("type", "file");
 
           start_element ("source") {
-            attribute ("file", path);
+            attribute ("file", "%s", path);
             if (construct_libvirt_xml_disk_source_seclabel (g, data, xo) == -1)
               return -1;
           } end_element ();
@@ -1489,7 +1426,7 @@ construct_libvirt_xml_disk (guestfs_h *g,
           attribute ("type", "block");
 
           start_element ("source") {
-            attribute ("dev", drv->src.u.path);
+            attribute ("dev", "%s", drv->src.u.path);
             if (construct_libvirt_xml_disk_source_seclabel (g, data, xo) == -1)
               return -1;
           } end_element ();
@@ -1521,9 +1458,9 @@ construct_libvirt_xml_disk (guestfs_h *g,
         attribute ("type", "network");
 
         start_element ("source") {
-          attribute ("protocol", protocol_str);
+          attribute ("protocol", "%s", protocol_str);
           if (STRNEQ (drv->src.u.exportname, ""))
-            attribute ("name", drv->src.u.exportname);
+            attribute ("name", "%s", drv->src.u.exportname);
           if (construct_libvirt_xml_disk_source_hosts (g, xo,
                                                        &drv->src) == -1)
             return -1;
@@ -1533,14 +1470,14 @@ construct_libvirt_xml_disk (guestfs_h *g,
 
         if (drv->src.username != NULL) {
           start_element ("auth") {
-            attribute ("username", drv->src.username);
+            attribute ("username", "%s", drv->src.username);
             r = find_secret (g, data, drv, &type, &uuid);
             if (r == -1)
               return -1;
             if (r == 1) {
               start_element ("secret") {
-                attribute ("type", type);
-                attribute ("uuid", uuid);
+                attribute ("type", "%s", type);
+                attribute ("uuid", "%s", uuid);
               } end_element ();
             }
           } end_element ();
@@ -1576,7 +1513,7 @@ construct_libvirt_xml_disk (guestfs_h *g,
 
     if (drv->disk_label) {
       start_element ("serial") {
-        string (drv->disk_label);
+        string ("%s", drv->disk_label);
       } end_element ();
     }
 
@@ -1597,7 +1534,7 @@ construct_libvirt_xml_disk_target (guestfs_h *g, xmlTextWriterPtr xo,
   guestfs_int_drive_name (drv_index, &drive_name[2]);
 
   start_element ("target") {
-    attribute ("dev", drive_name);
+    attribute ("dev", "%s", drive_name);
     attribute ("bus", "scsi");
   } end_element ();
 
@@ -1642,8 +1579,8 @@ construct_libvirt_xml_disk_driver_qemu (guestfs_h *g,
 
   start_element ("driver") {
     attribute ("name", "qemu");
-    attribute ("type", format);
-    attribute ("cache", cachemode);
+    attribute ("type", "%s", format);
+    attribute ("cache", "%s", cachemode);
     if (discard_unmap)
       attribute ("discard", "unmap");
     if (copyonread)
@@ -1679,7 +1616,7 @@ construct_libvirt_xml_disk_address (guestfs_h *g, xmlTextWriterPtr xo,
      * virtio-scsi driver, this is the ".id" field).  This is a number
      * in the range 0-255.
      */
-    attribute_format ("target", "%zu", drv_index);
+    attribute ("target", "%zu", drv_index);
 
     /* libvirt "unit" == qemu "lun".  This is the SCSI logical unit
      * number, which is a number in the range 0..16383.
@@ -1702,9 +1639,9 @@ construct_libvirt_xml_disk_source_hosts (guestfs_h *g,
       switch (src->servers[i].transport) {
       case drive_transport_none:
       case drive_transport_tcp: {
-        attribute ("name", src->servers[i].u.hostname);
+        attribute ("name", "%s", src->servers[i].u.hostname);
         if (src->servers[i].port > 0)
-          attribute_format ("port", "%d", src->servers[i].port);
+          attribute ("port", "%d", src->servers[i].port);
         break;
       }
 
@@ -1722,7 +1659,7 @@ construct_libvirt_xml_disk_source_hosts (guestfs_h *g,
         }
 
         attribute ("transport", "unix");
-        attribute ("socket", abs_socket);
+        attribute ("socket", "%s", abs_socket);
         break;
       }
       }
@@ -1758,11 +1695,11 @@ construct_libvirt_xml_appliance (guestfs_h *g,
     attribute ("device", "disk");
 
     start_element ("source") {
-      attribute ("file", params->appliance_overlay);
+      attribute ("file", "%s", params->appliance_overlay);
     } end_element ();
 
     start_element ("target") {
-      attribute ("dev", &params->appliance_dev[5]);
+      attribute ("dev", "%s", &params->appliance_dev[5]);
       attribute ("bus", "scsi");
     } end_element ();
 
@@ -1798,18 +1735,18 @@ construct_libvirt_xml_qemu_cmdline (guestfs_h *g,
 
     start_element ("qemu:env") {
       attribute ("name", "TMPDIR");
-      attribute ("value", tmpdir);
+      attribute ("value", "%s", tmpdir);
     } end_element ();
 
     /* The qemu command line arguments requested by the caller. */
     for (hp = g->hv_params; hp; hp = hp->next) {
       start_element ("qemu:arg") {
-        attribute ("value", hp->hv_param);
+        attribute ("value", "%s", hp->hv_param);
       } end_element ();
 
       if (hp->hv_value) {
         start_element ("qemu:arg") {
-          attribute ("value", hp->hv_value);
+          attribute ("value", "%s", hp->hv_value);
         } end_element ();
       }
     }
@@ -1828,8 +1765,8 @@ construct_libvirt_xml_secret (guestfs_h *g,
     attribute ("ephemeral", "yes");
     attribute ("private", "yes");
     start_element ("description") {
-      string_format ("guestfs secret associated with %s %s",
-                     data->name, drv->src.u.path);
+      string ("guestfs secret associated with %s %s",
+              data->name, drv->src.u.path);
     } end_element ();
   } end_element ();
 
diff --git a/p2v/physical-xml.c b/p2v/physical-xml.c
index f65a514d5..6ac8cc991 100644
--- a/p2v/physical-xml.c
+++ b/p2v/physical-xml.c
@@ -39,65 +39,20 @@
 
 #include "getprogname.h"
 
+#include "libxml2-writer-macros.h"
+
 #include "p2v.h"
 
+/* This macro is used by the macros in "libxml2-writer-macros.h"
+ * when an error occurs.
+ */
+#define xml_error(fn)                                           \
+  error (EXIT_FAILURE, errno,                                   \
+         "%s:%d: error constructing XML near call to \"%s\"",   \
+         __FILE__, __LINE__, (fn));
+
 static const char *map_interface_to_network (struct config *, const char *interface);
 
-/* Macros "inspired" by lib/launch-libvirt.c */
-/* <element */
-#define start_element(element)						\
-  if (xmlTextWriterStartElement (xo, BAD_CAST (element)) == -1)         \
-    error (EXIT_FAILURE, errno, "xmlTextWriterStartElement");		\
-  do
-
-/* finish current </element> */
-#define end_element()						\
-  while (0);							\
-  do {								\
-    if (xmlTextWriterEndElement (xo) == -1)			\
-      error (EXIT_FAILURE, errno, "xmlTextWriterEndElement");	\
-  } while (0)
-
-/* <element/> */
-#define empty_element(element)					\
-  do { start_element(element) {} end_element (); } while (0)
-
-/* key=value attribute of the current element. */
-#define attribute(key,value)                                            \
-  do {                                                                  \
-    if (xmlTextWriterWriteAttribute (xo, BAD_CAST (key), BAD_CAST (value)) == -1) \
-    error (EXIT_FAILURE, errno, "xmlTextWriterWriteAttribute");         \
-  } while (0)
-
-/* key=value, but value is a printf-style format string. */
-#define attribute_format(key,fs,...)                                    \
-  do {                                                                  \
-    if (xmlTextWriterWriteFormatAttribute (xo, BAD_CAST (key),          \
-                                           fs, ##__VA_ARGS__) == -1)	\
-      error (EXIT_FAILURE, errno, "xmlTextWriterWriteFormatAttribute"); \
-  } while (0)
-
-/* A string, eg. within an element. */
-#define string(str)                                             \
-  do {                                                          \
-    if (xmlTextWriterWriteString (xo, BAD_CAST (str)) == -1)	\
-      error (EXIT_FAILURE, errno, "xmlTextWriterWriteString");	\
-  } while (0)
-
-/* A string, using printf-style formatting. */
-#define string_format(fs,...)                                           \
-  do {                                                                  \
-    if (xmlTextWriterWriteFormatString (xo, fs, ##__VA_ARGS__) == -1)   \
-      error (EXIT_FAILURE, errno, "xmlTextWriterWriteFormatString");    \
-  } while (0)
-
-/* An XML comment. */
-#define comment(fs,...)                                                 \
-  do {                                                                  \
-    if (xmlTextWriterWriteFormatComment (xo, fs, ##__VA_ARGS__) == -1)	\
-      error (EXIT_FAILURE, errno, "xmlTextWriterWriteFormatComment");   \
-  } while (0)
-
 /**
  * Write the libvirt XML for this physical machine.
  *
@@ -143,21 +98,21 @@ generate_physical_xml (struct config *config, struct data_conn *data_conns,
     attribute ("type", "physical");
 
     start_element ("name") {
-      string (config->guestname);
+      string ("%s", config->guestname);
     } end_element ();
 
     start_element ("memory") {
       attribute ("unit", "KiB");
-      string_format ("%" PRIu64, memkb);
+      string ("%" PRIu64, memkb);
     } end_element ();
 
     start_element ("currentMemory") {
       attribute ("unit", "KiB");
-      string_format ("%" PRIu64, memkb);
+      string ("%" PRIu64, memkb);
     } end_element ();
 
     start_element ("vcpu") {
-      string_format ("%d", config->vcpus);
+      string ("%d", config->vcpus);
     } end_element ();
 
     if (config->cpu.vendor || config->cpu.model ||
@@ -167,23 +122,23 @@ generate_physical_xml (struct config *config, struct data_conn *data_conns,
         attribute ("match", "minimum");
         if (config->cpu.vendor) {
           start_element ("vendor") {
-            string (config->cpu.vendor);
+            string ("%s", config->cpu.vendor);
           } end_element ();
         }
         if (config->cpu.model) {
           start_element ("model") {
             attribute ("fallback", "allow");
-            string (config->cpu.model);
+            string ("%s", config->cpu.model);
           } end_element ();
         }
         if (config->cpu.sockets || config->cpu.cores || config->cpu.threads) {
           start_element ("topology") {
             if (config->cpu.sockets)
-              attribute_format ("sockets", "%u", config->cpu.sockets);
+              attribute ("sockets", "%u", config->cpu.sockets);
             if (config->cpu.cores)
-              attribute_format ("cores", "%u", config->cpu.cores);
+              attribute ("cores", "%u", config->cpu.cores);
             if (config->cpu.threads)
-              attribute_format ("threads", "%u", config->cpu.threads);
+              attribute ("threads", "%u", config->cpu.threads);
           } end_element ();
         }
       } end_element ();
@@ -200,7 +155,7 @@ generate_physical_xml (struct config *config, struct data_conn *data_conns,
         else {
           attribute ("offset", "variable");
           attribute ("basis", "utc");
-          attribute_format ("adjustment", "%d", config->rtc.offset);
+          attribute ("adjustment", "%d", config->rtc.offset);
         }
       } end_element ();
       break;
@@ -214,7 +169,7 @@ generate_physical_xml (struct config *config, struct data_conn *data_conns,
 
     start_element ("os") {
       start_element ("type") {
-        attribute ("arch", host_cpu);
+        attribute ("arch", "%s", host_cpu);
         string ("hvm");
       } end_element ();
     } end_element ();
@@ -252,11 +207,11 @@ generate_physical_xml (struct config *config, struct data_conn *data_conns,
             attribute ("protocol", "nbd");
             start_element ("host") {
               attribute ("name", "localhost");
-              attribute_format ("port", "%d", data_conns[i].nbd_remote_port);
+              attribute ("port", "%d", data_conns[i].nbd_remote_port);
             } end_element ();
           } end_element ();
           start_element ("target") {
-            attribute ("dev", target_dev);
+            attribute ("dev", "%s", target_dev);
             /* XXX Need to set bus to "ide" or "scsi" here. */
           } end_element ();
         } end_element ();
@@ -272,7 +227,7 @@ generate_physical_xml (struct config *config, struct data_conn *data_conns,
               attribute ("type", "raw");
             } end_element ();
             start_element ("target") {
-              attribute ("dev", config->removable[i]);
+              attribute ("dev", "%s", config->removable[i]);
             } end_element ();
           } end_element ();
         }
@@ -300,14 +255,14 @@ generate_physical_xml (struct config *config, struct data_conn *data_conns,
           start_element ("interface") {
             attribute ("type", "network");
             start_element ("source") {
-              attribute ("network", target_network);
+              attribute ("network", "%s", target_network);
             } end_element ();
             start_element ("target") {
-              attribute ("dev", config->interfaces[i]);
+              attribute ("dev", "%s", config->interfaces[i]);
             } end_element ();
             if (mac) {
               start_element ("mac") {
-                attribute ("address", mac);
+                attribute ("address", "%s", mac);
               } end_element ();
             }
           } end_element ();
-- 
2.19.0.rc0




More information about the Libguestfs mailing list