bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#63931: ls colors one symlink too much as non-broken in symlink chain


From: Pádraig Brady
Subject: bug#63931: ls colors one symlink too much as non-broken in symlink chain
Date: Tue, 6 Jun 2023 21:32:43 +0100
User-agent: Mozilla Thunderbird

On 06/06/2023 18:24, Martin Schulte wrote:
Hello coreutils-maintainers,

I create a long chain of symlinks - ls colors the 41st element as ok while the 
kernel already gives up after 40 symlinks:

$ uname -a
Linux martnix4 5.10.0-23-amd64 #1 SMP Debian 5.10.179-1 (2023-05-12) x86_64 
GNU/Linux
$ ls --version | head -n 1
ls (GNU coreutils) 8.32
$ mkdir empty
$ cd empty
$ last=00 ; touch $last ; for ln in {01..50}; do ln -s $last $ln; last=$ln; done
$ ls --color -l {38..42}
lrwxrwxrwx 1 u g 2 Jun  6 19:00 38 -> 37   <- 38 colored as symlink
lrwxrwxrwx 1 u g 2 Jun  6 19:00 39 -> 38   <- 39 colored as symlink
lrwxrwxrwx 1 u g 2 Jun  6 19:00 40 -> 39   <- 40 colored as symlink
lrwxrwxrwx 1 u g 2 Jun  6 19:00 41 -> 40   <- 41 colored as symlink
lrwxrwxrwx 1 u g 2 Jun  6 19:00 42 -> 41   <- 42 and 41 colored as broken link
$ cat 40
$ cat 41
cat: 41: Too many levels of symbolic links

This could be reproduced with "ls (GNU coreutils) 9.3.45-6a618" compiled from 
the git repository.

Best regards,

This is because we lstat() the link, and stat() the target,
I suppose as a small optimization in the normal case.
The following adjusts to stat the link instead,
which works for your case and passes existing tests.

I'll think a bit more about it and add a test before applying.

cheers,
Pádraig

diff --git a/src/ls.c b/src/ls.c
index 71d94fd6a..77be54248 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -3586,7 +3586,7 @@ gobble_file (char const *name, enum filetype type, ino_t 
inode,
              they won't be traced and when no indicator is needed.  */
           if (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;






reply via email to

[Prev in Thread] Current Thread [Next in Thread]