[PATCH 3/4] Introduce virXMLSaveFile as a wrapper for virFileRewrite

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Every time we write XML into a file we call virEmitXMLWarning to write a
warning that the file is automatically generated. virXMLSaveFile
simplifies this into a single step and makes rewriting existing XML file
safe by using virFileRewrite internally.
---
 src/conf/domain_conf.c   |   25 +++++++++++++++++++++----
 src/libvirt_private.syms |    1 +
 src/util/util.c          |    4 +++-
 src/util/xml.c           |   36 ++++++++++++++++++++++++++++++++++++
 src/util/xml.h           |    5 +++++
 5 files changed, 66 insertions(+), 5 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5959593..6656e8b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -11078,6 +11078,7 @@ int virDomainSaveXML(const char *configDir,
                      const char *xml)
 {
     char *configFile = NULL;
+    char *newfile = NULL;
     int fd = -1, ret = -1;
     size_t towrite;
 
@@ -11091,12 +11092,17 @@ int virDomainSaveXML(const char *configDir,
         goto cleanup;
     }
 
-    if ((fd = open(configFile,
+    if (virAsprintf(&newfile, "%s.new", configFile) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if ((fd = open(newfile,
                    O_WRONLY | O_CREAT | O_TRUNC,
                    S_IRUSR | S_IWUSR )) < 0) {
         virReportSystemError(errno,
                              _("cannot create config file '%s'"),
-                             configFile);
+                             newfile);
         goto cleanup;
     }
 
@@ -11106,14 +11112,21 @@ int virDomainSaveXML(const char *configDir,
     if (safewrite(fd, xml, towrite) < 0) {
         virReportSystemError(errno,
                              _("cannot write config file '%s'"),
-                             configFile);
+                             newfile);
         goto cleanup;
     }
 
     if (VIR_CLOSE(fd) < 0) {
         virReportSystemError(errno,
                              _("cannot save config file '%s'"),
-                             configFile);
+                             newfile);
+        goto cleanup;
+    }
+
+    if (rename(newfile, configFile) < 0) {
+        virReportSystemError(errno,
+                             _("cannot rename config file '%s' as '%s'"),
+                             newfile, configFile);
         goto cleanup;
     }
 
@@ -11121,6 +11134,10 @@ int virDomainSaveXML(const char *configDir,
  cleanup:
     VIR_FORCE_CLOSE(fd);
 
+    if (newfile) {
+        unlink(newfile);
+        VIR_FREE(newfile);
+    }
     VIR_FREE(configFile);
     return ret;
 }
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1c7910b..b05bf61 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1292,6 +1292,7 @@ virKeycodeValueTranslate;
 # xml.h
 virXMLParseHelper;
 virXMLPropString;
+virXMLSaveFile;
 virXPathBoolean;
 virXPathInt;
 virXPathLong;
diff --git a/src/util/util.c b/src/util/util.c
index dac616b..18763b1 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2485,8 +2485,10 @@ OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:\n\
 or other application using the libvirt API.\n\
 -->\n\n";
 
-    if (fd < 0 || !name || !cmd)
+    if (fd < 0 || !name || !cmd) {
+        errno = EINVAL;
         return -1;
+    }
 
     len = strlen(prologue);
     if (safewrite(fd, prologue, len) != len)
diff --git a/src/util/xml.c b/src/util/xml.c
index b0942da..1ff728e 100644
--- a/src/util/xml.c
+++ b/src/util/xml.c
@@ -16,12 +16,14 @@
 #include <stdarg.h>
 #include <limits.h>
 #include <math.h>               /* for isnan() */
+#include <sys/stat.h>
 
 #include "virterror_internal.h"
 #include "xml.h"
 #include "buf.h"
 #include "util.h"
 #include "memory.h"
+#include "virfile.h"
 
 #define VIR_FROM_THIS VIR_FROM_XML
 
@@ -797,3 +799,37 @@ error:
     }
     goto cleanup;
 }
+
+
+struct rewrite_data {
+    const char *warnName;
+    const char *warnCommand;
+    const char *xml;
+};
+
+static int
+virXMLRewriteFile(int fd, void *opaque)
+{
+    struct rewrite_data *data = opaque;
+
+    if (data->warnName && data->warnCommand) {
+        if (virEmitXMLWarning(fd, data->warnName, data->warnCommand) < 0)
+            return -1;
+    }
+
+    if (safewrite(fd, data->xml, strlen(data->xml)) < 0)
+        return -1;
+
+    return 0;
+}
+
+int
+virXMLSaveFile(const char *path,
+               const char *warnName,
+               const char *warnCommand,
+               const char *xml)
+{
+    struct rewrite_data data = { warnName, warnCommand, xml };
+
+    return virFileRewrite(path, S_IRUSR | S_IWUSR, virXMLRewriteFile, &data);
+}
diff --git a/src/util/xml.h b/src/util/xml.h
index d30e066..c492063 100644
--- a/src/util/xml.h
+++ b/src/util/xml.h
@@ -138,4 +138,9 @@ xmlDocPtr      virXMLParseHelper(int domcode,
 # define virXMLParseFileCtxt(filename, pctxt)                           \
     virXMLParseHelper(VIR_FROM_THIS, filename, NULL, NULL, pctxt)
 
+int virXMLSaveFile(const char *path,
+                   const char *warnName,
+                   const char *warnCommand,
+                   const char *xml);
+
 #endif                          /* __VIR_XML_H__ */
-- 
1.7.7

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]