]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stat-util: introduce fd_is_read_only_fs()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 10 Dec 2022 02:23:05 +0000 (11:23 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 14 Dec 2022 18:25:09 +0000 (03:25 +0900)
Then, reimplement path_is_read_only_fs() by the function to avoid race.

src/basic/stat-util.c

index 97dbcaac66a3348bd7a1b87985f0a532c7c683c2..0974f6178ab7845fef5cdb5fd726ae0fcffce81e 100644 (file)
@@ -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;