mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 08:56:15 +09:00
Merge pull request #27299 from yuwata/chase-absolute
chase: return absolute path when dir_fd points to the root directory
This commit is contained in:
@@ -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
|
||||
@@ -190,8 +204,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)
|
||||
@@ -373,6 +388,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;
|
||||
@@ -474,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;
|
||||
|
||||
@@ -484,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));
|
||||
@@ -515,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;
|
||||
|
||||
@@ -532,19 +551,27 @@ int chase(const char *path, const char *original_root, ChaseFlags flags, char **
|
||||
|
||||
if (ret_path) {
|
||||
if (!FLAGS_SET(flags, CHASE_EXTRACT_FILENAME)) {
|
||||
_cleanup_free_ char *q = NULL;
|
||||
|
||||
q = path_join(empty_to_root(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);
|
||||
@@ -556,6 +583,37 @@ int chase(const char *path, const char *original_root, ChaseFlags flags, char **
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -442,6 +442,43 @@ 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
|
||||
* 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);
|
||||
|
||||
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. */
|
||||
|
||||
@@ -611,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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user