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 01:02:24 +0400
committerCorinna Vinschen <corinna@vinschen.de>2007-08-02 01:02:24 +0400
commitae08b378c9f2348a07de9b14f0b0d4a1c4cda4b5 (patch)
treeebd8522f91b5932753a185061c815bf91810e624
parent13c9f5c677ad7a2c73802bd135bfbff81df5f7c0 (diff)
* 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.
-rw-r--r--winsup/cygwin/ChangeLog6
-rw-r--r--winsup/cygwin/syscalls.cc36
2 files changed, 41 insertions, 1 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 222d03f31..7cd946d4c 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 1c202e33e..2aeaa3fcb 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -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);