diff options
| author | Edward Thomson <ethomson@github.com> | 2017-02-17 16:36:53 +0000 |
|---|---|---|
| committer | Edward Thomson <ethomson@github.com> | 2017-02-28 13:28:36 +0000 |
| commit | 1229e1c4d7ea1eb4c5bcd5c0d89bc576053175db (patch) | |
| tree | eaa95a9af16669ea7497dc30091b220a54404d5d /src/fileops.c | |
| parent | 5a747e0c6c5170d29969eb15822c36d76dd3e4ac (diff) | |
| download | libgit2-1229e1c4d7ea1eb4c5bcd5c0d89bc576053175db.tar.gz | |
fsync parent directories when fsyncing
When fsync'ing files, fsync the parent directory in the case where we
rename a file into place, or create a new file, to ensure that the
directory entry is flushed correctly.
Diffstat (limited to 'src/fileops.c')
| -rw-r--r-- | src/fileops.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/src/fileops.c b/src/fileops.c index 13b1fc2a1..881d1bed4 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -265,8 +265,13 @@ int git_futils_writebuffer( return error; } - if ((error = p_close(fd)) < 0) + if ((error = p_close(fd)) < 0) { giterr_set(GITERR_OS, "error while closing '%s'", path); + return error; + } + + if (do_fsync && (flags & O_CREAT)) + error = git_futils_fsync_parent(path); return error; } @@ -1119,3 +1124,28 @@ void git_futils_filestamp_set_from_stat( memset(stamp, 0, sizeof(*stamp)); } } + +int git_futils_fsync_dir(const char *path) +{ + int fd, error = -1; + + if ((fd = p_open(path, O_RDONLY)) < 0) { + giterr_set(GITERR_OS, "failed to open directory '%s' for fsync", path); + return -1; + } + + if ((error = p_fsync(fd)) < 0) + giterr_set(GITERR_OS, "failed to fsync directory '%s'", path); + + p_close(fd); + return error; +} + +int git_futils_fsync_parent(const char *path) +{ + char *parent = git_path_dirname(path); + int error = git_futils_fsync_dir(parent); + + git__free(parent); + return error; +} |
