From c0552b359c5b5dc0c130b831ce0067af99149f27 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Apr 2023 05:04:27 +0900 Subject: [PATCH 1/9] chase: make chaseat() provides absolute path also when dir_fd points to the root directory Usually, we pass the file descriptor of the root directory to chaseat() when `--root=` is not specified. Previously, even in such case, the result was relative, and we need to prefix the path with "/" when we want to pass the path to other functions that do not support dir_fd, or log or show the path. That's inconvenient. --- src/basic/chase.c | 5 +++-- src/test/test-chase.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/basic/chase.c b/src/basic/chase.c index eb4bda07a6..a6a37978e8 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -190,8 +190,9 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int return -ENOMEM; /* If we receive an absolute path together with AT_FDCWD, we need to return an absolute path, because - * a relative path would be interpreted relative to the current working directory. */ - bool need_absolute = dir_fd == AT_FDCWD && path_is_absolute(path); + * a relative path would be interpreted relative to the current working directory. Also, let's make + * the result absolute when the file descriptor of the root directory is specified. */ + bool need_absolute = (dir_fd == AT_FDCWD && path_is_absolute(path)) || dir_fd_is_root(dir_fd) > 0; if (need_absolute) { done = strdup("/"); if (!done) diff --git a/src/test/test-chase.c b/src/test/test-chase.c index 1e98f5c6ed..52ea21a54c 100644 --- a/src/test/test-chase.c +++ b/src/test/test-chase.c @@ -442,6 +442,34 @@ TEST(chaseat) { assert_se(streq(result, "/usr")); result = mfree(result); + /* If the file descriptor points to the root directory, the result will be absolute. */ + + fd = open("/", O_CLOEXEC | O_DIRECTORY | O_PATH); + assert_se(fd >= 0); + + assert_se(chaseat(fd, p, 0, &result, NULL) >= 0); + assert_se(streq(result, "/usr")); + result = mfree(result); + + assert_se(chaseat(fd, p, CHASE_AT_RESOLVE_IN_ROOT, &result, NULL) >= 0); + assert_se(streq(result, "/usr")); + result = mfree(result); + + fd = safe_close(fd); + + /* If the file descriptor does not point to the root directory, the result will be relative. */ + + assert_se(chaseat(tfd, "abc", CHASE_AT_RESOLVE_IN_ROOT, NULL, NULL) == -ENOENT); + assert_se(chaseat(tfd, "/abc", CHASE_AT_RESOLVE_IN_ROOT, NULL, NULL) == -ENOENT); + + assert_se(chaseat(tfd, "abc", CHASE_AT_RESOLVE_IN_ROOT | CHASE_NONEXISTENT, &result, NULL) >= 0); + assert_se(streq(result, "usr")); + result = mfree(result); + + assert_se(chaseat(tfd, "/abc", CHASE_AT_RESOLVE_IN_ROOT | CHASE_NONEXISTENT, &result, NULL) >= 0); + assert_se(streq(result, "usr")); + result = mfree(result); + /* Test that absolute path or not are the same when resolving relative to a directory file * descriptor and that we always get a relative path back. */ From 24be89ebd8e9fbf97cb60c304b615ab26869c204 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Apr 2023 05:19:07 +0900 Subject: [PATCH 2/9] chase: make the result absolute when a symlink is absolute As the path may be outside of the specified dir_fd. --- src/basic/chase.c | 5 +++++ src/test/test-chase.c | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/basic/chase.c b/src/basic/chase.c index a6a37978e8..2b8befc7f7 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -374,6 +374,11 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int unsafe_transition(&st_child, &st)) return log_unsafe_transition(child, fd, path, flags); + /* When CHASE_AT_RESOLVE_IN_ROOT is not set, now the chased path may be + * outside of the specified dir_fd. Let's make the result absolute. */ + if (!FLAGS_SET(flags, CHASE_AT_RESOLVE_IN_ROOT)) + need_absolute = true; + r = free_and_strdup(&done, need_absolute ? "/" : NULL); if (r < 0) return r; diff --git a/src/test/test-chase.c b/src/test/test-chase.c index 52ea21a54c..c5fc08ca25 100644 --- a/src/test/test-chase.c +++ b/src/test/test-chase.c @@ -457,7 +457,16 @@ TEST(chaseat) { fd = safe_close(fd); - /* If the file descriptor does not point to the root directory, the result will be relative. */ + /* If the file descriptor does not point to the root directory, the result will be relative + * unless the result is outside of the specified file descriptor. */ + + assert_se(chaseat(tfd, "abc", 0, &result, NULL) >= 0); + assert_se(streq(result, "/usr")); + result = mfree(result); + + assert_se(chaseat(tfd, "/abc", 0, &result, NULL) >= 0); + assert_se(streq(result, "/usr")); + result = mfree(result); assert_se(chaseat(tfd, "abc", CHASE_AT_RESOLVE_IN_ROOT, NULL, NULL) == -ENOENT); assert_se(chaseat(tfd, "/abc", CHASE_AT_RESOLVE_IN_ROOT, NULL, NULL) == -ENOENT); From b3ef56bc8e5fdf7e26c2a544bd89fbc31b5b9b70 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Apr 2023 05:47:25 +0900 Subject: [PATCH 3/9] chase: update outdated comment about result path --- src/basic/chase.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/basic/chase.c b/src/basic/chase.c index 2b8befc7f7..2fb7faa444 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -111,12 +111,26 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int * given directory file descriptor, even if it is absolute. If the given directory file descriptor is * AT_FDCWD and "path" is absolute, it is interpreted relative to the root directory of the host. * - * If "dir_fd" is a valid directory fd, "path" is an absolute path and "ret_path" is not NULL, this - * functions returns a relative path in "ret_path" because openat() like functions generally ignore - * the directory fd if they are provided with an absolute path. On the other hand, if "dir_fd" is - * AT_FDCWD and "path" is an absolute path, we return an absolute path in "ret_path" because - * otherwise, if the caller passes the returned relative path to another openat() like function, it - * would be resolved relative to the current working directory instead of to "/". + * When "dir_fd" points to a non-root directory and CHASE_AT_RESOLVE_IN_ROOT is set, this function + * always returns a relative path in "ret_path", even if "path" is an absolute path, because openat() + * like functions generally ignore the directory fd if they are provided with an absolute path. When + * CHASE_AT_RESOLVE_IN_ROOT is not set, then this returns relative path to the specified file + * descriptor if all resolved symlinks are relative, otherwise absolute path will be returned. When + * "dir_fd" is AT_FDCWD and "path" is an absolute path, we return an absolute path in "ret_path" + * because otherwise, if the caller passes the returned relative path to another openat() like + * function, it would be resolved relative to the current working directory instead of to "/". + * + * Summary about the result path: + * - "dir_fd" points to the root directory + * → result will be absolute + * - "dir_fd" points to a non-root directory, and CHASE_AT_RESOLVE_IN_ROOT is set + * → relative + * - "dir_fd" points to a non-root directory, and CHASE_AT_RESOLVE_IN_ROOT is not set + * → relative when all resolved symlinks are relative, otherwise absolute + * - "dir_fd" is AT_FDCWD, and "path" is absolute + * → absolute + * - "dir_fd" is AT_FDCWD, and "path" is relative + * → relative when all resolved symlinks are relative, otherwise absolute * * Algorithmically this operates on two path buffers: "done" are the components of the path we * already processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we From 237bf933deca3093130ca0fee106a676d4ba47d0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Apr 2023 15:24:05 +0900 Subject: [PATCH 4/9] chase: drop repeated call of empty_to_root() --- src/basic/chase.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/basic/chase.c b/src/basic/chase.c index 2fb7faa444..aff2bfc3b7 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -494,8 +494,8 @@ chased_one: return 0; } -int chase(const char *path, const char *original_root, ChaseFlags flags, char **ret_path, int *ret_fd) { - _cleanup_free_ char *root = NULL, *absolute = NULL, *p = NULL; +int chase(const char *path, const char *root, ChaseFlags flags, char **ret_path, int *ret_fd) { + _cleanup_free_ char *root_abs = NULL, *absolute = NULL, *p = NULL; _cleanup_close_ int fd = -EBADF, pfd = -EBADF; int r; @@ -504,18 +504,17 @@ int chase(const char *path, const char *original_root, ChaseFlags flags, char ** if (isempty(path)) return -EINVAL; - /* A root directory of "/" or "" is identical to none */ - if (empty_or_root(original_root)) - original_root = NULL; - - if (original_root) { - r = path_make_absolute_cwd(original_root, &root); + /* A root directory of "/" or "" is identical to "/". */ + if (empty_or_root(root)) + root = "/"; + else { + r = path_make_absolute_cwd(root, &root_abs); if (r < 0) return r; /* Simplify the root directory, so that it has no duplicate slashes and nothing at the * end. While we won't resolve the root path we still simplify it. */ - path_simplify(root); + root = path_simplify(root_abs); assert(path_is_absolute(root)); assert(!empty_or_root(root)); @@ -535,14 +534,14 @@ int chase(const char *path, const char *original_root, ChaseFlags flags, char ** return r; } - path = path_startswith(absolute, empty_to_root(root)); + path = path_startswith(absolute, root); if (!path) return log_full_errno(FLAGS_SET(flags, CHASE_WARN) ? LOG_WARNING : LOG_DEBUG, SYNTHETIC_ERRNO(ECHRNG), "Specified path '%s' is outside of specified root directory '%s', refusing to resolve.", - absolute, empty_to_root(root)); + absolute, root); - fd = open(empty_to_root(root), O_CLOEXEC|O_DIRECTORY|O_PATH); + fd = open(root, O_CLOEXEC|O_DIRECTORY|O_PATH); if (fd < 0) return -errno; @@ -554,7 +553,7 @@ int chase(const char *path, const char *original_root, ChaseFlags flags, char ** if (!FLAGS_SET(flags, CHASE_EXTRACT_FILENAME)) { _cleanup_free_ char *q = NULL; - q = path_join(empty_to_root(root), p); + q = path_join(root, p); if (!q) return -ENOMEM; From 9a0dcf03faaf73527085c470f0ddf77e0457aecf Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Apr 2023 15:28:42 +0900 Subject: [PATCH 5/9] chase: prefix with the root directory only when it is not "/" --- src/basic/chase.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/basic/chase.c b/src/basic/chase.c index aff2bfc3b7..96b59e7845 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -551,19 +551,27 @@ int chase(const char *path, const char *root, ChaseFlags flags, char **ret_path, if (ret_path) { if (!FLAGS_SET(flags, CHASE_EXTRACT_FILENAME)) { - _cleanup_free_ char *q = NULL; - q = path_join(root, p); - if (!q) - return -ENOMEM; + /* When "root" points to the root directory, the result of chaseat() is always + * absolute, hence it is not necessary to prefix with the root. When "root" points to + * a non-root directory, the result path is always normalized and relative, hence + * we can simply call path_join() and not necessary to call path_simplify(). + * Note that the result of chaseat() may start with "." (more specifically, it may be + * "." or "./"), and we need to drop "." in that case. */ - path_simplify(q); + if (empty_or_root(root)) + assert(path_is_absolute(p)); + else { + char *q; - if (FLAGS_SET(flags, CHASE_TRAIL_SLASH) && ENDSWITH_SET(path, "/", "/.")) - if (!strextend(&q, "/")) + assert(!path_is_absolute(p)); + + q = path_join(root, p + (*p == '.')); + if (!q) return -ENOMEM; - free_and_replace(p, q); + free_and_replace(p, q); + } } *ret_path = TAKE_PTR(p); From 4b1e461c49ea935df0c740b31aecfd161b12d2e7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Apr 2023 23:26:47 +0900 Subject: [PATCH 6/9] mountpoint-util: check /proc is mounted on failure --- src/basic/mountpoint-util.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c index db36b2f2f6..e28ca825b3 100644 --- a/src/basic/mountpoint-util.c +++ b/src/basic/mountpoint-util.c @@ -123,7 +123,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *ret_mn r = read_full_virtual_file(path, &fdinfo, NULL); if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */ - return -EOPNOTSUPP; + return proc_mounted() > 0 ? -EOPNOTSUPP : -ENOSYS; if (r < 0) return r; @@ -280,7 +280,7 @@ int fd_is_mount_point(int fd, const char *filename, int flags) { fallback_fdinfo: r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); - if (IN_SET(r, -EOPNOTSUPP, -EACCES, -EPERM)) + if (IN_SET(r, -EOPNOTSUPP, -EACCES, -EPERM, -ENOSYS)) goto fallback_fstat; if (r < 0) return r; @@ -549,6 +549,8 @@ int dev_is_devtmpfs(void) { return r; r = fopen_unlocked("/proc/self/mountinfo", "re", &proc_self_mountinfo); + if (r == -ENOENT) + return proc_mounted() > 0 ? -ENOENT : -ENOSYS; if (r < 0) return r; From 8d3c49b1680a20ae5d157baa4adaa59c1ea33519 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Apr 2023 23:37:12 +0900 Subject: [PATCH 7/9] fd-util: skip to check mount ID if kernel is too old and /proc is not mounted Now, dir_fd_is_root() is heavily used in chaseat(), which is used at various places. If the kernel is too old and /proc is not mounted, then there is no way to get the mount ID of a directory. In that case, let's silently skip the mount ID check. Fixes https://github.com/systemd/systemd/pull/27299#issuecomment-1511403680. --- src/basic/fd-util.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c index 7125e28e1b..974a7aac65 100644 --- a/src/basic/fd-util.c +++ b/src/basic/fd-util.c @@ -911,10 +911,23 @@ int dir_fd_is_root(int dir_fd) { if (!statx_inode_same(&st.sx, &pst.sx)) return false; + /* Even if the parent directory has the same inode, the fd may not point to the root directory "/", + * and we also need to check that the mount ids are the same. Otherwise, a construct like the + * following could be used to trick us: + * + * $ mkdir /tmp/x /tmp/x/y + * $ mount --bind /tmp/x /tmp/x/y + * + * Note, statx() does not provide the mount ID and path_get_mnt_id_at() does not work when an old + * kernel is used without /proc mounted. In that case, let's assume that we do not have such spurious + * mount points in an early boot stage, and silently skip the following check. */ + if (!FLAGS_SET(st.nsx.stx_mask, STATX_MNT_ID)) { int mntid; r = path_get_mnt_id_at(dir_fd, "", &mntid); + if (r == -ENOSYS) + return true; /* skip the mount ID check */ if (r < 0) return r; assert(mntid >= 0); @@ -927,6 +940,8 @@ int dir_fd_is_root(int dir_fd) { int mntid; r = path_get_mnt_id_at(dir_fd, "..", &mntid); + if (r == -ENOSYS) + return true; /* skip the mount ID check */ if (r < 0) return r; assert(mntid >= 0); @@ -935,13 +950,6 @@ int dir_fd_is_root(int dir_fd) { pst.nsx.stx_mask |= STATX_MNT_ID; } - /* Even if the parent directory has the same inode, the fd may not point to the root directory "/", - * and we also need to check that the mount ids are the same. Otherwise, a construct like the - * following could be used to trick us: - * - * $ mkdir /tmp/x /tmp/x/y - * $ mount --bind /tmp/x /tmp/x/y - */ return statx_mount_same(&st.nsx, &pst.nsx); } From 60e761d8f3e14ebbadb26f2e2ca2c225f97660ef Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 18 Apr 2023 00:09:54 +0900 Subject: [PATCH 8/9] chase: replace path_prefix_root_cwd() with chaseat_prefix_root() The function path_prefix_root_cwd() was introduced for prefixing the result from chaseat() with root, but - it is named slightly generic, - the logic is different from what chase() does. This makes the name more explanative and specific for the result of the chaseat(), and make the logic consistent with chase(). Fixes https://github.com/systemd/systemd/pull/27199#issuecomment-1511387731. Follow-up for #27199. --- src/basic/chase.c | 31 +++++++++++++++++++++++++++++++ src/basic/chase.h | 2 ++ src/basic/os-util.c | 4 ++-- src/basic/path-util.c | 28 ---------------------------- src/basic/path-util.h | 1 - src/shared/find-esp.c | 4 ++-- src/test/test-chase.c | 37 +++++++++++++++++++++++++++++++++++++ src/test/test-path-util.c | 39 --------------------------------------- 8 files changed, 74 insertions(+), 72 deletions(-) diff --git a/src/basic/chase.c b/src/basic/chase.c index 96b59e7845..373252b645 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -583,6 +583,37 @@ int chase(const char *path, const char *root, ChaseFlags flags, char **ret_path, return r; } +int chaseat_prefix_root(const char *path, const char *root, char **ret) { + char *q; + int r; + + assert(path); + assert(ret); + + /* This is mostly for prefixing the result of chaseat(). */ + + if (!path_is_absolute(path)) { + _cleanup_free_ char *root_abs = NULL; + + /* If the dir_fd points to the root directory, chaseat() always returns an absolute path. */ + assert(!empty_or_root(root)); + + r = path_make_absolute_cwd(root, &root_abs); + if (r < 0) + return r; + + root = path_simplify(root_abs); + + q = path_join(root, path + (path[0] == '.' && IN_SET(path[1], '/', '\0'))); + } else + q = strdup(path); + if (!q) + return -ENOMEM; + + *ret = q; + return 0; +} + int chase_and_open(const char *path, const char *root, ChaseFlags chase_flags, int open_flags, char **ret_path) { _cleanup_close_ int path_fd = -EBADF; _cleanup_free_ char *p = NULL, *fname = NULL; diff --git a/src/basic/chase.h b/src/basic/chase.h index 40121f7d70..f37e836822 100644 --- a/src/basic/chase.h +++ b/src/basic/chase.h @@ -42,6 +42,8 @@ bool unsafe_transition(const struct stat *a, const struct stat *b); int chase(const char *path_with_prefix, const char *root, ChaseFlags chase_flags, char **ret_path, int *ret_fd); +int chaseat_prefix_root(const char *path, const char *root, char **ret); + int chase_and_open(const char *path, const char *root, ChaseFlags chase_flags, int open_flags, char **ret_path); int chase_and_opendir(const char *path, const char *root, ChaseFlags chase_flags, char **ret_path, DIR **ret_dir); int chase_and_stat(const char *path, const char *root, ChaseFlags chase_flags, char **ret_path, struct stat *ret_stat); diff --git a/src/basic/os-util.c b/src/basic/os-util.c index dd8faf2376..5d06e20871 100644 --- a/src/basic/os-util.c +++ b/src/basic/os-util.c @@ -155,7 +155,7 @@ int open_os_release(const char *root, char **ret_path, int *ret_fd) { return r; if (ret_path) { - r = path_prefix_root_cwd(p, root, ret_path); + r = chaseat_prefix_root(p, root, ret_path); if (r < 0) return r; } @@ -292,7 +292,7 @@ int open_extension_release( return r; if (ret_path) { - r = path_prefix_root_cwd(p, root, ret_path); + r = chaseat_prefix_root(p, root, ret_path); if (r < 0) return r; } diff --git a/src/basic/path-util.c b/src/basic/path-util.c index fa2e26789f..0b0f0da760 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -100,34 +100,6 @@ int path_make_absolute_cwd(const char *p, char **ret) { return 0; } -int path_prefix_root_cwd(const char *p, const char *root, char **ret) { - _cleanup_free_ char *root_abs = NULL; - char *c; - int r; - - assert(p); - assert(ret); - - /* Unlike path_make_absolute(), this always prefixes root path if specified. - * The root path is always simplified, but the provided path will not. - * This is useful for prefixing the result of chaseat(). */ - - if (empty_or_root(root)) - return path_make_absolute_cwd(p, ret); - - r = path_make_absolute_cwd(root, &root_abs); - if (r < 0) - return r; - - path_simplify(root_abs); - c = path_join(root_abs, p); - if (!c) - return -ENOMEM; - - *ret = c; - return 0; -} - int path_make_relative(const char *from, const char *to, char **ret) { _cleanup_free_ char *result = NULL; unsigned n_parents; diff --git a/src/basic/path-util.h b/src/basic/path-util.h index a0af9de674..7843599816 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -60,7 +60,6 @@ int path_split_and_make_absolute(const char *p, char ***ret); char* path_make_absolute(const char *p, const char *prefix); int safe_getcwd(char **ret); int path_make_absolute_cwd(const char *p, char **ret); -int path_prefix_root_cwd(const char *p, const char *root, char **ret); int path_make_relative(const char *from, const char *to, char **ret); int path_make_relative_parent(const char *from_child, const char *to, char **ret); char *path_startswith_full(const char *path, const char *prefix, bool accept_dot_dot) _pure_; diff --git a/src/shared/find-esp.c b/src/shared/find-esp.c index 6a0002a2bd..c4cf508517 100644 --- a/src/shared/find-esp.c +++ b/src/shared/find-esp.c @@ -540,7 +540,7 @@ int find_esp_and_warn( return r; if (ret_path) { - r = path_prefix_root_cwd(p, root, ret_path); + r = chaseat_prefix_root(p, root, ret_path); if (r < 0) return r; } @@ -859,7 +859,7 @@ int find_xbootldr_and_warn( return r; if (ret_path) { - r = path_prefix_root_cwd(p, root, ret_path); + r = chaseat_prefix_root(p, root, ret_path); if (r < 0) return r; } diff --git a/src/test/test-chase.c b/src/test/test-chase.c index c5fc08ca25..558f4109e3 100644 --- a/src/test/test-chase.c +++ b/src/test/test-chase.c @@ -648,4 +648,41 @@ static int intro(void) { return EXIT_SUCCESS; } +TEST(chaseat_prefix_root) { + _cleanup_free_ char *cwd = NULL, *ret = NULL, *expected = NULL; + + assert_se(safe_getcwd(&cwd) >= 0); + + assert_se(chaseat_prefix_root("/hoge", NULL, &ret) >= 0); + assert_se(streq(ret, "/hoge")); + + ret = mfree(ret); + + assert_se(chaseat_prefix_root("/hoge", "a/b/c", &ret) >= 0); + assert_se(streq(ret, "/hoge")); + + ret = mfree(ret); + + assert_se(chaseat_prefix_root("hoge", "/a/b//./c///", &ret) >= 0); + assert_se(streq(ret, "/a/b/c/hoge")); + + ret = mfree(ret); + + assert_se(chaseat_prefix_root("hoge", "a/b//./c///", &ret) >= 0); + assert_se(expected = path_join(cwd, "a/b/c/hoge")); + assert_se(streq(ret, expected)); + + ret = mfree(ret); + expected = mfree(expected); + + assert_se(chaseat_prefix_root("./hoge/aaa/../././b", "/a/b//./c///", &ret) >= 0); + assert_se(streq(ret, "/a/b/c/hoge/aaa/../././b")); + + ret = mfree(ret); + + assert_se(chaseat_prefix_root("./hoge/aaa/../././b", "a/b//./c///", &ret) >= 0); + assert_se(expected = path_join(cwd, "a/b/c/hoge/aaa/../././b")); + assert_se(streq(ret, expected)); +} + DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro); diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 22e8f3481a..e40ffea4d5 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -494,45 +494,6 @@ TEST(fsck_exists) { assert_se(fsck_exists_for_fstype("/../bin/") == 0); } -TEST(path_prefix_root_cwd) { - _cleanup_free_ char *cwd = NULL, *ret = NULL, *expected = NULL; - - assert_se(safe_getcwd(&cwd) >= 0); - - assert_se(path_prefix_root_cwd("hoge", NULL, &ret) >= 0); - assert_se(expected = path_join(cwd, "hoge")); - assert_se(streq(ret, expected)); - - ret = mfree(ret); - expected = mfree(expected); - - assert_se(path_prefix_root_cwd("/hoge", NULL, &ret) >= 0); - assert_se(streq(ret, "/hoge")); - - ret = mfree(ret); - - assert_se(path_prefix_root_cwd("hoge", "/a/b//./c///", &ret) >= 0); - assert_se(streq(ret, "/a/b/c/hoge")); - - ret = mfree(ret); - - assert_se(path_prefix_root_cwd("hoge", "a/b//./c///", &ret) >= 0); - assert_se(expected = path_join(cwd, "a/b/c/hoge")); - assert_se(streq(ret, expected)); - - ret = mfree(ret); - expected = mfree(expected); - - assert_se(path_prefix_root_cwd("/../hoge/aaa/../././b", "/a/b//./c///", &ret) >= 0); - assert_se(streq(ret, "/a/b/c/../hoge/aaa/../././b")); - - ret = mfree(ret); - - assert_se(path_prefix_root_cwd("/../hoge/aaa/../././b", "a/b//./c///", &ret) >= 0); - assert_se(expected = path_join(cwd, "a/b/c/../hoge/aaa/../././b")); - assert_se(streq(ret, expected)); -} - static void test_path_make_relative_one(const char *from, const char *to, const char *expected) { _cleanup_free_ char *z = NULL; int r; From c19f1cc9a5ef20f37e890df65fb9b8b95a0b18fa Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 19 Apr 2023 04:04:40 +0900 Subject: [PATCH 9/9] test: add regression tests for find_esp() and friend --- test/test-bootctl-json.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/test-bootctl-json.sh b/test/test-bootctl-json.sh index fde5fbd1de..4d7c468241 100755 --- a/test/test-bootctl-json.sh +++ b/test/test-bootctl-json.sh @@ -28,6 +28,15 @@ command -v jq >/dev/null || { "$bootctl" -R || test "$?" -eq 80 "$bootctl" -RR || test "$?" -eq 80 +# regression tests for +# https://github.com/systemd/systemd/pull/27199#issuecomment-1511387731 +if ret=$("$bootctl" --print-esp-path); then + test "$ret" = "/efi" -o "$ret" = "/boot" -o "$ret" = "/boot/efi" +fi +if ret=$("bootctl" --print-boot-path); then + test "$ret" = "/efi" -o "$ret" = "/boot" -o "$ret" = "/boot/efi" +fi + if "$bootctl" -R > /dev/null ; then P=$("$bootctl" -R) PP=$("$bootctl" -RR)