diff options
author | Jim Meyering <jim@meyering.net> | 2003-03-03 07:55:33 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2003-03-03 07:55:33 +0000 |
commit | 1678b8382e2318a31e6720190c2e15aee0f3a511 (patch) | |
tree | 4db9c8fa50a3c39a509db07342de892697b38684 | |
parent | 5e9ae632a42a6c6723c571cf73c072e1460c4418 (diff) | |
download | coreutils-1678b8382e2318a31e6720190c2e15aee0f3a511.tar.xz |
(remove_cwd_entries) [!ROOT_CAN_UNLINK_DIRS]: Give an
accurate diagnostic when failing to remove a file owned by some other
user. Reported by Ivo Timmermans via Michael Stone.
This fixes Debian bug# 178471.
-rw-r--r-- | src/remove.c | 64 |
1 files changed, 40 insertions, 24 deletions
diff --git a/src/remove.c b/src/remove.c index 549715ac9..da07f5d80 100644 --- a/src/remove.c +++ b/src/remove.c @@ -742,7 +742,7 @@ remove_entry (Dirstack_state const *ds, char const *filename, } -#else +#else /* ! ROOT_CAN_UNLINK_DIRS */ if (is_dir == T_YES && ! x->recursive) { @@ -866,34 +866,50 @@ remove_cwd_entries (Dirstack_state *ds, char **subdir, struct stat *subdir_sb, break; case RM_NONEMPTY_DIR: - /* Record dev/ino of F so that we can compare - that with dev/ino of `.' after the chdir. - This dev/ino pair is also used in cycle detection. */ - if (lstat (f, subdir_sb)) - error (EXIT_FAILURE, errno, _("cannot lstat %s"), - quote (full_filename (f))); - - if (chdir (f)) - { - error (0, errno, _("cannot chdir from %s to %s"), - quote_n (0, full_filename (".")), quote_n (1, f)); - AD_mark_as_unremovable (ds, f); - status = RM_ERROR; - break; - } - if (cycle_check (&ds->cycle_check_state, subdir_sb)) - { - error (0, 0, _("\ + { + /* Save a copy of errno, in case the preceding unlink (from + remove_entry's DO_UNLINK) of a non-directory failed due + to EPERM. */ + int saved_errno = errno; + + /* Record dev/ino of F so that we can compare + that with dev/ino of `.' after the chdir. + This dev/ino pair is also used in cycle detection. */ + if (lstat (f, subdir_sb)) + error (EXIT_FAILURE, errno, _("cannot lstat %s"), + quote (full_filename (f))); + + if (chdir (f)) + { + /* It is much more common that we reach this point for an + inaccessible directory. Hence the second diagnostic, below. + However it is also possible that F is a non-directory. + That can happen when we use the `! ROOT_CAN_UNLINK_DIRS' + block of code and when DO_UNLINK fails due to EPERM. + In that case, give a better diagnostic. */ + if (errno == ENOTDIR) + error (0, saved_errno, _("cannot remove %s"), quote (f)); + else + error (0, errno, _("cannot chdir from %s to %s"), + quote_n (0, full_filename (".")), quote_n (1, f)); + AD_mark_as_unremovable (ds, f); + status = RM_ERROR; + break; + } + if (cycle_check (&ds->cycle_check_state, subdir_sb)) + { + error (0, 0, _("\ WARNING: Circular directory structure.\n\ This almost certainly means that you have a corrupted file system.\n\ NOTIFY YOUR SYSTEM MANAGER.\n\ The following directory is part of the cycle:\n %s\n"), - quote (full_filename ("."))); - longjmp (ds->current_arg_jumpbuf, 1); - } + quote (full_filename ("."))); + longjmp (ds->current_arg_jumpbuf, 1); + } - *subdir = xstrdup (f); - break; + *subdir = xstrdup (f); + break; + } } /* Record status for this directory. */ |