* ntdll.h (STATUS_ACCESS_DENIED): Define.
* syscalls.cc (check_dir_not_empty): New static function. (unlink_nt): Move code checking for non-empty dir to check_dir_not_empty and call check_dir_not_empty instead. (rename): Add fault handler. Check oldpath and newpath for trailing . and .. path components and return EINVAL if so. Check oldpath for being on a vrtual file system. If renaming a dir fails with STATUS_ACCESS_DENIED, check if the target dir is non-empty and return ENOTEMPTY if so.
This commit is contained in:
parent
e9ff75192a
commit
8884a1682a
|
@ -1,3 +1,15 @@
|
||||||
|
2007-08-01 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* ntdll.h (STATUS_ACCESS_DENIED): Define.
|
||||||
|
* syscalls.cc (check_dir_not_empty): New static function.
|
||||||
|
(unlink_nt): Move code checking for non-empty dir to check_dir_not_empty
|
||||||
|
and call check_dir_not_empty instead.
|
||||||
|
(rename): Add fault handler. Check oldpath and newpath for trailing
|
||||||
|
. and .. path components and return EINVAL if so. Check oldpath
|
||||||
|
for being on a vrtual file system. If renaming a dir fails with
|
||||||
|
STATUS_ACCESS_DENIED, check if the target dir is non-empty and return
|
||||||
|
ENOTEMPTY if so.
|
||||||
|
|
||||||
2007-08-01 Corinna Vinschen <corinna@vinschen.de>
|
2007-08-01 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* localtime.cc (tzsetwall): Don't set TZ.
|
* localtime.cc (tzsetwall): Don't set TZ.
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
|
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
|
||||||
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xc0000010)
|
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xc0000010)
|
||||||
#define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xc0000013)
|
#define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xc0000013)
|
||||||
|
#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xc0000022)
|
||||||
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023)
|
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023)
|
||||||
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034)
|
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034)
|
||||||
#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
|
#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
|
||||||
|
|
|
@ -228,6 +228,38 @@ try_to_bin (path_conv &win32_path, HANDLE h)
|
||||||
recycler, status);
|
recycler, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
check_dir_not_empty (HANDLE dir)
|
||||||
|
{
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
const ULONG bufsiz = 3 * sizeof (FILE_NAMES_INFORMATION)
|
||||||
|
+ 3 * NAME_MAX * sizeof (WCHAR);
|
||||||
|
PFILE_NAMES_INFORMATION pfni = (PFILE_NAMES_INFORMATION)
|
||||||
|
alloca (bufsiz);
|
||||||
|
NTSTATUS status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io, pfni,
|
||||||
|
bufsiz, FileNamesInformation,
|
||||||
|
FALSE, NULL, TRUE);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
syscall_printf ("Checking if directory is empty failed, "
|
||||||
|
"status = %p", status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
int cnt = 1;
|
||||||
|
while (pfni->NextEntryOffset)
|
||||||
|
{
|
||||||
|
pfni = (PFILE_NAMES_INFORMATION)
|
||||||
|
((caddr_t) pfni + pfni->NextEntryOffset);
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
if (cnt > 2)
|
||||||
|
{
|
||||||
|
syscall_printf ("Directory not empty");
|
||||||
|
return STATUS_DIRECTORY_NOT_EMPTY;
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
unlink_nt (path_conv &pc)
|
unlink_nt (path_conv &pc)
|
||||||
{
|
{
|
||||||
|
@ -284,33 +316,12 @@ unlink_nt (path_conv &pc)
|
||||||
flags | FILE_SYNCHRONOUS_IO_NONALERT);
|
flags | FILE_SYNCHRONOUS_IO_NONALERT);
|
||||||
if (NT_SUCCESS (status))
|
if (NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
const ULONG bufsiz = 3 * sizeof (FILE_NAMES_INFORMATION)
|
status = check_dir_not_empty (fh);
|
||||||
+ 3 * NAME_MAX * sizeof (WCHAR);
|
|
||||||
PFILE_NAMES_INFORMATION pfni = (PFILE_NAMES_INFORMATION)
|
|
||||||
alloca (bufsiz);
|
|
||||||
status = NtQueryDirectoryFile (fh, NULL, NULL, 0, &io, pfni,
|
|
||||||
bufsiz, FileNamesInformation,
|
|
||||||
FALSE, NULL, TRUE);
|
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
NtClose (fh);
|
NtClose (fh);
|
||||||
syscall_printf ("Checking if directory is empty failed, "
|
|
||||||
"status = %p", status);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
int cnt = 1;
|
|
||||||
while (pfni->NextEntryOffset)
|
|
||||||
{
|
|
||||||
pfni = (PFILE_NAMES_INFORMATION)
|
|
||||||
((caddr_t) pfni + pfni->NextEntryOffset);
|
|
||||||
++cnt;
|
|
||||||
}
|
|
||||||
if (cnt > 2)
|
|
||||||
{
|
|
||||||
NtClose (fh);
|
|
||||||
syscall_printf ("Directory not empty");
|
|
||||||
return STATUS_DIRECTORY_NOT_EMPTY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1348,6 +1359,17 @@ rename (const char *oldpath, const char *newpath)
|
||||||
ULONG size;
|
ULONG size;
|
||||||
PFILE_RENAME_INFORMATION pfri;
|
PFILE_RENAME_INFORMATION pfri;
|
||||||
|
|
||||||
|
myfault efault;
|
||||||
|
if (efault.faulted (EFAULT))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (has_dot_last_component (oldpath, true)
|
||||||
|
|| has_dot_last_component (newpath, true))
|
||||||
|
{
|
||||||
|
set_errno (EINVAL);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
oldpc.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
|
oldpc.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
|
||||||
if (oldpc.error)
|
if (oldpc.error)
|
||||||
{
|
{
|
||||||
|
@ -1359,6 +1381,11 @@ rename (const char *oldpath, const char *newpath)
|
||||||
set_errno (ENOENT);
|
set_errno (ENOENT);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (oldpc.isspecial ()) /* No renames from virtual FS */
|
||||||
|
{
|
||||||
|
set_errno (EROFS);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
olen = strlen (oldpath);
|
olen = strlen (oldpath);
|
||||||
if (oldpc.known_suffix
|
if (oldpc.known_suffix
|
||||||
&& (strcasematch (oldpath + olen - 4, ".lnk")
|
&& (strcasematch (oldpath + olen - 4, ".lnk")
|
||||||
|
@ -1371,7 +1398,7 @@ rename (const char *oldpath, const char *newpath)
|
||||||
set_errno (newpc.error);
|
set_errno (newpc.error);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (newpc.isspecial ()) /* No renames out of the FS */
|
if (newpc.isspecial ()) /* No renames to virtual FSes */
|
||||||
{
|
{
|
||||||
set_errno (EROFS);
|
set_errno (EROFS);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1509,7 +1536,22 @@ rename (const char *oldpath, const char *newpath)
|
||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
/* Check in case of STATUS_ACCESS_DENIED and pc.isdir(),
|
||||||
|
whether we tried to rename to an existing non-empty dir.
|
||||||
|
In this case we have to set errno to EEXIST. */
|
||||||
|
if (status == STATUS_ACCESS_DENIED && dstpc->isdir ()
|
||||||
|
&& NT_SUCCESS (NtOpenFile (&fh, FILE_LIST_DIRECTORY | SYNCHRONIZE,
|
||||||
|
dstpc->get_object_attr (attr, sec_none_nih),
|
||||||
|
&io, FILE_SHARE_VALID_FLAGS,
|
||||||
|
FILE_OPEN_FOR_BACKUP_INTENT
|
||||||
|
| FILE_SYNCHRONOUS_IO_NONALERT)))
|
||||||
|
{
|
||||||
|
status = check_dir_not_empty (fh);
|
||||||
|
NtClose (fh);
|
||||||
|
}
|
||||||
__seterrno_from_nt_status (status);
|
__seterrno_from_nt_status (status);
|
||||||
|
}
|
||||||
NtClose (fh);
|
NtClose (fh);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
Loading…
Reference in New Issue