summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-10-24 10:33:20 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-10-24 10:33:20 +0200
commit7abeefa9f9e55592db14f3fdafc01ea8f90311e4 (patch)
treef91422895ffeda469dabd808cd4155d76638cc81
parent235ecb6d75f00384b3f42f449c769340e13fbd0b (diff)
downloadsystemd-chase-symlinks-rework.tar.gz
basic/fs-util: change CHASE_OPEN flag into a separate output parameterchase-symlinks-rework
chase_symlinks() would return negative on error, and either a non-negative status or a non-negative fd when CHASE_OPEN was given. This made the interface quite complicated, because dependning on the flags used, we would get two different "types" of return object. Coverity was always confused by this, and flagged every use of chase_symlinks() without CHASE_OPEN as a resource leak (because it would this that an fd is returned). This patch uses a saparate output parameter, so there is no confusion. (I think it is OK to have functions which return either an error or an fd. It's only returning *either* an fd or a non-fd that is confusing.)
-rw-r--r--src/basic/fs-util.c77
-rw-r--r--src/basic/fs-util.h16
-rw-r--r--src/basic/mkdir.c2
-rw-r--r--src/basic/mountpoint-util.c2
-rw-r--r--src/basic/path-util.c2
-rw-r--r--src/basic/stat-util.c2
-rw-r--r--src/core/dbus-manager.c2
-rw-r--r--src/core/namespace.c4
-rw-r--r--src/core/service.c21
-rw-r--r--src/core/socket.c2
-rw-r--r--src/core/unit.c2
-rw-r--r--src/delta/delta.c6
-rw-r--r--src/fstab-generator/fstab-generator.c2
-rw-r--r--src/journal/journalctl.c2
-rw-r--r--src/libsystemd/sd-device/sd-device.c4
-rw-r--r--src/machine/machine-dbus.c2
-rw-r--r--src/mount/mount-tool.c6
-rw-r--r--src/nspawn/nspawn-mount.c12
-rw-r--r--src/nspawn/nspawn.c15
-rw-r--r--src/portable/portablectl.c2
-rw-r--r--src/shared/dissect-image.c6
-rw-r--r--src/shared/dropin.c2
-rw-r--r--src/shared/machine-image.c6
-rw-r--r--src/shared/os-util.c16
-rw-r--r--src/shared/switch-root.c4
-rw-r--r--src/shared/unit-file.c2
-rw-r--r--src/systemctl/systemctl.c2
-rw-r--r--src/test/test-chase-symlinks.c22
-rw-r--r--src/test/test-copy.c2
-rw-r--r--src/test/test-fs-util.c104
-rw-r--r--src/tmpfiles/tmpfiles.c22
-rw-r--r--src/udev/udev-builtin-net_id.c4
-rw-r--r--src/volatile-root/volatile-root.c2
33 files changed, 197 insertions, 180 deletions
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index a92241ca02..d20b9a5df5 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -713,7 +713,7 @@ static int log_autofs_mount_point(int fd, const char *path, unsigned flags) {
n1, path);
}
-int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
+int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) {
_cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
_cleanup_close_ int fd = -1;
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);
/* Either the file may be missing, or we return an fd to the final object, but both make no sense */
- if (FLAGS_SET(flags, CHASE_NONEXISTENT | CHASE_OPEN))
+ if ((flags & CHASE_NONEXISTENT) && ret_fd)
return -EINVAL;
- if (FLAGS_SET(flags, CHASE_STEP | CHASE_OPEN))
+ if ((flags & CHASE_STEP) && ret_fd)
return -EINVAL;
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
* specified path.
*
- * There are three ways to invoke this function:
+ * There are five ways to invoke this function:
*
- * 1. Without CHASE_STEP or CHASE_OPEN: in this case the path is resolved and the normalized path is returned
- * in `ret`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0 is returned if the file
- * doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is returned if the destination was
- * found, -ENOENT if it wasn't.
+ * 1. Without CHASE_STEP or ret_fd: in this case the path is resolved and the normalized path is
+ * returned in `ret_path`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0
+ * is returned if the file doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is
+ * returned if the destination was found, -ENOENT if it wasn't.
*
- * 2. With CHASE_OPEN: in this case the destination is opened after chasing it as O_PATH and this file
+ * 2. With ret_fd: 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
* 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. CHASE_OPEN may not be combined with
+ * fd_reopen() or such) before it can be used for reading/writing. ret_fd may not be combined with
* CHASE_NONEXISTENT.
*
* 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
* is aborted and -EREMOTE is returned. If CHASE_WARN is also set, a warning showing the path of
* the mount point is emitted.
- *
*/
/* A root directory of "/" or "" is identical to none */
if (empty_or_root(original_root))
original_root = NULL;
- if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) {
- /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set
+ if (!original_root && !ret_path && !(flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_STEP)) && ret_fd) {
+ /* Shortcut the ret_fd 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. */
r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0));
if (r < 0)
return -errno;
- return r;
+ *ret_fd = r;
+ return 0;
}
if (original_root) {
@@ -803,7 +803,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return r;
if (flags & CHASE_PREFIX_ROOT) {
-
/* We don't support relative paths in combination with a root directory */
if (!path_is_absolute(path))
return -EINVAL;
@@ -948,7 +947,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) {
char *joined;
-
_cleanup_free_ char *destination = NULL;
/* This is a symlink, in this case read the destination. But let's make sure we don't follow
@@ -1034,15 +1032,15 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return -ENOMEM;
}
- if (ret)
- *ret = TAKE_PTR(done);
+ if (ret_path)
+ *ret_path = TAKE_PTR(done);
- if (flags & CHASE_OPEN) {
- /* 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. */
+ if (ret_fd) {
+ /* 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);
+ *ret_fd = TAKE_FD(fd);
}
if (flags & CHASE_STEP)
@@ -1051,14 +1049,14 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return exists;
chased_one:
- if (ret) {
+ if (ret_path) {
char *c;
c = strjoin(strempty(done), todo);
if (!c)
return -ENOMEM;
- *ret = c;
+ *ret_path = c;
}
return 0;
@@ -1087,9 +1085,10 @@ int chase_symlinks_and_open(
return r;
}
- path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
- if (path_fd < 0)
- return path_fd;
+ r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd);
+ if (r < 0)
+ return r;
+ assert(path_fd >= 0);
r = fd_reopen(path_fd, open_flags);
if (r < 0)
@@ -1112,6 +1111,7 @@ int chase_symlinks_and_opendir(
_cleanup_close_ int path_fd = -1;
_cleanup_free_ char *p = NULL;
DIR *d;
+ int r;
if (!ret_dir)
return -EINVAL;
@@ -1128,9 +1128,10 @@ int chase_symlinks_and_opendir(
return 0;
}
- path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
- if (path_fd < 0)
- return path_fd;
+ r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd);
+ if (r < 0)
+ return r;
+ assert(path_fd >= 0);
xsprintf(procfs_path, "/proc/self/fd/%i", path_fd);
d = opendir(procfs_path);
@@ -1149,10 +1150,12 @@ int chase_symlinks_and_stat(
const char *root,
unsigned chase_flags,
char **ret_path,
- struct stat *ret_stat) {
+ struct stat *ret_stat,
+ int *ret_fd) {
_cleanup_close_ int path_fd = -1;
_cleanup_free_ char *p = NULL;
+ int r;
assert(path);
assert(ret_stat);
@@ -1168,18 +1171,18 @@ int chase_symlinks_and_stat(
return 1;
}
- path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
- if (path_fd < 0)
- return path_fd;
+ r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd);
+ if (r < 0)
+ return r;
+ assert(path_fd >= 0);
if (fstat(path_fd, ret_stat) < 0)
return -errno;
if (ret_path)
*ret_path = TAKE_PTR(p);
-
- if (chase_flags & CHASE_OPEN)
- return TAKE_FD(path_fd);
+ if (ret_fd)
+ *ret_fd = TAKE_FD(path_fd);
return 1;
}
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index fa0f0de9a3..78d68be9fd 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -79,23 +79,21 @@ enum {
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_SAFE = 1 << 3, /* Return EPERM if we ever traverse from unprivileged to privileged files or directories */
- CHASE_OPEN = 1 << 4, /* Return an O_PATH object to the final component */
- CHASE_TRAIL_SLASH = 1 << 5, /* Any trailing slash will be preserved */
- CHASE_STEP = 1 << 6, /* Just execute a single step of the normalization */
- CHASE_NOFOLLOW = 1 << 7, /* Do not follow the path's right-most compontent. With CHASE_OPEN, when
- * 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 */
+ CHASE_TRAIL_SLASH = 1 << 4, /* Any trailing slash will be preserved */
+ CHASE_STEP = 1 << 5, /* Just execute a single step of the normalization */
+ CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most compontent. With ret_fd, when the path's
+ * right-most component refers to symlink, return O_PATH fd of the symlink. */
+ CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered */
};
/* How many iterations to execute before returning -ELOOP */
#define CHASE_SYMLINKS_MAX 32
-int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret);
+int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret_path, int *ret_fd);
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_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat);
+int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd);
/* Useful for usage with _cleanup_(), removes a directory and frees the pointer */
static inline void rmdir_and_free(char *p) {
diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c
index 6b82eab640..1f318252a9 100644
--- a/src/basic/mkdir.c
+++ b/src/basic/mkdir.c
@@ -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)) {
_cleanup_free_ char *p = NULL;
- r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p);
+ r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p, NULL);
if (r < 0)
return r;
if (r == 0)
diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c
index d3b8e44f18..a79377f05d 100644
--- a/src/basic/mountpoint-util.c
+++ b/src/basic/mountpoint-util.c
@@ -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
* look at needs to be /usr, not /. */
if (flags & AT_SYMLINK_FOLLOW) {
- r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical);
+ r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical, NULL);
if (r < 0)
return r;
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index b9544b4bac..98b6d0617f 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -273,7 +273,7 @@ char **path_strv_resolve(char **l, const char *root) {
} else
t = *s;
- r = chase_symlinks(t, root, 0, &u);
+ r = chase_symlinks(t, root, 0, &u, NULL);
if (r == -ENOENT) {
if (root) {
u = TAKE_PTR(orig);
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
index 2cd722c106..4572e004bb 100644
--- a/src/basic/stat-util.c
+++ b/src/basic/stat-util.c
@@ -335,7 +335,7 @@ int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) {
if (r < 0)
return r;
- return chase_symlinks(p, NULL, 0, ret);
+ return chase_symlinks(p, NULL, 0, ret, NULL);
}
int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno) {
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 035011e34f..d98ec32a0b 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1471,7 +1471,7 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
if (!path_is_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);
+ r = chase_symlinks(init, root, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &chased, NULL);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Could not resolve init executable %s: %m", init);
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 973b64007c..f6f7736819 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -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
* end and already have a fully normalized name. */
- r = chase_symlinks(mount_entry_path(m), root_directory, CHASE_STEP|CHASE_NONEXISTENT, &target);
+ r = chase_symlinks(mount_entry_path(m), root_directory, CHASE_STEP|CHASE_NONEXISTENT, &target, NULL);
if (r < 0)
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 */
@@ -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
* chase_symlinks() here. */
- r = chase_symlinks(mount_entry_source(m), NULL, CHASE_TRAIL_SLASH, &chased);
+ r = chase_symlinks(mount_entry_source(m), NULL, CHASE_TRAIL_SLASH, &chased, NULL);
if (r == -ENOENT && m->ignore) {
log_debug_errno(r, "Path %s does not exist, ignoring.", mount_entry_source(m));
return 0;
diff --git a/src/core/service.c b/src/core/service.c
index 256ca46fd8..525ce42890 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -946,22 +946,27 @@ static int service_load_pid_file(Service *s, bool may_warn) {
prio = may_warn ? LOG_INFO : LOG_DEBUG;
- fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN|CHASE_SAFE, NULL);
- if (fd == -ENOLINK) {
- log_unit_full(UNIT(s), LOG_DEBUG, fd, "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file);
+ r = chase_symlinks(s->pid_file, NULL, CHASE_SAFE, NULL, &fd);
+ if (r == -ENOLINK) {
+ log_unit_full(UNIT(s), LOG_DEBUG, r,
+ "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file);
questionable_pid_file = true;
- fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN, NULL);
+ r = chase_symlinks(s->pid_file, NULL, 0, NULL, &fd);
}
- if (fd < 0)
- 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));
+ if (r < 0)
+ 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));
- /* 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. */
+ /* 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. */
xsprintf(procfs, "/proc/self/fd/%i", fd);
r = read_one_line_file(procfs, &k);
if (r < 0)
- 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);
+ 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);
r = parse_pid(k, &pid);
if (r < 0)
diff --git a/src/core/socket.c b/src/core/socket.c
index 71ab3c647f..285aa641d3 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -1429,7 +1429,7 @@ static int socket_determine_selinux_label(Socket *s, char **ret) {
if (!c)
goto no_label;
- r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path);
+ r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path, NULL);
if (r < 0)
goto no_label;
diff --git a/src/core/unit.c b/src/core/unit.c
index 58c99d9e07..4fcc142ae9 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -4974,7 +4974,7 @@ int unit_fail_if_noncanonical(Unit *u, const char* where) {
assert(u);
assert(where);
- r = chase_symlinks(where, NULL, CHASE_NONEXISTENT, &canonical_where);
+ r = chase_symlinks(where, NULL, CHASE_NONEXISTENT, &canonical_where, NULL);
if (r < 0) {
log_unit_debug_errno(u, r, "Failed to check %s for symlinks, ignoring: %m", where);
return 0;
diff --git a/src/delta/delta.c b/src/delta/delta.c
index bc11aa828a..cd33850b96 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -73,11 +73,11 @@ static int equivalent(const char *a, const char *b) {
_cleanup_free_ char *x = NULL, *y = NULL;
int r;
- r = chase_symlinks(a, NULL, CHASE_TRAIL_SLASH, &x);
+ r = chase_symlinks(a, NULL, CHASE_TRAIL_SLASH, &x, NULL);
if (r < 0)
return r;
- r = chase_symlinks(b, NULL, CHASE_TRAIL_SLASH, &y);
+ r = chase_symlinks(b, NULL, CHASE_TRAIL_SLASH, &y, NULL);
if (r < 0)
return r;
@@ -378,7 +378,7 @@ static int should_skip_path(const char *prefix, const char *suffix) {
dirname = prefix_roota(prefix, suffix);
- if (chase_symlinks(dirname, NULL, 0, &target) < 0)
+ if (chase_symlinks(dirname, NULL, 0, &target, NULL) < 0)
return false;
NULSTR_FOREACH(p, prefixes) {
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 76270aec17..026a25f575 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -563,7 +563,7 @@ static int parse_fstab(bool initrd) {
* target is the final directory. */
r = chase_symlinks(where, initrd ? "/sysroot" : NULL,
CHASE_PREFIX_ROOT | CHASE_NONEXISTENT,
- &canonical_where);
+ &canonical_where, NULL);
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);
else if (streq(canonical_where, where)) /* If it was fully canonicalized, suppress the change */
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 6d6bb1cf63..6d9b5cfc2f 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -1086,7 +1086,7 @@ static int add_matches(sd_journal *j, char **args) {
_cleanup_free_ char *p = NULL, *t = NULL, *t2 = NULL, *interpreter = NULL;
struct stat st;
- r = chase_symlinks(*i, NULL, CHASE_TRAIL_SLASH, &p);
+ r = chase_symlinks(*i, NULL, CHASE_TRAIL_SLASH, &p, NULL);
if (r < 0)
return log_error_errno(r, "Couldn't canonicalize path: %m");
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index c4a7f2f3d3..4a5e8ff944 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -146,7 +146,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
_syspath);
if (verify) {
- r = chase_symlinks(_syspath, NULL, 0, &syspath);
+ r = chase_symlinks(_syspath, NULL, 0, &syspath, NULL);
if (r == -ENOENT)
return -ENODEV; /* the device does not exist (any more?) */
if (r < 0)
@@ -157,7 +157,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
char *p;
/* /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);
+ r = chase_symlinks("/sys", NULL, 0, &real_sys, NULL);
if (r < 0)
return log_debug_errno(r, "sd-device: Failed to chase symlink /sys: %m");
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 0d58b5eb8b..c2747112d4 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -846,7 +846,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
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.");
- r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, &chased_src);
+ r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, &chased_src, NULL);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to resolve source path: %m");
diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c
index 457ba4ea16..9f0220a75e 100644
--- a/src/mount/mount-tool.c
+++ b/src/mount/mount-tool.c
@@ -360,7 +360,7 @@ static int parse_argv(int argc, char *argv[]) {
if (!u)
return log_oom();
- r = chase_symlinks(u, NULL, 0, &arg_mount_what);
+ r = chase_symlinks(u, NULL, 0, &arg_mount_what, NULL);
if (r < 0)
return log_error_errno(r, "Failed to make path %s absolute: %m", u);
} else {
@@ -377,7 +377,7 @@ static int parse_argv(int argc, char *argv[]) {
if (argc > optind+1) {
if (arg_transport == BUS_TRANSPORT_LOCAL) {
- r = chase_symlinks(argv[optind+1], NULL, CHASE_NONEXISTENT, &arg_mount_where);
+ r = chase_symlinks(argv[optind+1], NULL, CHASE_NONEXISTENT, &arg_mount_where, NULL);
if (r < 0)
return log_error_errno(r, "Failed to make path %s absolute: %m", argv[optind+1]);
} else {
@@ -1004,7 +1004,7 @@ static int action_umount(
if (!u)
return log_oom();
- r = chase_symlinks(u, NULL, 0, &p);
+ r = chase_symlinks(u, NULL, 0, &p, NULL);
if (r < 0) {
r2 = log_error_errno(r, "Failed to make path %s absolute: %m", argv[i]);
continue;
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
index 2f842754a4..6407503c4c 100644
--- a/src/nspawn/nspawn-mount.c
+++ b/src/nspawn/nspawn-mount.c
@@ -633,7 +633,7 @@ int mount_all(const char *dest,
if (!tmpfs_tmp && (bool)(mount_table[k].mount_settings & MOUNT_APPLY_TMPFS_TMP))
continue;
- r = chase_symlinks(mount_table[k].where, dest, CHASE_NONEXISTENT|CHASE_PREFIX_ROOT, &where);
+ r = chase_symlinks(mount_table[k].where, dest, CHASE_NONEXISTENT|CHASE_PREFIX_ROOT, &where, NULL);
if (r < 0)
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)
return log_error_errno(errno, "Failed to stat %s: %m", m->source);
- r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
+ r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL);
if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r > 0) { /* Path exists already? */
@@ -795,7 +795,7 @@ static int mount_tmpfs(
assert(dest);
assert(m);
- r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
+ r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL);
if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r == 0) { /* Doesn't exist yet? */
@@ -835,7 +835,7 @@ static int mount_overlay(const char *dest, CustomMount *m) {
assert(dest);
assert(m);
- r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
+ r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL);
if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r == 0) { /* Doesn't exist yet? */
@@ -878,7 +878,7 @@ static int mount_inaccessible(const char *dest, CustomMount *m) {
assert(dest);
assert(m);
- r = chase_symlinks_and_stat(m->destination, dest, CHASE_PREFIX_ROOT, &where, &st);
+ r = chase_symlinks_and_stat(m->destination, dest, CHASE_PREFIX_ROOT, &where, &st, NULL);
if (r < 0) {
log_full_errno(m->graceful ? LOG_DEBUG : LOG_ERR, r, "Failed to resolve %s/%s: %m", dest, m->destination);
return m->graceful ? 0 : r;
@@ -906,7 +906,7 @@ static int mount_arbitrary(const char *dest, CustomMount *m) {
assert(dest);
assert(m);
- r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where);
+ r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL);
if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination);
if (r == 0) { /* Doesn't exist yet? */
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 40a7de981a..7760bcaa2d 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1668,7 +1668,7 @@ static int setup_timezone(const char *dest) {
if (m == TIMEZONE_OFF)
return 0;
- r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc);
+ r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc, NULL);
if (r < 0) {
log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m");
return 0;
@@ -1699,7 +1699,7 @@ static int setup_timezone(const char *dest) {
return 0; /* Already pointing to the right place? Then do nothing .. */
check = strjoina(dest, "/usr/share/zoneinfo/", z);
- r = chase_symlinks(check, dest, 0, NULL);
+ r = chase_symlinks(check, dest, 0, NULL, NULL);
if (r < 0)
log_debug_errno(r, "Timezone %s does not exist (or is not accessible) in container, not creating symlink: %m", z);
else {
@@ -1726,7 +1726,7 @@ static int setup_timezone(const char *dest) {
_cleanup_free_ char *resolved = NULL;
int found;
- found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
+ found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved, NULL);
if (found < 0) {
log_warning_errno(found, "Failed to resolve /etc/localtime path in container, ignoring: %m");
return 0;
@@ -1832,7 +1832,7 @@ static int setup_resolv_conf(const char *dest) {
if (m == RESOLV_CONF_OFF)
return 0;
- r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc);
+ r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc, NULL);
if (r < 0) {
log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m");
return 0;
@@ -1856,7 +1856,7 @@ static int setup_resolv_conf(const char *dest) {
_cleanup_free_ char *resolved = NULL;
int found;
- found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
+ found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved, NULL);
if (found < 0) {
log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m");
return 0;
@@ -2733,12 +2733,11 @@ static int chase_symlinks_and_update(char **p, unsigned flags) {
if (!*p)
return 0;
- r = chase_symlinks(*p, NULL, flags, &chased);
+ r = chase_symlinks(*p, NULL, flags, &chased, NULL);
if (r < 0)
return log_error_errno(r, "Failed to resolve path %s: %m", *p);
- free_and_replace(*p, chased);
- return r; /* r might be an fd here in case we ever use CHASE_OPEN in flags */
+ return free_and_replace(*p, chased);
}
static int determine_uid_shift(const char *directory) {
diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c
index 2f8b0254c8..06ab7735ad 100644
--- a/src/portable/portablectl.c
+++ b/src/portable/portablectl.c
@@ -67,7 +67,7 @@ static int determine_image(const char *image, bool permit_non_existing, char **r
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"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);
+ r = chase_symlinks(image, NULL, CHASE_TRAIL_SLASH | (permit_non_existing ? CHASE_NONEXISTENT : 0), ret, NULL);
if (r < 0)
return log_error_errno(r, "Cannot normalize specified image path '%s': %m", image);
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index a54714169e..3e75464966 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -833,7 +833,7 @@ static int mount_partition(
rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY);
if (directory) {
- r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased);
+ r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased, NULL);
if (r < 0)
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
* exists and is empty, and we didn't already mount the XBOOTLDR partition into it. */
- r = chase_symlinks("/efi", where, CHASE_PREFIX_ROOT, NULL);
+ r = chase_symlinks("/efi", where, CHASE_PREFIX_ROOT, NULL, NULL);
if (r >= 0) {
r = mount_partition(m->partitions + PARTITION_ESP, where, "/efi", uid_shift, flags);
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) {
_cleanup_free_ char *p = NULL;
- r = chase_symlinks("/boot", where, CHASE_PREFIX_ROOT, &p);
+ r = chase_symlinks("/boot", where, CHASE_PREFIX_ROOT, &p, NULL);
if (r >= 0 && dir_is_empty(p) > 0) {
r = mount_partition(m->partitions + PARTITION_ESP, where, "/boot", uid_shift, flags);
if (r < 0)
diff --git a/src/shared/dropin.c b/src/shared/dropin.c
index 2f67a44bf0..7328b7adde 100644
--- a/src/shared/dropin.c
+++ b/src/shared/dropin.c
@@ -106,7 +106,7 @@ static int unit_file_add_dir(
/* This adds [original_root]/path to dirs, if it exists. */
- r = chase_symlinks(path, original_root, 0, &chased);
+ r = chase_symlinks(path, original_root, 0, &chased, NULL);
if (r == -ENOENT) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */
return 0;
if (r == -ENAMETOOLONG) {
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index 7007374192..cceed58f74 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -1113,7 +1113,7 @@ int image_read_metadata(Image *i) {
_cleanup_free_ char *hostname = NULL;
_cleanup_free_ char *path = NULL;
- r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
+ r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL);
if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to chase /etc/hostname in image %s: %m", i->name);
else if (r >= 0) {
@@ -1124,7 +1124,7 @@ int image_read_metadata(Image *i) {
path = mfree(path);
- r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
+ r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL);
if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to chase /etc/machine-id in image %s: %m", i->name);
else if (r >= 0) {
@@ -1142,7 +1142,7 @@ int image_read_metadata(Image *i) {
path = mfree(path);
- r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
+ r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL);
if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to chase /etc/machine-info in image %s: %m", i->name);
else if (r >= 0) {
diff --git a/src/shared/os-util.c b/src/shared/os-util.c
index 2191a610ae..b2af8535f9 100644
--- a/src/shared/os-util.c
+++ b/src/shared/os-util.c
@@ -33,22 +33,24 @@ int path_is_os_tree(const char *path) {
int open_os_release(const char *root, char **ret_path, int *ret_fd) {
_cleanup_free_ char *q = NULL;
const char *p;
- int k;
+ int r, fd;
FOREACH_STRING(p, "/etc/os-release", "/usr/lib/os-release") {
- k = chase_symlinks(p, root, CHASE_PREFIX_ROOT|(ret_fd ? CHASE_OPEN : 0), (ret_path ? &q : NULL));
- if (k != -ENOENT)
+ r = chase_symlinks(p, root, CHASE_PREFIX_ROOT,
+ ret_path ? &q : NULL,
+ ret_fd ? &fd : NULL);
+ if (r != -ENOENT)
break;
}
- if (k < 0)
- return k;
+ if (r < 0)
+ return r;
if (ret_fd) {
int real_fd;
/* Convert the O_PATH fd into a proper, readable one */
- real_fd = fd_reopen(k, O_RDONLY|O_CLOEXEC|O_NOCTTY);
- safe_close(k);
+ real_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+ safe_close(fd);
if (real_fd < 0)
return real_fd;
diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c
index f721aff760..a807826378 100644
--- a/src/shared/switch-root.c
+++ b/src/shared/switch-root.c
@@ -52,7 +52,7 @@ int switch_root(const char *new_root,
}
/* 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);
+ r = chase_symlinks(old_root_after, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved_old_root_after, NULL);
if (r < 0)
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 */
@@ -68,7 +68,7 @@ int switch_root(const char *new_root,
FOREACH_STRING(i, "/sys", "/dev", "/run", "/proc") {
_cleanup_free_ char *chased = NULL;
- r = chase_symlinks(i, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &chased);
+ r = chase_symlinks(i, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &chased, NULL);
if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", new_root, i);
if (r > 0) {
diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c
index b015ff9338..28cd3c8600 100644
--- a/src/shared/unit-file.c
+++ b/src/shared/unit-file.c
@@ -303,7 +303,7 @@ int unit_file_build_name_map(
}
/* Get rid of "." and ".." components in target path */
- r = chase_symlinks(target, lp->root_dir, CHASE_NOFOLLOW | CHASE_NONEXISTENT, &simplified);
+ r = chase_symlinks(target, lp->root_dir, CHASE_NOFOLLOW | CHASE_NONEXISTENT, &simplified, NULL);
if (r < 0) {
log_warning_errno(r, "Failed to resolve symlink %s pointing to %s, ignoring: %m",
filename, target);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index e4b85d906c..05013484ad 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -2520,7 +2520,7 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **re
if (!path)
return log_oom();
- r = chase_symlinks(path, arg_root, 0, &lpath);
+ r = chase_symlinks(path, arg_root, 0, &lpath, NULL);
if (r == -ENOENT)
continue;
if (r == -ENOMEM)
diff --git a/src/test/test-chase-symlinks.c b/src/test/test-chase-symlinks.c
index 013b36e2a7..0b7dd8764f 100644
--- a/src/test/test-chase-symlinks.c
+++ b/src/test/test-chase-symlinks.c
@@ -8,21 +8,23 @@
static char *arg_root = NULL;
static int arg_flags = 0;
+static bool arg_open = false;
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_ROOT = 0x1000,
+ ARG_OPEN,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "root", required_argument, NULL, ARG_ROOT },
+ { "open", no_argument, NULL, ARG_OPEN },
{ "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT },
{ "nonexistent", no_argument, NULL, CHASE_NONEXISTENT },
{ "no_autofs", no_argument, NULL, CHASE_NO_AUTOFS },
{ "safe", no_argument, NULL, CHASE_SAFE },
- { "open", no_argument, NULL, CHASE_OPEN },
{ "trail-slash", no_argument, NULL, CHASE_TRAIL_SLASH },
{ "step", no_argument, NULL, CHASE_STEP },
{ "nofollow", no_argument, NULL, CHASE_NOFOLLOW },
@@ -51,11 +53,14 @@ static int parse_argv(int argc, char *argv[]) {
arg_root = optarg;
break;
+ case ARG_OPEN:
+ arg_open = true;
+ break;
+
case CHASE_PREFIX_ROOT:
case CHASE_NONEXISTENT:
case CHASE_NO_AUTOFS:
case CHASE_SAFE:
- case CHASE_OPEN:
case CHASE_TRAIL_SLASH:
case CHASE_STEP:
case CHASE_NOFOLLOW:
@@ -89,18 +94,21 @@ static int run(int argc, char **argv) {
for (int i = optind; i < argc; i++) {
_cleanup_free_ char *p = NULL;
+ _cleanup_close_ int fd = -1;
printf("%s ", argv[i]);
fflush(stdout);
- r = chase_symlinks(argv[i], arg_root, arg_flags, &p);
+ r = chase_symlinks(argv[i], arg_root, arg_flags, &p, arg_open ? &fd : NULL);
if (r < 0)
log_error_errno(r, "failed: %m");
- else
+ else {
log_info("→ %s", p);
-
- if (FLAGS_SET(arg_flags, CHASE_OPEN))
- safe_close(r);
+ if (arg_open)
+ assert(fd >= 0);
+ else
+ assert(fd == -1);
+ }
}
return 0;
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index 5f7b9e5ce8..ffabf95663 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -130,7 +130,7 @@ static void test_copy_tree(void) {
assert_se(f = strjoin(original_dir, *p));
assert_se(l = strjoin(copy_dir, *link));
- assert_se(chase_symlinks(l, NULL, 0, &target) == 1);
+ assert_se(chase_symlinks(l, NULL, 0, &target, NULL) == 1);
assert_se(path_equal(f, target));
}
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index 7cf4f4976b..ac8b95aece 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -61,45 +61,45 @@ static void test_chase_symlinks(void) {
/* Paths that use symlinks underneath the "root" */
- r = chase_symlinks(p, NULL, 0, &result);
+ r = chase_symlinks(p, NULL, 0, &result, NULL);
assert_se(r > 0);
assert_se(path_equal(result, "/usr"));
result = mfree(result);
pslash = strjoina(p, "/");
- r = chase_symlinks(pslash, NULL, 0, &result);
+ r = chase_symlinks(pslash, NULL, 0, &result, NULL);
assert_se(r > 0);
assert_se(path_equal(result, "/usr/"));
result = mfree(result);
- r = chase_symlinks(p, temp, 0, &result);
+ r = chase_symlinks(p, temp, 0, &result, NULL);
assert_se(r == -ENOENT);
- r = chase_symlinks(pslash, temp, 0, &result);
+ r = chase_symlinks(pslash, temp, 0, &result, NULL);
assert_se(r == -ENOENT);
q = strjoina(temp, "/usr");
- r = chase_symlinks(p, temp, CHASE_NONEXISTENT, &result);
+ r = chase_symlinks(p, temp, CHASE_NONEXISTENT, &result, NULL);
assert_se(r == 0);
assert_se(path_equal(result, q));
result = mfree(result);
qslash = strjoina(q, "/");
- r = chase_symlinks(pslash, temp, CHASE_NONEXISTENT, &result);
+ r = chase_symlinks(pslash, temp, CHASE_NONEXISTENT, &result, NULL);
assert_se(r == 0);
assert_se(path_equal(result, qslash));
result = mfree(result);
assert_se(mkdir(q, 0700) >= 0);
- r = chase_symlinks(p, temp, 0, &result);
+ r = chase_symlinks(p, temp, 0, &result, NULL);
assert_se(r > 0);
assert_se(path_equal(result, q));
result = mfree(result);
- r = chase_symlinks(pslash, temp, 0, &result);
+ r = chase_symlinks(pslash, temp, 0, &result, NULL);
assert_se(r > 0);
assert_se(path_equal(result, qslash));
result = mfree(result);
@@ -107,12 +107,12 @@ static void test_chase_symlinks(void) {
p = strjoina(temp, "/slash");
assert_se(symlink("/", p) >= 0);
- r = chase_symlinks(p, NULL, 0, &result);
+ r = chase_symlinks(p, NULL, 0, &result, NULL);
assert_se(r > 0);
assert_se(path_equal(result, "/"));
result = mfree(result);
- r = chase_symlinks(p, temp, 0, &result);
+ r = chase_symlinks(p, temp, 0, &result, NULL);
assert_se(r > 0);
assert_se(path_equal(result, temp));
result = mfree(result);
@@ -122,21 +122,21 @@ static void test_chase_symlinks(void) {
p = strjoina(temp, "/6dots");
assert_se(symlink("../../..", p) >= 0);
- r = chase_symlinks(p, temp, 0, &result);
+ r = chase_symlinks(p, temp, 0, &result, NULL);
assert_se(r > 0 && path_equal(result, temp));
result = mfree(result);
p = strjoina(temp, "/6dotsusr");
assert_se(symlink("../../../usr", p) >= 0);
- r = chase_symlinks(p, temp, 0, &result);
+ r = chase_symlinks(p, temp, 0, &result, NULL);
assert_se(r > 0 && path_equal(result, q));
result = mfree(result);
p = strjoina(temp, "/top/8dotsusr");
assert_se(symlink("../../../../usr", p) >= 0);
- r = chase_symlinks(p, temp, 0, &result);
+ r = chase_symlinks(p, temp, 0, &result, NULL);
assert_se(r > 0 && path_equal(result, q));
result = mfree(result);
@@ -145,12 +145,12 @@ static void test_chase_symlinks(void) {
p = strjoina(temp, "/slashslash");
assert_se(symlink("///usr///", p) >= 0);
- r = chase_symlinks(p, NULL, 0, &result);
+ r = chase_symlinks(p, NULL, 0, &result, NULL);
assert_se(r > 0);
assert_se(path_equal(result, "/usr"));
result = mfree(result);
- r = chase_symlinks(p, temp, 0, &result);
+ r = chase_symlinks(p, temp, 0, &result, NULL);
assert_se(r > 0);
assert_se(path_equal(result, q));
result = mfree(result);
@@ -169,48 +169,48 @@ static void test_chase_symlinks(void) {
assert_se(symlink("/", p) >= 0);
/* Fail when user-owned directories contain root-owned subdirectories. */
- r = chase_symlinks(p, temp, CHASE_SAFE, &result);
+ r = chase_symlinks(p, temp, CHASE_SAFE, &result, NULL);
assert_se(r == -ENOLINK);
result = mfree(result);
/* Allow this when the user-owned directories are all in the "root". */
- r = chase_symlinks(p, q, CHASE_SAFE, &result);
+ r = chase_symlinks(p, q, CHASE_SAFE, &result, NULL);
assert_se(r > 0);
result = mfree(result);
}
/* Paths using . */
- r = chase_symlinks("/etc/./.././", NULL, 0, &result);
+ r = chase_symlinks("/etc/./.././", NULL, 0, &result, NULL);
assert_se(r > 0);
assert_se(path_equal(result, "/"));
result = mfree(result);
- r = chase_symlinks("/etc/./.././", "/etc", 0, &result);
+ r = chase_symlinks("/etc/./.././", "/etc", 0, &result, NULL);
assert_se(r > 0 && path_equal(result, "/etc"));
result = mfree(result);
- r = chase_symlinks("/../.././//../../etc", NULL, 0, &result);
+ r = chase_symlinks("/../.././//../../etc", NULL, 0, &result, NULL);
assert_se(r > 0);
assert_se(streq(result, "/etc"));
result = mfree(result);
- r = chase_symlinks("/../.././//../../test-chase.fsldajfl", NULL, CHASE_NONEXISTENT, &result);
+ r = chase_symlinks("/../.././//../../test-chase.fsldajfl", NULL, CHASE_NONEXISTENT, &result, NULL);
assert_se(r == 0);
assert_se(streq(result, "/test-chase.fsldajfl"));
result = mfree(result);
- r = chase_symlinks("/../.././//../../etc", "/", CHASE_PREFIX_ROOT, &result);
+ r = chase_symlinks("/../.././//../../etc", "/", CHASE_PREFIX_ROOT, &result, NULL);
assert_se(r > 0);
assert_se(streq(result, "/etc"));
result = mfree(result);
- r = chase_symlinks("/../.././//../../test-chase.fsldajfl", "/", CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &result);
+ r = chase_symlinks("/../.././//../../test-chase.fsldajfl", "/", CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &result, NULL);
assert_se(r == 0);
assert_se(streq(result, "/test-chase.fsldajfl"));
result = mfree(result);
- r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result);
+ r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result, NULL);
assert_se(r == -ENOTDIR);
result = mfree(result);
@@ -218,25 +218,25 @@ static void test_chase_symlinks(void) {
p = strjoina(temp, "/recursive-symlink");
assert_se(symlink("recursive-symlink", p) >= 0);
- r = chase_symlinks(p, NULL, 0, &result);
+ r = chase_symlinks(p, NULL, 0, &result, NULL);
assert_se(r == -ELOOP);
/* Path which doesn't exist */
p = strjoina(temp, "/idontexist");
- r = chase_symlinks(p, NULL, 0, &result);
+ r = chase_symlinks(p, NULL, 0, &result, NULL);
assert_se(r == -ENOENT);
- r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
+ r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL);
assert_se(r == 0);
assert_se(path_equal(result, p));
result = mfree(result);
p = strjoina(temp, "/idontexist/meneither");
- r = chase_symlinks(p, NULL, 0, &result);
+ r = chase_symlinks(p, NULL, 0, &result, NULL);
assert_se(r == -ENOENT);
- r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
+ r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL);
assert_se(r == 0);
assert_se(path_equal(result, p));
result = mfree(result);
@@ -244,17 +244,17 @@ static void test_chase_symlinks(void) {
/* Path which doesn't exist, but contains weird stuff */
p = strjoina(temp, "/idontexist/..");
- r = chase_symlinks(p, NULL, 0, &result);
+ r = chase_symlinks(p, NULL, 0, &result, NULL);
assert_se(r == -ENOENT);
- r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
+ r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL);
assert_se(r == -ENOENT);
p = strjoina(temp, "/target");
q = strjoina(temp, "/top");
assert_se(symlink(q, p) >= 0);
p = strjoina(temp, "/target/idontexist");
- r = chase_symlinks(p, NULL, 0, &result);
+ r = chase_symlinks(p, NULL, 0, &result, NULL);
assert_se(r == -ENOENT);
if (geteuid() == 0) {
@@ -264,30 +264,30 @@ static void test_chase_symlinks(void) {
q = strjoina(p, "/priv2");
assert_se(mkdir(q, 0755) >= 0);
- assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0);
assert_se(chown(q, UID_NOBODY, GID_NOBODY) >= 0);
- assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0);
assert_se(chown(p, UID_NOBODY, GID_NOBODY) >= 0);
- assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0);
assert_se(chown(q, 0, 0) >= 0);
- assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -ENOLINK);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) == -ENOLINK);
assert_se(rmdir(q) >= 0);
assert_se(symlink("/etc/passwd", q) >= 0);
- assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -ENOLINK);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) == -ENOLINK);
assert_se(chown(p, 0, 0) >= 0);
- assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0);
}
p = strjoina(temp, "/machine-id-test");
assert_se(symlink("/usr/../etc/./machine-id", p) >= 0);
- pfd = chase_symlinks(p, NULL, CHASE_OPEN, NULL);
- if (pfd != -ENOENT) {
+ r = chase_symlinks(p, NULL, 0, NULL, &pfd);
+ if (r != -ENOENT) {
_cleanup_close_ int fd = -1;
sd_id128_t a, b;
@@ -307,8 +307,9 @@ static void test_chase_symlinks(void) {
p = strjoina(temp, "/target");
q = strjoina(temp, "/symlink");
assert_se(symlink(p, q) >= 0);
- pfd = chase_symlinks(q, NULL, CHASE_OPEN|CHASE_NOFOLLOW, &result);
- assert_se(pfd > 0);
+ r = chase_symlinks(q, NULL, CHASE_NOFOLLOW, &result, &pfd);
+ assert_se(r >= 0);
+ assert_se(pfd >= 0);
assert_se(path_equal(result, q));
assert_se(fstat(pfd, &st) >= 0);
assert_se(S_ISLNK(st.st_mode));
@@ -319,8 +320,9 @@ static void test_chase_symlinks(void) {
assert_se(symlink("s2", q) >= 0);
p = strjoina(temp, "/s2");
assert_se(symlink("nonexistent", p) >= 0);
- pfd = chase_symlinks(q, NULL, CHASE_OPEN|CHASE_NOFOLLOW, &result);
- assert_se(pfd > 0);
+ r = chase_symlinks(q, NULL, CHASE_NOFOLLOW, &result, &pfd);
+ assert_se(r >= 0);
+ assert_se(pfd >= 0);
assert_se(path_equal(result, q));
assert_se(fstat(pfd, &st) >= 0);
assert_se(S_ISLNK(st.st_mode));
@@ -329,42 +331,42 @@ static void test_chase_symlinks(void) {
/* Test CHASE_ONE */
p = strjoina(temp, "/start");
- r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL);
assert_se(r == 0);
p = strjoina(temp, "/top/dot/dotdota");
assert_se(streq(p, result));
result = mfree(result);
- r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL);
assert_se(r == 0);
p = strjoina(temp, "/top/./dotdota");
assert_se(streq(p, result));
result = mfree(result);
- r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL);
assert_se(r == 0);
p = strjoina(temp, "/top/../a");
assert_se(streq(p, result));
result = mfree(result);
- r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL);
assert_se(r == 0);
p = strjoina(temp, "/a");
assert_se(streq(p, result));
result = mfree(result);
- r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL);
assert_se(r == 0);
p = strjoina(temp, "/b");
assert_se(streq(p, result));
result = mfree(result);
- r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL);
assert_se(r == 0);
assert_se(streq("/usr", result));
result = mfree(result);
- r = chase_symlinks("/usr", NULL, CHASE_STEP, &result);
+ r = chase_symlinks("/usr", NULL, CHASE_STEP, &result, NULL);
assert_se(r > 0);
assert_se(streq("/usr", result));
result = mfree(result);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 19a2aa6f21..fae949863a 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -859,7 +859,7 @@ shortcut:
static int path_open_parent_safe(const char *path) {
_cleanup_free_ char *dn = NULL;
- int fd;
+ int r, fd;
if (path_equal(path, "/") || !path_is_normalized(path))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@@ -870,15 +870,15 @@ static int path_open_parent_safe(const char *path) {
if (!dn)
return log_oom();
- fd = chase_symlinks(dn, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN, NULL);
- if (fd < 0 && fd != -ENOLINK)
- return log_error_errno(fd, "Failed to validate path %s: %m", path);
+ r = chase_symlinks(dn, arg_root, CHASE_SAFE|CHASE_WARN, NULL, &fd);
+ if (r < 0 && r != -ENOLINK)
+ return log_error_errno(r, "Failed to validate path %s: %m", path);
- return fd;
+ return r < 0 ? r : fd;
}
static int path_open_safe(const char *path) {
- int fd;
+ int r, fd;
/* path_open_safe() returns a file descriptor opened with O_PATH after
* 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'.",
path);
- fd = chase_symlinks(path, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL);
- if (fd < 0 && fd != -ENOLINK)
- return log_error_errno(fd, "Failed to validate path %s: %m", path);
+ r = chase_symlinks(path, arg_root, CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL, &fd);
+ if (r < 0 && r != -ENOLINK)
+ return log_error_errno(r, "Failed to validate path %s: %m", path);
- return fd;
+ return r < 0 ? r : fd;
}
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;
- r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL);
+ r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL, NULL);
if (r == -EREMOTE) {
log_notice_errno(r, "Skipping %s", i->path);
return 0;
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index b82fd88497..e6d4659d9f 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -119,7 +119,7 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn
/* Check if this is a virtual function. */
physfn_link_file = strjoina(syspath, "/physfn");
- r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath);
+ r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath, NULL);
if (r < 0)
return r;
@@ -143,7 +143,7 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn
if (!virtfn_link_file)
return -ENOMEM;
- if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath) < 0)
+ if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath, NULL) < 0)
continue;
if (streq(syspath, virtfn_pci_syspath)) {
diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c
index d1193a7a24..af78a87d6f 100644
--- a/src/volatile-root/volatile-root.c
+++ b/src/volatile-root/volatile-root.c
@@ -21,7 +21,7 @@ static int make_volatile(const char *path) {
assert(path);
- r = chase_symlinks("/usr", path, CHASE_PREFIX_ROOT, &old_usr);
+ r = chase_symlinks("/usr", path, CHASE_PREFIX_ROOT, &old_usr, NULL);
if (r < 0)
return log_error_errno(r, "/usr not available in old root: %m");