]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
(remove_entry): Emit a better diagnostic when rm
authorJim Meyering <jim@meyering.net>
Wed, 2 Nov 2005 09:47:39 +0000 (09:47 +0000)
committerJim Meyering <jim@meyering.net>
Wed, 2 Nov 2005 09:47:39 +0000 (09:47 +0000)
(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.

src/remove.c

index 6572245fd001c12b9fd77e816dfd86493f977f00..52ef3b6251227a00f137baef43cb7dac741411bc 100644 (file)
@@ -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)