mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-19 04:49:25 +08:00
* syscalls.cc (enum bin_status): New type.
(try_to_bin): Return bin_status. Rename win32_path to pc. Rename h to fh. Rename fh to tmp_fh. Add code to set delete dispostion and more code to replace file moved to bin by another, temporary file. Add comments to explain why. (unlink_nt): Replace move_to_bin with bin_stat. Only set bin_stat to move_to_bin for non-remote files. As a last resort, call try_to_bin if setting delete-on-close failed. Only re-set R/O DOS attribute and only close handle if it's still valid.
This commit is contained in:
parent
b98c66ee2c
commit
8a0f3bbf2d
@ -1,3 +1,15 @@
|
|||||||
|
2009-01-12 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* syscalls.cc (enum bin_status): New type.
|
||||||
|
(try_to_bin): Return bin_status. Rename win32_path to pc. Rename h
|
||||||
|
to fh. Rename fh to tmp_fh. Add code to set delete dispostion and
|
||||||
|
more code to replace file moved to bin by another, temporary file.
|
||||||
|
Add comments to explain why.
|
||||||
|
(unlink_nt): Replace move_to_bin with bin_stat. Only set bin_stat
|
||||||
|
to move_to_bin for non-remote files. As a last resort, call try_to_bin
|
||||||
|
if setting delete-on-close failed. Only re-set R/O DOS attribute
|
||||||
|
and only close handle if it's still valid.
|
||||||
|
|
||||||
2009-01-11 Corinna Vinschen <corinna@vinschen.de>
|
2009-01-11 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* errno.cc (errmap): Set errno to ENOENT instead of ENOSHARE throughout.
|
* errno.cc (errmap): Set errno to ENOENT instead of ENOSHARE throughout.
|
||||||
|
@ -132,13 +132,21 @@ static BYTE info2[] =
|
|||||||
0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
enum bin_status
|
||||||
try_to_bin (path_conv &win32_path, HANDLE h)
|
|
||||||
{
|
{
|
||||||
|
dont_move,
|
||||||
|
move_to_bin,
|
||||||
|
has_been_moved
|
||||||
|
};
|
||||||
|
|
||||||
|
static bin_status
|
||||||
|
try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access)
|
||||||
|
{
|
||||||
|
bin_status bin_stat = move_to_bin;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
HANDLE rootdir = NULL, recyclerdir = NULL;
|
HANDLE rootdir = NULL, recyclerdir = NULL, tmp_fh = NULL;
|
||||||
USHORT recycler_base_len = 0, recycler_user_len = 0;
|
USHORT recycler_base_len = 0, recycler_user_len = 0;
|
||||||
UNICODE_STRING root, recycler, fname;
|
UNICODE_STRING root, recycler, fname;
|
||||||
WCHAR recyclerbuf[NAME_MAX + 1]; /* Enough for recycler + SID + filename */
|
WCHAR recyclerbuf[NAME_MAX + 1]; /* Enough for recycler + SID + filename */
|
||||||
@ -146,9 +154,10 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
PFILE_INTERNAL_INFORMATION pfii;
|
PFILE_INTERNAL_INFORMATION pfii;
|
||||||
PFILE_RENAME_INFORMATION pfri;
|
PFILE_RENAME_INFORMATION pfri;
|
||||||
BYTE infobuf[sizeof (FILE_NAME_INFORMATION ) + 32767 * sizeof (WCHAR)];
|
BYTE infobuf[sizeof (FILE_NAME_INFORMATION ) + 32767 * sizeof (WCHAR)];
|
||||||
|
FILE_DISPOSITION_INFORMATION disp = { TRUE };
|
||||||
|
|
||||||
pfni = (PFILE_NAME_INFORMATION) infobuf;
|
pfni = (PFILE_NAME_INFORMATION) infobuf;
|
||||||
status = NtQueryInformationFile (h, &io, pfni, sizeof infobuf,
|
status = NtQueryInformationFile (fh, &io, pfni, sizeof infobuf,
|
||||||
FileNameInformation);
|
FileNameInformation);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
@ -168,9 +177,9 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
RtlInitEmptyUnicodeString (&recycler, recyclerbuf, sizeof recyclerbuf);
|
RtlInitEmptyUnicodeString (&recycler, recyclerbuf, sizeof recyclerbuf);
|
||||||
if (wincap.has_recycle_dot_bin ()) /* NTFS and FAT since Vista */
|
if (wincap.has_recycle_dot_bin ()) /* NTFS and FAT since Vista */
|
||||||
RtlAppendUnicodeToString (&recycler, L"\\$Recycle.Bin\\");
|
RtlAppendUnicodeToString (&recycler, L"\\$Recycle.Bin\\");
|
||||||
else if (win32_path.fs_is_ntfs ()) /* NTFS up to 2K3 */
|
else if (pc.fs_is_ntfs ()) /* NTFS up to 2K3 */
|
||||||
RtlAppendUnicodeToString (&recycler, L"\\RECYCLER\\");
|
RtlAppendUnicodeToString (&recycler, L"\\RECYCLER\\");
|
||||||
else if (win32_path.fs_is_fat ()) /* FAT up to 2K3 */
|
else if (pc.fs_is_fat ()) /* FAT up to 2K3 */
|
||||||
RtlAppendUnicodeToString (&recycler, L"\\Recycled\\");
|
RtlAppendUnicodeToString (&recycler, L"\\Recycled\\");
|
||||||
else
|
else
|
||||||
goto out;
|
goto out;
|
||||||
@ -185,7 +194,7 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
|
|
||||||
/* Create root dir path from file name information. */
|
/* Create root dir path from file name information. */
|
||||||
RtlSplitUnicodePath (&fname, &fname, NULL);
|
RtlSplitUnicodePath (&fname, &fname, NULL);
|
||||||
RtlSplitUnicodePath (win32_path.get_nt_native_path (), &root, NULL);
|
RtlSplitUnicodePath (pc.get_nt_native_path (), &root, NULL);
|
||||||
root.Length -= fname.Length - sizeof (WCHAR);
|
root.Length -= fname.Length - sizeof (WCHAR);
|
||||||
|
|
||||||
/* Open root directory. All recycler bin ops are caseinsensitive. */
|
/* Open root directory. All recycler bin ops are caseinsensitive. */
|
||||||
@ -206,7 +215,7 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
/* On NTFS the recycler dir contains user specific subdirs, which are the
|
/* On NTFS the recycler dir contains user specific subdirs, which are the
|
||||||
actual recycle bins per user. The name if this dir is the string
|
actual recycle bins per user. The name if this dir is the string
|
||||||
representation of the user SID. */
|
representation of the user SID. */
|
||||||
if (win32_path.fs_is_ntfs ())
|
if (pc.fs_is_ntfs ())
|
||||||
{
|
{
|
||||||
UNICODE_STRING sid;
|
UNICODE_STRING sid;
|
||||||
WCHAR sidbuf[128];
|
WCHAR sidbuf[128];
|
||||||
@ -222,7 +231,7 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
/* Create hopefully unique filename. */
|
/* Create hopefully unique filename. */
|
||||||
RtlAppendUnicodeToString (&recycler, L"\\cyg");
|
RtlAppendUnicodeToString (&recycler, L"\\cyg");
|
||||||
pfii = (PFILE_INTERNAL_INFORMATION) infobuf;
|
pfii = (PFILE_INTERNAL_INFORMATION) infobuf;
|
||||||
status = NtQueryInformationFile (h, &io, pfii, sizeof infobuf,
|
status = NtQueryInformationFile (fh, &io, pfii, sizeof infobuf,
|
||||||
FileInternalInformation);
|
FileInternalInformation);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
@ -237,7 +246,7 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
pfri->RootDirectory = rootdir;
|
pfri->RootDirectory = rootdir;
|
||||||
pfri->FileNameLength = recycler.Length;
|
pfri->FileNameLength = recycler.Length;
|
||||||
memcpy (pfri->FileName, recycler.Buffer, recycler.Length);
|
memcpy (pfri->FileName, recycler.Buffer, recycler.Length);
|
||||||
status = NtSetInformationFile (h, &io, pfri, sizeof infobuf,
|
status = NtSetInformationFile (fh, &io, pfri, sizeof infobuf,
|
||||||
FileRenameInformation);
|
FileRenameInformation);
|
||||||
if (status == STATUS_OBJECT_PATH_NOT_FOUND)
|
if (status == STATUS_OBJECT_PATH_NOT_FOUND)
|
||||||
{
|
{
|
||||||
@ -260,7 +269,7 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
recycler.Length = recycler_base_len;
|
recycler.Length = recycler_base_len;
|
||||||
status = NtCreateFile (&recyclerdir,
|
status = NtCreateFile (&recyclerdir,
|
||||||
READ_CONTROL
|
READ_CONTROL
|
||||||
| (win32_path.fs_is_ntfs () ? 0 : FILE_ADD_FILE),
|
| (pc.fs_is_ntfs () ? 0 : FILE_ADD_FILE),
|
||||||
&attr, &io, NULL,
|
&attr, &io, NULL,
|
||||||
FILE_ATTRIBUTE_DIRECTORY
|
FILE_ATTRIBUTE_DIRECTORY
|
||||||
| FILE_ATTRIBUTE_SYSTEM
|
| FILE_ATTRIBUTE_SYSTEM
|
||||||
@ -274,7 +283,7 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
}
|
}
|
||||||
/* Next, if necessary, check if the recycler/SID dir exists and
|
/* Next, if necessary, check if the recycler/SID dir exists and
|
||||||
create it if not. */
|
create it if not. */
|
||||||
if (win32_path.fs_is_ntfs ())
|
if (pc.fs_is_ntfs ())
|
||||||
{
|
{
|
||||||
NtClose (recyclerdir);
|
NtClose (recyclerdir);
|
||||||
recycler.Length = recycler_user_len;
|
recycler.Length = recycler_user_len;
|
||||||
@ -296,11 +305,10 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
corrupted */
|
corrupted */
|
||||||
if (io.Information == FILE_CREATED)
|
if (io.Information == FILE_CREATED)
|
||||||
{
|
{
|
||||||
HANDLE fh;
|
|
||||||
RtlInitUnicodeString (&fname, L"desktop.ini");
|
RtlInitUnicodeString (&fname, L"desktop.ini");
|
||||||
InitializeObjectAttributes (&attr, &fname, OBJ_CASE_INSENSITIVE,
|
InitializeObjectAttributes (&attr, &fname, OBJ_CASE_INSENSITIVE,
|
||||||
recyclerdir, NULL);
|
recyclerdir, NULL);
|
||||||
status = NtCreateFile (&fh, FILE_GENERIC_WRITE, &attr, &io, NULL,
|
status = NtCreateFile (&tmp_fh, FILE_GENERIC_WRITE, &attr, &io, NULL,
|
||||||
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
|
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
|
||||||
FILE_SHARE_VALID_FLAGS, FILE_CREATE,
|
FILE_SHARE_VALID_FLAGS, FILE_CREATE,
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT
|
FILE_SYNCHRONOUS_IO_NONALERT
|
||||||
@ -309,18 +317,18 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
debug_printf ("NtCreateFile (%S) failed, %08x", &recycler, status);
|
debug_printf ("NtCreateFile (%S) failed, %08x", &recycler, status);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = NtWriteFile (fh, NULL, NULL, NULL, &io, desktop_ini,
|
status = NtWriteFile (tmp_fh, NULL, NULL, NULL, &io, desktop_ini,
|
||||||
sizeof desktop_ini - 1, NULL, NULL);
|
sizeof desktop_ini - 1, NULL, NULL);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
debug_printf ("NtWriteFile (%S) failed, %08x", &fname, status);
|
debug_printf ("NtWriteFile (%S) failed, %08x", &fname, status);
|
||||||
NtClose (fh);
|
NtClose (tmp_fh);
|
||||||
}
|
}
|
||||||
if (!wincap.has_recycle_dot_bin ()) /* No INFO2 file since Vista */
|
if (!wincap.has_recycle_dot_bin ()) /* No INFO2 file since Vista */
|
||||||
{
|
{
|
||||||
RtlInitUnicodeString (&fname, L"INFO2");
|
RtlInitUnicodeString (&fname, L"INFO2");
|
||||||
status = NtCreateFile (&fh, FILE_GENERIC_WRITE, &attr, &io, NULL,
|
status = NtCreateFile (&tmp_fh, FILE_GENERIC_WRITE, &attr, &io,
|
||||||
FILE_ATTRIBUTE_ARCHIVE
|
NULL, FILE_ATTRIBUTE_ARCHIVE
|
||||||
| FILE_ATTRIBUTE_HIDDEN,
|
| FILE_ATTRIBUTE_HIDDEN,
|
||||||
FILE_SHARE_VALID_FLAGS, FILE_CREATE,
|
FILE_SHARE_VALID_FLAGS, FILE_CREATE,
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT
|
FILE_SYNCHRONOUS_IO_NONALERT
|
||||||
| FILE_NON_DIRECTORY_FILE, NULL, 0);
|
| FILE_NON_DIRECTORY_FILE, NULL, 0);
|
||||||
@ -329,26 +337,75 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
&recycler, status);
|
&recycler, status);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = NtWriteFile (fh, NULL, NULL, NULL, &io, info2,
|
status = NtWriteFile (tmp_fh, NULL, NULL, NULL, &io, info2,
|
||||||
sizeof info2, NULL, NULL);
|
sizeof info2, NULL, NULL);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
debug_printf ("NtWriteFile (%S) failed, %08x",
|
debug_printf ("NtWriteFile (%S) failed, %08x",
|
||||||
&fname, status);
|
&fname, status);
|
||||||
NtClose (fh);
|
NtClose (tmp_fh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NtClose (recyclerdir);
|
NtClose (recyclerdir);
|
||||||
/* Shoot again. */
|
/* Shoot again. */
|
||||||
status = NtSetInformationFile (h, &io, pfri, sizeof infobuf,
|
status = NtSetInformationFile (fh, &io, pfri, sizeof infobuf,
|
||||||
FileRenameInformation);
|
FileRenameInformation);
|
||||||
}
|
}
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
debug_printf ("Move %S to %S failed, status = %p",
|
{
|
||||||
win32_path.get_nt_native_path (), &recycler, status);
|
debug_printf ("Move %S to %S failed, status = %p",
|
||||||
|
pc.get_nt_native_path (), &recycler, status);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* Moving to the bin worked. */
|
||||||
|
bin_stat = has_been_moved;
|
||||||
|
/* Now we try to set the delete disposition. If that worked, we're done.
|
||||||
|
We try this here first, as long as we still have the open handle.
|
||||||
|
Otherwise the below code closes the handle to allow replacing the file. */
|
||||||
|
status = NtSetInformationFile (fh, &io, &disp, sizeof disp,
|
||||||
|
FileDispositionInformation);
|
||||||
|
/* In case of success, restore R/O attribute to accommodate hardlinks.
|
||||||
|
That leaves potentially hardlinks around with the R/O bit suddenly
|
||||||
|
off if setting the delete disposition failed, but please, keep in
|
||||||
|
mind this is really a border case only. */
|
||||||
|
if ((access & FILE_WRITE_ATTRIBUTES) && NT_SUCCESS (status) && !pc.isdir ())
|
||||||
|
NtSetAttributesFile (fh, pc.file_attributes ());
|
||||||
|
NtClose (fh);
|
||||||
|
fh = NULL; /* So unlink_nt doesn't close the handle twice. */
|
||||||
|
/* On success or when trying to unlink a directory we just return here.
|
||||||
|
The below code only works for files. */
|
||||||
|
if (NT_SUCCESS (status) || pc.isdir ())
|
||||||
|
goto out;
|
||||||
|
/* The final trick. We create a temporary file with delete-on-close
|
||||||
|
semantic and rename that file to the file just moved to the bin.
|
||||||
|
This typically overwrites the original file and we get rid of it,
|
||||||
|
even if neither setting the delete dispostion, nor setting
|
||||||
|
delete-on-close on the original file succeeds. There are still
|
||||||
|
cases in which this fails, for instance, when trying to delete a
|
||||||
|
hardlink to a DLL used by the unlinking application itself. */
|
||||||
|
RtlAppendUnicodeToString (&recycler, L"X");
|
||||||
|
InitializeObjectAttributes (&attr, &recycler, 0, rootdir, NULL);
|
||||||
|
status = NtCreateFile (&tmp_fh, DELETE, &attr, &io, NULL,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, 0, FILE_SUPERSEDE,
|
||||||
|
FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE,
|
||||||
|
NULL, 0);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
debug_printf ("Creating file for overwriting failed, status = %p",
|
||||||
|
status);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
status = NtSetInformationFile (tmp_fh, &io, pfri, sizeof infobuf,
|
||||||
|
FileRenameInformation);
|
||||||
|
NtClose (tmp_fh);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
debug_printf ("Overwriting with another file failed, status = %p",
|
||||||
|
status);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (rootdir)
|
if (rootdir)
|
||||||
NtClose (rootdir);
|
NtClose (rootdir);
|
||||||
|
return bin_stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
@ -411,11 +468,13 @@ unlink_nt (path_conv &pc)
|
|||||||
bin so that it actually disappears from its directory even though its
|
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
|
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. */
|
we can go straight to setting the delete disposition flag. */
|
||||||
bool move_to_bin = false;
|
bin_status bin_stat = dont_move;
|
||||||
status = NtOpenFile (&fh, access, &attr, &io, FILE_SHARE_DELETE, flags);
|
status = NtOpenFile (&fh, access, &attr, &io, FILE_SHARE_DELETE, flags);
|
||||||
if (status == STATUS_SHARING_VIOLATION)
|
if (status == STATUS_SHARING_VIOLATION)
|
||||||
{
|
{
|
||||||
move_to_bin = true;
|
/* Bin is only accessible locally. */
|
||||||
|
if (!pc.isremote ())
|
||||||
|
bin_stat = move_to_bin;
|
||||||
if (!pc.isdir () || pc.isremote ())
|
if (!pc.isdir () || pc.isremote ())
|
||||||
status = NtOpenFile (&fh, access, &attr, &io,
|
status = NtOpenFile (&fh, access, &attr, &io,
|
||||||
FILE_SHARE_VALID_FLAGS, flags);
|
FILE_SHARE_VALID_FLAGS, flags);
|
||||||
@ -457,14 +516,15 @@ unlink_nt (path_conv &pc)
|
|||||||
syscall_printf ("Opening file for delete failed, status = %p", status);
|
syscall_printf ("Opening file for delete failed, status = %p", status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (move_to_bin && !pc.isremote ())
|
|
||||||
try_to_bin (pc, fh);
|
|
||||||
|
|
||||||
/* Get rid of read-only attribute. */
|
/* Get rid of read-only attribute. */
|
||||||
if (access & FILE_WRITE_ATTRIBUTES)
|
if (access & FILE_WRITE_ATTRIBUTES)
|
||||||
NtSetAttributesFile (fh, pc.file_attributes () & ~FILE_ATTRIBUTE_READONLY);
|
NtSetAttributesFile (fh, pc.file_attributes () & ~FILE_ATTRIBUTE_READONLY);
|
||||||
|
/* Try to move to bin if a sharing violation occured. If that worked,
|
||||||
|
we're done. */
|
||||||
|
if (bin_stat == move_to_bin
|
||||||
|
&& (bin_stat = try_to_bin (pc, fh, access)) == has_been_moved)
|
||||||
|
return 0;
|
||||||
|
/* Try to set delete disposition. */
|
||||||
FILE_DISPOSITION_INFORMATION disp = { TRUE };
|
FILE_DISPOSITION_INFORMATION disp = { TRUE };
|
||||||
status = NtSetInformationFile (fh, &io, &disp, sizeof disp,
|
status = NtSetInformationFile (fh, &io, &disp, sizeof disp,
|
||||||
FileDispositionInformation);
|
FileDispositionInformation);
|
||||||
@ -475,7 +535,7 @@ unlink_nt (path_conv &pc)
|
|||||||
/* Trying to delete a hardlink to a file in use by the system in some
|
/* 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
|
way (for instance, font files) by setting the delete disposition fails
|
||||||
with STATUS_CANNOT_DELETE. Strange enough, deleting these hardlinks
|
with STATUS_CANNOT_DELETE. Strange enough, deleting these hardlinks
|
||||||
using delete-on-close semantic works.
|
using delete-on-close semantic works... most of the time.
|
||||||
|
|
||||||
Don't use delete-on-close on remote shares. If two processes
|
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
|
have open handles on a file and one of them calls unlink, the
|
||||||
@ -494,26 +554,36 @@ unlink_nt (path_conv &pc)
|
|||||||
RtlInitUnicodeString (&fname, L"");
|
RtlInitUnicodeString (&fname, L"");
|
||||||
InitializeObjectAttributes (&attr, &fname, 0, fh, NULL);
|
InitializeObjectAttributes (&attr, &fname, 0, fh, NULL);
|
||||||
status = NtOpenFile (&fh2, DELETE, &attr, &io,
|
status = NtOpenFile (&fh2, DELETE, &attr, &io,
|
||||||
move_to_bin ? FILE_SHARE_VALID_FLAGS
|
bin_stat == move_to_bin ? FILE_SHARE_VALID_FLAGS
|
||||||
: FILE_SHARE_DELETE,
|
: FILE_SHARE_DELETE,
|
||||||
flags | FILE_DELETE_ON_CLOSE);
|
flags | FILE_DELETE_ON_CLOSE);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
syscall_printf ("Setting delete-on-close failed, status = %p",
|
{
|
||||||
status);
|
syscall_printf ("Setting delete-on-close failed, status = %p",
|
||||||
|
status);
|
||||||
|
/* This is really the last chance. If it hasn't been moved
|
||||||
|
to the bin already, try it now. If moving to the bin
|
||||||
|
succeeds, we got rid of the file in some way, even if
|
||||||
|
unlinking didn't work. */
|
||||||
|
if (bin_stat == dont_move)
|
||||||
|
bin_stat = try_to_bin (pc, fh, access);
|
||||||
|
if (bin_stat == has_been_moved)
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
NtClose (fh2);
|
NtClose (fh2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((access & FILE_WRITE_ATTRIBUTES)
|
if (fh)
|
||||||
&& (!NT_SUCCESS (status) || !pc.isdir ()))
|
|
||||||
{
|
{
|
||||||
/* Restore R/O attribute to accommodate hardlinks. Don't try this
|
/* Restore R/O attribute to accommodate hardlinks. Don't try this
|
||||||
with directories! For some reason the below NtSetInformationFile
|
with directories! For some reason the below NtSetInformationFile
|
||||||
changes the delete disposition back to FALSE, at least on XP. */
|
changes the delete disposition back to FALSE, at least on XP. */
|
||||||
NtSetAttributesFile (fh, pc.file_attributes ());
|
if ((access & FILE_WRITE_ATTRIBUTES)
|
||||||
|
&& (!NT_SUCCESS (status) || !pc.isdir ()))
|
||||||
|
NtSetAttributesFile (fh, pc.file_attributes ());
|
||||||
|
NtClose (fh);
|
||||||
}
|
}
|
||||||
|
|
||||||
NtClose (fh);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user