The above test is broken with latest glibc, seen first on openSUSE:Factory:
+ strace -o log -e stat,lstat,stat64,lstat64,newfstatat ls --color=always .
color-without-stat
dangle
log
log-help
++ wc -l
+ n_lines=3
++ expr 3 - 1
+ n_stat=2
+ case $n_stat in
+ fail=1
+ head -n30 log log-help
==> log <==
stat(".", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
stat(".", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
+++ exited with 0 +++
==> log-help <==
+++ exited with 0 +++
+ Exit 1
The effect is that for every directory-type argument, ls(1) does an extra
call to stat(). I could trace it down to main()->print_dirs() which in
turn calls glibc's opendir().
This is since glibc-2.22 ... and specifically this commit:
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=glibc-2.21-360-g46f894d
As can be seen in the following diff of strace outputs, opendir(".") has
been changed from a simple openat() to the sequence of stat()+open():
...
stat(".", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
-openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
+stat(".", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
+open(".", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
+fstat(3, {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
getdents(3, /* 5 entries */, 32768) = 152
getdents(3, /* 0 entries */, 32768) = 0
close(3) = 0
...
As we can't predict the number of stat() calls as before,
what shall we do to fix the test?
Have a nice day,
Berny