From a1904a46630694d65ba333418cf0c9590598f3e5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 1 Dec 2017 02:19:44 +0900 Subject: [PATCH 1/7] fs-util: chase_symlinks(): remove unnecessary slash at the head Before this, chase_symlinks("/../../foo/bar",...) returns //foo/bar. This removes the unnecessary slash at the head. --- src/basic/fs-util.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 475400177a6..3fe5c7cf133 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -722,6 +722,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, * what we got so far. But don't allow this if the remaining path contains "../ or "./" * or something else weird. */ + /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */ + if (streq_ptr(done, "/")) + *done = '\0'; + if (!strextend(&done, first, todo, NULL)) return -ENOMEM; @@ -794,6 +798,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, done = first; first = NULL; } else { + /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */ + if (streq(done, "/")) + *done = '\0'; + if (!strextend(&done, first, NULL)) return -ENOMEM; } From 46e92680e0a4edc6ca2817b80cc150d67d43d00b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 1 Dec 2017 01:15:42 +0900 Subject: [PATCH 2/7] fs-util: remove comment about non-existing function --- src/basic/fs-util.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 3fe5c7cf133..aa33da48b0d 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -621,10 +621,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this * function what to do when encountering a symlink with an absolute path as directory: prefix it by the - * specified path. - * - * Note: there's also chase_symlinks_prefix() (see below), which as first step prefixes the passed path by the - * passed root. */ + * specified path. */ if (original_root) { r = path_make_absolute_cwd(original_root, &root); From cd76d4c2fe34df5c941e7b4a71b8bd2ca954fdd6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 1 Dec 2017 02:23:53 +0900 Subject: [PATCH 3/7] test-fs-util: save current directory name --- src/test/test-fs-util.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 83ddc398b88..81aa9856b76 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -242,6 +242,7 @@ static void test_readlink_and_make_absolute(void) { char name2[] = "test-readlink_and_make_absolute/original"; char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias"; char *r = NULL; + _cleanup_free_ char *pwd = NULL; assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid(), false) >= 0); assert_se(touch(name) >= 0); @@ -252,6 +253,8 @@ static void test_readlink_and_make_absolute(void) { free(r); assert_se(unlink(name_alias) >= 0); + assert_se(pwd = get_current_dir_name()); + assert_se(chdir(tempdir) >= 0); assert_se(symlink(name2, name_alias) >= 0); assert_se(readlink_and_make_absolute(name_alias, &r) >= 0); @@ -259,6 +262,8 @@ static void test_readlink_and_make_absolute(void) { free(r); assert_se(unlink(name_alias) >= 0); + assert_se(chdir(pwd) >= 0); + assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } From 95f35cccf045b76cd2a4c28d873c239f5b50f638 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 3 Dec 2017 00:28:50 +0900 Subject: [PATCH 4/7] test-fs-util: add more tests for chase_symlinks() --- src/test/test-fs-util.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 81aa9856b76..86d963c4c78 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -168,6 +168,26 @@ static void test_chase_symlinks(void) { assert_se(r > 0 && path_equal(result, "/etc")); result = mfree(result); + r = chase_symlinks("/../.././//../../etc", NULL, 0, &result); + assert_se(r > 0); + assert_se(streq(result, "/etc")); + result = mfree(result); + + r = chase_symlinks("/../.././//../../test-chase.fsldajfl", NULL, CHASE_NONEXISTENT, &result); + assert_se(r == 0); + assert_se(streq(result, "/test-chase.fsldajfl")); + result = mfree(result); + + r = chase_symlinks("/../.././//../../etc", "/", CHASE_PREFIX_ROOT, &result); + assert_se(r > 0); + assert_se(streq(result, "/etc")); + result = mfree(result); + + r = chase_symlinks("/../.././//../../test-chase.fsldajfl", "/", CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &result); + assert_se(r == 0); + assert_se(streq(result, "/test-chase.fsldajfl")); + result = mfree(result); + r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result); assert_se(r == -ENOTDIR); result = mfree(result); From 6442c2109c18af9fd208b2631cacaf1347c384a7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 30 Nov 2017 17:55:04 +0900 Subject: [PATCH 5/7] mount: ignore error when stop non-existing automount unit The command `systemd-mount -u` tries to stop both mount and automount units. If the corresponding mount unit does not exist, then it is user's fault, that is, the specified path is not a mount point. However, not all mount units have corresponding autmount units. Thus, the error about non-existing automount unit is not user's falut, and showing the error may confuse users. So, let's ignore the error of such case. --- src/mount/mount-tool.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index dd5f62e824c..f9ac20be5b8 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -829,7 +829,7 @@ static int stop_mount( r = unit_name_from_path(where, suffix, &mount_unit); if (r < 0) - return log_error_errno(r, "Failed to make mount unit name from path %s: %m", where); + return log_error_errno(r, "Failed to make %s unit name from path %s: %m", suffix + 1, where); r = sd_bus_message_new_method_call( bus, @@ -853,8 +853,12 @@ static int stop_mount( polkit_agent_open_if_enabled(arg_transport, arg_ask_password); r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) - return log_error_errno(r, "Failed to stop mount unit: %s", bus_error_message(&error, r)); + if (r < 0) { + if (streq(suffix, ".automount") && + sd_bus_error_has_name(&error, "org.freedesktop.systemd1.NoSuchUnit")) + return 0; + return log_error_errno(r, "Failed to stop %s unit: %s", suffix + 1, bus_error_message(&error, r)); + } if (w) { const char *object; From f4938c2ea523336b11572af6111acd07107fa3dd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 1 Dec 2017 01:27:53 +0900 Subject: [PATCH 6/7] mount: do not require that the specified directory exists If the specified direcotry does not exist, then systemd creates it when the mount unit starts. So, it is not necessary to check the existence in the client tool. --- src/mount/mount-tool.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index f9ac20be5b8..b454c455184 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -30,6 +30,7 @@ #include "escape.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "fstab-util.h" #include "mount-util.h" #include "pager.h" @@ -361,16 +362,9 @@ static int parse_argv(int argc, char *argv[]) { if (argc > optind+1) { if (arg_transport == BUS_TRANSPORT_LOCAL) { - _cleanup_free_ char *p = NULL; - - r = path_make_absolute_cwd(argv[optind+1], &p); + r = chase_symlinks(argv[optind+1], NULL, CHASE_NONEXISTENT, &arg_mount_where); if (r < 0) return log_error_errno(r, "Failed to make path %s absolute: %m", argv[optind+1]); - - arg_mount_where = canonicalize_file_name(p); - if (!arg_mount_where) - return log_error_errno(errno, "Failed to canonicalize path %s: %m", p); - } else { arg_mount_where = strdup(argv[optind+1]); if (!arg_mount_where) From 5bc9f949a4b1496aac0e9aeda675e041119ffa92 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 1 Dec 2017 01:28:44 +0900 Subject: [PATCH 7/7] mount: use chase_symlinks() --- src/mount/mount-tool.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index b454c455184..da3647e7e2f 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -334,19 +334,15 @@ static int parse_argv(int argc, char *argv[]) { return log_oom(); } else if (arg_transport == BUS_TRANSPORT_LOCAL) { - _cleanup_free_ char *u = NULL, *p = NULL; + _cleanup_free_ char *u = NULL; u = fstab_node_to_udev_node(argv[optind]); if (!u) return log_oom(); - r = path_make_absolute_cwd(u, &p); + r = chase_symlinks(u, NULL, 0, &arg_mount_what); if (r < 0) return log_error_errno(r, "Failed to make path %s absolute: %m", u); - - arg_mount_what = canonicalize_file_name(p); - if (!arg_mount_what) - return log_error_errno(errno, "Failed to canonicalize path %s: %m", p); } else { arg_mount_what = strdup(argv[optind]); if (!arg_mount_what) @@ -989,26 +985,19 @@ static int action_umount( } for (i = optind; i < argc; i++) { - _cleanup_free_ char *u = NULL, *a = NULL, *p = NULL; + _cleanup_free_ char *u = NULL, *p = NULL; struct stat st; u = fstab_node_to_udev_node(argv[i]); if (!u) return log_oom(); - r = path_make_absolute_cwd(u, &a); + r = chase_symlinks(u, NULL, 0, &p); if (r < 0) { r2 = log_error_errno(r, "Failed to make path %s absolute: %m", argv[i]); continue; } - p = canonicalize_file_name(a); - - if (!p) { - r2 = log_error_errno(errno, "Failed to canonicalize path %s: %m", argv[i]); - continue; - } - if (stat(p, &st) < 0) return log_error_errno(errno, "Can't stat %s (from %s): %m", p, argv[i]);