OSDN Git Service

* syscalls.cc (rename): Move and add text to comment about testing
authorcorinna <corinna>
Thu, 2 Aug 2007 11:11:34 +0000 (11:11 +0000)
committercorinna <corinna>
Thu, 2 Aug 2007 11:11:34 +0000 (11:11 +0000)
oldpath and newpath referring to the same file.  Test if oldpath
has more than one hardlink before opening oldpath (idea by Eric Blake).
Reorder test so that file id is tested before volume serial number.

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

index d755bd4..713e528 100644 (file)
@@ -1,5 +1,12 @@
 2007-08-02  Corinna Vinschen  <corinna@vinschen.de>
 
+       * syscalls.cc (rename): Move and add text to comment about testing
+       oldpath and newpath referring to the same file.  Test if oldpath
+       has more than one hardlink before opening oldpath (idea by Eric Blake).
+       Reorder test so that file id is tested before volume serial number.  
+
+2007-08-02  Corinna Vinschen  <corinna@vinschen.de>
+
        * path.h (struct fs_info): Drop root_len and name_hash members.
        (fsinfo::length): Remove.
        (path_conv::rootdir): Remove.
index 35be660..03e0413 100644 (file)
@@ -1358,6 +1358,7 @@ rename (const char *oldpath, const char *newpath)
   OBJECT_ATTRIBUTES attr;
   IO_STATUS_BLOCK io;
   ULONG size;
+  FILE_STANDARD_INFORMATION ofsi;
   PFILE_RENAME_INFORMATION pfri;
 
   myfault efault;
@@ -1521,31 +1522,38 @@ rename (const char *oldpath, const char *newpath)
       __seterrno_from_nt_status (status);
       goto out;
     }
+  /* SUSv3: If the old argument and the new argument resolve to the same
+     existing file, rename() shall return successfully and perform no
+     other action.
+     The test tries to be as quick as possible.  First it tests if oldpath
+     has more than 1 hardlink, then it opens newpath and tests for identical
+     file ids.  If so, it tests for identical volume serial numbers,  If so,
+     oldpath and newpath refer to the same file. */
   if ((removepc || dstpc->exists ())
+      && NT_SUCCESS (NtQueryInformationFile (fh, &io, &ofsi, sizeof ofsi,
+                                            FileStandardInformation))
+      && ofsi.NumberOfLinks > 1
       && 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);
+      static const size_t vsiz = sizeof (FILE_FS_VOLUME_INFORMATION)
+                                + 32 * sizeof (WCHAR);
       FILE_INTERNAL_INFORMATION ofii, nfii;
+      PFILE_FS_VOLUME_INFORMATION opffvi, npffvi;
 
-      /* 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,
+      if (NT_SUCCESS (NtQueryInformationFile (fh, &io, &ofii, sizeof ofii,
+                                             FileInternalInformation))
+         && NT_SUCCESS (NtQueryInformationFile (nfh, &io, &nfii, sizeof nfii,
+                                                FileInternalInformation))
+         && ofii.FileId.QuadPart == nfii.FileId.QuadPart
+         && (opffvi = (PFILE_FS_VOLUME_INFORMATION) alloca (vsiz))
+         && (npffvi = (PFILE_FS_VOLUME_INFORMATION) alloca (vsiz))
+         && NT_SUCCESS (NtQueryVolumeInformationFile (fh, &io, opffvi, vsiz,
                                                    FileFsVolumeInformation))
-         && NT_SUCCESS (NtQueryVolumeInformationFile (nfh, &io, npffvi, size,
+         && NT_SUCCESS (NtQueryVolumeInformationFile (nfh, &io, npffvi, vsiz,
                                                    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)
+         && opffvi->VolumeSerialNumber == npffvi->VolumeSerialNumber)
        {
          debug_printf ("%s and %s are the same file", oldpath, newpath);
          NtClose (nfh);