diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2007-08-01 21:02:24 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2007-08-01 21:02:24 +0000 |
commit | ae08b378c9f2348a07de9b14f0b0d4a1c4cda4b5 (patch) | |
tree | ebd8522f91b5932753a185061c815bf91810e624 | |
parent | 13c9f5c677ad7a2c73802bd135bfbff81df5f7c0 (diff) | |
download | newlib-ae08b378c9f2348a07de9b14f0b0d4a1c4cda4b5.zip newlib-ae08b378c9f2348a07de9b14f0b0d4a1c4cda4b5.tar.gz newlib-ae08b378c9f2348a07de9b14f0b0d4a1c4cda4b5.tar.bz2 |
* 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/ChangeLog | 6 | ||||
-rw-r--r-- | winsup/cygwin/syscalls.cc | 36 |
2 files changed, 41 insertions, 1 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 222d03f..7cd946d 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 1c202e3..2aeaa3f 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); |