summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog6
-rw-r--r--winsup/cygwin/syscalls.cc17
2 files changed, 23 insertions, 0 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index d54883bdb..28bce1efd 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,9 @@
+2010-04-19 Corinna Vinschen <corinna@vinschen.de>
+
+ * syscalls.cc (rename): On STATUS_ACCESS_VIOLATION, retry to open
+ for DELETE until the STATUS_ACCESS_VIOLATION goes away. Add comment
+ to explain why.
+
2010-04-17 Corinna Vinschen <corinna@vinschen.de>
* sec_helper.cc (get_null_sd): Make static. Use PSECURITY_DESCRIPTOR
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 65bab2b10..8adf22edc 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -2002,6 +2002,7 @@ rename (const char *oldpath, const char *newpath)
|| (!removepc && dstpc->has_attribute (FILE_ATTRIBUTE_READONLY))))
start_transaction (old_trans, trans);
+retry:
/* DELETE is required to rename a file. Samba (only some versions?) doesn't
like the FILE_SHARE_DELETE mode if the file has the R/O attribute set
and returns STATUS_ACCESS_DENIED in that case. */
@@ -2013,6 +2014,22 @@ rename (const char *oldpath, const char *newpath)
| (oldpc.is_rep_symlink () ? FILE_OPEN_REPARSE_POINT : 0));
if (!NT_SUCCESS (status))
{
+ debug_printf ("status %p", status);
+ if (status == STATUS_SHARING_VIOLATION
+ && WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0)
+ {
+ /* Typical BLODA problem. Some virus scanners check newly generated
+ files and while doing that disallow DELETE access. That's really
+ bad because it breaks applications which copy files by creating
+ a temporary filename and then rename the temp filename to the
+ target filename. This renaming fails due to the jealous virus
+ scanner and the application fails to create the target file.
+
+ This kludge tries to work around that by yielding until the
+ sharing violation goes away, or a signal arrived. */
+ yield ();
+ goto retry;
+ }
__seterrno_from_nt_status (status);
goto out;
}