FYI, this is part of the solution to a minor problem with rm: it would print a bogus ELOOP diagnostic when failing to remove the slash-decorated name of a symlink-to-directory:
$ mkdir d && ln -s d s && env rm -r s/ rm: cannot remove 's': Too many levels of symbolic links With the change below and a trivial don't-trim-trailing-slashes adjustment to remove.c, it does this: $ env rm -r s/ rm: cannot remove 's/': Not a directory >From 99376a06eed07ded17919384cf1d633e43ad1bd0 Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyer...@redhat.com> Date: Tue, 4 Sep 2012 11:36:38 +0200 Subject: [PATCH] fts: reduce two or more trailing spaces to just one, usually * lib/fts.c (fts_open): Upon initialization, if a name ends in two or more slashes, trim all but the final one. But if a name consists solely of two or more slashes, reduce it to "//", not to "/". This is part of the solution to a minor problem with rm: it would print a bogus ELOOP diagnostic when failing to remove the slash-decorated name of a symlink-to-directory: $ mkdir d && ln -s d s && env rm -r s/ rm: cannot remove 's': Too many levels of symbolic links With the change below and a trivial don't-trim-trailing-slashes adjustment to remove.c, it does this: $ env rm -r s/ rm: cannot remove 's/': Not a directory --- ChangeLog | 18 ++++++++++++++++++ lib/fts.c | 8 ++++++++ 2 files changed, 26 insertions(+) diff --git a/ChangeLog b/ChangeLog index d4d2cb1..c7c2ad3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,23 @@ 2012-09-04 Jim Meyering <meyer...@redhat.com> + fts: reduce two or more trailing spaces to just one, usually + * lib/fts.c (fts_open): Upon initialization, if a name ends in two + or more slashes, trim all but the final one. But if a name consists + solely of two or more slashes, reduce it to "//", not to "/". + + This is part of the solution to a minor problem with rm: + it would print a bogus ELOOP diagnostic when failing to remove + the slash-decorated name of a symlink-to-directory: + + $ mkdir d && ln -s d s && env rm -r s/ + rm: cannot remove 's': Too many levels of symbolic links + + With the change below and a trivial don't-trim-trailing-slashes + adjustment to remove.c, it does this: + + $ env rm -r s/ + rm: cannot remove 's/': Not a directory + fts: when there is no risk of overlap, use memcpy, not memmove * lib/fts.c (fts_alloc): Fix unjustified memcopy: s/memmove/memcpy/ diff --git a/lib/fts.c b/lib/fts.c index ce14a80..a9db89a 100644 --- a/lib/fts.c +++ b/lib/fts.c @@ -487,6 +487,14 @@ fts_open (char * const *argv, for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) { /* *Do* allow zero-length file names. */ size_t len = strlen(*argv); + + /* If there are two or more trailing slashes, trim all but one, + but don't change "//" to "/". */ + char const *v = *argv; + if (2 < len && v[len - 1] == '/') + while (2 < len && v[len - 2] == '/') + --len; + if ((p = fts_alloc(sp, *argv, len)) == NULL) goto mem3; p->fts_level = FTS_ROOTLEVEL; -- 1.7.12.176.g3fc0e4c