summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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");