From 76a976817fb22c419557c6e010638b7ed2c2549b Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 3 Apr 2014 22:39:41 -0400 Subject: [PATCH] deploy: Call fsync() on parent directory before/after symlink swap Let's be conservative here and try hard to ensure the symlink has the correct content on disk. --- src/libotutil/ot-gio-utils.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c index da895fbc..6acb66de 100644 --- a/src/libotutil/ot-gio-utils.c +++ b/src/libotutil/ot-gio-utils.c @@ -386,6 +386,7 @@ ot_gfile_atomic_symlink_swap (GFile *path, gs_unref_object GFile *parent = g_file_get_parent (path); gs_free char *tmpname = g_strconcat (gs_file_get_basename_cached (path), ".tmp", NULL); gs_unref_object GFile *tmppath = g_file_get_child (parent, tmpname); + int parent_dfd = -1; if (!ot_gfile_ensure_unlinked (tmppath, cancellable, error)) goto out; @@ -393,10 +394,28 @@ ot_gfile_atomic_symlink_swap (GFile *path, if (!g_file_make_symbolic_link (tmppath, target, cancellable, error)) goto out; + if (!gs_file_open_dir_fd (parent, &parent_dfd, cancellable, error)) + goto out; + + /* Ensure the link has hit disk */ + if (fsync (parent_dfd) != 0) + { + ot_util_set_error_from_errno (error, errno); + goto out; + } + if (!gs_file_rename (tmppath, path, cancellable, error)) goto out; + /* And sync again for good measure */ + if (fsync (parent_dfd) != 0) + { + ot_util_set_error_from_errno (error, errno); + goto out; + } + ret = TRUE; out: + if (parent_dfd != -1) (void) close (parent_dfd); return ret; }