coreutils
[Top][All Lists]
Advanced

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

[PATCH] ls: issue error message on removed directory


From: Colin Watson
Subject: [PATCH] ls: issue error message on removed directory
Date: Tue, 11 Feb 2020 10:45:46 +0000
User-agent: Mutt/1.10.1 (2018-07-13)

If the current directory has been removed, then "ls" confusingly
produced no output and no error message, indistinguishable from the case
of running on an empty directory.  It makes more sense to report ENOENT
in this case.

Reported by Owen Thomas.

* src/ls.c (print_dir): Report ENOENT if readdir finds no directory
entries at all, not even "." or "..".
* tests/ls/removed-directory.sh: New file.
* tests/local.mk (all_tests): Add new test.
---
 src/ls.c                      | 12 +++++++++++
 tests/local.mk                |  1 +
 tests/ls/removed-directory.sh | 40 +++++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+)
 create mode 100755 tests/ls/removed-directory.sh

diff --git a/src/ls.c b/src/ls.c
index 4acf5f44d..de20bb63f 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -2892,6 +2892,7 @@ 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);
@@ -2967,6 +2968,7 @@ 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;
@@ -3012,6 +3014,16 @@ print_dir (char const *name, char const *realname, bool 
command_line_arg)
           if (errno != EOVERFLOW)
             break;
         }
+      else if (!found_any_entries)
+        {
+          /* If readdir finds no directory entries at all, not even "." or
+             "..", then it treats that as though it immediately reached the
+             end of the directory stream.  Thus, if we never saw any
+             directory entries, report that the directory doesn't exist.  */
+          errno = ENOENT;
+          file_failure (command_line_arg, _("reading directory %s"), name);
+          break;
+        }
       else
         break;
 
diff --git a/tests/local.mk b/tests/local.mk
index bbcb9d413..861da863b 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -614,6 +614,7 @@ all_tests =                                 \
   tests/ls/quote-align.sh                      \
   tests/ls/readdir-mountpoint-inode.sh         \
   tests/ls/recursive.sh                                \
+  tests/ls/removed-directory.sh                        \
   tests/ls/root-rel-symlink-color.sh           \
   tests/ls/rt-1.sh                             \
   tests/ls/slink-acl.sh                                \
diff --git a/tests/ls/removed-directory.sh b/tests/ls/removed-directory.sh
new file mode 100755
index 000000000..37e680223
--- /dev/null
+++ b/tests/ls/removed-directory.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+# If ls is asked to list a removed directory (e.g. the parent process's
+# current working directory that has been removed by another process), it
+# emits an error message.
+
+# Copyright (C) 2020 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ ls
+
+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
+cd "$cwd" || framework_failure_
+compare /dev/null out || fail=1
+compare exp-err err || fail=1
+
+Exit $fail
-- 
2.17.1




reply via email to

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