Patch: MoveFileEx.diff Martin Wilck <Martin.Wilck@fujitsu-siemens.com> Patch against: CVS 2002-09-13 ** This patch obsoletes my earlier MoveFileEx() patch: ** http://www.winehq.com/hypermail/wine-patches/2002/09/0114.html Modified files: - wine/files: file.c MoveFileEx(): - return correct error codes - Fix behaviour if files are on different Wine drives. * delete source if copy successful * try rename() - files may be on the same Unix file system - Try copy/delete if rename() fails: files may be on the same DOS drive, but on different Unix file systems Index: files/file.c =================================================================== RCS file: /home/wine/wine/files/file.c,v retrieving revision 1.160 diff -u -r1.160 file.c --- files/file.c 12 Sep 2002 22:28:01 -0000 1.160 +++ files/file.c 13 Sep 2002 14:26:47 -0000 @@ -2579,6 +2579,7 @@ { DOS_FULL_NAME full_name1, full_name2; HANDLE hFile; + DWORD attr = INVALID_FILE_ATTRIBUTES; TRACE("(%s,%s,%04lx)\n", debugstr_w(fn1), debugstr_w(fn2), flag); @@ -2619,8 +2620,7 @@ /* target exists, check if we may overwrite */ if (!(flag & MOVEFILE_REPLACE_EXISTING)) { - /* FIXME: Use right error code */ - SetLastError( ERROR_ACCESS_DENIED ); + SetLastError( ERROR_FILE_EXISTS ); return FALSE; } } @@ -2647,17 +2647,17 @@ return FILE_AddBootRenameEntry( fn1, fn2, flag ); } + attr = GetFileAttributesA( full_name1.long_name ); + if ( attr == INVALID_FILE_ATTRIBUTES ) return FALSE; + /* check if we are allowed to rename the source */ hFile = FILE_CreateFile( full_name1.long_name, 0, 0, NULL, OPEN_EXISTING, 0, 0, TRUE, GetDriveTypeW( full_name1.short_name ) ); if (!hFile) { - DWORD attr; - if (GetLastError() != ERROR_ACCESS_DENIED) return FALSE; - attr = GetFileAttributesA( full_name1.long_name ); - if (attr == (DWORD)-1 || !(attr & FILE_ATTRIBUTE_DIRECTORY)) return FALSE; + if ( !(attr & FILE_ATTRIBUTE_DIRECTORY) ) return FALSE; /* if it's a directory we can continue */ } else CloseHandle(hFile); @@ -2672,20 +2672,36 @@ if (full_name1.drive != full_name2.drive) { - /* use copy, if allowed */ if (!(flag & MOVEFILE_COPY_ALLOWED)) { - /* FIXME: Use right error code */ - SetLastError( ERROR_FILE_EXISTS ); + SetLastError( ERROR_NOT_SAME_DEVICE ); + return FALSE; + } + else if ( attr & FILE_ATTRIBUTE_DIRECTORY ) + { + /* Strange, but that's what Windows returns */ + SetLastError ( ERROR_ACCESS_DENIED ); return FALSE; } - return CopyFileW( fn1, fn2, !(flag & MOVEFILE_REPLACE_EXISTING) ); } if (rename( full_name1.long_name, full_name2.long_name ) == -1) - { - FILE_SetDosError(); - return FALSE; - } + /* Try copy/delete unless it's a directory. */ + /* FIXME: This does not handle the (unlikely) case that the two locations + are on the same Wine drive, but on different Unix file systems. */ + { + if ( attr & FILE_ATTRIBUTE_DIRECTORY ) + { + FILE_SetDosError(); + return FALSE; + } + else + { + if ( ! CopyFileW( fn1, fn2, !(flag & MOVEFILE_REPLACE_EXISTING) )) + return FALSE; + if ( ! DeleteFileW ( fn1 ) ) + return FALSE; + } + } if (is_executable( full_name1.long_name ) != is_executable( full_name2.long_name )) { struct stat fstat; -- Martin Wilck Phone: +49 5251 8 15113 Fujitsu Siemens Computers Fax: +49 5251 8 20409 Heinz-Nixdorf-Ring 1 mailto:Martin.Wilck@Fujitsu-Siemens.com D-33106 Paderborn http://www.fujitsu-siemens.com/primergy