* ntdll.h (struct _OBJECT_NAME_INFORMATION): Define.

* syscalls.cc (unlink_nt): Check shared directory for being empty
	before trying to move and mark for deletion.
This commit is contained in:
Corinna Vinschen 2007-03-02 20:04:26 +00:00
parent 3532877889
commit 788e7da136
3 changed files with 65 additions and 2 deletions

View File

@ -1,3 +1,9 @@
2007-03-02 Corinna Vinschen <corinna@vinschen.de>
* ntdll.h (struct _OBJECT_NAME_INFORMATION): Define.
* syscalls.cc (unlink_nt): Check shared directory for being empty
before trying to move and mark for deletion.
2007-03-02 Corinna Vinschen <corinna@vinschen.de>
* security.cc (get_file_attribute): Avoid compiler warning.

View File

@ -79,6 +79,14 @@ typedef enum _FILE_INFORMATION_CLASS
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _FILE_NAMES_INFORMATION
{
ULONG NextEntryOffset;
ULONG FileIndex;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
typedef struct _FILE_BOTH_DIR_INFORMATION
{
ULONG NextEntryOffset;

View File

@ -283,8 +283,57 @@ unlink_nt (path_conv &win32_name, bool setattrs)
if (status == STATUS_SHARING_VIOLATION)
{
move_to_bin = true;
status = NtOpenFile (&h, DELETE, &attr, &io, FILE_SHARE_VALID_FLAGS,
flags);
if (!win32_name.isdir () || win32_name.isremote ())
status = NtOpenFile (&h, DELETE, &attr, &io, FILE_SHARE_VALID_FLAGS,
flags);
else
{
/* It's getting tricky. The directory is opened in some process,
so we're supposed to move it to the recycler and mark it for
deletion. But what if the directory is not empty? The move
will work, but the subsequent delete will fail. So we would
have to move it back. That's bad, because the directory would
be moved around which results in a temporary inconsistent state.
So, what we do here is to test if the directory is empty. If
not, we bail out with ERROR_DIR_NOT_EMTPY. The below code
tests for at least three entries in the directory, ".", "..",
and another one. Three entries means, not empty. This doesn't
work for the root directory of a drive, but the root dir can
neither be deleted, nor moved anyway. */
status = NtOpenFile (&h, DELETE | SYNCHRONIZE | FILE_LIST_DIRECTORY,
&attr, &io, FILE_SHARE_VALID_FLAGS,
flags | FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS (status))
{
const ULONG bufsiz = 3 * sizeof (FILE_NAMES_INFORMATION)
+ 3 * NAME_MAX * sizeof (WCHAR);
PFILE_NAMES_INFORMATION pfni = (PFILE_NAMES_INFORMATION)
alloca (bufsiz);
status = NtQueryDirectoryFile (h, NULL, NULL, 0, &io, pfni,
bufsiz, FileNamesInformation,
FALSE, NULL, TRUE);
if (!NT_SUCCESS (status))
{
NtClose (h);
syscall_printf ("Checking if directory is empty failed, "
"status = %p", status);
return RtlNtStatusToDosError (status);
}
int cnt = 1;
while (pfni->NextEntryOffset)
{
pfni = (PFILE_NAMES_INFORMATION)
((caddr_t) pfni + pfni->NextEntryOffset);
++cnt;
}
if (cnt > 2)
{
NtClose (h);
syscall_printf ("Directory not empty");
return ERROR_DIR_NOT_EMPTY;
}
}
}
}
if (!NT_SUCCESS (status))
{