]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
libmount-util: introduce two helper functions 36154/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 25 Jan 2025 00:33:58 +0000 (09:33 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 25 Jan 2025 00:34:01 +0000 (09:34 +0900)
This introduces libmount_parse_mountinfo() and libmount_parse_with_utab().
The former one parses only mountinfo, but the latter one also parse
utab. Hopefully this avoids pitfalls like issue #35949.

src/core/mount.c
src/mount/mount-tool.c
src/shared/libmount-util.c
src/shared/libmount-util.h
src/shared/mount-util.c
src/shutdown/test-umount.c
src/shutdown/umount.c
src/shutdown/umount.h
src/test/test-libmount.c
src/test/test-mount-util.c

index 073e9c71933a8ac2caf2cb7f84d03e0d956899c0..6fff94d19b294562194b5596a4d6dcad3b152425 100644 (file)
@@ -1927,7 +1927,7 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
 
         assert(m);
 
-        r = libmount_parse(NULL, NULL, &table, &iter);
+        r = libmount_parse_with_utab(&table, &iter);
         if (r < 0)
                 return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
index 5f9cf44b5df76e43b4ab65b7bf4ea2d4adf47af9..d1b4773ce8cb1d5d337112e9b879ef4d89e771d4 100644 (file)
@@ -805,7 +805,7 @@ static int find_mount_points(const char *what, char ***list) {
         /* Returns all mount points obtained from /proc/self/mountinfo in *list,
          * and the number of mount points as return value. */
 
-        r = libmount_parse(NULL, NULL, &table, &iter);
+        r = libmount_parse_mountinfo(/* source = */ NULL, &table, &iter);
         if (r < 0)
                 return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
index 381890473326fa89038d14f48e71718282458f44..1a6b68f9202d2cfa541e2fc6efdee8a2a6dbfc17 100644 (file)
@@ -4,7 +4,7 @@
 
 #include "libmount-util.h"
 
-int libmount_parse(
+int libmount_parse_full(
                 const char *path,
                 FILE *source,
                 struct libmnt_table **ret_table,
index 2f789e7426f53e0d2d2a9c5712f10441d645c67a..a363f7e9b74460c6e0da83b8e4626180574af26b 100644 (file)
@@ -9,12 +9,27 @@
 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct libmnt_table*, mnt_free_table, NULL);
 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct libmnt_iter*, mnt_free_iter, NULL);
 
-int libmount_parse(
+int libmount_parse_full(
                 const char *path,
                 FILE *source,
                 struct libmnt_table **ret_table,
                 struct libmnt_iter **ret_iter);
 
+static inline int libmount_parse_mountinfo(
+                FILE *source,
+                struct libmnt_table **ret_table,
+                struct libmnt_iter **ret_iter) {
+
+        return libmount_parse_full("/proc/self/mountinfo", source, ret_table, ret_iter);
+}
+
+static inline int libmount_parse_with_utab(
+                struct libmnt_table **ret_table,
+                struct libmnt_iter **ret_iter) {
+
+        return libmount_parse_full(NULL, NULL, ret_table, ret_iter);
+}
+
 int libmount_is_leaf(
                 struct libmnt_table *table,
                 struct libmnt_fs *fs);
index 720965c46e8ae15cdfaddef6a82312cd7ed92bc1..75a18051bc1184052a4e8331f14901f9d1fbdf87 100644 (file)
@@ -60,7 +60,7 @@ int umount_recursive_full(const char *prefix, int flags, char **keep) {
                 _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
                 bool again = false;
 
-                r = libmount_parse("/proc/self/mountinfo", f, &table, &iter);
+                r = libmount_parse_mountinfo(f, &table, &iter);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
@@ -217,7 +217,7 @@ int bind_remount_recursive_with_mountinfo(
 
                 rewind(proc_self_mountinfo);
 
-                r = libmount_parse("/proc/self/mountinfo", proc_self_mountinfo, &table, &iter);
+                r = libmount_parse_mountinfo(proc_self_mountinfo, &table, &iter);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
@@ -1571,7 +1571,7 @@ int get_sub_mounts(const char *prefix, SubMount **ret_mounts, size_t *ret_n_moun
         assert(ret_mounts);
         assert(ret_n_mounts);
 
-        r = libmount_parse("/proc/self/mountinfo", NULL, &table, &iter);
+        r = libmount_parse_mountinfo(/* source = */ NULL, &table, &iter);
         if (r < 0)
                 return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
@@ -1894,9 +1894,12 @@ static int path_get_mount_info_at(
         if (r < 0)
                 return log_debug_errno(r, "Failed to get mount ID: %m");
 
-        /* When getting options is requested, do not pass filename, otherwise utab will not read, and
-         * userspace options like "_netdev" will be lost. */
-        r = libmount_parse(ret_options ? NULL : "/proc/self/mountinfo", /* source = */ NULL, &table, &iter);
+        /* When getting options is requested, we also need to parse utab, otherwise userspace options like
+         * "_netdev" will be lost. */
+        if (ret_options)
+                r = libmount_parse_with_utab(&table, &iter);
+        else
+                r = libmount_parse_mountinfo(/* source = */ NULL, &table, &iter);
         if (r < 0)
                 return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
index 93da2e0fc34a415419249330871c12c903d869b7..fe30d9a2fe84abba626599927055bb3d36cdd665 100644 (file)
@@ -3,6 +3,7 @@
 #include "alloc-util.h"
 #include "detach-swap.h"
 #include "errno-util.h"
+#include "fd-util.h"
 #include "log.h"
 #include "path-util.h"
 #include "string-util.h"
 
 static void test_mount_points_list_one(const char *fname) {
         _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
-        _cleanup_free_ char *testdata_fname = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
 
         log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/self/mountinfo");
 
         if (fname) {
+                _cleanup_free_ char *testdata_fname = NULL;
                 assert_se(get_testdata_dir(fname, &testdata_fname) >= 0);
-                fname = testdata_fname;
+                ASSERT_NOT_NULL(f = fopen(testdata_fname, "re"));
         }
 
         LIST_HEAD_INIT(mp_list_head);
-        assert_se(mount_points_list_get(fname, &mp_list_head) >= 0);
+        assert_se(mount_points_list_get(f, &mp_list_head) >= 0);
 
         LIST_FOREACH(mount_point, m, mp_list_head)
                 log_debug("path=%s o=%s f=0x%lx try-ro=%s",
index 4bc01c75e0870c49b88a579b89770a155b86d332..a788f8cf8381f833c879b8f0f827d07dbed7984f 100644 (file)
@@ -47,16 +47,16 @@ void mount_points_list_free(MountPoint **head) {
                 mount_point_free(head, *head);
 }
 
-int mount_points_list_get(const char *mountinfo, MountPoint **head) {
+int mount_points_list_get(FILE *f, MountPoint **head) {
         _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
         _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
         int r;
 
         assert(head);
 
-        r = libmount_parse(mountinfo, NULL, &table, &iter);
+        r = libmount_parse_mountinfo(f, &table, &iter);
         if (r < 0)
-                return log_error_errno(r, "Failed to parse %s: %m", mountinfo ?: "/proc/self/mountinfo");
+                return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
         for (;;) {
                 _cleanup_free_ char *options = NULL, *remount_options = NULL;
@@ -70,7 +70,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
                 if (r == 1) /* EOF */
                         break;
                 if (r < 0)
-                        return log_error_errno(r, "Failed to get next entry from %s: %m", mountinfo ?: "/proc/self/mountinfo");
+                        return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
 
                 path = mnt_fs_get_target(fs);
                 if (!path)
@@ -141,7 +141,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
 
                 r = libmount_is_leaf(table, fs);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to get children mounts for %s from %s: %m", path, mountinfo ?: "/proc/self/mountinfo");
+                        return log_error_errno(r, "Failed to get children mounts for %s from /proc/self/mountinfo: %m", path);
                 bool leaf = r;
 
                 *m = (MountPoint) {
index f8f9ae8038094c0737ede634938e12b92b0a5e27..22498e1e776df68de8c43b292093c8ee13b7af3c 100644 (file)
@@ -6,6 +6,7 @@
 ***/
 
 #include <stdbool.h>
+#include <stdio.h>
 
 #include "list.h"
 
@@ -22,5 +23,5 @@ typedef struct MountPoint {
         LIST_FIELDS(struct MountPoint, mount_point);
 } MountPoint;
 
-int mount_points_list_get(const char *mountinfo, MountPoint **head);
+int mount_points_list_get(FILE *f, MountPoint **head);
 void mount_points_list_free(MountPoint **head);
index 9ba428e5befbeea99cb0b82cdaf60ac7f7db254f..d514bb94d3b6859cf877679f431d59ce6c04cdb1 100644 (file)
@@ -24,7 +24,7 @@ static void test_libmount_unescaping_one(
         f = fmemopen((char*) string, strlen(string), "r");
         assert_se(f);
 
-        assert_se(libmount_parse(title, f, &table, &iter) >= 0);
+        assert_se(libmount_parse_mountinfo(f, &table, &iter) >= 0);
 
         struct libmnt_fs *fs;
         const char *source, *target;
index 352c5a1af68ce7a53a9bca9c10766c80541c75e3..5fb4d23f3e8d2c081e8a913c13c5a00fb9180179 100644 (file)
@@ -393,7 +393,7 @@ TEST(umount_recursive) {
 
                         assert_se(umount_recursive_full(t->prefix, MNT_DETACH, (char**) t->keep) >= 0);
 
-                        r = libmount_parse("/proc/self/mountinfo", f, &table, &iter);
+                        r = libmount_parse_mountinfo(f, &table, &iter);
                         if (r < 0) {
                                 log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
                                 _exit(EXIT_FAILURE);