diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a81966d8f7..3366ac971a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1181,6 +1181,7 @@ virFileDirectFdFree; virFileDirectFdNew; virFileFclose; virFileFdopen; +virFileRewrite; # virnetmessage.h diff --git a/src/util/virfile.c b/src/util/virfile.c index 11589988c0..cbc3fccccc 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -334,3 +334,59 @@ int virFileUnlock(int fd ATTRIBUTE_UNUSED, return -ENOSYS; } #endif + +int +virFileRewrite(const char *path, + mode_t mode, + virFileRewriteFunc rewrite, + void *opaque) +{ + char *newfile = NULL; + int fd = -1; + int ret = -1; + + if (virAsprintf(&newfile, "%s.new", path) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((fd = open(newfile, O_WRONLY | O_CREAT | O_TRUNC, mode)) < 0) { + virReportSystemError(errno, _("cannot create file '%s'"), + newfile); + goto cleanup; + } + + if (rewrite(fd, opaque) < 0) { + virReportSystemError(errno, _("cannot write data to file '%s'"), + newfile); + goto cleanup; + } + + if (fsync(fd) < 0) { + virReportSystemError(errno, _("cannot sync file '%s'"), + newfile); + goto cleanup; + } + + if (VIR_CLOSE(fd) < 0) { + virReportSystemError(errno, _("cannot save file '%s'"), + newfile); + goto cleanup; + } + + if (rename(newfile, path) < 0) { + virReportSystemError(errno, _("cannot rename file '%s' as '%s'"), + newfile, path); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FORCE_CLOSE(fd); + if (newfile) { + unlink(newfile); + VIR_FREE(newfile); + } + return ret; +} diff --git a/src/util/virfile.h b/src/util/virfile.h index e02561456b..a6e659712b 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -68,4 +68,10 @@ void virFileDirectFdFree(virFileDirectFdPtr dfd); int virFileLock(int fd, bool shared, off_t start, off_t len); int virFileUnlock(int fd, off_t start, off_t len); +typedef int (*virFileRewriteFunc)(int fd, void *opaque); +int virFileRewrite(const char *path, + mode_t mode, + virFileRewriteFunc rewrite, + void *opaque); + #endif /* __VIR_FILES_H */