diff options
author | Jim Meyering <jim@meyering.net> | 2005-11-02 09:47:39 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2005-11-02 09:47:39 +0000 |
commit | 588df316d95e633dde9b878745c451bc7d2ad306 (patch) | |
tree | af18ed522b0b1fe970f8ed958e8772b8aff0423c | |
parent | 4db5b5cf1191005af254f174baa18a241cad7aab (diff) | |
download | coreutils-588df316d95e633dde9b878745c451bc7d2ad306.tar.xz |
(remove_entry): Emit a better diagnostic when rm
(without -r) fails to remove a directory on a non-Linux system.
This change affects only newer Solaris systems (with priv_*
functions like priv_allocset). Reported by Keith Thompson.
-rw-r--r-- | src/remove.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/remove.c b/src/remove.c index 6572245fd..52ef3b625 100644 --- a/src/remove.c +++ b/src/remove.c @@ -657,6 +657,19 @@ prompt (Dirstack_state const *ds, char const *filename, return RM_OK; } +/* Return true if FILENAME is a directory (and not a symlink to a directory). + Otherwise, including the case in which lstat fails, return false. + Do not modify errno. */ +static inline bool +is_dir_lstat (char const *filename) +{ + struct stat sbuf; + int saved_errno = errno; + bool is_dir = lstat (filename, &sbuf) == 0 && S_ISDIR (sbuf.st_mode); + errno = saved_errno; + return is_dir; +} + #if HAVE_STRUCT_DIRENT_D_TYPE /* True if the type of the directory entry D is known. */ @@ -760,6 +773,12 @@ remove_entry (Dirstack_state const *ds, char const *filename, DO_UNLINK (filename, x); + /* Upon a failed attempt to unlink a directory, most non-Linux systems + set errno to the POSIX-required value EPERM. In that case, change + errno to EISDIR so that we emit a better diagnostic. */ + if (! x->recursive && errno == EPERM && is_dir_lstat (filename)) + errno = EISDIR; + if (! x->recursive || errno == ENOENT || errno == ENOTDIR || errno == ELOOP || errno == ENAMETOOLONG) |