Subject: Re: bug#25817: Why were Gnu coding standards violated in favor of posix for 'rm -fr .'?: request for reversion of behavior

From: Eric Blake <[email-masked]>
Date: Tue, 21 Feb 2017 08:08:16 -0600

On 02/21/2017 07:42 AM, Eric Blake wrote:
> On 02/21/2017 02:41 AM, L A Walsh wrote:
>>
>>     Do you really need me to find the older version
>> of 'rm' in your source tree?
> 
> It wouldn't hurt to point out which commit id changed behavior, if you
> indeed want to call that commit a regression.  Being able to read the
> commit itself, as well as mailing list traffic at the time, will help
> current readers get a more-informed picture of whether such a change was
> intentional or accidental.

A bit more research shows that:

1) we don't seem to have any tests that cover 'rm -r .' behavior (so
even if we change the code now, we'd first need to add a test; and
without a test, it's entirely possible that a commit in the past altered
behavior without being noticed because of lack of testsuite coverage)

$ git grep 'rm .*r.* \.' tests/rm
$

So a testsuite addition is welcome, and if nothing else, this bug should
not be closed until we have testsuite coverage, whether or not we change
rm itself.

2) the current behavior is due to this code in src/remove.c:rm_fts():

        {
          /* POSIX says:
             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)))

and a git blame easily shows that portion of the function has been in
place since at least commit 4f73ecaf "rm: rewrite to use fts" (Sep 2009,
release 8.0).  Prior to that date, there is no rm_fts(), so the
archaeology gets trickier, but even as far back as ff59218d "New file.
Contains guts of old rm.c." (Jan 1998, release 4.5.1), there is:

static enum RM_status
rm (struct File_spec *fs, int user_specified_name)
{
  mode_t filetype_mode;

  if (user_specified_name)
    {
      char *base = base_name (fs->filename);

      if (DOT_OR_DOTDOT (base))
        {
          error (0, 0, _("cannot remove `.' or `..'"));
          return RM_ERROR;
        }
    }

I've already spent too much time on this, and did not go digging through
earlier history of rm.c or reading any changelogs prior to that point.
Please, if you have evidence of a version where GNU rm behaved
differently, you will do yourself a favor by pointing it out to us,
rather than making a vague assertion that we have changed behavior with
nothing to back up your claim.  A little bit of research on your side
will go a long ways to making your report credible.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org