diff options
author | dec05eba <dec05eba@protonmail.com> | 2021-04-20 12:47:09 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2021-04-20 12:47:09 +0200 |
commit | 43cd46e9e7040b4653340f91d3b190831103ca79 (patch) | |
tree | 140a5c14a96696d1f58d563cd33725ead7f7ad6e /src | |
parent | e212594553122502540c1596f3bbc6c86a25cfd1 (diff) |
Make rename properly atomic
Diffstat (limited to 'src')
-rw-r--r-- | src/fileutils.c | 24 |
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); } |