[libvirt] [PATCH 2/4] Introduce virFileRewrite for safe file rewrite
Daniel P. Berrange
berrange at redhat.com
Thu Oct 20 09:21:25 UTC 2011
On Wed, Oct 19, 2011 at 07:26:25PM +0200, Jiri Denemark wrote:
> When saving config files we just overwrite old content of the file. In
> case something fails during that process (e.g. disk gets full) we lose
> both old and new content. This patch makes the process more robust by
> writing the new content into a separate file and only if that succeeds
> the original file is atomically replaced with the new one.
> ---
> src/libvirt_private.syms | 1 +
> src/util/virfile.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
> src/util/virfile.h | 6 +++++
> 3 files changed, 63 insertions(+), 0 deletions(-)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 9666a0a..1c7910b 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1172,6 +1172,7 @@ virFileDirectFdFree;
> virFileDirectFdNew;
> virFileFclose;
> virFileFdopen;
> +virFileRewrite;
> virFileSync;
>
>
> diff --git a/src/util/virfile.c b/src/util/virfile.c
> index 50b8aab..8c00e86 100644
> --- a/src/util/virfile.c
> +++ b/src/util/virfile.c
> @@ -350,3 +350,59 @@ virFileSync(int fd, bool metadata)
>
> return ret;
> }
> +
> +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 (virFileSync(fd, true) < 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 0b14e1d..c26ff5a 100644
> --- a/src/util/virfile.h
> +++ b/src/util/virfile.h
> @@ -70,4 +70,10 @@ int virFileUnlock(int fd, off_t start, off_t len);
>
> int virFileSync(int fd, bool metadata);
>
> +typedef int (*virFileRewriteFunc)(int fd, void *opaque);
> +int virFileRewrite(const char *path,
> + mode_t mode,
> + virFileRewriteFunc rewrite,
> + void *opaque);
> +
> #endif /* __VIR_FILES_H */
ACK
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list