chiark / gitweb /
fs-util: add new CHASE_TRAIL_SLASH flag for chase_symlinks()
authorLennart Poettering <lennart@poettering.net>
Thu, 22 Mar 2018 18:54:24 +0000 (19:54 +0100)
committerSven Eden <yamakuzure@gmx.net>
Fri, 24 Aug 2018 14:47:08 +0000 (16:47 +0200)
This rearranges chase_symlinks() a bit: if no special flags are
specified it will now revert to behaviour before
b12d25a8d631af00b200e7aa9dbba6ba4a4a59ff. However, if the new
CHASE_TRAIL_SLASH flag is specified it will follow the behaviour
introduced by that commit.

I wasn't sure which one to make the beaviour that requires specification
of a flag to enable. I opted to make the "append trailing slash"
behaviour the one to enable by a flag, following the thinking that the
function should primarily be used to generate a normalized path, and I
am pretty sure a path without trailing slash is the more "normalized"
one, as the trailing slash is not really a part of it, but merely a
"decorator" that tells various system calls to generate ENOTDIR if the
path doesn't refer to a path.

Or to say this differently: if the slash was part of normalization then
we really should add it in all cases when the final path is a directory,
not just when the user originally specified it.

Fixes: #8544
Replaces: #8545

src/basic/fs-util.c
src/basic/fs-util.h
src/basic/mount-util.c

index 12255fe0c71bdffaa62c1c4ab5b431d33bd5ce23..8617968c15f91f525655d3cccad9ff1affbac073 100644 (file)
@@ -469,8 +469,10 @@ int get_files_in_directory(const char *path, char ***list) {
                         n++;
         }
 
-        if (list)
-                *list = TAKE_PTR(l);
+        if (list) {
+                *list = l;
+                l = NULL; /* avoid freeing */
+        }
 
         return n;
 }
@@ -698,8 +700,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
                 /* Just a single slash? Then we reached the end. */
                 if (path_equal(first, "/")) {
                         /* Preserve the trailing slash */
-                        if (!strextend(&done, "/", NULL))
-                                return -ENOMEM;
+
+                        if (flags & CHASE_TRAIL_SLASH)
+                                if (!strextend(&done, "/", NULL))
+                                        return -ENOMEM;
 
                         break;
                 }
@@ -745,7 +749,8 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
                         }
 
                         safe_close(fd);
-                        fd = TAKE_FD(fd_parent);
+                        fd = fd_parent;
+                        fd_parent = -1;
 
                         continue;
                 }
@@ -850,9 +855,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
                 }
 
                 /* If this is not a symlink, then let's just add the name we read to what we already verified. */
-                if (!done)
-                        done = TAKE_PTR(first);
-                else {
+                if (!done) {
+                        done = first;
+                        first = NULL;
+                } else {
                         /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
                         if (streq(done, "/"))
                                 *done = '\0';
@@ -863,7 +869,8 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
 
                 /* And iterate again, but go one directory further down. */
                 safe_close(fd);
-                fd = TAKE_FD(child);
+                fd = child;
+                child = -1;
         }
 
         if (!done) {
@@ -873,15 +880,22 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
                         return -ENOMEM;
         }
 
-        if (ret)
-                *ret = TAKE_PTR(done);
+        if (ret) {
+                *ret = done;
+                done = NULL;
+        }
 
         if (flags & CHASE_OPEN) {
+                int q;
+
                 /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by
                  * opening /proc/self/fd/xyz. */
 
                 assert(fd >= 0);
-                return TAKE_FD(fd);
+                q = fd;
+                fd = -1;
+
+                return q;
         }
 
         return exists;
index c089cc55596652e6b5e1ddf3dd1e0a47bef397f2..97bcd1a13be3f645b98717cabd9edf9e4392825f 100644 (file)
@@ -102,6 +102,7 @@ enum {
         CHASE_NO_AUTOFS   = 1U << 2,   /* If set, return -EREMOTE if autofs mount point found */
         CHASE_SAFE        = 1U << 3,   /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */
         CHASE_OPEN        = 1U << 4,   /* If set, return an O_PATH object to the final component */
+        CHASE_TRAIL_SLASH = 1U << 5,   /* If set, any trailing slash will be preserved */
 };
 
 int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret);
index b74d51a26a2cd54ee1f0b95b9484a76fb14320d1..751702d33c71bbd9915794b9d7faf4793be932e0 100644 (file)
@@ -81,8 +81,10 @@ int name_to_handle_at_loop(
 
                 if (name_to_handle_at(fd, path, h, &mnt_id, flags) >= 0) {
 
-                        if (ret_handle)
-                                *ret_handle = TAKE_PTR(h);
+                        if (ret_handle) {
+                                *ret_handle = h;
+                                h = NULL;
+                        }
 
                         if (ret_mnt_id)
                                 *ret_mnt_id = mnt_id;
@@ -294,7 +296,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, 0, &canonical);
+                r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical);
                 if (r < 0)
                         return r;
 
@@ -954,7 +956,8 @@ int mount_option_mangle(
         }
 
         *ret_mount_flags = mount_flags;
-        *ret_remaining_options = TAKE_PTR(ret);
+        *ret_remaining_options = ret;
+        ret = NULL;
 
         return 0;
 }