Cygwin: utilize FILE_DISPOSITION_POSIX_SEMANTICS
- short-circuit most code in unlink_nt since it's not necessary anymore if FILE_DISPOSITION_POSIX_SEMANTICS is supported. - Immediately remove O_TMPFILE from filesystem after creation. Disable code for now because we have to implement /proc/self/fd opening by handle first, lest linkat fails. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
0c25ca40ce
commit
a7f392686b
@ -658,23 +658,64 @@ unlink_nt (path_conv &pc)
|
|||||||
HANDLE fh, fh_ro = NULL;
|
HANDLE fh, fh_ro = NULL;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
|
ACCESS_MASK access = DELETE;
|
||||||
|
ULONG flags = FILE_OPEN_FOR_BACKUP_INTENT;
|
||||||
HANDLE old_trans = NULL, trans = NULL;
|
HANDLE old_trans = NULL, trans = NULL;
|
||||||
ULONG num_links = 1;
|
ULONG num_links = 1;
|
||||||
FILE_DISPOSITION_INFORMATION disp = { TRUE };
|
FILE_DISPOSITION_INFORMATION disp = { TRUE };
|
||||||
int reopened = 0;
|
int reopened = 0;
|
||||||
|
|
||||||
bin_status bin_stat = dont_move;
|
bin_status bin_stat = dont_move;
|
||||||
|
|
||||||
syscall_printf ("Trying to delete %S, isdir = %d",
|
syscall_printf ("Trying to delete %S, isdir = %d",
|
||||||
pc.get_nt_native_path (), pc.isdir ());
|
pc.get_nt_native_path (), pc.isdir ());
|
||||||
ACCESS_MASK access = DELETE;
|
|
||||||
ULONG flags = FILE_OPEN_FOR_BACKUP_INTENT;
|
|
||||||
/* Add the reparse point flag to known reparse points, otherwise we remove
|
/* Add the reparse point flag to known reparse points, otherwise we remove
|
||||||
the target, not the reparse point. */
|
the target, not the reparse point. */
|
||||||
if (pc.is_known_reparse_point ())
|
if (pc.is_known_reparse_point ())
|
||||||
flags |= FILE_OPEN_REPARSE_POINT;
|
flags |= FILE_OPEN_REPARSE_POINT;
|
||||||
|
|
||||||
pc.get_object_attr (attr, sec_none_nih);
|
pc.get_object_attr (attr, sec_none_nih);
|
||||||
|
|
||||||
|
/* First check if we can use POSIX unlink semantics: W10 1709++, local NTFS.
|
||||||
|
With POSIX unlink semantics the entire job gets MUCH easier and faster.
|
||||||
|
Just try to do it and if it fails, it fails. */
|
||||||
|
if (wincap.has_posix_file_info () && !pc.isremote () && pc.fs_is_ntfs ())
|
||||||
|
{
|
||||||
|
FILE_DISPOSITION_INFORMATION_EX fdie;
|
||||||
|
|
||||||
|
if (pc.file_attributes () & FILE_ATTRIBUTE_READONLY)
|
||||||
|
access |= FILE_WRITE_ATTRIBUTES;
|
||||||
|
status = NtOpenFile (&fh, access, &attr, &io, FILE_SHARE_VALID_FLAGS,
|
||||||
|
flags);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
goto out;
|
||||||
|
/* Why didn't the devs add a FILE_DELETE_IGNORE_READONLY_ATTRIBUTE
|
||||||
|
flag just like they did with FILE_LINK_IGNORE_READONLY_ATTRIBUTE
|
||||||
|
and FILE_LINK_IGNORE_READONLY_ATTRIBUTE???
|
||||||
|
|
||||||
|
POSIX unlink semantics are nice, but they still fail if the file
|
||||||
|
has the R/O attribute set. Removing the file is very much a safe
|
||||||
|
bet afterwards, so, no transaction. */
|
||||||
|
if (pc.file_attributes () & FILE_ATTRIBUTE_READONLY)
|
||||||
|
{
|
||||||
|
status = NtSetAttributesFile (fh, pc.file_attributes ()
|
||||||
|
& ~FILE_ATTRIBUTE_READONLY);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
NtClose (fh);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fdie.Flags = FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS;
|
||||||
|
status = NtSetInformationFile (fh, &io, &fdie, sizeof fdie,
|
||||||
|
FileDispositionInformationEx);
|
||||||
|
/* Restore R/O attribute in case we have multiple hardlinks. */
|
||||||
|
if (pc.file_attributes () & FILE_ATTRIBUTE_READONLY)
|
||||||
|
NtSetAttributesFile (fh, pc.file_attributes ());
|
||||||
|
NtClose (fh);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the R/O attribute is set, we have to open the file with
|
/* If the R/O attribute is set, we have to open the file with
|
||||||
FILE_WRITE_ATTRIBUTES to be able to remove this flags before trying
|
FILE_WRITE_ATTRIBUTES to be able to remove this flags before trying
|
||||||
to delete it. We do this separately because there are filesystems
|
to delete it. We do this separately because there are filesystems
|
||||||
@ -1426,7 +1467,39 @@ open (const char *unix_path, int flags, ...)
|
|||||||
if ((fh->is_fs_special () && fh->device_access_denied (flags))
|
if ((fh->is_fs_special () && fh->device_access_denied (flags))
|
||||||
|| !fh->open_with_arch (flags, mode & 07777))
|
|| !fh->open_with_arch (flags, mode & 07777))
|
||||||
__leave; /* errno already set */
|
__leave; /* errno already set */
|
||||||
|
#if 0
|
||||||
|
/* W10 1709 POSIX unlink semantics:
|
||||||
|
|
||||||
|
TODO: Works nicely for O_TEMPFILE but using linkat requires that
|
||||||
|
we first fix /proc/self/fd handling to allow opening by handle
|
||||||
|
rather than by symlinked filename only. */
|
||||||
|
if ((flags & O_TMPFILE) && wincap.has_posix_file_info ()
|
||||||
|
&& fh->pc.fs_is_ntfs ())
|
||||||
|
{
|
||||||
|
HANDLE del_h;
|
||||||
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
NTSTATUS status;
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
FILE_DISPOSITION_INFORMATION_EX fdie;
|
||||||
|
|
||||||
|
status = NtOpenFile (&del_h, DELETE,
|
||||||
|
fh->pc.init_reopen_attr (attr, fh->get_handle ()), &io,
|
||||||
|
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
debug_printf ("reopening tmpfile handle failed, status %y", status);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fdie.Flags = FILE_DISPOSITION_DELETE
|
||||||
|
| FILE_DISPOSITION_POSIX_SEMANTICS;
|
||||||
|
status = NtSetInformationFile (del_h, &io, &fdie, sizeof fdie,
|
||||||
|
FileDispositionInformationEx);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
debug_printf ("Setting POSIX delete disposition on tmpfile "
|
||||||
|
"failed, status = %y", status);
|
||||||
|
NtClose (del_h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
fd = fh;
|
fd = fh;
|
||||||
if (fd <= 2)
|
if (fd <= 2)
|
||||||
set_std_handle (fd);
|
set_std_handle (fd);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user