Currently, due to the way virFileRewrite() works, the rewritten
file is owned by user and group that the daemon runs under. So
far, this is not a problem, because the function is used to write
XML files or secrets for persistent objects (domains, networks,
etc.) and we don't need other users to read/write those files.
But shortly, this function is going to be used for creating files
for QEMU domains. There we want the QEMU process (i.e. different
user) to read the file.
Therefore, introduce two new arguments: @uid and @gid that allow
setting desired owner of the file. Pass -1 to preserve current
behaviour (i.e. create the file owned by the user running the
daemon).
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
src/util/virfile.c | 28 +++++++++++++++++++++++++---
src/util/virfile.h | 1 +
src/util/virxml.c | 3 ++-
3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/src/util/virfile.c b/src/util/virfile.c
index 0b79772da7..f99e7f95e1 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -484,9 +484,28 @@ int virFileUnlock(int fd G_GNUC_UNUSED,
#endif /* WIN32 */
+/**
+ * virFileRewrite:
+ * @path: file to rewrite
+ * @mode: mode of the file
+ * @uid: uid that should own file
+ * @gid: gid that should own file
+ * @rewrite: callback to write file contents
+ * @opaque: opaque data to pass to the callback
+ *
+ * Rewrite given @path atomically. This is achieved by writing a
+ * temporary file on a side and renaming it to the desired name.
+ * The temporary file is created using supplied @mode and
+ * @uid:@gid (pass -1 for current uid/gid) and written by
+ * @rewrite callback.
+ *
+ * Returns: 0 on success,
+ * -1 otherwise (with error reported)
+ */
int
virFileRewrite(const char *path,
mode_t mode,
+ uid_t uid, gid_t gid,
virFileRewriteFunc rewrite,
const void *opaque)
{
@@ -496,8 +515,11 @@ virFileRewrite(const char *path,
newfile = g_strdup_printf("%s.new", path);
- if ((fd = open(newfile, O_WRONLY | O_CREAT | O_TRUNC, mode)) < 0) {
- virReportSystemError(errno, _("cannot create file '%s'"),
+ if ((fd = virFileOpenAs(newfile, O_WRONLY | O_CREAT | O_TRUNC, mode,
+ uid, gid,
+ VIR_FILE_OPEN_FORCE_OWNER | VIR_FILE_OPEN_FORCE_MODE)) <
0) {
+ virReportSystemError(-fd,
+ _("Failed to create file '%s'"),
newfile);
goto cleanup;
}
@@ -552,7 +574,7 @@ virFileRewriteStr(const char *path,
mode_t mode,
const char *str)
{
- return virFileRewrite(path, mode,
+ return virFileRewrite(path, mode, -1, -1,
virFileRewriteStrHelper, str);
}
diff --git a/src/util/virfile.h b/src/util/virfile.h
index 967c9a9b4f..34184b32aa 100644
--- a/src/util/virfile.h
+++ b/src/util/virfile.h
@@ -126,6 +126,7 @@ int virFileUnlock(int fd, off_t start, off_t len)
typedef int (*virFileRewriteFunc)(int fd, const void *opaque);
int virFileRewrite(const char *path,
mode_t mode,
+ uid_t uid, gid_t gid,
virFileRewriteFunc rewrite,
const void *opaque);
int virFileRewriteStr(const char *path,
diff --git a/src/util/virxml.c b/src/util/virxml.c
index bb1ae3e305..a55eb9629b 100644
--- a/src/util/virxml.c
+++ b/src/util/virxml.c
@@ -1195,7 +1195,8 @@ virXMLSaveFile(const char *path,
{
struct virXMLRewriteFileData data = { warnName, warnCommand, xml };
- return virFileRewrite(path, S_IRUSR | S_IWUSR, virXMLRewriteFile, &data);
+ return virFileRewrite(path, S_IRUSR | S_IWUSR, -1, -1,
+ virXMLRewriteFile, &data);
}
/**
--
2.34.1