From: Yu Watanabe Date: Sat, 10 Dec 2022 02:23:05 +0000 (+0900) Subject: stat-util: introduce fd_is_read_only_fs() X-Git-Tag: v253-rc1~283^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dc1752ea72ef9cda3fc4c9445a8dc436bd900884;p=thirdparty%2Fsystemd.git stat-util: introduce fd_is_read_only_fs() Then, reimplement path_is_read_only_fs() by the function to avoid race. --- diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 97dbcaac66a..0974f6178ab 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -163,26 +163,37 @@ int null_or_empty_fd(int fd) { return null_or_empty(&st); } -int path_is_read_only_fs(const char *path) { +static int fd_is_read_only_fs(int fd) { struct statvfs st; - assert(path); + assert(fd >= 0); - if (statvfs(path, &st) < 0) + if (fstatvfs(fd, &st) < 0) return -errno; if (st.f_flag & ST_RDONLY) return true; - /* On NFS, statvfs() might not reflect whether we can actually - * write to the remote share. Let's try again with - * access(W_OK) which is more reliable, at least sometimes. */ - if (access(path, W_OK) < 0 && errno == EROFS) + /* On NFS, fstatvfs() might not reflect whether we can actually write to the remote share. Let's try + * again with access(W_OK) which is more reliable, at least sometimes. */ + if (access_fd(fd, W_OK) == -EROFS) return true; return false; } +int path_is_read_only_fs(const char *path) { + _cleanup_close_ int fd = -EBADFD; + + assert(path); + + fd = open(path, O_CLOEXEC | O_PATH); + if (fd < 0) + return -errno; + + return fd_is_read_only_fs(fd); +} + int files_same(const char *filea, const char *fileb, int flags) { struct stat a, b;