Compare commits

..

No commits in common. "a5648b809457d120500b2acb18b31e2168a4817a" and "1048436869416d58071803e8c4fcc897b373af30" have entirely different histories.

34 changed files with 183 additions and 199 deletions

View File

@ -713,7 +713,7 @@ static int log_autofs_mount_point(int fd, const char *path, unsigned flags) {
n1, path); n1, path);
} }
int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) { int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
_cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL; _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
unsigned max_follow = CHASE_SYMLINKS_MAX; /* how many symlinks to follow before giving up and returning ELOOP */ unsigned max_follow = CHASE_SYMLINKS_MAX; /* how many symlinks to follow before giving up and returning ELOOP */
@ -725,10 +725,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
assert(path); assert(path);
/* Either the file may be missing, or we return an fd to the final object, but both make no sense */ /* Either the file may be missing, or we return an fd to the final object, but both make no sense */
if ((flags & CHASE_NONEXISTENT) && ret_fd) if (FLAGS_SET(flags, CHASE_NONEXISTENT | CHASE_OPEN))
return -EINVAL; return -EINVAL;
if ((flags & CHASE_STEP) && ret_fd) if (FLAGS_SET(flags, CHASE_STEP | CHASE_OPEN))
return -EINVAL; return -EINVAL;
if (isempty(path)) if (isempty(path))
@ -754,17 +754,17 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* function what to do when encountering a symlink with an absolute path as directory: prefix it by the * function what to do when encountering a symlink with an absolute path as directory: prefix it by the
* specified path. * specified path.
* *
* There are five ways to invoke this function: * There are three ways to invoke this function:
* *
* 1. Without CHASE_STEP or ret_fd: in this case the path is resolved and the normalized path is * 1. Without CHASE_STEP or CHASE_OPEN: in this case the path is resolved and the normalized path is returned
* returned in `ret_path`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0 * in `ret`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0 is returned if the file
* is returned if the file doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is * doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is returned if the destination was
* returned if the destination was found, -ENOENT if it wasn't. * found, -ENOENT if it wasn't.
* *
* 2. With ret_fd: in this case the destination is opened after chasing it as O_PATH and this file * 2. With CHASE_OPEN: in this case the destination is opened after chasing it as O_PATH and this file
* descriptor is returned as return value. This is useful to open files relative to some root * descriptor is returned as return value. This is useful to open files relative to some root
* directory. Note that the returned O_PATH file descriptors must be converted into a regular one (using * directory. Note that the returned O_PATH file descriptors must be converted into a regular one (using
* fd_reopen() or such) before it can be used for reading/writing. ret_fd may not be combined with * fd_reopen() or such) before it can be used for reading/writing. CHASE_OPEN may not be combined with
* CHASE_NONEXISTENT. * CHASE_NONEXISTENT.
* *
* 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only the first * 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only the first
@ -780,21 +780,21 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, path normalization * 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, path normalization
* is aborted and -EREMOTE is returned. If CHASE_WARN is also set, a warning showing the path of * is aborted and -EREMOTE is returned. If CHASE_WARN is also set, a warning showing the path of
* the mount point is emitted. * the mount point is emitted.
*
*/ */
/* A root directory of "/" or "" is identical to none */ /* A root directory of "/" or "" is identical to none */
if (empty_or_root(original_root)) if (empty_or_root(original_root))
original_root = NULL; original_root = NULL;
if (!original_root && !ret_path && !(flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_STEP)) && ret_fd) { if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) {
/* Shortcut the ret_fd case if the caller isn't interested in the actual path and has no root set /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set
* and doesn't care about any of the other special features we provide either. */ * and doesn't care about any of the other special features we provide either. */
r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0)); r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0));
if (r < 0) if (r < 0)
return -errno; return -errno;
*ret_fd = r; return r;
return 0;
} }
if (original_root) { if (original_root) {
@ -803,6 +803,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return r; return r;
if (flags & CHASE_PREFIX_ROOT) { if (flags & CHASE_PREFIX_ROOT) {
/* We don't support relative paths in combination with a root directory */ /* We don't support relative paths in combination with a root directory */
if (!path_is_absolute(path)) if (!path_is_absolute(path))
return -EINVAL; return -EINVAL;
@ -947,6 +948,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) { if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) {
char *joined; char *joined;
_cleanup_free_ char *destination = NULL; _cleanup_free_ char *destination = NULL;
/* This is a symlink, in this case read the destination. But let's make sure we don't follow /* This is a symlink, in this case read the destination. But let's make sure we don't follow
@ -1032,15 +1034,15 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return -ENOMEM; return -ENOMEM;
} }
if (ret_path) if (ret)
*ret_path = TAKE_PTR(done); *ret = TAKE_PTR(done);
if (ret_fd) { if (flags & CHASE_OPEN) {
/* Return the O_PATH fd we currently are looking to the caller. It can translate it to a /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by
* proper fd by opening /proc/self/fd/xyz. */ * opening /proc/self/fd/xyz. */
assert(fd >= 0); assert(fd >= 0);
*ret_fd = TAKE_FD(fd); return TAKE_FD(fd);
} }
if (flags & CHASE_STEP) if (flags & CHASE_STEP)
@ -1049,14 +1051,14 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return exists; return exists;
chased_one: chased_one:
if (ret_path) { if (ret) {
char *c; char *c;
c = strjoin(strempty(done), todo); c = strjoin(strempty(done), todo);
if (!c) if (!c)
return -ENOMEM; return -ENOMEM;
*ret_path = c; *ret = c;
} }
return 0; return 0;
@ -1085,10 +1087,9 @@ int chase_symlinks_and_open(
return r; return r;
} }
r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
if (r < 0) if (path_fd < 0)
return r; return path_fd;
assert(path_fd >= 0);
r = fd_reopen(path_fd, open_flags); r = fd_reopen(path_fd, open_flags);
if (r < 0) if (r < 0)
@ -1111,7 +1112,6 @@ int chase_symlinks_and_opendir(
_cleanup_close_ int path_fd = -1; _cleanup_close_ int path_fd = -1;
_cleanup_free_ char *p = NULL; _cleanup_free_ char *p = NULL;
DIR *d; DIR *d;
int r;
if (!ret_dir) if (!ret_dir)
return -EINVAL; return -EINVAL;
@ -1128,10 +1128,9 @@ int chase_symlinks_and_opendir(
return 0; return 0;
} }
r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
if (r < 0) if (path_fd < 0)
return r; return path_fd;
assert(path_fd >= 0);
xsprintf(procfs_path, "/proc/self/fd/%i", path_fd); xsprintf(procfs_path, "/proc/self/fd/%i", path_fd);
d = opendir(procfs_path); d = opendir(procfs_path);
@ -1150,12 +1149,10 @@ int chase_symlinks_and_stat(
const char *root, const char *root,
unsigned chase_flags, unsigned chase_flags,
char **ret_path, char **ret_path,
struct stat *ret_stat, struct stat *ret_stat) {
int *ret_fd) {
_cleanup_close_ int path_fd = -1; _cleanup_close_ int path_fd = -1;
_cleanup_free_ char *p = NULL; _cleanup_free_ char *p = NULL;
int r;
assert(path); assert(path);
assert(ret_stat); assert(ret_stat);
@ -1171,18 +1168,18 @@ int chase_symlinks_and_stat(
return 1; return 1;
} }
r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
if (r < 0) if (path_fd < 0)
return r; return path_fd;
assert(path_fd >= 0);
if (fstat(path_fd, ret_stat) < 0) if (fstat(path_fd, ret_stat) < 0)
return -errno; return -errno;
if (ret_path) if (ret_path)
*ret_path = TAKE_PTR(p); *ret_path = TAKE_PTR(p);
if (ret_fd)
*ret_fd = TAKE_FD(path_fd); if (chase_flags & CHASE_OPEN)
return TAKE_FD(path_fd);
return 1; return 1;
} }

View File

@ -79,21 +79,23 @@ enum {
CHASE_NONEXISTENT = 1 << 1, /* It's OK if the path doesn't actually exist. */ CHASE_NONEXISTENT = 1 << 1, /* It's OK if the path doesn't actually exist. */
CHASE_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */ CHASE_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */
CHASE_SAFE = 1 << 3, /* Return EPERM if we ever traverse from unprivileged to privileged files or directories */ CHASE_SAFE = 1 << 3, /* Return EPERM if we ever traverse from unprivileged to privileged files or directories */
CHASE_TRAIL_SLASH = 1 << 4, /* Any trailing slash will be preserved */ CHASE_OPEN = 1 << 4, /* Return an O_PATH object to the final component */
CHASE_STEP = 1 << 5, /* Just execute a single step of the normalization */ CHASE_TRAIL_SLASH = 1 << 5, /* Any trailing slash will be preserved */
CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most compontent. With ret_fd, when the path's CHASE_STEP = 1 << 6, /* Just execute a single step of the normalization */
* right-most component refers to symlink, return O_PATH fd of the symlink. */ CHASE_NOFOLLOW = 1 << 7, /* Do not follow the path's right-most compontent. With CHASE_OPEN, when
CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered */ * the path's right-most component refers to symlink, return O_PATH fd of
* the symlink. */
CHASE_WARN = 1 << 8, /* Emit an appropriate warning when an error is encountered */
}; };
/* How many iterations to execute before returning -ELOOP */ /* How many iterations to execute before returning -ELOOP */
#define CHASE_SYMLINKS_MAX 32 #define CHASE_SYMLINKS_MAX 32
int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret_path, int *ret_fd); int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret);
int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path); int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path);
int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir); int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir);
int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd); int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat);
/* Useful for usage with _cleanup_(), removes a directory and frees the pointer */ /* Useful for usage with _cleanup_(), removes a directory and frees the pointer */
static inline void rmdir_and_free(char *p) { static inline void rmdir_and_free(char *p) {

View File

@ -33,7 +33,7 @@ int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, Mkd
if ((flags & MKDIR_FOLLOW_SYMLINK) && S_ISLNK(st.st_mode)) { if ((flags & MKDIR_FOLLOW_SYMLINK) && S_ISLNK(st.st_mode)) {
_cleanup_free_ char *p = NULL; _cleanup_free_ char *p = NULL;
r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p, NULL); r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p);
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) if (r == 0)

View File

@ -264,7 +264,7 @@ int path_is_mount_point(const char *t, const char *root, int flags) {
* /bin -> /usr/bin/ and /usr is a mount point, then the parent that we * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
* look at needs to be /usr, not /. */ * look at needs to be /usr, not /. */
if (flags & AT_SYMLINK_FOLLOW) { if (flags & AT_SYMLINK_FOLLOW) {
r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical, NULL); r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -273,7 +273,7 @@ char **path_strv_resolve(char **l, const char *root) {
} else } else
t = *s; t = *s;
r = chase_symlinks(t, root, 0, &u, NULL); r = chase_symlinks(t, root, 0, &u);
if (r == -ENOENT) { if (r == -ENOENT) {
if (root) { if (root) {
u = TAKE_PTR(orig); u = TAKE_PTR(orig);

View File

@ -335,7 +335,7 @@ int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) {
if (r < 0) if (r < 0)
return r; return r;
return chase_symlinks(p, NULL, 0, ret, NULL); return chase_symlinks(p, NULL, 0, ret);
} }
int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno) { int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno) {

View File

@ -1471,7 +1471,7 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
if (!path_is_absolute(init)) if (!path_is_absolute(init))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path to init binary '%s' not absolute.", init); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path to init binary '%s' not absolute.", init);
r = chase_symlinks(init, root, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &chased, NULL); r = chase_symlinks(init, root, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &chased);
if (r < 0) if (r < 0)
return sd_bus_error_set_errnof(error, r, "Could not resolve init executable %s: %m", init); return sd_bus_error_set_errnof(error, r, "Could not resolve init executable %s: %m", init);

View File

@ -875,7 +875,7 @@ static int follow_symlink(
* a time by specifying CHASE_STEP. This function returns 0 if we resolved one step, and > 0 if we reached the * a time by specifying CHASE_STEP. This function returns 0 if we resolved one step, and > 0 if we reached the
* end and already have a fully normalized name. */ * end and already have a fully normalized name. */
r = chase_symlinks(mount_entry_path(m), root_directory, CHASE_STEP|CHASE_NONEXISTENT, &target, NULL); r = chase_symlinks(mount_entry_path(m), root_directory, CHASE_STEP|CHASE_NONEXISTENT, &target);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to chase symlinks '%s': %m", mount_entry_path(m)); return log_debug_errno(r, "Failed to chase symlinks '%s': %m", mount_entry_path(m));
if (r > 0) /* Reached the end, nothing more to resolve */ if (r > 0) /* Reached the end, nothing more to resolve */
@ -957,7 +957,7 @@ static int apply_mount(
* mount source paths are always relative to the host root, hence we pass NULL as root directory to * mount source paths are always relative to the host root, hence we pass NULL as root directory to
* chase_symlinks() here. */ * chase_symlinks() here. */
r = chase_symlinks(mount_entry_source(m), NULL, CHASE_TRAIL_SLASH, &chased, NULL); r = chase_symlinks(mount_entry_source(m), NULL, CHASE_TRAIL_SLASH, &chased);
if (r == -ENOENT && m->ignore) { if (r == -ENOENT && m->ignore) {
log_debug_errno(r, "Path %s does not exist, ignoring.", mount_entry_source(m)); log_debug_errno(r, "Path %s does not exist, ignoring.", mount_entry_source(m));
return 0; return 0;

View File

@ -946,27 +946,22 @@ static int service_load_pid_file(Service *s, bool may_warn) {
prio = may_warn ? LOG_INFO : LOG_DEBUG; prio = may_warn ? LOG_INFO : LOG_DEBUG;
r = chase_symlinks(s->pid_file, NULL, CHASE_SAFE, NULL, &fd); fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN|CHASE_SAFE, NULL);
if (r == -ENOLINK) { if (fd == -ENOLINK) {
log_unit_full(UNIT(s), LOG_DEBUG, r, log_unit_full(UNIT(s), LOG_DEBUG, fd, "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file);
"Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file);
questionable_pid_file = true; questionable_pid_file = true;
r = chase_symlinks(s->pid_file, NULL, 0, NULL, &fd); fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN, NULL);
} }
if (r < 0) if (fd < 0)
return log_unit_full(UNIT(s), prio, fd, return log_unit_full(UNIT(s), prio, fd, "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state));
"Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state));
/* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd /* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd chase_symlinks() returned us into a proper fd first. */
* chase_symlinks() returned us into a proper fd first. */
xsprintf(procfs, "/proc/self/fd/%i", fd); xsprintf(procfs, "/proc/self/fd/%i", fd);
r = read_one_line_file(procfs, &k); r = read_one_line_file(procfs, &k);
if (r < 0) if (r < 0)
return log_unit_error_errno(UNIT(s), r, return log_unit_error_errno(UNIT(s), r, "Can't convert PID files %s O_PATH file descriptor to proper file descriptor: %m", s->pid_file);
"Can't convert PID files %s O_PATH file descriptor to proper file descriptor: %m",
s->pid_file);
r = parse_pid(k, &pid); r = parse_pid(k, &pid);
if (r < 0) if (r < 0)

View File

@ -1429,7 +1429,7 @@ static int socket_determine_selinux_label(Socket *s, char **ret) {
if (!c) if (!c)
goto no_label; goto no_label;
r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path, NULL); r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path);
if (r < 0) if (r < 0)
goto no_label; goto no_label;

View File

@ -4974,7 +4974,7 @@ int unit_fail_if_noncanonical(Unit *u, const char* where) {
assert(u); assert(u);
assert(where); assert(where);
r = chase_symlinks(where, NULL, CHASE_NONEXISTENT, &canonical_where, NULL); r = chase_symlinks(where, NULL, CHASE_NONEXISTENT, &canonical_where);
if (r < 0) { if (r < 0) {
log_unit_debug_errno(u, r, "Failed to check %s for symlinks, ignoring: %m", where); log_unit_debug_errno(u, r, "Failed to check %s for symlinks, ignoring: %m", where);
return 0; return 0;

View File

@ -73,11 +73,11 @@ static int equivalent(const char *a, const char *b) {
_cleanup_free_ char *x = NULL, *y = NULL; _cleanup_free_ char *x = NULL, *y = NULL;
int r; int r;
r = chase_symlinks(a, NULL, CHASE_TRAIL_SLASH, &x, NULL); r = chase_symlinks(a, NULL, CHASE_TRAIL_SLASH, &x);
if (r < 0) if (r < 0)
return r; return r;
r = chase_symlinks(b, NULL, CHASE_TRAIL_SLASH, &y, NULL); r = chase_symlinks(b, NULL, CHASE_TRAIL_SLASH, &y);
if (r < 0) if (r < 0)
return r; return r;
@ -378,7 +378,7 @@ static int should_skip_path(const char *prefix, const char *suffix) {
dirname = prefix_roota(prefix, suffix); dirname = prefix_roota(prefix, suffix);
if (chase_symlinks(dirname, NULL, 0, &target, NULL) < 0) if (chase_symlinks(dirname, NULL, 0, &target) < 0)
return false; return false;
NULSTR_FOREACH(p, prefixes) { NULSTR_FOREACH(p, prefixes) {

View File

@ -563,7 +563,7 @@ static int parse_fstab(bool initrd) {
* target is the final directory. */ * target is the final directory. */
r = chase_symlinks(where, initrd ? "/sysroot" : NULL, r = chase_symlinks(where, initrd ? "/sysroot" : NULL,
CHASE_PREFIX_ROOT | CHASE_NONEXISTENT, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT,
&canonical_where, NULL); &canonical_where);
if (r < 0) /* If we can't canonicalize we continue on as if it wasn't a symlink */ if (r < 0) /* If we can't canonicalize we continue on as if it wasn't a symlink */
log_debug_errno(r, "Failed to read symlink target for %s, ignoring: %m", where); log_debug_errno(r, "Failed to read symlink target for %s, ignoring: %m", where);
else if (streq(canonical_where, where)) /* If it was fully canonicalized, suppress the change */ else if (streq(canonical_where, where)) /* If it was fully canonicalized, suppress the change */

View File

@ -1086,7 +1086,7 @@ static int add_matches(sd_journal *j, char **args) {
_cleanup_free_ char *p = NULL, *t = NULL, *t2 = NULL, *interpreter = NULL; _cleanup_free_ char *p = NULL, *t = NULL, *t2 = NULL, *interpreter = NULL;
struct stat st; struct stat st;
r = chase_symlinks(*i, NULL, CHASE_TRAIL_SLASH, &p, NULL); r = chase_symlinks(*i, NULL, CHASE_TRAIL_SLASH, &p);
if (r < 0) if (r < 0)
return log_error_errno(r, "Couldn't canonicalize path: %m"); return log_error_errno(r, "Couldn't canonicalize path: %m");

View File

@ -146,7 +146,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
_syspath); _syspath);
if (verify) { if (verify) {
r = chase_symlinks(_syspath, NULL, 0, &syspath, NULL); r = chase_symlinks(_syspath, NULL, 0, &syspath);
if (r == -ENOENT) if (r == -ENOENT)
return -ENODEV; /* the device does not exist (any more?) */ return -ENODEV; /* the device does not exist (any more?) */
if (r < 0) if (r < 0)
@ -157,7 +157,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
char *p; char *p;
/* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */ /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
r = chase_symlinks("/sys", NULL, 0, &real_sys, NULL); r = chase_symlinks("/sys", NULL, 0, &real_sys);
if (r < 0) if (r < 0)
return log_debug_errno(r, "sd-device: Failed to chase symlink /sys: %m"); return log_debug_errno(r, "sd-device: Failed to chase symlink /sys: %m");

View File

@ -846,7 +846,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
if (laccess(p, F_OK) < 0) if (laccess(p, F_OK) < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points."); return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points.");
r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, &chased_src, NULL); r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, &chased_src);
if (r < 0) if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to resolve source path: %m"); return sd_bus_error_set_errnof(error, r, "Failed to resolve source path: %m");

View File

@ -360,7 +360,7 @@ static int parse_argv(int argc, char *argv[]) {
if (!u) if (!u)
return log_oom(); return log_oom();
r = chase_symlinks(u, NULL, 0, &arg_mount_what, NULL); r = chase_symlinks(u, NULL, 0, &arg_mount_what);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to make path %s absolute: %m", u); return log_error_errno(r, "Failed to make path %s absolute: %m", u);
} else { } else {
@ -377,7 +377,7 @@ static int parse_argv(int argc, char *argv[]) {
if (argc > optind+1) { if (argc > optind+1) {
if (arg_transport == BUS_TRANSPORT_LOCAL) { if (arg_transport == BUS_TRANSPORT_LOCAL) {
r = chase_symlinks(argv[optind+1], NULL, CHASE_NONEXISTENT, &arg_mount_where, NULL); r = chase_symlinks(argv[optind+1], NULL, CHASE_NONEXISTENT, &arg_mount_where);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to make path %s absolute: %m", argv[optind+1]); return log_error_errno(r, "Failed to make path %s absolute: %m", argv[optind+1]);
} else { } else {
@ -1004,7 +1004,7 @@ static int action_umount(
if (!u) if (!u)
return log_oom(); return log_oom();
r = chase_symlinks(u, NULL, 0, &p, NULL); r = chase_symlinks(u, NULL, 0, &p);
if (r < 0) { if (r < 0) {
r2 = log_error_errno(r, "Failed to make path %s absolute: %m", argv[i]); r2 = log_error_errno(r, "Failed to make path %s absolute: %m", argv[i]);
continue; continue;

View File

@ -633,7 +633,7 @@ int mount_all(const char *dest,
if (!tmpfs_tmp && (bool)(mount_table[k].mount_settings & MOUNT_APPLY_TMPFS_TMP)) if (!tmpfs_tmp && (bool)(mount_table[k].mount_settings & MOUNT_APPLY_TMPFS_TMP))
continue; continue;
r = chase_symlinks(mount_table[k].where, dest, CHASE_NONEXISTENT|CHASE_PREFIX_ROOT, &where, NULL); r = chase_symlinks(mount_table[k].where, dest, CHASE_NONEXISTENT|CHASE_PREFIX_ROOT, &where);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].where); return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].where);
@ -734,7 +734,7 @@ static int mount_bind(const char *dest, CustomMount *m) {
if (stat(m->source, &source_st) < 0) if (stat(m->source, &source_st) < 0)
return log_error_errno(errno, "Failed to stat %s: %m", m->source); return log_error_errno(errno, "Failed to stat %s: %m", m->source);
r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r > 0) { /* Path exists already? */ if (r > 0) { /* Path exists already? */
@ -795,7 +795,7 @@ static int mount_tmpfs(
assert(dest); assert(dest);
assert(m); assert(m);
r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r == 0) { /* Doesn't exist yet? */ if (r == 0) { /* Doesn't exist yet? */
@ -835,7 +835,7 @@ static int mount_overlay(const char *dest, CustomMount *m) {
assert(dest); assert(dest);
assert(m); assert(m);
r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r == 0) { /* Doesn't exist yet? */ if (r == 0) { /* Doesn't exist yet? */
@ -878,7 +878,7 @@ static int mount_inaccessible(const char *dest, CustomMount *m) {
assert(dest); assert(dest);
assert(m); assert(m);
r = chase_symlinks_and_stat(m->destination, dest, CHASE_PREFIX_ROOT, &where, &st, NULL); r = chase_symlinks_and_stat(m->destination, dest, CHASE_PREFIX_ROOT, &where, &st);
if (r < 0) { if (r < 0) {
log_full_errno(m->graceful ? LOG_DEBUG : LOG_ERR, r, "Failed to resolve %s/%s: %m", dest, m->destination); log_full_errno(m->graceful ? LOG_DEBUG : LOG_ERR, r, "Failed to resolve %s/%s: %m", dest, m->destination);
return m->graceful ? 0 : r; return m->graceful ? 0 : r;
@ -906,7 +906,7 @@ static int mount_arbitrary(const char *dest, CustomMount *m) {
assert(dest); assert(dest);
assert(m); assert(m);
r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r == 0) { /* Doesn't exist yet? */ if (r == 0) { /* Doesn't exist yet? */

View File

@ -1668,7 +1668,7 @@ static int setup_timezone(const char *dest) {
if (m == TIMEZONE_OFF) if (m == TIMEZONE_OFF)
return 0; return 0;
r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc, NULL); r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc);
if (r < 0) { if (r < 0) {
log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m"); log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m");
return 0; return 0;
@ -1699,7 +1699,7 @@ static int setup_timezone(const char *dest) {
return 0; /* Already pointing to the right place? Then do nothing .. */ return 0; /* Already pointing to the right place? Then do nothing .. */
check = strjoina(dest, "/usr/share/zoneinfo/", z); check = strjoina(dest, "/usr/share/zoneinfo/", z);
r = chase_symlinks(check, dest, 0, NULL, NULL); r = chase_symlinks(check, dest, 0, NULL);
if (r < 0) if (r < 0)
log_debug_errno(r, "Timezone %s does not exist (or is not accessible) in container, not creating symlink: %m", z); log_debug_errno(r, "Timezone %s does not exist (or is not accessible) in container, not creating symlink: %m", z);
else { else {
@ -1726,7 +1726,7 @@ static int setup_timezone(const char *dest) {
_cleanup_free_ char *resolved = NULL; _cleanup_free_ char *resolved = NULL;
int found; int found;
found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved, NULL); found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
if (found < 0) { if (found < 0) {
log_warning_errno(found, "Failed to resolve /etc/localtime path in container, ignoring: %m"); log_warning_errno(found, "Failed to resolve /etc/localtime path in container, ignoring: %m");
return 0; return 0;
@ -1832,7 +1832,7 @@ static int setup_resolv_conf(const char *dest) {
if (m == RESOLV_CONF_OFF) if (m == RESOLV_CONF_OFF)
return 0; return 0;
r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc, NULL); r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc);
if (r < 0) { if (r < 0) {
log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m"); log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m");
return 0; return 0;
@ -1856,7 +1856,7 @@ static int setup_resolv_conf(const char *dest) {
_cleanup_free_ char *resolved = NULL; _cleanup_free_ char *resolved = NULL;
int found; int found;
found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved, NULL); found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
if (found < 0) { if (found < 0) {
log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m"); log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m");
return 0; return 0;
@ -2733,11 +2733,12 @@ static int chase_symlinks_and_update(char **p, unsigned flags) {
if (!*p) if (!*p)
return 0; return 0;
r = chase_symlinks(*p, NULL, flags, &chased, NULL); r = chase_symlinks(*p, NULL, flags, &chased);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to resolve path %s: %m", *p); return log_error_errno(r, "Failed to resolve path %s: %m", *p);
return free_and_replace(*p, chased); free_and_replace(*p, chased);
return r; /* r might be an fd here in case we ever use CHASE_OPEN in flags */
} }
static int determine_uid_shift(const char *directory) { static int determine_uid_shift(const char *directory) {

View File

@ -67,7 +67,7 @@ static int determine_image(const char *image, bool permit_non_existing, char **r
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Operations on images by path not supported when connecting to remote systems."); "Operations on images by path not supported when connecting to remote systems.");
r = chase_symlinks(image, NULL, CHASE_TRAIL_SLASH | (permit_non_existing ? CHASE_NONEXISTENT : 0), ret, NULL); r = chase_symlinks(image, NULL, CHASE_TRAIL_SLASH | (permit_non_existing ? CHASE_NONEXISTENT : 0), ret);
if (r < 0) if (r < 0)
return log_error_errno(r, "Cannot normalize specified image path '%s': %m", image); return log_error_errno(r, "Cannot normalize specified image path '%s': %m", image);

View File

@ -833,7 +833,7 @@ static int mount_partition(
rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY); rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY);
if (directory) { if (directory) {
r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased, NULL); r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased);
if (r < 0) if (r < 0)
return r; return r;
@ -909,7 +909,7 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
/* Mount the ESP to /efi if it exists. If it doesn't exist, use /boot instead, but only if it /* Mount the ESP to /efi if it exists. If it doesn't exist, use /boot instead, but only if it
* exists and is empty, and we didn't already mount the XBOOTLDR partition into it. */ * exists and is empty, and we didn't already mount the XBOOTLDR partition into it. */
r = chase_symlinks("/efi", where, CHASE_PREFIX_ROOT, NULL, NULL); r = chase_symlinks("/efi", where, CHASE_PREFIX_ROOT, NULL);
if (r >= 0) { if (r >= 0) {
r = mount_partition(m->partitions + PARTITION_ESP, where, "/efi", uid_shift, flags); r = mount_partition(m->partitions + PARTITION_ESP, where, "/efi", uid_shift, flags);
if (r < 0) if (r < 0)
@ -918,7 +918,7 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
} else if (boot_mounted <= 0) { } else if (boot_mounted <= 0) {
_cleanup_free_ char *p = NULL; _cleanup_free_ char *p = NULL;
r = chase_symlinks("/boot", where, CHASE_PREFIX_ROOT, &p, NULL); r = chase_symlinks("/boot", where, CHASE_PREFIX_ROOT, &p);
if (r >= 0 && dir_is_empty(p) > 0) { if (r >= 0 && dir_is_empty(p) > 0) {
r = mount_partition(m->partitions + PARTITION_ESP, where, "/boot", uid_shift, flags); r = mount_partition(m->partitions + PARTITION_ESP, where, "/boot", uid_shift, flags);
if (r < 0) if (r < 0)

View File

@ -106,7 +106,7 @@ static int unit_file_add_dir(
/* This adds [original_root]/path to dirs, if it exists. */ /* This adds [original_root]/path to dirs, if it exists. */
r = chase_symlinks(path, original_root, 0, &chased, NULL); r = chase_symlinks(path, original_root, 0, &chased);
if (r == -ENOENT) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */ if (r == -ENOENT) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */
return 0; return 0;
if (r == -ENAMETOOLONG) { if (r == -ENAMETOOLONG) {

View File

@ -1113,7 +1113,7 @@ int image_read_metadata(Image *i) {
_cleanup_free_ char *hostname = NULL; _cleanup_free_ char *hostname = NULL;
_cleanup_free_ char *path = NULL; _cleanup_free_ char *path = NULL;
r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL); r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
if (r < 0 && r != -ENOENT) if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to chase /etc/hostname in image %s: %m", i->name); log_debug_errno(r, "Failed to chase /etc/hostname in image %s: %m", i->name);
else if (r >= 0) { else if (r >= 0) {
@ -1124,7 +1124,7 @@ int image_read_metadata(Image *i) {
path = mfree(path); path = mfree(path);
r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL); r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
if (r < 0 && r != -ENOENT) if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to chase /etc/machine-id in image %s: %m", i->name); log_debug_errno(r, "Failed to chase /etc/machine-id in image %s: %m", i->name);
else if (r >= 0) { else if (r >= 0) {
@ -1142,7 +1142,7 @@ int image_read_metadata(Image *i) {
path = mfree(path); path = mfree(path);
r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL); r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
if (r < 0 && r != -ENOENT) if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to chase /etc/machine-info in image %s: %m", i->name); log_debug_errno(r, "Failed to chase /etc/machine-info in image %s: %m", i->name);
else if (r >= 0) { else if (r >= 0) {

View File

@ -33,24 +33,22 @@ int path_is_os_tree(const char *path) {
int open_os_release(const char *root, char **ret_path, int *ret_fd) { int open_os_release(const char *root, char **ret_path, int *ret_fd) {
_cleanup_free_ char *q = NULL; _cleanup_free_ char *q = NULL;
const char *p; const char *p;
int r, fd; int k;
FOREACH_STRING(p, "/etc/os-release", "/usr/lib/os-release") { FOREACH_STRING(p, "/etc/os-release", "/usr/lib/os-release") {
r = chase_symlinks(p, root, CHASE_PREFIX_ROOT, k = chase_symlinks(p, root, CHASE_PREFIX_ROOT|(ret_fd ? CHASE_OPEN : 0), (ret_path ? &q : NULL));
ret_path ? &q : NULL, if (k != -ENOENT)
ret_fd ? &fd : NULL);
if (r != -ENOENT)
break; break;
} }
if (r < 0) if (k < 0)
return r; return k;
if (ret_fd) { if (ret_fd) {
int real_fd; int real_fd;
/* Convert the O_PATH fd into a proper, readable one */ /* Convert the O_PATH fd into a proper, readable one */
real_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY); real_fd = fd_reopen(k, O_RDONLY|O_CLOEXEC|O_NOCTTY);
safe_close(fd); safe_close(k);
if (real_fd < 0) if (real_fd < 0)
return real_fd; return real_fd;

View File

@ -52,7 +52,7 @@ int switch_root(const char *new_root,
} }
/* Determine where we shall place the old root after the transition */ /* Determine where we shall place the old root after the transition */
r = chase_symlinks(old_root_after, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved_old_root_after, NULL); r = chase_symlinks(old_root_after, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved_old_root_after);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", new_root, old_root_after); return log_error_errno(r, "Failed to resolve %s/%s: %m", new_root, old_root_after);
if (r == 0) /* Doesn't exist yet. Let's create it */ if (r == 0) /* Doesn't exist yet. Let's create it */
@ -68,7 +68,7 @@ int switch_root(const char *new_root,
FOREACH_STRING(i, "/sys", "/dev", "/run", "/proc") { FOREACH_STRING(i, "/sys", "/dev", "/run", "/proc") {
_cleanup_free_ char *chased = NULL; _cleanup_free_ char *chased = NULL;
r = chase_symlinks(i, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &chased, NULL); r = chase_symlinks(i, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &chased);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", new_root, i); return log_error_errno(r, "Failed to resolve %s/%s: %m", new_root, i);
if (r > 0) { if (r > 0) {

View File

@ -303,7 +303,7 @@ int unit_file_build_name_map(
} }
/* Get rid of "." and ".." components in target path */ /* Get rid of "." and ".." components in target path */
r = chase_symlinks(target, lp->root_dir, CHASE_NOFOLLOW | CHASE_NONEXISTENT, &simplified, NULL); r = chase_symlinks(target, lp->root_dir, CHASE_NOFOLLOW | CHASE_NONEXISTENT, &simplified);
if (r < 0) { if (r < 0) {
log_warning_errno(r, "Failed to resolve symlink %s pointing to %s, ignoring: %m", log_warning_errno(r, "Failed to resolve symlink %s pointing to %s, ignoring: %m",
filename, target); filename, target);

View File

@ -2520,7 +2520,7 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **re
if (!path) if (!path)
return log_oom(); return log_oom();
r = chase_symlinks(path, arg_root, 0, &lpath, NULL); r = chase_symlinks(path, arg_root, 0, &lpath);
if (r == -ENOENT) if (r == -ENOENT)
continue; continue;
if (r == -ENOMEM) if (r == -ENOMEM)

View File

@ -8,23 +8,21 @@
static char *arg_root = NULL; static char *arg_root = NULL;
static int arg_flags = 0; static int arg_flags = 0;
static bool arg_open = false;
static int parse_argv(int argc, char *argv[]) { static int parse_argv(int argc, char *argv[]) {
enum { enum {
ARG_ROOT = 0x1000, ARG_ROOT = 0x1000,
ARG_OPEN,
}; };
static const struct option options[] = { static const struct option options[] = {
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "root", required_argument, NULL, ARG_ROOT }, { "root", required_argument, NULL, ARG_ROOT },
{ "open", no_argument, NULL, ARG_OPEN },
{ "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT }, { "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT },
{ "nonexistent", no_argument, NULL, CHASE_NONEXISTENT }, { "nonexistent", no_argument, NULL, CHASE_NONEXISTENT },
{ "no_autofs", no_argument, NULL, CHASE_NO_AUTOFS }, { "no_autofs", no_argument, NULL, CHASE_NO_AUTOFS },
{ "safe", no_argument, NULL, CHASE_SAFE }, { "safe", no_argument, NULL, CHASE_SAFE },
{ "open", no_argument, NULL, CHASE_OPEN },
{ "trail-slash", no_argument, NULL, CHASE_TRAIL_SLASH }, { "trail-slash", no_argument, NULL, CHASE_TRAIL_SLASH },
{ "step", no_argument, NULL, CHASE_STEP }, { "step", no_argument, NULL, CHASE_STEP },
{ "nofollow", no_argument, NULL, CHASE_NOFOLLOW }, { "nofollow", no_argument, NULL, CHASE_NOFOLLOW },
@ -53,14 +51,11 @@ static int parse_argv(int argc, char *argv[]) {
arg_root = optarg; arg_root = optarg;
break; break;
case ARG_OPEN:
arg_open = true;
break;
case CHASE_PREFIX_ROOT: case CHASE_PREFIX_ROOT:
case CHASE_NONEXISTENT: case CHASE_NONEXISTENT:
case CHASE_NO_AUTOFS: case CHASE_NO_AUTOFS:
case CHASE_SAFE: case CHASE_SAFE:
case CHASE_OPEN:
case CHASE_TRAIL_SLASH: case CHASE_TRAIL_SLASH:
case CHASE_STEP: case CHASE_STEP:
case CHASE_NOFOLLOW: case CHASE_NOFOLLOW:
@ -94,21 +89,18 @@ static int run(int argc, char **argv) {
for (int i = optind; i < argc; i++) { for (int i = optind; i < argc; i++) {
_cleanup_free_ char *p = NULL; _cleanup_free_ char *p = NULL;
_cleanup_close_ int fd = -1;
printf("%s ", argv[i]); printf("%s ", argv[i]);
fflush(stdout); fflush(stdout);
r = chase_symlinks(argv[i], arg_root, arg_flags, &p, arg_open ? &fd : NULL); r = chase_symlinks(argv[i], arg_root, arg_flags, &p);
if (r < 0) if (r < 0)
log_error_errno(r, "failed: %m"); log_error_errno(r, "failed: %m");
else {
log_info("→ %s", p);
if (arg_open)
assert(fd >= 0);
else else
assert(fd == -1); log_info("→ %s", p);
}
if (FLAGS_SET(arg_flags, CHASE_OPEN))
safe_close(r);
} }
return 0; return 0;

View File

@ -130,7 +130,7 @@ static void test_copy_tree(void) {
assert_se(f = strjoin(original_dir, *p)); assert_se(f = strjoin(original_dir, *p));
assert_se(l = strjoin(copy_dir, *link)); assert_se(l = strjoin(copy_dir, *link));
assert_se(chase_symlinks(l, NULL, 0, &target, NULL) == 1); assert_se(chase_symlinks(l, NULL, 0, &target) == 1);
assert_se(path_equal(f, target)); assert_se(path_equal(f, target));
} }

View File

@ -61,45 +61,45 @@ static void test_chase_symlinks(void) {
/* Paths that use symlinks underneath the "root" */ /* Paths that use symlinks underneath the "root" */
r = chase_symlinks(p, NULL, 0, &result, NULL); r = chase_symlinks(p, NULL, 0, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(path_equal(result, "/usr")); assert_se(path_equal(result, "/usr"));
result = mfree(result); result = mfree(result);
pslash = strjoina(p, "/"); pslash = strjoina(p, "/");
r = chase_symlinks(pslash, NULL, 0, &result, NULL); r = chase_symlinks(pslash, NULL, 0, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(path_equal(result, "/usr/")); assert_se(path_equal(result, "/usr/"));
result = mfree(result); result = mfree(result);
r = chase_symlinks(p, temp, 0, &result, NULL); r = chase_symlinks(p, temp, 0, &result);
assert_se(r == -ENOENT); assert_se(r == -ENOENT);
r = chase_symlinks(pslash, temp, 0, &result, NULL); r = chase_symlinks(pslash, temp, 0, &result);
assert_se(r == -ENOENT); assert_se(r == -ENOENT);
q = strjoina(temp, "/usr"); q = strjoina(temp, "/usr");
r = chase_symlinks(p, temp, CHASE_NONEXISTENT, &result, NULL); r = chase_symlinks(p, temp, CHASE_NONEXISTENT, &result);
assert_se(r == 0); assert_se(r == 0);
assert_se(path_equal(result, q)); assert_se(path_equal(result, q));
result = mfree(result); result = mfree(result);
qslash = strjoina(q, "/"); qslash = strjoina(q, "/");
r = chase_symlinks(pslash, temp, CHASE_NONEXISTENT, &result, NULL); r = chase_symlinks(pslash, temp, CHASE_NONEXISTENT, &result);
assert_se(r == 0); assert_se(r == 0);
assert_se(path_equal(result, qslash)); assert_se(path_equal(result, qslash));
result = mfree(result); result = mfree(result);
assert_se(mkdir(q, 0700) >= 0); assert_se(mkdir(q, 0700) >= 0);
r = chase_symlinks(p, temp, 0, &result, NULL); r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(path_equal(result, q)); assert_se(path_equal(result, q));
result = mfree(result); result = mfree(result);
r = chase_symlinks(pslash, temp, 0, &result, NULL); r = chase_symlinks(pslash, temp, 0, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(path_equal(result, qslash)); assert_se(path_equal(result, qslash));
result = mfree(result); result = mfree(result);
@ -107,12 +107,12 @@ static void test_chase_symlinks(void) {
p = strjoina(temp, "/slash"); p = strjoina(temp, "/slash");
assert_se(symlink("/", p) >= 0); assert_se(symlink("/", p) >= 0);
r = chase_symlinks(p, NULL, 0, &result, NULL); r = chase_symlinks(p, NULL, 0, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(path_equal(result, "/")); assert_se(path_equal(result, "/"));
result = mfree(result); result = mfree(result);
r = chase_symlinks(p, temp, 0, &result, NULL); r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(path_equal(result, temp)); assert_se(path_equal(result, temp));
result = mfree(result); result = mfree(result);
@ -122,21 +122,21 @@ static void test_chase_symlinks(void) {
p = strjoina(temp, "/6dots"); p = strjoina(temp, "/6dots");
assert_se(symlink("../../..", p) >= 0); assert_se(symlink("../../..", p) >= 0);
r = chase_symlinks(p, temp, 0, &result, NULL); r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0 && path_equal(result, temp)); assert_se(r > 0 && path_equal(result, temp));
result = mfree(result); result = mfree(result);
p = strjoina(temp, "/6dotsusr"); p = strjoina(temp, "/6dotsusr");
assert_se(symlink("../../../usr", p) >= 0); assert_se(symlink("../../../usr", p) >= 0);
r = chase_symlinks(p, temp, 0, &result, NULL); r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0 && path_equal(result, q)); assert_se(r > 0 && path_equal(result, q));
result = mfree(result); result = mfree(result);
p = strjoina(temp, "/top/8dotsusr"); p = strjoina(temp, "/top/8dotsusr");
assert_se(symlink("../../../../usr", p) >= 0); assert_se(symlink("../../../../usr", p) >= 0);
r = chase_symlinks(p, temp, 0, &result, NULL); r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0 && path_equal(result, q)); assert_se(r > 0 && path_equal(result, q));
result = mfree(result); result = mfree(result);
@ -145,12 +145,12 @@ static void test_chase_symlinks(void) {
p = strjoina(temp, "/slashslash"); p = strjoina(temp, "/slashslash");
assert_se(symlink("///usr///", p) >= 0); assert_se(symlink("///usr///", p) >= 0);
r = chase_symlinks(p, NULL, 0, &result, NULL); r = chase_symlinks(p, NULL, 0, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(path_equal(result, "/usr")); assert_se(path_equal(result, "/usr"));
result = mfree(result); result = mfree(result);
r = chase_symlinks(p, temp, 0, &result, NULL); r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(path_equal(result, q)); assert_se(path_equal(result, q));
result = mfree(result); result = mfree(result);
@ -169,48 +169,48 @@ static void test_chase_symlinks(void) {
assert_se(symlink("/", p) >= 0); assert_se(symlink("/", p) >= 0);
/* Fail when user-owned directories contain root-owned subdirectories. */ /* Fail when user-owned directories contain root-owned subdirectories. */
r = chase_symlinks(p, temp, CHASE_SAFE, &result, NULL); r = chase_symlinks(p, temp, CHASE_SAFE, &result);
assert_se(r == -ENOLINK); assert_se(r == -ENOLINK);
result = mfree(result); result = mfree(result);
/* Allow this when the user-owned directories are all in the "root". */ /* Allow this when the user-owned directories are all in the "root". */
r = chase_symlinks(p, q, CHASE_SAFE, &result, NULL); r = chase_symlinks(p, q, CHASE_SAFE, &result);
assert_se(r > 0); assert_se(r > 0);
result = mfree(result); result = mfree(result);
} }
/* Paths using . */ /* Paths using . */
r = chase_symlinks("/etc/./.././", NULL, 0, &result, NULL); r = chase_symlinks("/etc/./.././", NULL, 0, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(path_equal(result, "/")); assert_se(path_equal(result, "/"));
result = mfree(result); result = mfree(result);
r = chase_symlinks("/etc/./.././", "/etc", 0, &result, NULL); r = chase_symlinks("/etc/./.././", "/etc", 0, &result);
assert_se(r > 0 && path_equal(result, "/etc")); assert_se(r > 0 && path_equal(result, "/etc"));
result = mfree(result); result = mfree(result);
r = chase_symlinks("/../.././//../../etc", NULL, 0, &result, NULL); r = chase_symlinks("/../.././//../../etc", NULL, 0, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(streq(result, "/etc")); assert_se(streq(result, "/etc"));
result = mfree(result); result = mfree(result);
r = chase_symlinks("/../.././//../../test-chase.fsldajfl", NULL, CHASE_NONEXISTENT, &result, NULL); r = chase_symlinks("/../.././//../../test-chase.fsldajfl", NULL, CHASE_NONEXISTENT, &result);
assert_se(r == 0); assert_se(r == 0);
assert_se(streq(result, "/test-chase.fsldajfl")); assert_se(streq(result, "/test-chase.fsldajfl"));
result = mfree(result); result = mfree(result);
r = chase_symlinks("/../.././//../../etc", "/", CHASE_PREFIX_ROOT, &result, NULL); r = chase_symlinks("/../.././//../../etc", "/", CHASE_PREFIX_ROOT, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(streq(result, "/etc")); assert_se(streq(result, "/etc"));
result = mfree(result); result = mfree(result);
r = chase_symlinks("/../.././//../../test-chase.fsldajfl", "/", CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &result, NULL); r = chase_symlinks("/../.././//../../test-chase.fsldajfl", "/", CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &result);
assert_se(r == 0); assert_se(r == 0);
assert_se(streq(result, "/test-chase.fsldajfl")); assert_se(streq(result, "/test-chase.fsldajfl"));
result = mfree(result); result = mfree(result);
r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result, NULL); r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result);
assert_se(r == -ENOTDIR); assert_se(r == -ENOTDIR);
result = mfree(result); result = mfree(result);
@ -218,25 +218,25 @@ static void test_chase_symlinks(void) {
p = strjoina(temp, "/recursive-symlink"); p = strjoina(temp, "/recursive-symlink");
assert_se(symlink("recursive-symlink", p) >= 0); assert_se(symlink("recursive-symlink", p) >= 0);
r = chase_symlinks(p, NULL, 0, &result, NULL); r = chase_symlinks(p, NULL, 0, &result);
assert_se(r == -ELOOP); assert_se(r == -ELOOP);
/* Path which doesn't exist */ /* Path which doesn't exist */
p = strjoina(temp, "/idontexist"); p = strjoina(temp, "/idontexist");
r = chase_symlinks(p, NULL, 0, &result, NULL); r = chase_symlinks(p, NULL, 0, &result);
assert_se(r == -ENOENT); assert_se(r == -ENOENT);
r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL); r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
assert_se(r == 0); assert_se(r == 0);
assert_se(path_equal(result, p)); assert_se(path_equal(result, p));
result = mfree(result); result = mfree(result);
p = strjoina(temp, "/idontexist/meneither"); p = strjoina(temp, "/idontexist/meneither");
r = chase_symlinks(p, NULL, 0, &result, NULL); r = chase_symlinks(p, NULL, 0, &result);
assert_se(r == -ENOENT); assert_se(r == -ENOENT);
r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL); r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
assert_se(r == 0); assert_se(r == 0);
assert_se(path_equal(result, p)); assert_se(path_equal(result, p));
result = mfree(result); result = mfree(result);
@ -244,17 +244,17 @@ static void test_chase_symlinks(void) {
/* Path which doesn't exist, but contains weird stuff */ /* Path which doesn't exist, but contains weird stuff */
p = strjoina(temp, "/idontexist/.."); p = strjoina(temp, "/idontexist/..");
r = chase_symlinks(p, NULL, 0, &result, NULL); r = chase_symlinks(p, NULL, 0, &result);
assert_se(r == -ENOENT); assert_se(r == -ENOENT);
r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL); r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
assert_se(r == -ENOENT); assert_se(r == -ENOENT);
p = strjoina(temp, "/target"); p = strjoina(temp, "/target");
q = strjoina(temp, "/top"); q = strjoina(temp, "/top");
assert_se(symlink(q, p) >= 0); assert_se(symlink(q, p) >= 0);
p = strjoina(temp, "/target/idontexist"); p = strjoina(temp, "/target/idontexist");
r = chase_symlinks(p, NULL, 0, &result, NULL); r = chase_symlinks(p, NULL, 0, &result);
assert_se(r == -ENOENT); assert_se(r == -ENOENT);
if (geteuid() == 0) { if (geteuid() == 0) {
@ -264,30 +264,30 @@ static void test_chase_symlinks(void) {
q = strjoina(p, "/priv2"); q = strjoina(p, "/priv2");
assert_se(mkdir(q, 0755) >= 0); assert_se(mkdir(q, 0755) >= 0);
assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
assert_se(chown(q, UID_NOBODY, GID_NOBODY) >= 0); assert_se(chown(q, UID_NOBODY, GID_NOBODY) >= 0);
assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
assert_se(chown(p, UID_NOBODY, GID_NOBODY) >= 0); assert_se(chown(p, UID_NOBODY, GID_NOBODY) >= 0);
assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
assert_se(chown(q, 0, 0) >= 0); assert_se(chown(q, 0, 0) >= 0);
assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) == -ENOLINK); assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -ENOLINK);
assert_se(rmdir(q) >= 0); assert_se(rmdir(q) >= 0);
assert_se(symlink("/etc/passwd", q) >= 0); assert_se(symlink("/etc/passwd", q) >= 0);
assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) == -ENOLINK); assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -ENOLINK);
assert_se(chown(p, 0, 0) >= 0); assert_se(chown(p, 0, 0) >= 0);
assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
} }
p = strjoina(temp, "/machine-id-test"); p = strjoina(temp, "/machine-id-test");
assert_se(symlink("/usr/../etc/./machine-id", p) >= 0); assert_se(symlink("/usr/../etc/./machine-id", p) >= 0);
r = chase_symlinks(p, NULL, 0, NULL, &pfd); pfd = chase_symlinks(p, NULL, CHASE_OPEN, NULL);
if (r != -ENOENT) { if (pfd != -ENOENT) {
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
sd_id128_t a, b; sd_id128_t a, b;
@ -307,9 +307,8 @@ static void test_chase_symlinks(void) {
p = strjoina(temp, "/target"); p = strjoina(temp, "/target");
q = strjoina(temp, "/symlink"); q = strjoina(temp, "/symlink");
assert_se(symlink(p, q) >= 0); assert_se(symlink(p, q) >= 0);
r = chase_symlinks(q, NULL, CHASE_NOFOLLOW, &result, &pfd); pfd = chase_symlinks(q, NULL, CHASE_OPEN|CHASE_NOFOLLOW, &result);
assert_se(r >= 0); assert_se(pfd > 0);
assert_se(pfd >= 0);
assert_se(path_equal(result, q)); assert_se(path_equal(result, q));
assert_se(fstat(pfd, &st) >= 0); assert_se(fstat(pfd, &st) >= 0);
assert_se(S_ISLNK(st.st_mode)); assert_se(S_ISLNK(st.st_mode));
@ -320,9 +319,8 @@ static void test_chase_symlinks(void) {
assert_se(symlink("s2", q) >= 0); assert_se(symlink("s2", q) >= 0);
p = strjoina(temp, "/s2"); p = strjoina(temp, "/s2");
assert_se(symlink("nonexistent", p) >= 0); assert_se(symlink("nonexistent", p) >= 0);
r = chase_symlinks(q, NULL, CHASE_NOFOLLOW, &result, &pfd); pfd = chase_symlinks(q, NULL, CHASE_OPEN|CHASE_NOFOLLOW, &result);
assert_se(r >= 0); assert_se(pfd > 0);
assert_se(pfd >= 0);
assert_se(path_equal(result, q)); assert_se(path_equal(result, q));
assert_se(fstat(pfd, &st) >= 0); assert_se(fstat(pfd, &st) >= 0);
assert_se(S_ISLNK(st.st_mode)); assert_se(S_ISLNK(st.st_mode));
@ -331,42 +329,42 @@ static void test_chase_symlinks(void) {
/* Test CHASE_ONE */ /* Test CHASE_ONE */
p = strjoina(temp, "/start"); p = strjoina(temp, "/start");
r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); r = chase_symlinks(p, NULL, CHASE_STEP, &result);
assert_se(r == 0); assert_se(r == 0);
p = strjoina(temp, "/top/dot/dotdota"); p = strjoina(temp, "/top/dot/dotdota");
assert_se(streq(p, result)); assert_se(streq(p, result));
result = mfree(result); result = mfree(result);
r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); r = chase_symlinks(p, NULL, CHASE_STEP, &result);
assert_se(r == 0); assert_se(r == 0);
p = strjoina(temp, "/top/./dotdota"); p = strjoina(temp, "/top/./dotdota");
assert_se(streq(p, result)); assert_se(streq(p, result));
result = mfree(result); result = mfree(result);
r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); r = chase_symlinks(p, NULL, CHASE_STEP, &result);
assert_se(r == 0); assert_se(r == 0);
p = strjoina(temp, "/top/../a"); p = strjoina(temp, "/top/../a");
assert_se(streq(p, result)); assert_se(streq(p, result));
result = mfree(result); result = mfree(result);
r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); r = chase_symlinks(p, NULL, CHASE_STEP, &result);
assert_se(r == 0); assert_se(r == 0);
p = strjoina(temp, "/a"); p = strjoina(temp, "/a");
assert_se(streq(p, result)); assert_se(streq(p, result));
result = mfree(result); result = mfree(result);
r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); r = chase_symlinks(p, NULL, CHASE_STEP, &result);
assert_se(r == 0); assert_se(r == 0);
p = strjoina(temp, "/b"); p = strjoina(temp, "/b");
assert_se(streq(p, result)); assert_se(streq(p, result));
result = mfree(result); result = mfree(result);
r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); r = chase_symlinks(p, NULL, CHASE_STEP, &result);
assert_se(r == 0); assert_se(r == 0);
assert_se(streq("/usr", result)); assert_se(streq("/usr", result));
result = mfree(result); result = mfree(result);
r = chase_symlinks("/usr", NULL, CHASE_STEP, &result, NULL); r = chase_symlinks("/usr", NULL, CHASE_STEP, &result);
assert_se(r > 0); assert_se(r > 0);
assert_se(streq("/usr", result)); assert_se(streq("/usr", result));
result = mfree(result); result = mfree(result);

View File

@ -66,7 +66,7 @@ static void test_socket_address_parse_one(const char *in, int ret, int family, c
} }
#define SUN_PATH_LEN (sizeof(((struct sockaddr_un){}).sun_path)) #define SUN_PATH_LEN (sizeof(((struct sockaddr_un){}).sun_path))
assert_cc(SUN_PATH_LEN == 108); assert_cc(sizeof(((struct sockaddr_un){}).sun_path) == 108);
static void test_socket_address_parse(void) { static void test_socket_address_parse(void) {
log_info("/* %s */", __func__); log_info("/* %s */", __func__);
@ -126,7 +126,6 @@ static void test_socket_address_parse(void) {
static void test_socket_print_unix_one(const char *in, size_t len_in, const char *expected) { static void test_socket_print_unix_one(const char *in, size_t len_in, const char *expected) {
_cleanup_free_ char *out = NULL, *c = NULL; _cleanup_free_ char *out = NULL, *c = NULL;
assert(len_in <= SUN_PATH_LEN);
SocketAddress a = { .sockaddr = { .un = { .sun_family = AF_UNIX } }, SocketAddress a = { .sockaddr = { .un = { .sun_family = AF_UNIX } },
.size = offsetof(struct sockaddr_un, sun_path) + len_in, .size = offsetof(struct sockaddr_un, sun_path) + len_in,
.type = SOCK_STREAM, .type = SOCK_STREAM,
@ -153,6 +152,8 @@ static void test_socket_print_unix(void) {
"@_________________________there\\'s 108 characters in this string_____________________________________________"); "@_________________________there\\'s 108 characters in this string_____________________________________________");
test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 108, test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 108,
"////////////////////////////////////////////////////////////////////////////////////////////////////////////"); "////////////////////////////////////////////////////////////////////////////////////////////////////////////");
test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 109,
"////////////////////////////////////////////////////////////////////////////////////////////////////////////");
test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000"); test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000");
} }

View File

@ -859,7 +859,7 @@ shortcut:
static int path_open_parent_safe(const char *path) { static int path_open_parent_safe(const char *path) {
_cleanup_free_ char *dn = NULL; _cleanup_free_ char *dn = NULL;
int r, fd; int fd;
if (path_equal(path, "/") || !path_is_normalized(path)) if (path_equal(path, "/") || !path_is_normalized(path))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@ -870,15 +870,15 @@ static int path_open_parent_safe(const char *path) {
if (!dn) if (!dn)
return log_oom(); return log_oom();
r = chase_symlinks(dn, arg_root, CHASE_SAFE|CHASE_WARN, NULL, &fd); fd = chase_symlinks(dn, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN, NULL);
if (r < 0 && r != -ENOLINK) if (fd < 0 && fd != -ENOLINK)
return log_error_errno(r, "Failed to validate path %s: %m", path); return log_error_errno(fd, "Failed to validate path %s: %m", path);
return r < 0 ? r : fd; return fd;
} }
static int path_open_safe(const char *path) { static int path_open_safe(const char *path) {
int r, fd; int fd;
/* path_open_safe() returns a file descriptor opened with O_PATH after /* path_open_safe() returns a file descriptor opened with O_PATH after
* verifying that the path doesn't contain unsafe transitions, except * verifying that the path doesn't contain unsafe transitions, except
@ -891,11 +891,11 @@ static int path_open_safe(const char *path) {
"Failed to open invalid path '%s'.", "Failed to open invalid path '%s'.",
path); path);
r = chase_symlinks(path, arg_root, CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL, &fd); fd = chase_symlinks(path, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL);
if (r < 0 && r != -ENOLINK) if (fd < 0 && fd != -ENOLINK)
return log_error_errno(r, "Failed to validate path %s: %m", path); return log_error_errno(fd, "Failed to validate path %s: %m", path);
return r < 0 ? r : fd; return fd;
} }
static int path_set_perms(Item *i, const char *path) { static int path_set_perms(Item *i, const char *path) {
@ -2257,7 +2257,7 @@ static int process_item(Item *i, OperationMask operation) {
i->done |= operation; i->done |= operation;
r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL, NULL); r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL);
if (r == -EREMOTE) { if (r == -EREMOTE) {
log_notice_errno(r, "Skipping %s", i->path); log_notice_errno(r, "Skipping %s", i->path);
return 0; return 0;

View File

@ -119,7 +119,7 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn
/* Check if this is a virtual function. */ /* Check if this is a virtual function. */
physfn_link_file = strjoina(syspath, "/physfn"); physfn_link_file = strjoina(syspath, "/physfn");
r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath, NULL); r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath);
if (r < 0) if (r < 0)
return r; return r;
@ -143,7 +143,7 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn
if (!virtfn_link_file) if (!virtfn_link_file)
return -ENOMEM; return -ENOMEM;
if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath, NULL) < 0) if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath) < 0)
continue; continue;
if (streq(syspath, virtfn_pci_syspath)) { if (streq(syspath, virtfn_pci_syspath)) {

View File

@ -21,7 +21,7 @@ static int make_volatile(const char *path) {
assert(path); assert(path);
r = chase_symlinks("/usr", path, CHASE_PREFIX_ROOT, &old_usr, NULL); r = chase_symlinks("/usr", path, CHASE_PREFIX_ROOT, &old_usr);
if (r < 0) if (r < 0)
return log_error_errno(r, "/usr not available in old root: %m"); return log_error_errno(r, "/usr not available in old root: %m");