return 0;
}
+static int empty_or_root_to_null(const char **path) {
+ int r;
+
+ assert(path);
+
+ /* This nullifies the input path when the path is empty or points to "/". */
+
+ if (empty_or_root(*path)) {
+ *path = NULL;
+ return 0;
+ }
+
+ r = path_is_root(*path);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ *path = NULL;
+
+ return 0;
+}
+
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;
if (isempty(path))
return -EINVAL;
+ r = empty_or_root_to_null(&root);
+ if (r < 0)
+ return r;
+
/* A root directory of "/" or "" is identical to "/". */
if (empty_or_root(root)) {
root = "/";
if (!path_is_absolute(path)) {
_cleanup_free_ char *root_abs = NULL;
+ r = empty_or_root_to_null(&root);
+ if (r < 0 && r != -ENOENT)
+ return r;
+
/* If the dir_fd points to the root directory, chaseat() always returns an absolute path. */
- assert(!empty_or_root(root));
+ if (empty_or_root(root))
+ return -EINVAL;
r = path_make_absolute_cwd(root, &root_abs);
if (r < 0)
if (!path_is_absolute(path))
return -EINVAL;
+ r = empty_or_root_to_null(&root);
+ if (r < 0 && r != -ENOENT)
+ return r;
+
if (!empty_or_root(root)) {
_cleanup_free_ char *root_abs = NULL;
int fd_get_diskseq(int fd, uint64_t *ret);
int path_is_root_at(int dir_fd, const char *path);
+static inline int path_is_root(const char *path) {
+ return path_is_root_at(AT_FDCWD, path);
+}
static inline int dir_fd_is_root(int dir_fd) {
return path_is_root_at(dir_fd, NULL);
}
assert_se(path_equal(result, "/usr"));
result = mfree(result);
+ r = chase(p, "/.//../../../", 0, &result, NULL);
+ assert_se(r > 0);
+ assert_se(path_equal(result, "/usr"));
+ result = mfree(result);
+
pslash = strjoina(p, "/");
r = chase(pslash, NULL, 0, &result, NULL);
assert_se(r > 0);