mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-31 11:30:56 +08:00
* fhandler_disk_file.cc (fhandler_disk_file::link): Use FILE_ANY_ACCESS.
(fhandler_base::utimes_fs): Fix white space. (fhandler_disk_file::lock): Remove 9x blurb from comment. (fhandler_disk_file::mkdir): Use NtCreateFile/NtClose instead of CreateDirectoryA. (fhandler_disk_file::rmdir): Accommodate changes to unlink_nt. Simplify post-delete SMB-related tests. Use NtQueryAttributesFile instead of GetFileAttributes. * ntdll.h (STATUS_DIRECTORY_NOT_EMPTY): Define. (NtQueryAttributesFile): Declare. * syscalls.cc (unlink_nt): Return NTSTATUS. Drop setattrs parameter. Never use FILE_DELETE_ON_CLOSE, always use NtSetInformationFile(FileDispositionInformation) instead. Check for R/O attributes and open file with FILE_WRITE_ATTRIBUTES access if any of them are set. Remove R/O attributes before marking for delete if necessary. Revert them afterwards if necessary. (unlink): Accommodate changes to unlink_nt.
This commit is contained in:
parent
4368984a7b
commit
ed7ec849f6
@ -1,3 +1,23 @@
|
|||||||
|
2007-07-29 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* fhandler_disk_file.cc (fhandler_disk_file::link): Use FILE_ANY_ACCESS.
|
||||||
|
(fhandler_base::utimes_fs): Fix white space.
|
||||||
|
(fhandler_disk_file::lock): Remove 9x blurb from comment.
|
||||||
|
(fhandler_disk_file::mkdir): Use NtCreateFile/NtClose instead of
|
||||||
|
CreateDirectoryA.
|
||||||
|
(fhandler_disk_file::rmdir): Accommodate changes to unlink_nt.
|
||||||
|
Simplify post-delete SMB-related tests. Use NtQueryAttributesFile
|
||||||
|
instead of GetFileAttributes.
|
||||||
|
* ntdll.h (STATUS_DIRECTORY_NOT_EMPTY): Define.
|
||||||
|
(NtQueryAttributesFile): Declare.
|
||||||
|
* syscalls.cc (unlink_nt): Return NTSTATUS. Drop setattrs parameter.
|
||||||
|
Never use FILE_DELETE_ON_CLOSE, always use
|
||||||
|
NtSetInformationFile(FileDispositionInformation) instead.
|
||||||
|
Check for R/O attributes and open file with FILE_WRITE_ATTRIBUTES
|
||||||
|
access if any of them are set. Remove R/O attributes before
|
||||||
|
marking for delete if necessary. Revert them afterwards if necessary.
|
||||||
|
(unlink): Accommodate changes to unlink_nt.
|
||||||
|
|
||||||
2007-07-29 Corinna Vinschen <corinna@vinschen.de>
|
2007-07-29 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* fhandler_disk_file.cc: Use get_handle throughout.
|
* fhandler_disk_file.cc: Use get_handle throughout.
|
||||||
|
@ -1094,7 +1094,8 @@ fhandler_disk_file::link (const char *newpath)
|
|||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
status = NtOpenFile (&fh, 0, pc.get_object_attr (attr, sec_none_nih), &io,
|
status = NtOpenFile (&fh, FILE_ANY_ACCESS,
|
||||||
|
pc.get_object_attr (attr, sec_none_nih), &io,
|
||||||
FILE_SHARE_VALID_FLAGS,
|
FILE_SHARE_VALID_FLAGS,
|
||||||
FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT);
|
FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
@ -1182,7 +1183,7 @@ fhandler_base::utimes_fs (const struct timeval *tvp)
|
|||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
FILE_BASIC_INFORMATION fbi;
|
FILE_BASIC_INFORMATION fbi;
|
||||||
fbi.CreationTime.QuadPart = 0LL;
|
fbi.CreationTime.QuadPart = 0LL;
|
||||||
fbi.LastAccessTime= lastaccess;
|
fbi.LastAccessTime = lastaccess;
|
||||||
fbi.LastWriteTime = lastwrite;
|
fbi.LastWriteTime = lastwrite;
|
||||||
fbi.ChangeTime.QuadPart = 0LL;
|
fbi.ChangeTime.QuadPart = 0LL;
|
||||||
fbi.FileAttributes = 0;
|
fbi.FileAttributes = 0;
|
||||||
@ -1318,11 +1319,7 @@ fhandler_disk_file::pwrite (void *buf, size_t count, _off64_t offset)
|
|||||||
/* FIXME: The correct way to do this to get POSIX locking semantics is to
|
/* FIXME: The correct way to do this to get POSIX locking semantics is to
|
||||||
keep a linked list of posix lock requests and map them into Win32 locks.
|
keep a linked list of posix lock requests and map them into Win32 locks.
|
||||||
he problem is that Win32 does not deal correctly with overlapping lock
|
he problem is that Win32 does not deal correctly with overlapping lock
|
||||||
requests. Also another pain is that Win95 doesn't do non-blocking or
|
requests. */
|
||||||
non-exclusive locks at all. For '95 just convert all lock requests into
|
|
||||||
blocking,exclusive locks. This shouldn't break many apps but denying all
|
|
||||||
locking would. For now just convert to Win32 locks and hope for
|
|
||||||
the best. */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_disk_file::lock (int cmd, struct __flock64 *fl)
|
fhandler_disk_file::lock (int cmd, struct __flock64 *fl)
|
||||||
@ -1471,17 +1468,31 @@ fhandler_disk_file::mkdir (mode_t mode)
|
|||||||
set_security_attribute (S_IFDIR | ((mode & 07777) & ~cygheap->umask),
|
set_security_attribute (S_IFDIR | ((mode & 07777) & ~cygheap->umask),
|
||||||
&sa, sd);
|
&sa, sd);
|
||||||
|
|
||||||
if (CreateDirectoryA (get_win32_name (), &sa))
|
NTSTATUS status;
|
||||||
{
|
HANDLE dir;
|
||||||
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
ULONG fattr = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
#ifdef HIDDEN_DOT_FILES
|
#ifdef HIDDEN_DOT_FILES
|
||||||
char *c = strrchr (real_dir.get_win32 (), '\\');
|
UNICODE_STRING basename;
|
||||||
if ((c && c[1] == '.') || *get_win32_name () == '.')
|
|
||||||
SetFileAttributes (get_win32_name (), FILE_ATTRIBUTE_HIDDEN);
|
RtlSplitUnicodePath (pc.get_nt_native_path (), NULL, &basename);
|
||||||
|
if (basename.Buffer[0] == L'.')
|
||||||
|
fattr |= FILE_ATTRIBUTE_HIDDEN;
|
||||||
#endif
|
#endif
|
||||||
|
status = NtCreateFile (&dir, FILE_LIST_DIRECTORY | SYNCHRONIZE,
|
||||||
|
pc.get_object_attr (attr, sa), &io, NULL,
|
||||||
|
fattr, FILE_SHARE_VALID_FLAGS, FILE_CREATE,
|
||||||
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
|
||||||
|
| FILE_OPEN_FOR_BACKUP_INTENT,
|
||||||
|
NULL, 0);
|
||||||
|
if (NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
NtClose (dir);
|
||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
__seterrno ();
|
__seterrno_from_nt_status (status);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -1489,47 +1500,43 @@ fhandler_disk_file::mkdir (mode_t mode)
|
|||||||
int
|
int
|
||||||
fhandler_disk_file::rmdir ()
|
fhandler_disk_file::rmdir ()
|
||||||
{
|
{
|
||||||
extern DWORD unlink_nt (path_conv &win32_name, bool setattrs);
|
extern NTSTATUS unlink_nt (path_conv &pc);
|
||||||
|
|
||||||
int res = -1;
|
|
||||||
|
|
||||||
if (!pc.isdir ())
|
if (!pc.isdir ())
|
||||||
{
|
{
|
||||||
set_errno (ENOTDIR);
|
set_errno (ENOTDIR);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Even own directories can't be removed if R/O attribute is set. */
|
if (!pc.exists ())
|
||||||
if (pc.has_attribute (FILE_ATTRIBUTE_READONLY))
|
|
||||||
SetFileAttributes (get_win32_name (),
|
|
||||||
(DWORD) pc & ~FILE_ATTRIBUTE_READONLY);
|
|
||||||
|
|
||||||
DWORD err, att = 0;
|
|
||||||
|
|
||||||
int rc = !(err = unlink_nt (pc, pc.has_attribute (FILE_ATTRIBUTE_READONLY)));
|
|
||||||
if (err)
|
|
||||||
SetLastError (err);
|
|
||||||
|
|
||||||
if (isremote () && exists ())
|
|
||||||
att = GetFileAttributes (get_win32_name ());
|
|
||||||
|
|
||||||
/* Sometimes smb indicates failure when it really succeeds, so check for
|
|
||||||
this case specifically. */
|
|
||||||
if (rc || att == INVALID_FILE_ATTRIBUTES)
|
|
||||||
{
|
{
|
||||||
/* RemoveDirectory on a samba drive doesn't return an error if the
|
set_errno (ENOENT);
|
||||||
directory can't be removed because it's not empty. Checking for
|
return -1;
|
||||||
existence afterwards keeps us informed about success. */
|
|
||||||
if (!isremote () || att == INVALID_FILE_ATTRIBUTES)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err = ERROR_DIR_NOT_EMPTY;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
err = GetLastError ();
|
|
||||||
|
|
||||||
__seterrno_from_win_error (err);
|
NTSTATUS status = unlink_nt (pc);
|
||||||
|
|
||||||
return res;
|
/* Check for existence of remote dirs after trying to delete them.
|
||||||
|
Two reasons:
|
||||||
|
- Sometimes SMB indicates failure when it really succeeds.
|
||||||
|
- Removeing a directory on a samba drive doesn't return an error if the
|
||||||
|
directory can't be removed because it's not empty. */
|
||||||
|
if (isremote ())
|
||||||
|
{
|
||||||
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
FILE_BASIC_INFORMATION fbi;
|
||||||
|
|
||||||
|
if (NT_SUCCESS (NtQueryAttributesFile
|
||||||
|
(pc.get_object_attr (attr, sec_none_nih), &fbi)))
|
||||||
|
status = STATUS_DIRECTORY_NOT_EMPTY;
|
||||||
|
else
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
__seterrno_from_nt_status (status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the minimal number of entries which fit into the readdir cache.
|
/* This is the minimal number of entries which fit into the readdir cache.
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056)
|
#define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056)
|
||||||
#define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1)
|
#define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1)
|
||||||
#define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xc00000bb)
|
#define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xc00000bb)
|
||||||
|
#define STATUS_DIRECTORY_NOT_EMPTY ((NTSTATUS) 0xc0000101)
|
||||||
#define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106)
|
#define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106)
|
||||||
#define STATUS_INVALID_LEVEL ((NTSTATUS) 0xc0000148)
|
#define STATUS_INVALID_LEVEL ((NTSTATUS) 0xc0000148)
|
||||||
#define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006)
|
#define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006)
|
||||||
@ -752,6 +753,8 @@ extern "C"
|
|||||||
BOOLEAN, PULONG, PULONG);
|
BOOLEAN, PULONG, PULONG);
|
||||||
NTSTATUS NTAPI NtQueryEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
|
NTSTATUS NTAPI NtQueryEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
|
||||||
BOOLEAN, PVOID, ULONG, PULONG, BOOLEAN);
|
BOOLEAN, PVOID, ULONG, PULONG, BOOLEAN);
|
||||||
|
NTSTATUS NTAPI NtQueryAttributesFile (POBJECT_ATTRIBUTES,
|
||||||
|
PFILE_BASIC_INFORMATION);
|
||||||
NTSTATUS NTAPI NtQueryFullAttributesFile (POBJECT_ATTRIBUTES,
|
NTSTATUS NTAPI NtQueryFullAttributesFile (POBJECT_ATTRIBUTES,
|
||||||
PFILE_NETWORK_OPEN_INFORMATION);
|
PFILE_NETWORK_OPEN_INFORMATION);
|
||||||
NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID,
|
NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID,
|
||||||
|
@ -228,43 +228,31 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
|||||||
recycler, status);
|
recycler, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
NTSTATUS
|
||||||
unlink_nt (path_conv &win32_name, bool setattrs)
|
unlink_nt (path_conv &pc)
|
||||||
{
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
HANDLE fh;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
NTSTATUS status;
|
FILE_BASIC_INFORMATION fbi;
|
||||||
HANDLE h;
|
|
||||||
|
ACCESS_MASK access = DELETE;
|
||||||
|
/* If one of the R/O attributes is set, we have to open the file with
|
||||||
|
FILE_WRITE_ATTRIBUTES to be able to remove these flags before trying
|
||||||
|
to delete it. */
|
||||||
|
if (pc.file_attributes () & (FILE_ATTRIBUTE_READONLY
|
||||||
|
| FILE_ATTRIBUTE_SYSTEM
|
||||||
|
| FILE_ATTRIBUTE_HIDDEN))
|
||||||
|
access |= FILE_WRITE_ATTRIBUTES;
|
||||||
|
|
||||||
ULONG flags = FILE_OPEN_FOR_BACKUP_INTENT;
|
ULONG flags = FILE_OPEN_FOR_BACKUP_INTENT;
|
||||||
/* Don't open directories with "delete on close", because the NT internal
|
|
||||||
semantic is apparently different from the file semantic. If a directory
|
|
||||||
is opened "delete on close", the rename operation in try_to_bin fails
|
|
||||||
with STATUS_ACCESS_DENIED. So directories must be deleted using
|
|
||||||
NtSetInformationFile, class FileDispositionInformation, which works fine.
|
|
||||||
|
|
||||||
Correction, moving a directory opened with delete-on-close fails ONLY
|
|
||||||
on XP. Note to myself: Never take anything for granted on Windows!
|
|
||||||
|
|
||||||
Don't try "delete on close" if the file is on a remote share. If two
|
|
||||||
processes have open handles on a file and one of them calls unlink, then
|
|
||||||
it happens that the file is removed from the remote share even though the
|
|
||||||
other process still has an open handle. This other process than gets
|
|
||||||
Win32 error 59, ERROR_UNEXP_NET_ERR when trying to access the file. That
|
|
||||||
does not happen when using NtSetInformationFile, class
|
|
||||||
FileDispositionInformation, which nicely succeeds but still, the file is
|
|
||||||
available for the other process. Microsoft KB 837665 describes this
|
|
||||||
problem as a bug in 2K3, but I have reproduced it on shares on Samba
|
|
||||||
2.2.8, Samba 3.0.2, NT4SP6, XP64SP1 and 2K3 and in all cases, DeleteFile
|
|
||||||
works, "delete on close" does not. */
|
|
||||||
if (!win32_name.isdir () && !win32_name.isremote ())
|
|
||||||
flags |= FILE_DELETE_ON_CLOSE;
|
|
||||||
/* Add the reparse point flag to native symlinks, otherwise we remove the
|
/* Add the reparse point flag to native symlinks, otherwise we remove the
|
||||||
target, not the symlink. */
|
target, not the symlink. */
|
||||||
if (win32_name.is_rep_symlink ())
|
if (pc.is_rep_symlink ())
|
||||||
flags |= FILE_OPEN_REPARSE_POINT;
|
flags |= FILE_OPEN_REPARSE_POINT;
|
||||||
|
|
||||||
win32_name.get_object_attr (attr, sec_none_nih);
|
pc.get_object_attr (attr, sec_none_nih);
|
||||||
/* First try to open the file with sharing not allowed. If the file
|
/* 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
|
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
|
file has to be moved to the recycle bin so that it actually disappears
|
||||||
@ -272,13 +260,13 @@ unlink_nt (path_conv &win32_name, bool setattrs)
|
|||||||
doesn't fail, the file is not in use and by simply closing the handle
|
doesn't fail, the file is not in use and by simply closing the handle
|
||||||
the file will disappear. */
|
the file will disappear. */
|
||||||
bool move_to_bin = false;
|
bool move_to_bin = false;
|
||||||
status = NtOpenFile (&h, DELETE, &attr, &io, 0, flags);
|
status = NtOpenFile (&fh, access, &attr, &io, 0, flags);
|
||||||
if (status == STATUS_SHARING_VIOLATION)
|
if (status == STATUS_SHARING_VIOLATION)
|
||||||
{
|
{
|
||||||
move_to_bin = true;
|
move_to_bin = true;
|
||||||
if (!win32_name.isdir () || win32_name.isremote ())
|
if (!pc.isdir () || pc.isremote ())
|
||||||
status = NtOpenFile (&h, DELETE, &attr, &io, FILE_SHARE_VALID_FLAGS,
|
status = NtOpenFile (&fh, access, &attr, &io,
|
||||||
flags);
|
FILE_SHARE_VALID_FLAGS, flags);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* It's getting tricky. The directory is opened in some process,
|
/* It's getting tricky. The directory is opened in some process,
|
||||||
@ -293,7 +281,7 @@ unlink_nt (path_conv &win32_name, bool setattrs)
|
|||||||
and another one. Three entries means, not empty. This doesn't
|
and another one. Three entries means, not empty. This doesn't
|
||||||
work for the root directory of a drive, but the root dir can
|
work for the root directory of a drive, but the root dir can
|
||||||
neither be deleted, nor moved anyway. */
|
neither be deleted, nor moved anyway. */
|
||||||
status = NtOpenFile (&h, DELETE | SYNCHRONIZE | FILE_LIST_DIRECTORY,
|
status = NtOpenFile (&fh, access | FILE_LIST_DIRECTORY | SYNCHRONIZE,
|
||||||
&attr, &io, FILE_SHARE_VALID_FLAGS,
|
&attr, &io, FILE_SHARE_VALID_FLAGS,
|
||||||
flags | FILE_SYNCHRONOUS_IO_NONALERT);
|
flags | FILE_SYNCHRONOUS_IO_NONALERT);
|
||||||
if (NT_SUCCESS (status))
|
if (NT_SUCCESS (status))
|
||||||
@ -302,15 +290,15 @@ unlink_nt (path_conv &win32_name, bool setattrs)
|
|||||||
+ 3 * NAME_MAX * sizeof (WCHAR);
|
+ 3 * NAME_MAX * sizeof (WCHAR);
|
||||||
PFILE_NAMES_INFORMATION pfni = (PFILE_NAMES_INFORMATION)
|
PFILE_NAMES_INFORMATION pfni = (PFILE_NAMES_INFORMATION)
|
||||||
alloca (bufsiz);
|
alloca (bufsiz);
|
||||||
status = NtQueryDirectoryFile (h, NULL, NULL, 0, &io, pfni,
|
status = NtQueryDirectoryFile (fh, NULL, NULL, 0, &io, pfni,
|
||||||
bufsiz, FileNamesInformation,
|
bufsiz, FileNamesInformation,
|
||||||
FALSE, NULL, TRUE);
|
FALSE, NULL, TRUE);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
NtClose (h);
|
NtClose (fh);
|
||||||
syscall_printf ("Checking if directory is empty failed, "
|
syscall_printf ("Checking if directory is empty failed, "
|
||||||
"status = %p", status);
|
"status = %p", status);
|
||||||
return RtlNtStatusToDosError (status);
|
return status;
|
||||||
}
|
}
|
||||||
int cnt = 1;
|
int cnt = 1;
|
||||||
while (pfni->NextEntryOffset)
|
while (pfni->NextEntryOffset)
|
||||||
@ -321,9 +309,9 @@ unlink_nt (path_conv &win32_name, bool setattrs)
|
|||||||
}
|
}
|
||||||
if (cnt > 2)
|
if (cnt > 2)
|
||||||
{
|
{
|
||||||
NtClose (h);
|
NtClose (fh);
|
||||||
syscall_printf ("Directory not empty");
|
syscall_printf ("Directory not empty");
|
||||||
return ERROR_DIR_NOT_EMPTY;
|
return STATUS_DIRECTORY_NOT_EMPTY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,46 +320,46 @@ unlink_nt (path_conv &win32_name, bool setattrs)
|
|||||||
{
|
{
|
||||||
if (status == STATUS_DELETE_PENDING)
|
if (status == STATUS_DELETE_PENDING)
|
||||||
{
|
{
|
||||||
syscall_printf ("Delete already pending, status = %p", status);
|
syscall_printf ("Delete already pending");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
syscall_printf ("Opening file for delete failed, status = %p", status);
|
syscall_printf ("Opening file for delete failed, status = %p", status);
|
||||||
return RtlNtStatusToDosError (status);
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setattrs)
|
if (move_to_bin && !pc.isremote ())
|
||||||
SetFileAttributes (win32_name, (DWORD) win32_name);
|
try_to_bin (pc, fh);
|
||||||
|
|
||||||
if (move_to_bin && !win32_name.isremote ())
|
/* Get rid of read-only attributes. */
|
||||||
try_to_bin (win32_name, h);
|
if (access & FILE_WRITE_ATTRIBUTES)
|
||||||
|
|
||||||
DWORD lasterr = 0;
|
|
||||||
|
|
||||||
if (win32_name.isdir () || win32_name.isremote ())
|
|
||||||
{
|
{
|
||||||
FILE_DISPOSITION_INFORMATION disp = { TRUE };
|
FILE_BASIC_INFORMATION fbi;
|
||||||
status = NtSetInformationFile (h, &io, &disp, sizeof disp,
|
fbi.CreationTime.QuadPart = fbi.LastAccessTime.QuadPart =
|
||||||
FileDispositionInformation);
|
fbi.LastWriteTime.QuadPart = fbi.ChangeTime.QuadPart = 0LL;
|
||||||
if (!NT_SUCCESS (status))
|
fbi.FileAttributes = pc.file_attributes ()
|
||||||
{
|
& ~(FILE_ATTRIBUTE_READONLY
|
||||||
syscall_printf ("Setting delete disposition failed, status = %p",
|
| FILE_ATTRIBUTE_SYSTEM
|
||||||
status);
|
| FILE_ATTRIBUTE_HIDDEN);
|
||||||
lasterr = RtlNtStatusToDosError (status);
|
NtSetInformationFile (fh, &io, &fbi, sizeof fbi, FileBasicInformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE_DISPOSITION_INFORMATION disp = { TRUE };
|
||||||
|
status = NtSetInformationFile (fh, &io, &disp, sizeof disp,
|
||||||
|
FileDispositionInformation);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
syscall_printf ("Setting delete disposition failed, status = %p", status);
|
||||||
|
/* Restore R/O attributes. */
|
||||||
|
if (access & FILE_WRITE_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
fbi.FileAttributes = pc.file_attributes ();
|
||||||
|
NtSetInformationFile (fh, &io, &fbi, sizeof fbi,
|
||||||
|
FileBasicInformation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status = NtClose (h);
|
NtClose (fh);
|
||||||
if (!NT_SUCCESS (status))
|
return status;
|
||||||
{
|
|
||||||
/* Maybe that's really paranoid, but not being able to close the file
|
|
||||||
also means that deleting fails. */
|
|
||||||
syscall_printf ("%p = NtClose (%p)", status, h);
|
|
||||||
if (!lasterr)
|
|
||||||
lasterr = RtlNtStatusToDosError (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
syscall_printf ("Deleting succeeded");
|
|
||||||
return lasterr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int
|
extern "C" int
|
||||||
@ -379,7 +367,7 @@ unlink (const char *ourname)
|
|||||||
{
|
{
|
||||||
int res = -1;
|
int res = -1;
|
||||||
DWORD devn;
|
DWORD devn;
|
||||||
DWORD lasterr;
|
NTSTATUS status;
|
||||||
|
|
||||||
path_conv win32_name (ourname, PC_SYM_NOFOLLOW,
|
path_conv win32_name (ourname, PC_SYM_NOFOLLOW,
|
||||||
transparent_exe ? stat_suffixes : NULL);
|
transparent_exe ? stat_suffixes : NULL);
|
||||||
@ -412,30 +400,13 @@ unlink (const char *ourname)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setattrs;
|
status = unlink_nt (win32_name);
|
||||||
if (!((DWORD) win32_name & (FILE_ATTRIBUTE_READONLY
|
if (NT_SUCCESS (status))
|
||||||
| FILE_ATTRIBUTE_SYSTEM
|
|
||||||
| FILE_ATTRIBUTE_HIDDEN)))
|
|
||||||
setattrs = false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Allow us to delete even if read-only */
|
|
||||||
setattrs = SetFileAttributes (win32_name,
|
|
||||||
(DWORD) win32_name
|
|
||||||
& ~(FILE_ATTRIBUTE_READONLY
|
|
||||||
| FILE_ATTRIBUTE_SYSTEM
|
|
||||||
| FILE_ATTRIBUTE_HIDDEN));
|
|
||||||
}
|
|
||||||
|
|
||||||
lasterr = unlink_nt (win32_name, setattrs);
|
|
||||||
if (!lasterr)
|
|
||||||
res = 0;
|
res = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetFileAttributes (win32_name, (DWORD) win32_name);
|
|
||||||
|
|
||||||
/* FIXME: Can we get rid of the delqueue now? */
|
/* FIXME: Can we get rid of the delqueue now? */
|
||||||
if (lasterr == ERROR_SHARING_VIOLATION)
|
if (status == STATUS_SHARING_VIOLATION)
|
||||||
{
|
{
|
||||||
/* Add file to the "to be deleted" queue. */
|
/* Add file to the "to be deleted" queue. */
|
||||||
syscall_printf ("Sharing violation, couldn't delete file");
|
syscall_printf ("Sharing violation, couldn't delete file");
|
||||||
@ -443,7 +414,7 @@ unlink (const char *ourname)
|
|||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
__seterrno_from_win_error (lasterr);
|
__seterrno_from_nt_status (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@ -1467,7 +1438,7 @@ rename (const char *oldpath, const char *newpath)
|
|||||||
else if (MoveFileEx (real_old.get_win32 (), real_new.get_win32 (),
|
else if (MoveFileEx (real_old.get_win32 (), real_new.get_win32 (),
|
||||||
MOVEFILE_REPLACE_EXISTING))
|
MOVEFILE_REPLACE_EXISTING))
|
||||||
res = 0;
|
res = 0;
|
||||||
else if ((lasterr = unlink_nt (real_new, false)))
|
else if ((lasterr = unlink_nt (real_new)))
|
||||||
{
|
{
|
||||||
SetLastError (lasterr);
|
SetLastError (lasterr);
|
||||||
syscall_printf ("Can't remove target file/dir, %E");
|
syscall_printf ("Can't remove target file/dir, %E");
|
||||||
@ -1503,7 +1474,7 @@ done:
|
|||||||
if (lnk_suffix)
|
if (lnk_suffix)
|
||||||
{
|
{
|
||||||
*lnk_suffix = '.';
|
*lnk_suffix = '.';
|
||||||
unlink_nt (real_new, false);
|
unlink_nt (real_new);
|
||||||
}
|
}
|
||||||
/* Shortcut hack, No. 3, part 2 */
|
/* Shortcut hack, No. 3, part 2 */
|
||||||
/* If a file with the given name exists, it must be deleted after the
|
/* If a file with the given name exists, it must be deleted after the
|
||||||
@ -1515,7 +1486,7 @@ done:
|
|||||||
{
|
{
|
||||||
lnk_suffix = strrchr (real_new.get_win32 (), '.');
|
lnk_suffix = strrchr (real_new.get_win32 (), '.');
|
||||||
*lnk_suffix = '\0';
|
*lnk_suffix = '\0';
|
||||||
unlink_nt (real_new, false);
|
unlink_nt (real_new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user