diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-04-30 19:44:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-30 19:44:17 +0200 |
commit | adb7b782f83ca076b09b60a905f9ffb311835693 (patch) | |
tree | 048032608f772a273f4177b866c49e0448a97fe5 | |
parent | 9f3f596477ba68d4ece645536586756caea4ae97 (diff) | |
parent | 2f2d81d957b2d5ef7a0f8a702dcf7f71348cffe3 (diff) | |
download | systemd-adb7b782f83ca076b09b60a905f9ffb311835693.tar.gz |
Merge pull request #12218 from keszybz/use-libmount-more
Use libmount more
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | src/core/mount.c | 20 | ||||
-rw-r--r-- | src/mount/mount-tool.c | 58 | ||||
-rw-r--r-- | src/shared/libmount-util.h | 37 | ||||
-rw-r--r-- | src/shared/mount-util.c | 123 | ||||
-rw-r--r-- | src/shutdown/umount.c | 13 | ||||
-rw-r--r-- | src/test/test-libmount.c | 5 |
7 files changed, 121 insertions, 136 deletions
diff --git a/meson.build b/meson.build index 33fff909b4..24ef643d44 100644 --- a/meson.build +++ b/meson.build @@ -2470,6 +2470,7 @@ exe = executable('systemd-mount', 'src/mount/mount-tool.c', include_directories : includes, link_with : [libshared], + dependencies: [libmount], install_rpath : rootlibexecdir, install : true) public_programs += exe diff --git a/src/core/mount.c b/src/core/mount.c index b7fd35fc67..e32db2bf63 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1597,31 +1597,25 @@ static int mount_setup_unit( } static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { - _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL; - _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL; + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; int r; assert(m); - t = mnt_new_table(); - i = mnt_new_iter(MNT_ITER_FORWARD); - if (!t || !i) - return log_oom(); - - r = mnt_table_parse_mtab(t, NULL); + r = libmount_parse(NULL, NULL, &table, &iter); if (r < 0) return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); for (;;) { struct libmnt_fs *fs; const char *device, *path, *options, *fstype; - int k; - k = mnt_table_next_fs(t, i, &fs); - if (k == 1) + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) break; - if (k < 0) - return log_error_errno(k, "Failed to get next entry from /proc/self/mountinfo: %m"); + if (r < 0) + return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m"); device = mnt_fs_get_source(fs); path = mnt_fs_get_target(fs); diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index b290095b0e..739f52c219 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -17,6 +17,7 @@ #include "format-util.h" #include "fs-util.h" #include "fstab-util.h" +#include "libmount-util.h" #include "main-func.h" #include "mount-util.h" #include "mountpoint-util.h" @@ -713,9 +714,11 @@ static int start_transient_automount( } static int find_mount_points(const char *what, char ***list) { - _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; _cleanup_strv_free_ char **l = NULL; size_t bufsize = 0, n = 0; + int r; assert(what); assert(list); @@ -723,55 +726,42 @@ 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. */ - proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); - if (!proc_self_mountinfo) - return log_error_errno(errno, "Can't open /proc/self/mountinfo: %m"); + r = libmount_parse(NULL, NULL, &table, &iter); + if (r < 0) + return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); for (;;) { - _cleanup_free_ char *path = NULL, *where = NULL, *dev = NULL; - int r; + struct libmnt_fs *fs; + const char *source, *target; - r = fscanf(proc_self_mountinfo, - "%*s " /* (1) mount id */ - "%*s " /* (2) parent id */ - "%*s " /* (3) major:minor */ - "%*s " /* (4) root */ - "%ms " /* (5) mount point */ - "%*s" /* (6) mount options */ - "%*[^-]" /* (7) optional fields */ - "- " /* (8) separator */ - "%*s " /* (9) file system type */ - "%ms" /* (10) mount source */ - "%*s" /* (11) mount options 2 */ - "%*[^\n]", /* some rubbish at the end */ - &path, &dev); - if (r != 2) { - if (r == EOF) - break; - - continue; - } + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) + break; + if (r < 0) + return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m"); - if (!streq(what, dev)) + source = mnt_fs_get_source(fs); + target = mnt_fs_get_target(fs); + if (!source || !target) continue; - r = cunescape(path, UNESCAPE_RELAX, &where); - if (r < 0) + if (!path_equal(source, what)) continue; /* one extra slot is needed for the terminating NULL */ - if (!GREEDY_REALLOC(l, bufsize, n + 2)) + if (!GREEDY_REALLOC0(l, bufsize, n + 2)) return log_oom(); - l[n++] = TAKE_PTR(where); + l[n] = strdup(target); + if (!l[n]) + return log_oom(); + n++; } - if (!GREEDY_REALLOC(l, bufsize, n + 1)) + if (!GREEDY_REALLOC0(l, bufsize, n + 1)) return log_oom(); - l[n] = NULL; *list = TAKE_PTR(l); - return n; } diff --git a/src/shared/libmount-util.h b/src/shared/libmount-util.h index 7d94468e52..7c3b855df5 100644 --- a/src/shared/libmount-util.h +++ b/src/shared/libmount-util.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include <stdio.h> + /* This needs to be after sys/mount.h */ #include <libmount.h> @@ -8,3 +10,38 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table); DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter); + +static inline int libmount_parse( + const char *path, + FILE *source, + struct libmnt_table **ret_table, + struct libmnt_iter **ret_iter) { + + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; + int r; + + /* Older libmount seems to require this. */ + assert(!source || path); + + table = mnt_new_table(); + iter = mnt_new_iter(MNT_ITER_FORWARD); + if (!table || !iter) + return -ENOMEM; + + /* If source or path are specified, we use on the functions which ignore utab. + * Only if both are empty, we use mnt_table_parse_mtab(). */ + + if (source) + r = mnt_table_parse_stream(table, source, path); + else if (path) + r = mnt_table_parse_file(table, path); + else + r = mnt_table_parse_mtab(table, NULL); + if (r < 0) + return r; + + *ret_table = TAKE_PTR(table); + *ret_iter = TAKE_PTR(iter); + return 0; +} diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c index 44c80f60ba..9129ad5f6b 100644 --- a/src/shared/mount-util.c +++ b/src/shared/mount-util.c @@ -8,16 +8,13 @@ #include <sys/statvfs.h> #include <unistd.h> -/* Include later */ -#include <libmount.h> - #include "alloc-util.h" -#include "escape.h" #include "extract-word.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hashmap.h" +#include "libmount-util.h" #include "mount-util.h" #include "mountpoint-util.h" #include "parse-util.h" @@ -36,52 +33,38 @@ int umount_recursive(const char *prefix, int flags) { * unmounting them until they are gone. */ do { - _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; again = false; - r = fopen_unlocked("/proc/self/mountinfo", "re", &proc_self_mountinfo); + r = libmount_parse("/proc/self/mountinfo", NULL, &table, &iter); if (r < 0) - return r; + return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m"); for (;;) { - _cleanup_free_ char *path = NULL, *p = NULL; - int k; - - k = fscanf(proc_self_mountinfo, - "%*s " /* (1) mount id */ - "%*s " /* (2) parent id */ - "%*s " /* (3) major:minor */ - "%*s " /* (4) root */ - "%ms " /* (5) mount point */ - "%*s" /* (6) mount options */ - "%*[^-]" /* (7) optional fields */ - "- " /* (8) separator */ - "%*s " /* (9) file system type */ - "%*s" /* (10) mount source */ - "%*s" /* (11) mount options 2 */ - "%*[^\n]", /* some rubbish at the end */ - &path); - if (k != 1) { - if (k == EOF) - break; + struct libmnt_fs *fs; + const char *path; - continue; - } + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) + break; + if (r < 0) + return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m"); - k = cunescape(path, UNESCAPE_RELAX, &p); - if (k < 0) - return k; + path = mnt_fs_get_target(fs); + if (!path) + continue; - if (!path_startswith(p, prefix)) + if (!path_startswith(path, prefix)) continue; - if (umount2(p, flags) < 0) { - r = log_debug_errno(errno, "Failed to umount %s: %m", p); + if (umount2(path, flags) < 0) { + r = log_debug_errno(errno, "Failed to umount %s: %m", path); continue; } - log_debug("Successfully unmounted %s", p); + log_debug("Successfully unmounted %s", path); again = true; n++; @@ -91,7 +74,7 @@ int umount_recursive(const char *prefix, int flags) { } while (again); - return r < 0 ? r : n; + return n; } static int get_mount_flags(const char *path, unsigned long *flags) { @@ -141,6 +124,8 @@ int bind_remount_recursive_with_mountinfo( for (;;) { _cleanup_set_free_free_ Set *todo = NULL; + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; bool top_autofs = false; char *x; unsigned long orig_flags; @@ -151,56 +136,45 @@ int bind_remount_recursive_with_mountinfo( rewind(proc_self_mountinfo); - for (;;) { - _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL; - int k; - - k = fscanf(proc_self_mountinfo, - "%*s " /* (1) mount id */ - "%*s " /* (2) parent id */ - "%*s " /* (3) major:minor */ - "%*s " /* (4) root */ - "%ms " /* (5) mount point */ - "%*s" /* (6) mount options (superblock) */ - "%*[^-]" /* (7) optional fields */ - "- " /* (8) separator */ - "%ms " /* (9) file system type */ - "%*s" /* (10) mount source */ - "%*s" /* (11) mount options (bind mount) */ - "%*[^\n]", /* some rubbish at the end */ - &path, - &type); - if (k != 2) { - if (k == EOF) - break; + r = libmount_parse("/proc/self/mountinfo", proc_self_mountinfo, &table, &iter); + if (r < 0) + return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m"); - continue; - } + for (;;) { + struct libmnt_fs *fs; + const char *path, *type; - r = cunescape(path, UNESCAPE_RELAX, &p); + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) + break; if (r < 0) - return r; + return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m"); - if (!path_startswith(p, cleaned)) + path = mnt_fs_get_target(fs); + type = mnt_fs_get_fstype(fs); + if (!path || !type) continue; - /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount we shall - * operate on. */ - if (!path_equal(cleaned, p)) { + if (!path_startswith(path, cleaned)) + continue; + + /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount + * we shall operate on. */ + if (!path_equal(path, cleaned)) { bool blacklisted = false; char **i; STRV_FOREACH(i, blacklist) { - if (path_equal(*i, cleaned)) continue; if (!path_startswith(*i, cleaned)) continue; - if (path_startswith(p, *i)) { + if (path_startswith(path, *i)) { blacklisted = true; - log_debug("Not remounting %s blacklisted by %s, called for %s", p, *i, cleaned); + log_debug("Not remounting %s blacklisted by %s, called for %s", + path, *i, cleaned); break; } } @@ -215,15 +189,12 @@ int bind_remount_recursive_with_mountinfo( * already triggered, then we will find * another entry for this. */ if (streq(type, "autofs")) { - top_autofs = top_autofs || path_equal(cleaned, p); + top_autofs = top_autofs || path_equal(path, cleaned); continue; } - if (!set_contains(done, p)) { - r = set_consume(todo, p); - p = NULL; - if (r == -EEXIST) - continue; + if (!set_contains(done, path)) { + r = set_put_strdup(todo, path); if (r < 0) return r; } diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index e30b475c75..c75be39fef 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -55,18 +55,13 @@ void mount_points_list_free(MountPoint **head) { } int mount_points_list_get(const char *mountinfo, MountPoint **head) { - _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL; - _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL; + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; int r; assert(head); - t = mnt_new_table(); - i = mnt_new_iter(MNT_ITER_FORWARD); - if (!t || !i) - return log_oom(); - - r = mnt_table_parse_mtab(t, mountinfo); + r = libmount_parse(mountinfo, NULL, &table, &iter); if (r < 0) return log_error_errno(r, "Failed to parse %s: %m", mountinfo); @@ -79,7 +74,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) { bool try_remount_ro; _cleanup_free_ MountPoint *m = NULL; - r = mnt_table_next_fs(t, i, &fs); + r = mnt_table_next_fs(table, iter, &fs); if (r == 1) break; if (r < 0) diff --git a/src/test/test-libmount.c b/src/test/test-libmount.c index fc28f27d53..c3395493d4 100644 --- a/src/test/test-libmount.c +++ b/src/test/test-libmount.c @@ -21,13 +21,10 @@ static void test_libmount_unescaping_one( _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; _cleanup_fclose_ FILE *f = NULL; - assert_se(table = mnt_new_table()); - assert_se(iter = mnt_new_iter(MNT_ITER_FORWARD)); - f = fmemopen((char*) string, strlen(string), "re"); assert_se(f); - assert_se(mnt_table_parse_stream(table, f, title) >= 0); + assert_se(libmount_parse(title, f, &table, &iter) >= 0); struct libmnt_fs *fs; const char *source, *target; |