From 693e51ef82d0baba936f7a6e7f9f38f2a4890e7c Mon Sep 17 00:00:00 2001 From: corinna Date: Wed, 7 Jan 2009 18:18:23 +0000 Subject: [PATCH] * ntdll.h: Reorder NT status flags. Fix a case difference. Add STATUS_CANNOT_DELETE flag. * syscalls.cc (unlink_nt): Change initial NtOpenFile to request FILE_SHARE_DELETE sharing mode. Change comment accordingly. If setting delete disposition failed with STATUS_CANNOT_DELETE, try to delete using delete-on-close. Explain why. Rearrange setting R/O DOS attribute after trying to delete. Simplify comment. --- winsup/cygwin/ChangeLog | 11 ++++++++++ winsup/cygwin/ntdll.h | 5 +++-- winsup/cygwin/syscalls.cc | 56 ++++++++++++++++++++++++++++++++++++----------- 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 2faa2e5147..6753d2a0e5 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,5 +1,16 @@ 2009-01-07 Corinna Vinschen + * ntdll.h: Reorder NT status flags. Fix a case difference. Add + STATUS_CANNOT_DELETE flag. + * syscalls.cc (unlink_nt): Change initial NtOpenFile to request + FILE_SHARE_DELETE sharing mode. Change comment accordingly. + If setting delete disposition failed with STATUS_CANNOT_DELETE, try + to delete using delete-on-close. Explain why. + Rearrange setting R/O DOS attribute after trying to delete. Simplify + comment. + +2009-01-07 Corinna Vinschen + * fhandler_disk_file.cc (fhandler_disk_file::link): Only add .exe if original file has .exe as well. * path.cc (path_conv::is_binary): Only recognize Windows 32 and 64 bit diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index d38bdaff0d..da297260e8 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -8,6 +8,7 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ +#define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106) #define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000) #define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005) #define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006) @@ -28,7 +29,7 @@ #define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034) #define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xc000003A) #define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043) -#define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xC000004f) +#define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xc000004f) #define STATUS_EA_TOO_LARGE ((NTSTATUS) 0xc0000050) #define STATUS_NONEXISTENT_EA_ENTRY ((NTSTATUS) 0xc0000051) #define STATUS_NO_EAS_ON_FILE ((NTSTATUS) 0xc0000052) @@ -37,7 +38,7 @@ #define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1) #define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xc00000bb) #define STATUS_DIRECTORY_NOT_EMPTY ((NTSTATUS) 0xc0000101) -#define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106) +#define STATUS_CANNOT_DELETE ((NTSTATUS) 0xc0000121) #define STATUS_INVALID_LEVEL ((NTSTATUS) 0xc0000148) #define STATUS_DLL_NOT_FOUND ((NTSTATUS) 0xc0000135) #define STATUS_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xc0000139) diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 858413cdee..0548ebb75c 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -405,14 +405,14 @@ unlink_nt (path_conv &pc) flags |= FILE_OPEN_REPARSE_POINT; pc.get_object_attr (attr, sec_none_nih); - /* First try to open the file with sharing not allowed. If the file - has an open handle on it, this will fail. That indicates that the - file has to be moved to the recycle bin so that it actually disappears - from its directory even though its in use. Otherwise, if opening - doesn't fail, the file is not in use and by simply closing the handle - the file will disappear. */ + /* First try to open the file with only allowing sharing for delete. If + the file has an open handle on it, other than just for deletion, this + will fail. That indicates that the file has to be moved to the recycle + bin so that it actually disappears from its directory even though its + in use. Otherwise, if opening doesn't fail, the file is not in use and + we can go straight to setting the delete disposition flag. */ bool move_to_bin = false; - status = NtOpenFile (&fh, access, &attr, &io, 0, flags); + status = NtOpenFile (&fh, access, &attr, &io, FILE_SHARE_DELETE, flags); if (status == STATUS_SHARING_VIOLATION) { move_to_bin = true; @@ -470,16 +470,46 @@ unlink_nt (path_conv &pc) FileDispositionInformation); if (!NT_SUCCESS (status)) { - syscall_printf ("Setting delete disposition failed, status = %p", status); - /* Restore R/O attributes. */ - if (access & FILE_WRITE_ATTRIBUTES) - NtSetAttributesFile (fh, pc.file_attributes ()); + syscall_printf ("Setting delete disposition failed, status = %p", + status); + /* Trying to delete a hardlink to a file in use by the system in some + way (for instance, font files) by setting the delete disposition fails + with STATUS_CANNOT_DELETE. Strange enough, deleting these hardlinks + using delete-on-close semantic works. + + Don't use delete-on-close on remote shares. If two processes + have open handles on a file and one of them calls unlink, the + file is removed from the remote share even though the other + process still has an open handle. That process than gets Win32 + error 59, ERROR_UNEXP_NET_ERR when trying to access the file. + Microsoft KB 837665 describes this problem as a bug in 2K3, but + I have reproduced it on other systems. */ + if (status == STATUS_CANNOT_DELETE && !pc.isremote ()) + { + HANDLE fh2; + UNICODE_STRING fname; + + /* Re-open from handle so we open the correct file no matter if it + has been moved to the bin or not. */ + RtlInitUnicodeString (&fname, L""); + InitializeObjectAttributes (&attr, &fname, 0, fh, NULL); + status = NtOpenFile (&fh2, DELETE, &attr, &io, + move_to_bin ? FILE_SHARE_VALID_FLAGS + : FILE_SHARE_DELETE, + flags | FILE_DELETE_ON_CLOSE); + if (!NT_SUCCESS (status)) + syscall_printf ("Setting delete-on-close failed, status = %p", + status); + else + NtClose (fh2); + } } - else if ((access & FILE_WRITE_ATTRIBUTES) && !pc.isdir ()) + if ((access & FILE_WRITE_ATTRIBUTES) + && (!NT_SUCCESS (status) || !pc.isdir ())) { /* Restore R/O attribute to accommodate hardlinks. Don't try this with directories! For some reason the below NtSetInformationFile - changes the disposition for delete back to FALSE, at least on XP. */ + changes the delete disposition back to FALSE, at least on XP. */ NtSetAttributesFile (fh, pc.file_attributes ()); } -- 2.11.0