On 3/5/20 1:43 PM, Paul Eggert wrote:
Why is this code even there at all? If readdir(3) says that the current directory has no entries, shouldn't 'ls' just say that? Why should ls report an error simply because the current directory isn't reachable from the filesystem? Whether the current directory is unreachable has nothing to do with ls's job, which is to report whether the current directory has entries.
Attached is a proposed patch to fix this.
>From 511d0c323bc90a0ab7e8f3672b07a1144885a9e8 Mon Sep 17 00:00:00 2001 From: Paul Eggert <egg...@cs.ucla.edu> Date: Thu, 5 Mar 2020 17:25:29 -0800 Subject: [PATCH] ls: restore 8.31 behavior on removed directories * NEWS: Mention this. * src/ls.c: Do not include <sys/sycall.h> (print_dir): Don't worry about whether the directory is removed. * tests/ls/removed-directory.sh: Adjust to match new (i.e., old) behavior. --- NEWS | 6 ++++++ src/ls.c | 22 ---------------------- tests/ls/removed-directory.sh | 10 ++-------- 3 files changed, 8 insertions(+), 30 deletions(-) diff --git a/NEWS b/NEWS index fdc8bf5db..653e7178b 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,12 @@ GNU coreutils NEWS -*- outline -*- * Noteworthy changes in release ?.? (????-??-??) [?] +** Changes in behavior + + On GNU/Linux systems, ls no longer issues an error message on + directory merely because it was removed. This reverts a change + that was made in release 8.32. + * Noteworthy changes in release 8.32 (2020-03-05) [stable] diff --git a/src/ls.c b/src/ls.c index 24b983287..4acf5f44d 100644 --- a/src/ls.c +++ b/src/ls.c @@ -49,10 +49,6 @@ # include <sys/ptem.h> #endif -#ifdef __linux__ -# include <sys/syscall.h> -#endif - #include <stdio.h> #include <assert.h> #include <setjmp.h> @@ -2896,7 +2892,6 @@ print_dir (char const *name, char const *realname, bool command_line_arg) struct dirent *next; uintmax_t total_blocks = 0; static bool first = true; - bool found_any_entries = false; errno = 0; dirp = opendir (name); @@ -2972,7 +2967,6 @@ print_dir (char const *name, char const *realname, bool command_line_arg) next = readdir (dirp); if (next) { - found_any_entries = true; if (! file_ignored (next->d_name)) { enum filetype type = unknown; @@ -3018,22 +3012,6 @@ print_dir (char const *name, char const *realname, bool command_line_arg) if (errno != EOVERFLOW) break; } -#ifdef __linux__ - else if (! found_any_entries) - { - /* If readdir finds no directory entries at all, not even "." or - "..", then double check that the directory exists. */ - if (syscall (SYS_getdents, dirfd (dirp), NULL, 0) == -1 - && errno != EINVAL) - { - /* We exclude EINVAL as that pertains to buffer handling, - and we've passed NULL as the buffer for simplicity. - ENOENT is returned if appropriate before buffer handling. */ - file_failure (command_line_arg, _("reading directory %s"), name); - } - break; - } -#endif else break; diff --git a/tests/ls/removed-directory.sh b/tests/ls/removed-directory.sh index e8c835dab..fe8f929a1 100755 --- a/tests/ls/removed-directory.sh +++ b/tests/ls/removed-directory.sh @@ -26,20 +26,14 @@ case $host_triplet in *) skip_ 'non linux kernel' ;; esac -LS_FAILURE=2 - -cat <<\EOF >exp-err || framework_failure_ -ls: reading directory '.': No such file or directory -EOF - cwd=$(pwd) mkdir d || framework_failure_ cd d || framework_failure_ rmdir ../d || framework_failure_ -returns_ $LS_FAILURE ls >../out 2>../err || fail=1 +ls >../out 2>../err || fail=1 cd "$cwd" || framework_failure_ compare /dev/null out || fail=1 -compare exp-err err || fail=1 +compare /dev/null err || fail=1 Exit $fail -- 2.24.1