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 From: Chris Faylor Date: Mon, 17 Apr 2000 20:50:14 -0400 To: cygwin-developers AT sourceware DOT cygnus DOT com Subject: Re: rename() is sometimes unsafe on remote drives. Message-ID: <20000417205014.A5050@cygnus.com> Reply-To: cygwin-developers AT sourceware DOT cygnus DOT com Mail-Followup-To: cgf AT cygnus DOT com, cygwin-developers AT sourceware DOT cygnus DOT com References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.1.8i In-Reply-To: ; from fujieda@jaist.ac.jp on Mon, Apr 17, 2000 at 01:37:24PM +0900 This patch seems to make sense but I was wondering if you'd be interested in going a step further? If, for some reason, the MoveFile of an existing file fails, the target file will be gone. rename on UNIX doesn't work this way. To fix this will require renaming the target file, then doing the MoveFile. If the MoveFile works then the renamed target file is deleted. Otherwise, the target file is renamed back. Do you have the time to implement something like this? cgf On Mon, Apr 17, 2000 at 01:37:24PM +0900, Kazuhiro Fujieda wrote: >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 -- cgf AT cygnus DOT com Cygnus Solutions, a Red Hat company http://sourcware.cygnus.com/ http://www.redhat.com/