Subject: bug#15926: RFE: unlink command already uses 'unlink' call; make 'rm' use 'remove' call

From: Bob Proulx <[email-masked]>
Date: Tue, 19 Nov 2013 13:45:11 -0700

Linda Walsh wrote:
> but there seems to be no command corresponding to the POSIX
> remove command,

The language here is confusing.  There isn't any "remove command".
There is only the remove(3) library call.

  man 3 remove

> it seems upgrading 'rm' to use the 'remove' POSIX call would be a
> beneficial move of all the recent POSIX changes.

That would introduce a significant behavior change and with certainty
would introduce bugs.  Therefore it shouldn't be done.

> Eric Blake wrote:
> > Linda Walsh wrote:
> > > Pádraig Brady wrote:
> > > > Linda Walsh wrote:
> > > > > So how about upgrading 'rm' to use the remove function so
> > > > > it would work on empty directories as well.
> > > >
> > > > Well we have the -d option to rm to explicitly do that.
> > >
> > > Does the posix "remove" call require a -d?

Right at this point there is confusion.  The only POSIX remove() is
the libc library call remove(3).

> > Huh? There is no POSIX remove(1),

Yes.  Huh?

> Since when do you think of a "call" as being a command?

We don't.  But from what you wrote ("Does the posix "remove" call
require a -d?") makes it appear that you think the posix remove(3)
library call is a command.  Because library calls do not take options
like that while commands do.

> > Sorry, but to change that, you'd have to go back in time 30 or 40 years
> > to when rm(1) was first written.  People have grown to rely on 'rm(1)'
> > being a wrapper around unlink(2), 'rmdir(1)' being a wrapper around
> > rumdir(2), and 'rm(1) -R' being a wrapper around rmdir(2) or unlink(2)
> > as needed.

Agreed.  Let's not break this.

>    People relied on rm removing files in a depth first search order
> for 30-40 years.

When using 'rm -rf' they do.  But only with the -r option.  Never
without it.

The change you have proposed would for the first time in all of those
years have rm remove a directory without the -r option.  That would be
bad because it would introduce bugs into scripts that are expecting
the existing behavior of rm not removing directories.  (Unless the -r
option is given.)

> Posix changed that requiring special checks for ".".  Scripts relied
> on that behavior for 30-40 years as well...  If you want to use that
> reasoning, rm should go back to doing depth first deletion and
> reporting an error with deleting "." when it is finished.

I actually agree with you on that point. ;-)
(Regarding 'rm -rf .')

> > Sorry, but doing things in rm(1) in a different order than POSIX
> > describes would lead to subtle breakage to lots of existing scripts.
> ----
>    I claim not.  Come up with 1 case where scripts rely on the current
> behavior -- to "die" before doing anything useful, vs. the pre-existing
> behavior which was to issue an error (suppressible with "-f") on the
> final deletion failing.

I have seen many various script writing styles.  Some of them are
atrocious indeed.  I would expect to at some point see someone use rm
on file system objects with abandon thinking that they won't remove
directories.  Suddenly they will be able to remove directories.  That
would be a change in behavior.  Changing established behavior is bad.

I routinely use the opposite side of things myself.  I routinely use
rmdir on empty directories knowing that if the directory is not empty
that it will fail and not remove any actual file content.  I could
definitely see someone counting on the behavior that rm removes files
but never removes directories.  (Unless the -r option is given.)

>    I am calling your bluff -- show me the scripts (other than a posix
> conformance test script), that would fail -- subtly or otherwise.

Anything I show would be contrived.  But that doesn't mean that
changing the behavior should be done.

  mkdir a b c
  touch aa bb cc
  for f in *; do rm "$f"; done

With existing behavior the directories would remain.  With the new
proposed behavior the directories would be removed.  That is a
behavior change that should not be made.

If you want that behavior then the -d option is present and
available.  Simply use the -d option.

  mkdir a b c
  touch aa bb cc
  for f in *; do rm -d "$f"; done

That gives you the behavior you are requesting.

>    I assert they don't exist for 2 reasons.  The foremost being
> that working scripts cannot rely on upon the deletion failure
> stopping any useful work being done by the command.

See the above example.

> The 2nd being it was a new change in posix that appeared in gnu
> utils in only the past few years.  The previous 25-35 years of
> scripts would have relied on it working as *documented* (depth
> first).

Since you are mentioning depth first I can only think you are talking
about 'rm -r'.  How does that tie into remove(3)?

> Checking pathnames before you start depth first traversal is not
> strictly depth first.

Again, what does depth first traversal have to do with remove(3)?

> By your own standards for not changing something, "rm" should
> be fixed to be the way it was for 30-40 years, as.

Huh?  Stop here.  Please explain.  Your words here do not follow.

> The problem is, is that by implementing that change, functionality
> was lost and removed in "rm".   The earlier version had more
> functionality.  So you can't come up with scripts that rely on
> missing functionality to get things done.  It's like relying on
> missing water to water your plants or missing food to feed yourself.

Are you talking about 'rm -rf .'?  I agree with you on that one.  That
was a bad change to disallow it.  It just wasn't as severe as what you
are proposing.  Disallowing 'rm -rf .' is a nanny-state type of
behavior.  It annoys me.  It shouldn't have been done.  But changing
unlink(2) to remove(3) is much more severe and really, really
shouldn't be done.

Bob