Paul Eggert wrote: > I was about to suggest the following, on GNU/Linux: > > # Don't do this unless you know what you're doing! > rm -fr /proc/self/cwd/ > > Except it doesn't work! Not even if I append '.': > > $ mkdir /tmp/victim > $ cd /tmp/victim > $ touch foo > $ rm -fr /proc/self/cwd/ > rm: cannot remove `/proc/self/cwd': Too many levels of symbolic links > $ rm -fr /proc/self/cwd/. > rm: cannot remove directory: `/proc/self/cwd/.' > $ ls > foo > > Aren't these bugs, at least?
With the following patch, I see new behavior. It's an improvement, but we're still not there: $ mkdir -p d/e/f; ln -s d s; rm -r s/ rm: cannot remove 's/': Not a directory [Exit 1] $ find . ./s ./d Notice how it did traverse s/ into d/, and removed d/e and d/e/f. The only problem is that when it attempted to remove the command-line specified "s/", unlinkat (AT_FDCWD, "s/", AT_REMOVEDIR) failed: unlinkat(4, "d", 0) = 0 unlinkat(5, "f", AT_REMOVEDIR) = 0 unlinkat(4, "e", AT_REMOVEDIR) = 0 unlinkat(AT_FDCWD, "s/", AT_REMOVEDIR) = -1 ENOTDIR (Not a directory) rm: cannot remove 's/': Not a directory +++ exited with 1 +++ Now, this looks like a problem with unlinkat. Debating whether to add a test. Just writing the above, I know the answer. I will add a test. ================================================================== >From 958c553a84d37bdd8669ae68bfc8c4d4c5e7d2e1 Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyer...@redhat.com> Date: Tue, 4 Sep 2012 14:40:11 +0200 Subject: [PATCH] rm: avoid bogus diagnostic for a slash-decorated symlink-to-dir These commands would evoke an invalid diagnostic: $ mkdir d && ln -s d s && env rm -r s/ rm: cannot remove 's': Too many levels of symbolic links remove.c was stripping trailing slashes from "s/" before passing the name to "rm". But a trailing slash may change the semantics, and thus should not be stripped. * src/remove.c (rm_fts): Do not strip trailing slashes. * tests/rm/v-slash.sh: Adapt to new expected output. * gnulib: Update to latest, for an improved fts.c that merely normalizes trailing slashes. Reported by Paul Eggert in discussion of http://bugs.gnu.org/12339 --- gnulib | 2 +- src/remove.c | 3 --- tests/rm/v-slash.sh | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/gnulib b/gnulib index 68f693f..3a9002d 160000 --- a/gnulib +++ b/gnulib @@ -1 +1 @@ -Subproject commit 68f693ff1db33bf24695f0f42c62e7801966fd06 +Subproject commit 3a9002d3cc63da7110f133b1040d2d2b0aad8305 diff --git a/src/remove.c b/src/remove.c index 69faae6..847a5cc 100644 --- a/src/remove.c +++ b/src/remove.c @@ -433,9 +433,6 @@ rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x) /* Perform checks that can apply only for command-line arguments. */ if (ent->fts_level == FTS_ROOTLEVEL) { - if (strip_trailing_slashes (ent->fts_path)) - ent->fts_pathlen = strlen (ent->fts_path); - /* If the basename of a command line argument is "." or "..", diagnose it and do nothing more with that argument. */ if (dot_or_dotdot (last_component (ent->fts_accpath))) diff --git a/tests/rm/v-slash.sh b/tests/rm/v-slash.sh index 504f4ff..ec77bd0 100755 --- a/tests/rm/v-slash.sh +++ b/tests/rm/v-slash.sh @@ -26,7 +26,7 @@ touch a/x || framework_failure_ rm --verbose -r a/// > out || fail=1 cat <<\EOF > exp || fail=1 removed 'a/x' -removed directory: 'a' +removed directory: 'a/' EOF compare exp out || fail=1 -- 1.7.12.176.g3fc0e4c