From: Lennart Poettering Date: Wed, 3 Feb 2021 19:40:40 +0000 (+0100) Subject: fs-util: allow fsync_directory_of_file() on directories too X-Git-Tag: v248-rc3~71^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9041e36d075cb16bd58bbc92c5e441ca569ea67f;p=thirdparty%2Fsystemd.git fs-util: allow fsync_directory_of_file() on directories too (in which case the parent dir is synced) --- diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 3a3daa9a05d..9423b9bf7ac 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -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; + + return r; + } - dfd = open_parent(path, O_CLOEXEC, 0); - if (dfd < 0) - return dfd; + 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;