Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-developers-owner AT sourceware DOT cygnus DOT com Delivered-To: mailing list cygwin-developers AT sourceware DOT cygnus DOT com To: cygwin-developers AT sourceware DOT cygnus DOT com Subject: rename() is sometimes unsafe on remote drives. Mime-Version: 1.0 (generated by tm-edit 7.106) Content-Type: text/plain; charset=US-ASCII From: Kazuhiro Fujieda Date: 17 Apr 2000 13:37:24 +0900 Message-ID: Lines: 108 X-Mailer: Gnus v5.3/Emacs 19.34 rename() simply deletes a file on remote drives when its source and destination are identical without distinction of their case. The following session illustrates this problem. /jizai/tmp $ touch aa (A remote drive is mounted on /jizai) /jizai/tmp $ ls -l aa -rw-r--r-- 1 fujieda Domain U 0 Apr 17 13:18 aa /jizai/tmp $ mv aa AA mv: cannot move `aa' to `AA': No such file or directory /jizai/tmp $ ls -l aa ls: aa: No such file or directory /jizai/tmp $ ls -l AA ls: AA: No such file or directory It is caused by MoveFileEx(..., MOVEFILE_REPLACE_EXISTING) in _rename(). The following patch modify _rename() so that it tries MoveFile() at first, then tries MoveFileEx(..., MOVEFILE_REPLACE_EXISTING) on WinNT or the loop of DeleteFileA() and MoveFile() on Win9x. ChangeLog: Mon Apr 17 12:08:47 2000 Kazuhiro Fujieda * syscalls.cc (_rename): Try MoveFile() at first before MoveFileEx(..., MOVEFILE_REPLACE_EXISTING). Index: syscalls.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v retrieving revision 1.14 diff -u -p -r1.14 syscalls.cc --- syscalls.cc 2000/04/16 22:57:05 1.14 +++ syscalls.cc 2000/04/17 03:58:43 @@ -1200,42 +1200,44 @@ _rename (const char *oldpath, const char SetFileAttributesA (real_new.get_win32 (), newatts & ~ FILE_ATTRIBUTE_READONLY); } - /* First make sure we have the permissions */ - if (!MoveFileEx (real_old.get_win32 (), real_new.get_win32 (), MOVEFILE_REPLACE_EXISTING)) - { - res = -1; + if (!MoveFile (real_old.get_win32 (), real_new.get_win32 ())) + res = -1; + + if (res == 0 || GetLastError () != ERROR_ALREADY_EXISTS) + goto done; - /* !!! fixme, check for windows version before trying this.. */ - if (GetLastError () == ERROR_CALL_NOT_IMPLEMENTED) + if (os_being_run == winNT) + { + if (MoveFileEx (real_old.get_win32 (), real_new.get_win32 (), + MOVEFILE_REPLACE_EXISTING)) + res = 0; + } + else + { + syscall_printf ("try win95 hack"); + for (;;) { - /* How sad, we must be on win95, try it the stupid way */ - syscall_printf ("try win95 hack"); - for (;;) + if (!DeleteFileA (real_new.get_win32 ()) && + GetLastError () != ERROR_FILE_NOT_FOUND) + { + syscall_printf ("deleting %s to be paranoid", + real_new.get_win32 ()); + break; + } + else { if (MoveFile (real_old.get_win32 (), real_new.get_win32 ())) { res = 0; break; } - - if (GetLastError () != ERROR_ALREADY_EXISTS) - { - syscall_printf ("%s already_exists", real_new.get_win32 ()); - break; - } - - if (!DeleteFileA (real_new.get_win32 ()) && - GetLastError () != ERROR_FILE_NOT_FOUND) - { - syscall_printf ("deleting %s to be paranoid", - real_new.get_win32 ()); - break; - } } } - if (res) - __seterrno (); } + +done: + if (res) + __seterrno (); if (res == 0) { ____ | AIST Kazuhiro Fujieda | HOKURIKU School of Information Science o_/ 1990 Japan Advanced Institute of Science and Technology