]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
ls: use more standard symlink traversal
authorPádraig Brady <P@draigBrady.com>
Wed, 7 Jun 2023 11:32:46 +0000 (12:32 +0100)
committerPádraig Brady <P@draigBrady.com>
Wed, 7 Jun 2023 18:59:30 +0000 (19:59 +0100)
* src/ls.c (gobble_file): stat() symlinks directly,
rather than their targets.  This will be more consistent
with how symlinks are generally accessed.
(make_link_name): Remove no longer used function.
Addresses https://bugs.gnu.org/63931

src/ls.c

index 71d94fd6a0134eef7390e6ff7b6f5e04480e19d2..fbeb9b6dcfe57b7b96297b0941fc6484c48c337a 100644 (file)
--- a/src/ls.c
+++ b/src/ls.c
@@ -262,7 +262,6 @@ static size_t quote_name_buf (char **inbuf, size_t bufsize, char *name,
                               struct quoting_options const *options,
                               int needs_general_quoting, size_t *width,
                               bool *pad);
-static char *make_link_name (char const *name, char const *linkname);
 static int decode_switches (int argc, char **argv);
 static bool file_ignored (char const *name);
 static uintmax_t gobble_file (char const *name, enum filetype type,
@@ -3575,23 +3574,21 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
           struct stat linkstats;
 
           get_link_name (full_name, f, command_line_arg);
-          char *linkname = make_link_name (full_name, f->linkname);
 
           /* Use the slower quoting path for this entry, though
              don't update CWD_SOME_QUOTED since alignment not affected.  */
-          if (linkname && f->quoted == 0 && needs_quoting (f->linkname))
+          if (f->linkname && f->quoted == 0 && needs_quoting (f->linkname))
             f->quoted = -1;
 
-          /* Avoid following symbolic links when possible, ie, when
+          /* Avoid following symbolic links when possible, i.e., when
              they won't be traced and when no indicator is needed.  */
-          if (linkname
+          if (f->linkname
               && (file_type <= indicator_style || check_symlink_mode)
-              && stat_for_mode (linkname, &linkstats) == 0)
+              && stat_for_mode (full_name, &linkstats) == 0)
             {
               f->linkok = true;
               f->linkmode = linkstats.st_mode;
             }
-          free (linkname);
         }
 
       if (S_ISLNK (f->stat.st_mode))
@@ -3724,38 +3721,6 @@ get_link_name (char const *filename, struct fileinfo *f, bool command_line_arg)
                   filename);
 }
 
-/* If LINKNAME is a relative name and NAME contains one or more
-   leading directories, return LINKNAME with those directories
-   prepended; otherwise, return a copy of LINKNAME.
-   If LINKNAME is NULL, return NULL.  */
-
-static char *
-make_link_name (char const *name, char const *linkname)
-{
-  if (!linkname)
-    return NULL;
-
-  if (IS_ABSOLUTE_FILE_NAME (linkname))
-    return xstrdup (linkname);
-
-  /* The link is to a relative name.  Prepend any leading directory
-     in 'name' to the link name.  */
-  size_t prefix_len = dir_len (name);
-  if (prefix_len == 0)
-    return xstrdup (linkname);
-
-  char *p = xmalloc (prefix_len + 1 + strlen (linkname) + 1);
-
-  /* PREFIX_LEN usually specifies a string not ending in slash.
-     In that case, extend it by one, since the next byte *is* a slash.
-     Otherwise, the prefix is "/", so leave the length unchanged.  */
-  if ( ! ISSLASH (name[prefix_len - 1]))
-    ++prefix_len;
-
-  stpcpy (stpncpy (p, name, prefix_len), linkname);
-  return p;
-}
-
 /* Return true if the last component of NAME is '.' or '..'
    This is so we don't try to recurse on '././././. ...' */