diff options
author | codekipper <codekipper@gmail.com> | 2017-04-27 01:49:06 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2017-04-26 19:49:06 -0400 |
commit | 5a1d67639d8d3c25f817cf2958348c3f3193a573 (patch) | |
tree | 47cc5182393931f57d4b983d7f4d4ae5af29b0e8 | |
parent | 6385cb31ef443be3e0d6da5ea62a267a49174688 (diff) |
update-done: Create using a temporary file (#5789)
'/etc/.updated' is created without using a temporary file, this can be
problematic with filesystems that cache writes. Modify so that the
timestamp is written to a temporary file and then use an atomic move
to move it to its correct place.
-rw-r--r-- | src/update-done/update-done.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c index d466e1b759..06e2d7b71b 100644 --- a/src/update-done/update-done.c +++ b/src/update-done/update-done.c @@ -17,8 +17,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "io-util.h" #include "selinux-util.h" #include "util.h" @@ -36,6 +38,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) { _cleanup_fclose_ FILE *f = NULL; int fd = -1; int r; + _cleanup_(unlink_and_freep) char *tmp = NULL; assert(path); assert(ts); @@ -50,20 +53,20 @@ static int apply_timestamp(const char *path, struct timespec *ts) { if (r < 0) return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); - fd = open(path, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); + fd = open_tmpfile_linkable(path, O_WRONLY|O_CLOEXEC, &tmp); mac_selinux_create_file_clear(); if (fd < 0) { if (errno == EROFS) - return log_debug("Can't create timestamp file %s, file system is read-only.", path); + return log_debug("Can't create temporary timestamp file %s, file system is read-only.", tmp); - return log_error_errno(errno, "Failed to create/open timestamp file %s: %m", path); + return log_error_errno(errno, "Failed to create/open temporary timestamp file %s: %m", tmp); } f = fdopen(fd, "we"); if (!f) { safe_close(fd); - return log_error_errno(errno, "Failed to fdopen() timestamp file %s: %m", path); + return log_error_errno(errno, "Failed to fdopen() timestamp file %s: %m", tmp); } (void) fprintf(f, @@ -76,7 +79,15 @@ static int apply_timestamp(const char *path, struct timespec *ts) { return log_error_errno(r, "Failed to write timestamp file: %m"); if (futimens(fd, twice) < 0) - return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); + return log_error_errno(errno, "Failed to update timestamp on %s: %m", tmp); + + /* fix permissions */ + (void) fchmod(fd, 0644); + r = link_tmpfile(fd, tmp, path); + if (r < 0) + return log_error_errno(r, "Failed to move \"%s\" to \"%s\": %m", tmp, path); + + tmp = mfree(tmp); return 0; } |