mount-util: introduce path_is_network_fs_harder()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 5 Nov 2024 19:37:55 +0000 (04:37 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 5 Nov 2024 19:58:55 +0000 (04:58 +0900)
It also detects e.g. glusterfs or mounts with "_netdev" option.

src/shared/mount-util.c
src/shared/mount-util.h
src/test/test-mount-util.c

index 3c89a18790c871139badbeaa2167bbd55b0a4bd3..8ef952a035a26a69975ad61eabe36ad33b4d19e4 100644 (file)
@@ -19,6 +19,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
+#include "fstab-util.h"
 #include "glyph-util.h"
 #include "hashmap.h"
 #include "initrd-util.h"
@@ -1820,3 +1821,70 @@ char* umount_and_unlink_and_free(char *p) {
         (void) unlink(p);
         return mfree(p);
 }
+
+static int path_get_mount_info(
+                const char *path,
+                char **ret_fstype,
+                char **ret_options) {
+
+        _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+        _cleanup_free_ char *fstype = NULL, *options = NULL;
+        struct libmnt_fs *fs;
+        int r;
+
+        assert(path);
+
+        table = mnt_new_table();
+        if (!table)
+                return -ENOMEM;
+
+        r = mnt_table_parse_mtab(table, /* filename = */ NULL);
+        if (r < 0)
+                return r;
+
+        fs = mnt_table_find_mountpoint(table, path, MNT_ITER_FORWARD);
+        if (!fs)
+                return -EINVAL;
+
+        if (ret_fstype) {
+                fstype = strdup(strempty(mnt_fs_get_fstype(fs)));
+                if (!fstype)
+                        return -ENOMEM;
+        }
+
+        if (ret_options) {
+                options = strdup(strempty(mnt_fs_get_options(fs)));
+                if (!options)
+                        return -ENOMEM;
+        }
+
+        if (ret_fstype)
+                *ret_fstype = TAKE_PTR(fstype);
+        if (ret_options)
+                *ret_options = TAKE_PTR(options);
+
+        return 0;
+}
+
+int path_is_network_fs_harder(const char *path) {
+        _cleanup_free_ char *fstype = NULL, *options = NULL;
+        int r, ret;
+
+        assert(path);
+
+        ret = path_is_network_fs(path);
+        if (ret > 0)
+                return true;
+
+        r = path_get_mount_info(path, &fstype, &options);
+        if (r < 0)
+                return RET_GATHER(ret, r);
+
+        if (fstype_is_network(fstype))
+                return true;
+
+        if (fstab_test_option(options, "_netdev\0"))
+                return true;
+
+        return false;
+}
index eb068d5b44f4a2a097a7d0567fb37cc49358ddb4..067ed0e4d942720e767e1f03ad4835d2c4e3ac53 100644 (file)
@@ -180,3 +180,5 @@ unsigned long credentials_fs_mount_flags(bool ro);
 int mount_credentials_fs(const char *path, size_t size, bool ro);
 
 int make_fsmount(int error_log_level, const char *what, const char *type, unsigned long flags, const char *options, int userns_fd);
+
+int path_is_network_fs_harder(const char *path);
index 4f6da39f48e99b47d587463fdbe623f0112b1623..28d171de338752be1ad54099798ae62b2f6c4e47 100644 (file)
@@ -537,4 +537,11 @@ TEST(bind_mount_submounts) {
         assert_se(umount_recursive(b, 0) >= 0);
 }
 
+TEST(path_is_network_fs_harder) {
+        ASSERT_OK(path_is_network_fs_harder("/"));
+        ASSERT_OK_ZERO(path_is_network_fs_harder("/dev"));
+        ASSERT_OK_ZERO(path_is_network_fs_harder("/sys"));
+        ASSERT_OK_ZERO(path_is_network_fs_harder("/run"));
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);