This is the mail archive of the cygwin-developers@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: rename() is sometimes unsafe on remote drives.


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 <fujieda@jaist.ac.jp>
>	* 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 <fujieda@jaist.ac.jp>
>  | HOKURIKU  School of Information Science
>o_/ 1990      Japan Advanced Institute of Science and Technology

-- 
cgf@cygnus.com                        Cygnus Solutions, a Red Hat company
http://sourcware.cygnus.com/          http://www.redhat.com/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]