From 7d48cb09b85b81f707565db6d35b1ba0d247b6b4 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 45/55] 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 | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/grubby.c b/grubby.c index 5202485a541..11ee64a02b9 100644 --- a/grubby.c +++ b/grubby.c @@ -1789,6 +1789,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; @@ -1903,16 +1904,42 @@ static int writeConfig(struct grubConfig *cfg, char *outName, } if (tmpOutName) { - if (rename(tmpOutName, outName)) { + /* 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 moving %s to %s: %s\n"), - tmpOutName, outName, strerror(errno)); - unlink(outName); - return 1; - } + _("grubby: error flushing data: %m\n")); } - return 0; + return rc; } static int numEntries(struct grubConfig *cfg) -- 2.17.1