fs-util: allow fsync_directory_of_file() on directories too

(in which case the parent dir is synced)
This commit is contained in:
Lennart Poettering
2021-02-03 20:40:40 +01:00
parent dbdcd51f78
commit 9041e36d07

View File

@@ -1413,33 +1413,45 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
int fsync_directory_of_file(int fd) {
_cleanup_free_ char *path = NULL;
_cleanup_close_ int dfd = -1;
struct stat st;
int r;
r = fd_verify_regular(fd);
if (r < 0)
return r;
assert(fd >= 0);
r = fd_get_path(fd, &path);
if (r < 0) {
log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m",
fd,
r == -ENOSYS ? ", ignoring" : "");
/* We only reasonably can do this for regular files and directories, hence check for that */
if (fstat(fd, &st) < 0)
return -errno;
if (r == -ENOSYS)
/* If /proc is not available, we're most likely running in some
* chroot environment, and syncing the directory is not very
* important in that case. Let's just silently do nothing. */
return 0;
if (S_ISREG(st.st_mode)) {
return r;
}
r = fd_get_path(fd, &path);
if (r < 0) {
log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m",
fd,
r == -ENOSYS ? ", ignoring" : "");
if (!path_is_absolute(path))
return -EINVAL;
if (r == -ENOSYS)
/* If /proc is not available, we're most likely running in some
* chroot environment, and syncing the directory is not very
* important in that case. Let's just silently do nothing. */
return 0;
dfd = open_parent(path, O_CLOEXEC, 0);
if (dfd < 0)
return dfd;
return r;
}
if (!path_is_absolute(path))
return -EINVAL;
dfd = open_parent(path, O_CLOEXEC|O_NOFOLLOW, 0);
if (dfd < 0)
return dfd;
} else if (S_ISDIR(st.st_mode)) {
dfd = openat(fd, "..", O_RDONLY|O_DIRECTORY|O_CLOEXEC, 0);
if (dfd < 0)
return -errno;
} else
return -ENOTTY;
if (fsync(dfd) < 0)
return -errno;