From: Jim Meyering Date: Mon, 26 Jun 2006 13:02:01 +0000 (+0000) Subject: * NEWS: rm no longer fails to remove an empty, unreadable directory X-Git-Tag: v6.0~278 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=78b166d1b163df894d567b79d3bb5744156fb0fe;p=thirdparty%2Fcoreutils.git * NEWS: rm no longer fails to remove an empty, unreadable directory * src/remove.c (remove_cwd_entries): If we can't open a directory, and the failure is not being ignored, try to remove the directory with rmdir (aka unlinkat-with-AT_REMOVEDIR), in case it's empty. Problem report and test case from Paul Eggert in . * tests/rm/empty-inacc: New test, for the above. --- diff --git a/ChangeLog b/ChangeLog index 2efa74a904..a55c5034d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2006-06-26 Jim Meyering + * NEWS: rm no longer fails to remove an empty, unreadable directory + * src/remove.c (remove_cwd_entries): If we can't open a directory, + and the failure is not being ignored, try to remove the directory + with rmdir (aka unlinkat-with-AT_REMOVEDIR), in case it's empty. + Problem report and test case from Paul Eggert in + . + * tests/rm/empty-inacc: New test, for the above. + Avoid a segfault for wc --files0=- < /dev/null. * src/wc.c (compute_number_width): Return right away if nfiles == 0. diff --git a/NEWS b/NEWS index 3763af5314..2a0a9067ae 100644 --- a/NEWS +++ b/NEWS @@ -72,6 +72,8 @@ GNU coreutils NEWS -*- outline -*- rm --interactive now takes an optional argument, although the default of using no argument still acts like -i. + rm no longer fails to remove an empty, unreadable directory + sort now reports incompatible options (e.g., -i and -n) rather than silently ignoring one of them. diff --git a/src/remove.c b/src/remove.c index bfb0a32641..076ad64c30 100644 --- a/src/remove.c +++ b/src/remove.c @@ -1125,13 +1125,28 @@ remove_cwd_entries (DIR **dirp, x, errno, subdir_sb, ds, NULL); if (subdir_dirp == NULL) { + status = RM_ERROR; + /* CAUTION: this test and diagnostic are identical to those following the other use of fd_to_subdirp. */ - if (errno != ENOENT || !x->ignore_missing_files) - error (0, errno, - _("cannot remove %s"), quote (full_filename (f))); - AD_mark_as_unremovable (ds, f); - status = RM_ERROR; + if (errno == ENOENT && x->ignore_missing_files) + { + /* With -f, don't report "file not found". */ + } + else + { + /* Upon fd_to_subdirp failure, try to remove F directly, + in case it's just an empty directory. */ + int saved_errno = errno; + if (unlinkat (dirfd (*dirp), f, AT_REMOVEDIR) == 0) + status = RM_OK; + else + error (0, saved_errno, + _("cannot remove %s"), quote (full_filename (f))); + } + + if (status == RM_ERROR) + AD_mark_as_unremovable (ds, f); break; } @@ -1214,6 +1229,9 @@ remove_dir (int fd_cwd, Dirstack_state *ds, char const *dir, { /* If fd_to_subdirp fails due to permissions, then try to remove DIR via rmdir, in case it's just an empty directory. */ + /* This use of rmdir just works, at least in the sole test I + have that exercises this code, but it'll soon go, to be + replaced by a use of unlinkat-with-AT_REMOVEDIR. */ if (rmdir (dir) == 0) return RM_OK; diff --git a/tests/rm/empty-inacc b/tests/rm/empty-inacc index 02da7257c4..6c009759fd 100755 --- a/tests/rm/empty-inacc +++ b/tests/rm/empty-inacc @@ -18,6 +18,10 @@ mkdir -p $tmp || framework_failure=1 cd $tmp || framework_failure=1 mkdir -m0 inacc || framework_failure=1 +# Also exercise the different code path that's taken for a directory +# that is empty (hence removable) and unreadable. +mkdir -m a-r -p a/unreadable + if test $framework_failure = 1; then echo "$0: failure in testing framework" 1>&2 (exit 1); exit 1 @@ -29,4 +33,8 @@ fail=0 rm -rf inacc || fail=1 test -d inacc && fail=1 +# This would fail for e.g., coreutils-5.97. +rm -rf a || fail=1 +test -d a && fail=1 + (exit $fail); exit $fail