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