Issue: #984. Thank You, Axel for reporting this, the patch, and the test code.

This commit is contained in:
Robin Mills 2014-09-01 17:57:58 +00:00
parent 5131bfb2f1
commit f93877f94b
2 changed files with 45 additions and 0 deletions

View File

@ -0,0 +1,23 @@
#include <stdio.h>
#include <windows.h>
int main(int argc, char** argv)
{
printf("Opening file '%s' with FILE_SHARE_DELETE acess...\n", argv[1]);
HANDLE hFile = CreateFile(argv[1], GENERIC_READ,
FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("failed to open file\n");
return -1;
}
sleep(10);
CloseHandle(hFile);
return 0;
}

View File

@ -710,6 +710,16 @@ namespace Exiv2 {
// MSVCRT rename that does not overwrite existing files
#ifdef EXV_UNICODE_PATH
if (p_->wpMode_ == Impl::wpUnicode) {
#if defined WIN32 && !defined __CYGWIN__
// Windows implementation that deals with the fact that ::rename fails
// if the target filename still exists, which regularly happens when
// that file has been opened with FILE_SHARE_DELETE by another process,
// like a virus scanner or disk indexer
// (see also http://stackoverflow.com/a/11023068)
if (ReplaceFileW(wpf, fileIo->wpath().c_str(), NULL, REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL) == 0) {
throw WError(17, fileIo->wpath(), wpf, strError().c_str());
}
#else
if (fileExists(wpf) && ::_wremove(wpf) != 0) {
throw WError(2, wpf, strError().c_str(), "::_wremove");
}
@ -717,6 +727,7 @@ namespace Exiv2 {
throw WError(17, fileIo->wpath(), wpf, strError().c_str());
}
::_wremove(fileIo->wpath().c_str());
#endif
// Check permissions of new file
struct _stat buf2;
if (statOk && ::_wstat(wpf, &buf2) == -1) {
@ -737,6 +748,16 @@ namespace Exiv2 {
else
#endif // EXV_UNICODE_PATH
{
#if defined WIN32 && !defined __CYGWIN__
// Windows implementation that deals with the fact that ::rename fails
// if the target filename still exists, which regularly happens when
// that file has been opened with FILE_SHARE_DELETE by another process,
// like a virus scanner or disk indexer
// (see also http://stackoverflow.com/a/11023068)
if (ReplaceFile(pf, fileIo->path().c_str(), NULL, REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL) == 0) {
throw Error(17, fileIo->path(), pf, strError());
}
#else
if (fileExists(pf) && ::remove(pf) != 0) {
throw Error(2, pf, strError(), "::remove");
}
@ -744,6 +765,7 @@ namespace Exiv2 {
throw Error(17, fileIo->path(), pf, strError());
}
::remove(fileIo->path().c_str());
#endif
// Check permissions of new file
struct stat buf2;
if (statOk && ::stat(pf, &buf2) == -1) {