rm: be even more careful when using a replacement errno value
authorJim Meyering <meyering@redhat.com>
Wed, 19 Sep 2012 07:35:12 +0000 (09:35 +0200)
committerJim Meyering <meyering@redhat.com>
Wed, 19 Sep 2012 07:44:22 +0000 (09:44 +0200)
* src/remove.c (excise): The change in commit v8.19-107-gccbd3f3 made
the "rm -rf D" (for unreadable dir, D) diagnostic worse on Solaris 10:
  -rm: cannot remove 'D': Permission denied
  +rm: cannot remove 'D': File exists
That happened because unlinkat would fail with EEXIST there, given
an unreadable directory, which made the two tests, tests/rm/unread2
and tests/rm/unreadable fail.  Accommodate the EEXIST case, too.

src/remove.c

index a141718..8385012 100644 (file)
@@ -393,11 +393,13 @@ excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
     return RM_OK;
 
   /* When failing to rmdir an unreadable directory, we see errno values
-     like EISDIR or ENOTDIR, but they would be meaningless in a diagnostic.
-     When that happens and the errno value from the failed open is EPERM
-     or EACCES, use the earlier, more descriptive errno value.  */
+     like EISDIR or ENOTDIR (or, on Solaris 10, EEXIST), but they would be
+     meaningless in a diagnostic.  When that happens and the errno value
+     from the failed open is EPERM or EACCES, use the earlier, more
+     descriptive errno value.  */
   if (ent->fts_info == FTS_DNR
-      && (errno == ENOTEMPTY || errno == EISDIR || errno == ENOTDIR)
+      && (errno == ENOTEMPTY || errno == EISDIR || errno == ENOTDIR
+          || errno == EEXIST)
       && (ent->fts_errno == EPERM || ent->fts_errno == EACCES))
     errno = ent->fts_errno;
   error (0, errno, _("cannot remove %s"), quote (ent->fts_path));