From d9406b061cef40bd42ed813e13bd02b3a285adae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= Date: Fri, 23 Jun 2017 23:56:50 +0200 Subject: [PATCH 44/60] Be more thorough about flushing our config file when writing. Add missing fclose() at the end of writeConfig Use fflush(out) + fsync(fileno(out) on temporary file fsync() the destination directory after rename --- grubby.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/grubby.c b/grubby.c index 345195c..951abb7 100644 --- a/grubby.c +++ b/grubby.c @@ -1591,6 +1591,7 @@ static int writeConfig(struct grubConfig * cfg, char * outName, int needs = MAIN_DEFAULT; struct stat sb; int i; + int rc = 0; if (!strcmp(outName, "-")) { out = stdout; @@ -1694,15 +1695,42 @@ static int writeConfig(struct grubConfig * cfg, char * outName, } if (tmpOutName) { - if (rename(tmpOutName, outName)) { - fprintf(stderr, _("grubby: error moving %s to %s: %s\n"), - tmpOutName, outName, strerror(errno)); - unlink(outName); - return 1; + /* write userspace buffers */ + if (fflush(out)) + rc = 1; + + /* purge the write-back cache with fsync() */ + if (fsync(fileno(out))) + rc = 1; + + if (fclose(out)) + rc = 1; + + if (rc == 0 && rename(tmpOutName, outName)) { + unlink(tmpOutName); + rc = 1; + } + + /* fsync() the destination directory after rename */ + if (rc == 0) { + int dirfd; + + dirfd = open(dirname(strdupa(outName)), O_RDONLY); + if (dirfd < 0) + rc = 1; + else if (fsync(dirfd)) + rc = 1; + + if (dirfd >= 0) + close(dirfd); } + + if (rc == 1) + fprintf(stderr, + _("grubby: error flushing data: %m\n")); } - return 0; + return rc; } static int numEntries(struct grubConfig *cfg) { -- 2.19.1