OSDN Git Service

* syscalls.cc (rename): Check if oldpath and newpath refer to the
authorcorinna <corinna>
Wed, 1 Aug 2007 21:02:24 +0000 (21:02 +0000)
committercorinna <corinna>
Wed, 1 Aug 2007 21:02:24 +0000 (21:02 +0000)
same file.  If so, return successfully and perform no other action,
as per SUSv3.

winsup/cygwin/ChangeLog
winsup/cygwin/syscalls.cc

index 222d03f..7cd946d 100644 (file)
@@ -1,5 +1,11 @@
 2007-08-01  Corinna Vinschen  <corinna@vinschen.de>
 
+       * syscalls.cc (rename): Check if oldpath and newpath refer to the
+       same file.  If so, return successfully and perform no other action,
+       as per SUSv3.
+
+2007-08-01  Corinna Vinschen  <corinna@vinschen.de>
+
        * ntdll.h (STATUS_ACCESS_DENIED): Define.
        * syscalls.cc (check_dir_not_empty): New static function.
        (unlink_nt): Move code checking for non-empty dir to check_dir_not_empty
index 1c202e3..2aeaa3f 100644 (file)
@@ -1353,7 +1353,7 @@ rename (const char *oldpath, const char *newpath)
   bool old_explicit_suffix = false, new_explicit_suffix = false;
   size_t olen, nlen;
   NTSTATUS status;
-  HANDLE fh;
+  HANDLE fh, nfh;
   OBJECT_ATTRIBUTES attr;
   IO_STATUS_BLOCK io;
   ULONG size;
@@ -1520,6 +1520,40 @@ rename (const char *oldpath, const char *newpath)
       __seterrno_from_nt_status (status);
       goto out;
     }
+  if ((removepc || dstpc->exists ())
+      && NT_SUCCESS (NtOpenFile (&nfh, READ_CONTROL,
+                    (removepc ?: dstpc)->get_object_attr (attr, sec_none_nih),
+                    &io, FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT)))
+    {
+      size_t size = sizeof (FILE_FS_VOLUME_INFORMATION) + 32 * sizeof (WCHAR);
+      PFILE_FS_VOLUME_INFORMATION opffvi = (PFILE_FS_VOLUME_INFORMATION)
+                                          alloca (size);
+      PFILE_FS_VOLUME_INFORMATION npffvi = (PFILE_FS_VOLUME_INFORMATION)
+                                          alloca (size);
+      FILE_INTERNAL_INFORMATION ofii, nfii;
+
+      /* SUSv3: If the old argument and the new argument resolve to the same
+        existing file, rename() shall return successfully and perform no
+        other action. */
+      if (NT_SUCCESS (NtQueryVolumeInformationFile (fh, &io, opffvi, size,
+                                                   FileFsVolumeInformation))
+         && NT_SUCCESS (NtQueryVolumeInformationFile (nfh, &io, npffvi, size,
+                                                   FileFsVolumeInformation))
+         && opffvi->VolumeSerialNumber == npffvi->VolumeSerialNumber
+         && NT_SUCCESS (NtQueryInformationFile (fh, &io, &ofii, sizeof ofii,
+                                                   FileInternalInformation))
+         && NT_SUCCESS (NtQueryInformationFile (nfh, &io, &nfii, sizeof nfii,
+                                                   FileInternalInformation))
+         && ofii.FileId.QuadPart == nfii.FileId.QuadPart)
+       {
+         debug_printf ("%s and %s are the same file", oldpath, newpath);
+         NtClose (nfh);
+         NtClose (fh);
+         res = 0;
+         goto out;
+       }
+      NtClose (nfh);
+    }
   size = sizeof (FILE_RENAME_INFORMATION)
         + dstpc->get_nt_native_path ()->Length;
   pfri = (PFILE_RENAME_INFORMATION) alloca (size);