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