Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2007-08-02 15:11:34 +0400
committerCorinna Vinschen <corinna@vinschen.de>2007-08-02 15:11:34 +0400
commite84b3704c41b0b298c61101509f79893748e1b48 (patch)
treea7a63d0cb9ab1e01faa67918362a1b2096f80aaf
parent98144884f8e6d46732f8d02f82ac08ec90b53e5c (diff)
* 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.
-rw-r--r--winsup/cygwin/ChangeLog7
-rw-r--r--winsup/cygwin/syscalls.cc40
2 files changed, 31 insertions, 16 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index d755bd43d..713e52818 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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.
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 35be660b2..03e041348 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -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);