bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#12339: Bug: rm -fr . doesn't dir depth first deletion yet it is docu


From: Bernhard Voelker
Subject: bug#12339: Bug: rm -fr . doesn't dir depth first deletion yet it is documented to do so.
Date: Tue, 04 Sep 2012 07:20:59 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120825 Thunderbird/15.0

On 09/03/2012 10:04 PM, 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


That is in rm_fts():

      /* 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);

ent->fts_path is stripped from /proc/self/cwd/ to /proc/self/cwd.
Then this:

        Ternary is_empty_directory;
        enum RM_status s = prompt (fts, ent, true /*is_dir*/, x,
                                   PA_DESCEND_INTO_DIR, &is_empty_directory);

        if (s == RM_OK && is_empty_directory == T_YES)
          {
            /* When we know (from prompt when in interactive mode)
               that this is an empty directory, don't prompt twice.  */
            s = excise (fts, ent, x, true);
            fts_skip_tree (fts, ent);
          }

s is RM_OK, but is_empty_directory is T_NO, because it's no DIR ...
The FTS loop continues and diagnoses ELOOP. That's the strace output:

  newfstatat(AT_FDCWD, "/proc/self/cwd/", {st_mode=S_IFDIR|0755, st_size=4096, 
...}, AT_SYMLINK_NOFOLLOW) = 0
  openat(AT_FDCWD, "/proc/self/cwd", 
O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = -1 ELOOP (Too many 
levels of
symbolic links)
  openat(AT_FDCWD, "/proc/self/cwd", 
O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = -1 ELOOP (Too many 
levels of
symbolic links)
  unlinkat(AT_FDCWD, "/proc/self/cwd", AT_REMOVEDIR) = -1 EACCES (Permission 
denied)

The example applies to all symlinks to directories (i.e. not only
to /proc/self/cwd):

  $ mkdir d
  $ touch d/file
  $ ln -s d dl
  $ rm -rv dl/
  /home/berny/cu/src/rm: cannot remove ‘dl’: Too many levels of symbolic links

However, in this case, unlinkat returns ENOTDIR:

  unlinkat(AT_FDCWD, "dl", AT_REMOVEDIR)  = -1 ENOTDIR (Not a directory)



>   $ rm -fr /proc/self/cwd/.
>   rm: cannot remove directory: `/proc/self/cwd/.'
>   $ ls
>   foo

That's the dot case.

> Aren't these bugs, at least?

The latter: no, because dot must not be removed.
The former: maybe, but the question is what rm should remove:
the symlink or the target? The info page is quiet about this.
I tend to say it's okay as it is, because if someone wants to
remove the target of a symlink,(s)he can always to
  $ rm -rv $(readlink -f dl)
Only the diagnostic (ELOOP) looks a bit strange ...

Have a nice day,
Berny





reply via email to

[Prev in Thread] Current Thread [Next in Thread]