This rearranges chase_symlinks() a bit: if no special flags are
specified it will now revert to behaviour before
b12d25a8d631af00b200e7aa9dbba6ba4a4a59ff. However, if the new
CHASE_TRAIL_SLASH flag is specified it will follow the behaviour
introduced by that commit.
I wasn't sure which one to make the beaviour that requires specification
of a flag to enable. I opted to make the "append trailing slash"
behaviour the one to enable by a flag, following the thinking that the
function should primarily be used to generate a normalized path, and I
am pretty sure a path without trailing slash is the more "normalized"
one, as the trailing slash is not really a part of it, but merely a
"decorator" that tells various system calls to generate ENOTDIR if the
path doesn't refer to a path.
Or to say this differently: if the slash was part of normalization then
we really should add it in all cases when the final path is a directory,
not just when the user originally specified it.
Fixes: #8544
Replaces: #8545
n++;
}
- if (list)
- *list = TAKE_PTR(l);
+ if (list) {
+ *list = l;
+ l = NULL; /* avoid freeing */
+ }
return n;
}
/* Just a single slash? Then we reached the end. */
if (path_equal(first, "/")) {
/* Preserve the trailing slash */
- if (!strextend(&done, "/", NULL))
- return -ENOMEM;
+
+ if (flags & CHASE_TRAIL_SLASH)
+ if (!strextend(&done, "/", NULL))
+ return -ENOMEM;
break;
}
}
safe_close(fd);
- fd = TAKE_FD(fd_parent);
+ fd = fd_parent;
+ fd_parent = -1;
continue;
}
}
/* If this is not a symlink, then let's just add the name we read to what we already verified. */
- if (!done)
- done = TAKE_PTR(first);
- else {
+ if (!done) {
+ 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';
/* And iterate again, but go one directory further down. */
safe_close(fd);
- fd = TAKE_FD(child);
+ fd = child;
+ child = -1;
}
if (!done) {
return -ENOMEM;
}
- if (ret)
- *ret = TAKE_PTR(done);
+ if (ret) {
+ *ret = done;
+ done = NULL;
+ }
if (flags & CHASE_OPEN) {
+ int q;
+
/* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by
* opening /proc/self/fd/xyz. */
assert(fd >= 0);
- return TAKE_FD(fd);
+ q = fd;
+ fd = -1;
+
+ return q;
}
return exists;
CHASE_NO_AUTOFS = 1U << 2, /* If set, return -EREMOTE if autofs mount point found */
CHASE_SAFE = 1U << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */
CHASE_OPEN = 1U << 4, /* If set, return an O_PATH object to the final component */
+ CHASE_TRAIL_SLASH = 1U << 5, /* If set, any trailing slash will be preserved */
};
int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret);
if (name_to_handle_at(fd, path, h, &mnt_id, flags) >= 0) {
- if (ret_handle)
- *ret_handle = TAKE_PTR(h);
+ if (ret_handle) {
+ *ret_handle = h;
+ h = NULL;
+ }
if (ret_mnt_id)
*ret_mnt_id = mnt_id;
* /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
* look at needs to be /usr, not /. */
if (flags & AT_SYMLINK_FOLLOW) {
- r = chase_symlinks(t, root, 0, &canonical);
+ r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical);
if (r < 0)
return r;
}
*ret_mount_flags = mount_flags;
- *ret_remaining_options = TAKE_PTR(ret);
+ *ret_remaining_options = ret;
+ ret = NULL;
return 0;
}