aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-04-20 12:47:09 +0200
committerdec05eba <dec05eba@protonmail.com>2021-04-20 12:47:09 +0200
commit43cd46e9e7040b4653340f91d3b190831103ca79 (patch)
tree140a5c14a96696d1f58d563cd33725ead7f7ad6e /src
parente212594553122502540c1596f3bbc6c86a25cfd1 (diff)
Make rename properly atomic
Diffstat (limited to 'src')
-rw-r--r--src/fileutils.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/src/fileutils.c b/src/fileutils.c
index 72d9c29..d7021dc 100644
--- a/src/fileutils.c
+++ b/src/fileutils.c
@@ -180,11 +180,27 @@ int file_overwrite_in_dir(const char *dir, const char *filename, const char *dat
strcpy(tmp_filepath, filepath);
strcpy(tmp_filepath + filepath_len, ".tmp");
- int result = file_overwrite(tmp_filepath, data, size);
- if(result != 0)
- return result;
+ int fd = open(tmp_filepath, O_CREAT | O_WRONLY, 0666);
+ if(fd == -1) {
+ perror(filepath);
+ return -1;
+ }
+
+ ssize_t bytes_written = write(fd, data, size);
+ if(bytes_written != (ssize_t)size) {
+ fprintf(stderr, "Failed to write all bytes to file %s. Expected to write %zu bytes, only wrote %zd bytes\n", filepath, size, bytes_written);
+ close(fd);
+ return -1;
+ }
+
+ if(fsync(fd) == -1) {
+ perror(filepath);
+ close(fd);
+ return -1;
+ }
- /* Rename is atomic! */
+ close(fd);
+ /* fsync + rename is atomic! */
return rename(tmp_filepath, filepath);
}