summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/fileio.c32
-rw-r--r--src/basic/fileio.h10
-rw-r--r--src/boot/bootctl.c14
-rw-r--r--src/firstboot/firstboot.c8
-rw-r--r--src/hwdb/hwdb.c25
-rw-r--r--src/locale/keymap-util.c2
-rw-r--r--src/sysusers/sysusers.c14
-rw-r--r--src/udev/udevadm-hwdb.c42
8 files changed, 100 insertions, 47 deletions
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index a025038588..277aea51a9 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -71,7 +71,7 @@ int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, stru
return fflush_and_check(f);
}
-static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline) {
+static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline, bool sync) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
int r;
@@ -86,6 +86,9 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor
(void) fchmod_umask(fileno(f), 0644);
r = write_string_stream(f, line, enforce_newline);
+ if (r >= 0 && sync)
+ r = fflush_sync_and_check(f);
+
if (r >= 0) {
if (rename(p, fn) < 0)
r = -errno;
@@ -104,10 +107,14 @@ int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags
assert(fn);
assert(line);
+ /* We don't know how to verify whether the file contents is on-disk. */
+ assert(!((flags & WRITE_STRING_FILE_SYNC) && (flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE)));
+
if (flags & WRITE_STRING_FILE_ATOMIC) {
assert(flags & WRITE_STRING_FILE_CREATE);
- r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE),
+ flags & WRITE_STRING_FILE_SYNC);
if (r < 0)
goto fail;
@@ -144,6 +151,12 @@ int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags
if (r < 0)
goto fail;
+ if (flags & WRITE_STRING_FILE_SYNC) {
+ r = fflush_sync_and_check(f);
+ if (r < 0)
+ return r;
+ }
+
return 0;
fail:
@@ -1126,6 +1139,21 @@ int fflush_and_check(FILE *f) {
return 0;
}
+int fflush_sync_and_check(FILE *f) {
+ int r;
+
+ assert(f);
+
+ r = fflush_and_check(f);
+ if (r < 0)
+ return r;
+
+ if (fsync(fileno(f)) < 0)
+ return -errno;
+
+ return 0;
+}
+
/* This is much like mkostemp() but is subject to umask(). */
int mkostemp_safe(char *pattern) {
_cleanup_umask_ mode_t u = 0;
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 6098562265..b4238746d6 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -29,10 +29,11 @@
#include "time-util.h"
typedef enum {
- WRITE_STRING_FILE_CREATE = 1,
- WRITE_STRING_FILE_ATOMIC = 2,
- WRITE_STRING_FILE_AVOID_NEWLINE = 4,
- WRITE_STRING_FILE_VERIFY_ON_FAILURE = 8,
+ WRITE_STRING_FILE_CREATE = 1<<0,
+ WRITE_STRING_FILE_ATOMIC = 1<<1,
+ WRITE_STRING_FILE_AVOID_NEWLINE = 1<<2,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1<<3,
+ WRITE_STRING_FILE_SYNC = 1<<4,
} WriteStringFileFlags;
int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts);
@@ -77,6 +78,7 @@ int search_and_fopen_nulstr(const char *path, const char *mode, const char *root
} else
int fflush_and_check(FILE *f);
+int fflush_sync_and_check(FILE *f);
int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
int mkostemp_safe(char *pattern);
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 233bc80292..85f3b42c48 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -539,12 +539,18 @@ static int copy_file_with_version_check(const char *from, const char *to, bool f
r = copy_bytes(fd_from, fd_to, (uint64_t) -1, COPY_REFLINK);
if (r < 0) {
- unlink(t);
- return log_error_errno(errno, "Failed to copy data from \"%s\" to \"%s\": %m", from, t);
+ (void) unlink(t);
+ return log_error_errno(r, "Failed to copy data from \"%s\" to \"%s\": %m", from, t);
}
(void) copy_times(fd_from, fd_to);
+ r = fsync(fd_to);
+ if (r < 0) {
+ (void) unlink_noerrno(t);
+ return log_error_errno(errno, "Failed to copy data from \"%s\" to \"%s\": %m", from, t);
+ }
+
r = renameat(AT_FDCWD, t, AT_FDCWD, to);
if (r < 0) {
(void) unlink_noerrno(t);
@@ -912,7 +918,7 @@ static int install_loader_config(const char *esp_path) {
r = sd_id128_get_machine(&machine_id);
if (r < 0)
- return log_error_errno(r, "Failed to get machine did: %m");
+ return log_error_errno(r, "Failed to get machine id: %m");
p = strjoina(esp_path, "/loader/loader.conf");
@@ -932,7 +938,7 @@ static int install_loader_config(const char *esp_path) {
fprintf(f, "#timeout 3\n");
fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
- r = fflush_and_check(f);
+ r = fflush_sync_and_check(f);
if (r < 0)
return log_error_errno(r, "Failed to write \"%s\": %m", p);
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index b3578d3e16..586674d458 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -411,7 +411,8 @@ static int process_hostname(void) {
return 0;
mkdir_parents(etc_hostname, 0755);
- r = write_string_file(etc_hostname, arg_hostname, WRITE_STRING_FILE_CREATE);
+ r = write_string_file(etc_hostname, arg_hostname,
+ WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC);
if (r < 0)
return log_error_errno(r, "Failed to write %s: %m", etc_hostname);
@@ -432,7 +433,8 @@ static int process_machine_id(void) {
return 0;
mkdir_parents(etc_machine_id, 0755);
- r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id), WRITE_STRING_FILE_CREATE);
+ r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id),
+ WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC);
if (r < 0)
return log_error_errno(r, "Failed to write machine id: %m");
@@ -503,7 +505,7 @@ static int write_root_shadow(const char *path, const struct spwd *p) {
if (putspent(p, f) != 0)
return errno > 0 ? -errno : -EIO;
- return fflush_and_check(f);
+ return fflush_sync_and_check(f);
}
static int process_root_password(void) {
diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c
index 793398ca68..ead4e1770b 100644
--- a/src/hwdb/hwdb.c
+++ b/src/hwdb/hwdb.c
@@ -403,14 +403,14 @@ static int trie_store(struct trie *trie, const char *filename) {
t.strings_off = sizeof(struct trie_header_f);
trie_store_nodes_size(&t, trie->root);
- r = fopen_temporary(filename , &t.f, &filename_tmp);
+ r = fopen_temporary(filename, &t.f, &filename_tmp);
if (r < 0)
return r;
fchmod(fileno(t.f), 0444);
/* write nodes */
if (fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET) < 0)
- goto error;
+ goto error_fclose;
root_off = trie_store_nodes(&t, trie->root);
h.nodes_root_off = htole64(root_off);
@@ -425,13 +425,20 @@ static int trie_store(struct trie *trie, const char *filename) {
size = ftello(t.f);
h.file_size = htole64(size);
if (fseeko(t.f, 0, SEEK_SET) < 0)
- goto error;
-
+ goto error_fclose;
fwrite(&h, sizeof(struct trie_header_f), 1, t.f);
- if (fclose(t.f) < 0 || rename(filename_tmp, filename) < 0) {
- unlink_noerrno(filename_tmp);
- return -errno;
- }
+
+ if (ferror(t.f))
+ goto error_fclose;
+ if (fflush(t.f) < 0)
+ goto error_fclose;
+ if (fsync(fileno(t.f)) < 0)
+ goto error_fclose;
+ if (rename(filename_tmp, filename) < 0)
+ goto error_fclose;
+
+ /* write succeeded */
+ fclose(t.f);
log_debug("=== trie on-disk ===");
log_debug("size: %8"PRIi64" bytes", size);
@@ -446,7 +453,7 @@ static int trie_store(struct trie *trie, const char *filename) {
log_debug("strings start: %8"PRIu64, t.strings_off);
return 0;
- error:
+ error_fclose:
r = -errno;
fclose(t.f);
unlink(filename_tmp);
diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c
index 5cefeb6135..7068603f0f 100644
--- a/src/locale/keymap-util.c
+++ b/src/locale/keymap-util.c
@@ -382,7 +382,7 @@ int x11_write_data(Context *c) {
fputs_unlocked("EndSection\n", f);
- r = fflush_and_check(f);
+ r = fflush_sync_and_check(f);
if (r < 0)
goto fail;
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index fbe51a6ed5..448f584733 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -233,8 +233,14 @@ static int make_backup(const char *target, const char *x) {
if (futimens(fileno(dst), ts) < 0)
log_warning_errno(errno, "Failed to fix access and modification time of %s: %m", backup);
- if (rename(temp, backup) < 0)
+ r = fflush_sync_and_check(dst);
+ if (r < 0)
+ goto fail;
+
+ if (rename(temp, backup) < 0) {
+ r = -errno;
goto fail;
+ }
return 0;
@@ -532,7 +538,7 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
return errno ? -errno : -EIO;
}
- r = fflush_and_check(shadow);
+ r = fflush_sync_and_check(shadow);
if (r < 0)
return r;
@@ -616,7 +622,7 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char **
group_changed = true;
}
- r = fflush_and_check(group);
+ r = fflush_sync_and_check(group);
if (r < 0)
return r;
@@ -693,7 +699,7 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch
group_changed = true;
}
- r = fflush_and_check(gshadow);
+ r = fflush_sync_and_check(gshadow);
if (r < 0)
return r;
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
index 69b0b9025c..7688f8192b 100644
--- a/src/udev/udevadm-hwdb.c
+++ b/src/udev/udevadm-hwdb.c
@@ -364,18 +364,14 @@ static int trie_store(struct trie *trie, const char *filename) {
t.strings_off = sizeof(struct trie_header_f);
trie_store_nodes_size(&t, trie->root);
- err = fopen_temporary(filename , &t.f, &filename_tmp);
+ err = fopen_temporary(filename, &t.f, &filename_tmp);
if (err < 0)
return err;
fchmod(fileno(t.f), 0444);
/* write nodes */
- err = fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET);
- if (err < 0) {
- fclose(t.f);
- unlink_noerrno(filename_tmp);
- return -errno;
- }
+ if (fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET) < 0)
+ goto error_fclose;
root_off = trie_store_nodes(&t, trie->root);
h.nodes_root_off = htole64(root_off);
pos = ftello(t.f);
@@ -388,21 +384,21 @@ static int trie_store(struct trie *trie, const char *filename) {
/* write header */
size = ftello(t.f);
h.file_size = htole64(size);
- err = fseeko(t.f, 0, SEEK_SET);
- if (err < 0) {
- fclose(t.f);
- unlink_noerrno(filename_tmp);
- return -errno;
- }
+ if (fseeko(t.f, 0, SEEK_SET < 0))
+ goto error_fclose;
fwrite(&h, sizeof(struct trie_header_f), 1, t.f);
- err = ferror(t.f);
- if (err)
- err = -errno;
+
+ if (ferror(t.f))
+ goto error_fclose;
+ if (fflush(t.f) < 0)
+ goto error_fclose;
+ if (fsync(fileno(t.f)) < 0)
+ goto error_fclose;
+ if (rename(filename_tmp, filename) < 0)
+ goto error_fclose;
+
+ /* write succeeded */
fclose(t.f);
- if (err < 0 || rename(filename_tmp, filename) < 0) {
- unlink_noerrno(filename_tmp);
- return err < 0 ? err : -errno;
- }
log_debug("=== trie on-disk ===");
log_debug("size: %8"PRIi64" bytes", size);
@@ -417,6 +413,12 @@ static int trie_store(struct trie *trie, const char *filename) {
log_debug("strings start: %8"PRIu64, t.strings_off);
return 0;
+
+ error_fclose:
+ err = -errno;
+ fclose(t.f);
+ unlink(filename_tmp);
+ return err;
}
static int insert_data(struct trie *trie, struct udev_list *match_list,