[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: rm -r gives up before going deeper upon encountering hindrances
From: |
Jim Meyering |
Subject: |
Re: rm -r gives up before going deeper upon encountering hindrances |
Date: |
Fri, 07 May 2004 18:50:30 +0200 |
Dan Jacobson <address@hidden> wrote:
> Here I though rm would go in and still remove all it could.
> But it turns out that it gives up before going deeper upon encountering
> hindrances.
> $ id
> uid=1000(jidanni) gid=1000(jidanni) groups=1000(jidanni)
> $ ls -la cds
> drwxrwxrwx 3 root staff 4096 2003-12-06 10:49 .
> drwxrwsr-x 4 root staff 4096 2003-12-06 10:29 ..
> -r--r--r-- 1 jidanni jidanni 510021216 2003-12-06 10:15 data.bin
> $ /bin/rm -rf *
> /bin/rm: cannot remove `cds': Permission denied
> $ /bin/rm -rf cds
> /bin/rm: cannot remove `cds': Permission denied
> $ ls -l cds/data.bin
> -r--r--r-- 1 jidanni jidanni 510021216 2003-12-06 10:15 cds/data.bin
> $ /bin/rm -rf cds/data.bin
> The file is now finally gone.
> OK, next time I'll use find cds -type f|xargs rm, etc.
> Anyway, the docs don't seem to document the above case.
Thank you for noticing and reporting that!
Here's a tentative patch:
Index: remove.c
===================================================================
RCS file: /fetish/cu/src/remove.c,v
retrieving revision 1.102
diff -u -p -r1.102 remove.c
--- a/remove.c 27 Apr 2004 15:00:32 -0000 1.102
+++ b/remove.c 7 May 2004 15:23:14 -0000
@@ -762,10 +762,11 @@ remove_entry (Dirstack_state const *ds,
DO_UNLINK (filename, x);
- /* Accept either EISDIR or EPERM as an indication that FILENAME may be
- a directory. POSIX says that unlink must set errno to EPERM when it
- fails to remove a directory, while Linux-2.4.18 sets it to EISDIR. */
- if ((errno != EISDIR && errno != EPERM) || ! x->recursive)
+ /* Accept either EISDIR, EPERM, or EACCES as an indication that FILENAME may
+ be a directory. POSIX says that unlink must set errno to EPERM when it
+ fails to remove a directory, while Linux-2.4.18 sets it to EISDIR.
+ unlink fails with EACCES when the parent directory is write-protected. */
+ if ((errno != EISDIR && errno != EPERM && errno != EACCES) || ! x->recursive)
{
/* some other error code. Report it and fail.
Likewise, if we're trying to remove a directory without
@@ -993,10 +994,12 @@ remove_dir (Dirstack_state *ds, char con
{
if (! S_ISDIR (dir_sb.st_mode))
{
- /* This happens on Linux-2.4.18 when a non-privileged user tries
- to delete a file that is owned by another user in a directory
- like /tmp that has the S_ISVTX flag set. */
- assert (saved_errno == EPERM);
+ /* saved_errno is EPERM on Linux-2.4.18 when a non-privileged user
+ tries to delete a file that is owned by another user in a directory
+ like /tmp that has the S_ISVTX flag set. It is far more common
+ to have saved_errno == EACCES -- that happens at least when failing
+ to unlink a non-directory due to restricted permissions. */
+ assert (saved_errno == EPERM || saved_errno == EACCES);
error (0, saved_errno,
_("cannot remove %s"), quote (full_filename (dir)));
}