summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2019-04-30 19:44:17 +0200
committerGitHub <noreply@github.com>2019-04-30 19:44:17 +0200
commitadb7b782f83ca076b09b60a905f9ffb311835693 (patch)
tree048032608f772a273f4177b866c49e0448a97fe5
parent9f3f596477ba68d4ece645536586756caea4ae97 (diff)
parent2f2d81d957b2d5ef7a0f8a702dcf7f71348cffe3 (diff)
downloadsystemd-adb7b782f83ca076b09b60a905f9ffb311835693.tar.gz
Merge pull request #12218 from keszybz/use-libmount-more
Use libmount more
-rw-r--r--meson.build1
-rw-r--r--src/core/mount.c20
-rw-r--r--src/mount/mount-tool.c58
-rw-r--r--src/shared/libmount-util.h37
-rw-r--r--src/shared/mount-util.c123
-rw-r--r--src/shutdown/umount.c13
-rw-r--r--src/test/test-libmount.c5
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;