summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2003-05-02 12:53:02 +0000
committerJim Meyering <jim@meyering.net>2003-05-02 12:53:02 +0000
commit4ed5c260a3b39ba5a75a8399152dc8e7599fa012 (patch)
treed0546e407a592d7896083c60048b8e9d02d13771
parentee0dc0c2ceca47f32eddd26e22248fffd8a4c80a (diff)
downloadcoreutils-4ed5c260a3b39ba5a75a8399152dc8e7599fa012.tar.xz
Work around nasty readdir bug with Darwin6.5 and hfs file system.
(IF_READDIR_NEEDS_REWINDDIR): Define. [! HAVE_WORKING_READDIR] (remove_cwd_entries): If readdir has just returned NULL and there has been at least one successful unlink or rmdir call since the opendir or previous rewinddir, then call rewinddir and reiterate the loop.
-rw-r--r--src/remove.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/remove.c b/src/remove.c
index a8be3dac9..cf808dd21 100644
--- a/src/remove.c
+++ b/src/remove.c
@@ -55,6 +55,12 @@
# define ROOT_CAN_UNLINK_DIRS 1
#endif
+#if HAVE_WORKING_READDIR
+# define IF_READDIR_NEEDS_REWINDDIR(Code) /* empty */
+#else
+# define IF_READDIR_NEEDS_REWINDDIR(Code) Code
+#endif
+
enum Ternary
{
T_UNKNOWN = 2,
@@ -804,6 +810,7 @@ remove_cwd_entries (Dirstack_state *ds, char **subdir, struct stat *subdir_sb,
DIR *dirp = opendir (".");
struct AD_ent *top = AD_stack_top (ds);
enum RM_status status = top->status;
+ IF_READDIR_NEEDS_REWINDDIR (int performed_unlink_or_rmdir = 0);
assert (VALID_STATUS (status));
*subdir = NULL;
@@ -839,6 +846,19 @@ remove_cwd_entries (Dirstack_state *ds, char **subdir, struct stat *subdir_sb,
/* Arrange to give a diagnostic after exiting this loop. */
dirp = NULL;
}
+ else
+ {
+#if ! HAVE_WORKING_READDIR
+ /* On buggy systems, call rewinddir if we've called unlink
+ or rmdir since the opendir or a previous rewinddir. */
+ if (performed_unlink_or_rmdir)
+ {
+ rewinddir (dirp);
+ performed_unlink_or_rmdir = 0;
+ continue;
+ }
+#endif
+ }
break;
}
@@ -856,7 +876,9 @@ remove_cwd_entries (Dirstack_state *ds, char **subdir, struct stat *subdir_sb,
switch (tmp_status)
{
case RM_OK:
- /* do nothing */
+ /* On buggy systems, record the fact that we've just
+ removed a directory entry. */
+ IF_READDIR_NEEDS_REWINDDIR (performed_unlink_or_rmdir = 1);
break;
case RM_ERROR: