* 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.
This commit is contained in:
parent
3bee7767a8
commit
f4ad04049f
|
@ -1,3 +1,14 @@
|
|||
2009-01-07 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* 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 <corinna@vinschen.de>
|
||||
|
||||
* fhandler_disk_file.cc (fhandler_disk_file::link): Only add .exe if
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue