]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/fs-util: change CHASE_OPEN flag into a separate output parameter
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 24 Oct 2019 08:33:20 +0000 (10:33 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 24 Oct 2019 13:44:24 +0000 (22:44 +0900)
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.)

33 files changed:
src/basic/fs-util.c
src/basic/fs-util.h
src/basic/mkdir.c
src/basic/mountpoint-util.c
src/basic/path-util.c
src/basic/stat-util.c
src/core/dbus-manager.c
src/core/namespace.c
src/core/service.c
src/core/socket.c
src/core/unit.c
src/delta/delta.c
src/fstab-generator/fstab-generator.c
src/journal/journalctl.c
src/libsystemd/sd-device/sd-device.c
src/machine/machine-dbus.c
src/mount/mount-tool.c
src/nspawn/nspawn-mount.c
src/nspawn/nspawn.c
src/portable/portablectl.c
src/shared/dissect-image.c
src/shared/dropin.c
src/shared/machine-image.c
src/shared/os-util.c
src/shared/switch-root.c
src/shared/unit-file.c
src/systemctl/systemctl.c
src/test/test-chase-symlinks.c
src/test/test-copy.c
src/test/test-fs-util.c
src/tmpfiles/tmpfiles.c
src/udev/udev-builtin-net_id.c
src/volatile-root/volatile-root.c

index a92241ca02a10346827e6ef11b2ee102f17ea92c..d20b9a5df552f74c158d115d222b616667758b86 100644 (file)
@@ -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;
 }
index fa0f0de9a347f80bad598de1a46bb091ae836051..78d68be9fd855ba2396e4b93abec8ed0b6efd265 100644 (file)
@@ -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) {
index 6b82eab640978965a859ec2fbe916e41c32eab0d..1f318252a98e1e0445f54431a3ff8b1e9449f7f4 100644 (file)
@@ -33,7 +33,7 @@ int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, Mkd
         if ((flags & MKDIR_FOLLOW_SYMLINK) && S_ISLNK(st.st_mode)) {
                 _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)
index d3b8e44f1845e92121dd3a90d4d2518ee1082ae3..a79377f05d0ec43bb36b359b9c5ea01cae5d4292 100644 (file)
@@ -264,7 +264,7 @@ int path_is_mount_point(const char *t, const char *root, int flags) {
          * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
          * 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;
 
index b9544b4bacce90cb906b29a743864ff98660a8d7..98b6d0617f288e3aa266455b5c8256441afce285 100644 (file)
@@ -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);
index 2cd722c1064be5ba4fd76525100c90a125ca574e..4572e004bbb5aafa58ac3bbcbc4327a29d1feb01 100644 (file)
@@ -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) {
index 035011e34f9bd23f29b55f1db0f56e8a187a54c9..d98ec32a0bfc9d0b3f076a28f0a0b53ef141aee3 100644 (file)
@@ -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);
 
index 973b64007cf8719c87568a74c3ccbd0473ce1c92..f6f7736819bbd0d944986c53b0a66dfe9fcec75f 100644 (file)
@@ -875,7 +875,7 @@ static int follow_symlink(
          * a time by specifying CHASE_STEP. This function returns 0 if we resolved one step, and > 0 if we reached the
          * 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;
index 256ca46fd88cc30a52c8553aa96303c8f92ae20a..525ce4289011aec193cae65f2c29c6a7dc850b6b 100644 (file)
@@ -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)
index 71ab3c647f95b5047adacbea431ae2ec6865cda6..285aa641d3c5e941cd1ff0959bde867e64e351c7 100644 (file)
@@ -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;
 
index 58c99d9e073d08a59b486a113319210694906f02..4fcc142ae9a78d1695185325a658f15f3d7457e5 100644 (file)
@@ -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;
index bc11aa828a6f2f395fb9f6ec032009aa44a98451..cd33850b969c7772b0750e07e4ba1b10435f7fcb 100644 (file)
@@ -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) {
index 76270aec17f22ca4c284f699c9764b5e7738de1c..026a25f5758479ac964923a35ffd6caa2c1c0974 100644 (file)
@@ -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 */
index 6d6bb1cf63c32bd47117373ad24c602c564d73f5..6d9b5cfc2fbf730d921c599e6d2b0f053f2b3d74 100644 (file)
@@ -1086,7 +1086,7 @@ static int add_matches(sd_journal *j, char **args) {
                         _cleanup_free_ char *p = NULL, *t = NULL, *t2 = NULL, *interpreter = NULL;
                         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");
 
index c4a7f2f3d340455fa7849b580400e1cf3f0711df..4a5e8ff944aa585d2adc1cb36538a9d3b6a95647 100644 (file)
@@ -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");
 
index 0d58b5eb8b6f4f6cb65702a9d6ff59a98ebf11a2..c2747112d4fe9680bc7012bfbbf6920eb491d4ac 100644 (file)
@@ -846,7 +846,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
         if (laccess(p, F_OK) < 0)
                 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");
 
index 457ba4ea16f043fb3d46f99cedac779ccbf4a465..9f0220a75e7e4a4959dda6b34d79f8aa4936f902 100644 (file)
@@ -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;
index 2f842754a4f4ba66597ede4309bd7fd42653670f..6407503c4c9116c9cd1196d8b616fc7f47044d69 100644 (file)
@@ -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? */
index 40a7de981acfe2dd9acfb597479640b3b3907d79..7760bcaa2d31e25169839dab817e098b4f43fd9b 100644 (file)
@@ -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) {
index 2f8b0254c802f8bc99cf1bf92dd461bb7fc21bae..06ab7735adef1b18a5c5e1ffe26e1556011a5148 100644 (file)
@@ -67,7 +67,7 @@ static int determine_image(const char *image, bool permit_non_existing, char **r
                 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
                                        "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);
 
index a54714169e0485cc0e160f2b95399dd89c58679d..3e7546496694a733099adc2f32e7c892fadcd320 100644 (file)
@@ -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)
index 2f67a44bf0b90b9a87f9a616466f9440cb7cc318..7328b7adde5ecbec017446c5694734c460ea23bb 100644 (file)
@@ -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) {
index 7007374192796488bdffd47818ec811d40b831f5..cceed58f74489b9f8d055f4693b566f9aaa80e13 100644 (file)
@@ -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) {
index 2191a610ae26d3ba917e59b18d084494256185ee..b2af8535f9c5a2cab62af09850dfd713db33fd0c 100644 (file)
@@ -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;
 
index f721aff76071182940f5191f725ca6615463f1af..a807826378d92a0d8b952e6eae3bf69331d1f7f7 100644 (file)
@@ -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) {
index b015ff93381d1fe6f0350a0269466743e2f40024..28cd3c860091e4ddc5bf3b64ac49d85d56a7cdec 100644 (file)
@@ -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);
index e4b85d906ca68d9215b2fd23d42bc33512989588..05013484ad1ac505a9d2ebf3ddff634e9f58b5bd 100644 (file)
@@ -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)
index 013b36e2a7a5e502892343046574dc9d2313855a..0b7dd8764f0d941e40df4c4bcc0b6d636d146932 100644 (file)
@@ -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;
index 5f7b9e5ce8dca2fd30129736abd73aeb21042d09..ffabf95663ccfcc60e1caa8a3c70f8456740623d 100644 (file)
@@ -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));
         }
 
index 7cf4f4976bcd55f1b10591c2b82d170329c6170d..ac8b95aece0eaed479a1d419a67fe8965909c97f 100644 (file)
@@ -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);
index 19a2aa6f21eee3782b6b1a7b8d65a67fd6ac31be..fae949863a4c9b036f03c14a9236bff841d0c386 100644 (file)
@@ -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;
index b82fd884972e1ca589063476aa036a1890b4868a..e6d4659d9f7cab1687a0061e3b27af8ecfe0259d 100644 (file)
@@ -119,7 +119,7 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn
 
         /* Check if this is a virtual function. */
         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)) {
index d1193a7a24a2e698d2e66ff6d346c0ba8968aa2a..af78a87d6feff1a8b50f07f672c39a80c06c4433 100644 (file)
@@ -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");