From 7d991d4818dcf55916c1076003c3508c91df9934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 4 Apr 2019 13:41:47 +0200 Subject: [PATCH] mount-tool: use libmount to parse /proc/self/mountinfo Same motivation as in other places: let's use a single logic to parse this. Use path_equal() to compare the path. A bug in error handling is fixed: if we failed after the GREEDY_REALLOC but before the line that sets the last item to NULL, we would jump to _cleanup_strv_free_ with the strv unterminated. Let's use GREEDY_REALLOC0 to avoid the issue. --- meson.build | 1 + src/mount/mount-tool.c | 67 +++++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/meson.build b/meson.build index 15e3394b91..d24e8000e9 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/mount/mount-tool.c b/src/mount/mount-tool.c index b290095b0e..fc18dd28d7 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,47 @@ 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"); + table = mnt_new_table(); + iter = mnt_new_iter(MNT_ITER_FORWARD); + if (!table || !iter) + return log_oom(); + + r = mnt_table_parse_mtab(table, NULL); + 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; - } - - if (!streq(what, dev)) - continue; - - r = cunescape(path, UNESCAPE_RELAX, &where); + 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"); + + source = mnt_fs_get_source(fs); + target = mnt_fs_get_target(fs); + if (!source || !target) + continue; + + 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; }