4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-22 16:49:45 +08:00

* ntdll.h (STATUS_NO_SUCH_FILE): Define.

* path.cc (get_nt_native_path): Reset upath.Length to 0 on each
	invocation.
	(symlink_info::check): Use NT native functions.
This commit is contained in:
Corinna Vinschen 2007-08-23 07:43:24 +00:00
parent e1e4b104b6
commit a888c0799c
3 changed files with 85 additions and 32 deletions

View File

@ -1,3 +1,10 @@
2007-08-23 Corinna Vinschen <corinna@vinschen.de>
* ntdll.h (STATUS_NO_SUCH_FILE): Define.
* path.cc (get_nt_native_path): Reset upath.Length to 0 on each
invocation.
(symlink_info::check): Use NT native functions.
2007-08-21 Corinna Vinschen <corinna@vinschen.de> 2007-08-21 Corinna Vinschen <corinna@vinschen.de>
* uinfo.cc (pwdgrp::load): Use NT native functions. * uinfo.cc (pwdgrp::load): Use NT native functions.

View File

@ -15,6 +15,7 @@
#endif #endif
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004) #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d) #define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
#define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xc000000f)
#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_ACCESS_DENIED ((NTSTATUS) 0xc0000022)

View File

@ -545,6 +545,7 @@ path_conv::set_normalized_path (const char *path_copy, bool strip_tail)
PUNICODE_STRING PUNICODE_STRING
get_nt_native_path (const char *path, UNICODE_STRING &upath) get_nt_native_path (const char *path, UNICODE_STRING &upath)
{ {
upath.Length = 0;
if (path[0] == '/') /* special path w/o NT path representation. */ if (path[0] == '/') /* special path w/o NT path representation. */
str2uni_cat (upath, path); str2uni_cat (upath, path);
else if (path[0] != '\\') /* X:\... or NUL, etc. */ else if (path[0] != '\\') /* X:\... or NUL, etc. */
@ -3511,47 +3512,91 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
pflags &= ~(PATH_SYMLINK | PATH_LNK | PATH_REP); pflags &= ~(PATH_SYMLINK | PATH_LNK | PATH_REP);
case_clash = false; case_clash = false;
/* TODO: Temporarily do all char->UNICODE conversion here. This should
already be slightly faster than using Ascii functions. */
UNICODE_STRING upath;
OBJECT_ATTRIBUTES attr;
size_t len = (strlen (path) + 8 + 8 + 1) * sizeof (WCHAR);
RtlInitEmptyUnicodeString (&upath, (PCWSTR) alloca (len), len);
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
while (suffix.next ()) while (suffix.next ())
{ {
error = 0; FILE_BASIC_INFORMATION fbi;
fileattr = GetFileAttributes (suffix.path); NTSTATUS status;
if (fileattr == INVALID_FILE_ATTRIBUTES)
{
/* The GetFileAttributes call can fail for reasons that don't
matter, so we just return 0. For example, getting the
attributes of \\HOST will typically fail. */
debug_printf ("GetFileAttributes (%s) failed", suffix.path);
/* The above comment is not *quite* right. When calling error = 0;
GetFileAttributes for a non-existant file an a Win9x share, get_nt_native_path (suffix.path, upath);
GetLastError returns ERROR_INVALID_FUNCTION. Go figure! status = NtQueryAttributesFile (&attr, &fbi);
Also, GetFileAttributes fails with ERROR_SHARING_VIOLATION if (NT_SUCCESS (status))
if the file is locked exclusively by another process, or with fileattr = fbi.FileAttributes;
ERROR_ACCESS_DENIED if the file exists but the user has no right else
to open the file with FILE_READ_ATTRIBUTES.
If we don't special handle this here, the file is accidentally
treated as non-existant. */
DWORD win_error = GetLastError ();
if (win_error == ERROR_INVALID_FUNCTION)
win_error = ERROR_FILE_NOT_FOUND;
else if (win_error == ERROR_SHARING_VIOLATION
|| win_error == ERROR_ACCESS_DENIED)
{ {
/* This is easily converted to NT functions at one point, debug_printf ("%p = NtQueryAttributesFile (%S)", status, &upath);
see fhandler_base::fstat_by_name. */ fileattr = INVALID_FILE_ATTRIBUTES;
WIN32_FIND_DATA data;
HANDLE f = FindFirstFile (suffix.path, &data); /* One of the inner path components is invalid. Bail out. */
if (f != INVALID_HANDLE_VALUE) if (status == STATUS_OBJECT_PATH_NOT_FOUND)
{ {
FindClose (f); set_error (ENOENT);
fileattr = data.dwFileAttributes; break;
}
if (status != STATUS_OBJECT_NAME_NOT_FOUND
&& status != STATUS_NO_SUCH_FILE) /* File not found on 9x share */
{
/* The file exists, but the user can't access it for one reason
or the other. To get the file attributes we try to access the
information by opening the parent directory and getting the
file attributes using a matching NtQueryDirectoryFile call. */
UNICODE_STRING dirname, basename;
OBJECT_ATTRIBUTES dattr;
HANDLE dir;
IO_STATUS_BLOCK io;
FILE_DIRECTORY_INFORMATION fdi;
RtlSplitUnicodePath (&upath, &dirname, &basename);
InitializeObjectAttributes (&dattr, &dirname,
OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
&dattr, &io, FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_DIRECTORY_FILE);
if (!NT_SUCCESS (status))
{
debug_printf ("%p = NtOpenFile(%S)", status, &dirname);
fileattr = 0;
} }
else else
{
status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io,
&fdi, sizeof fdi,
FileDirectoryInformation,
TRUE, &basename, TRUE);
NtClose (dir);
/* Per MSDN, ZwQueryDirectoryFile allows to specify a buffer
which only fits the static parts of the structure (without
filename that is) in the first call. The buffer actually
contains valid data, even though ZwQueryDirectoryFile
returned STATUS_BUFFER_OVERFLOW.
Please note that this doesn't work for the info class
FileIdBothDirectoryInformation, unfortunately, so we don't
use this technique in fhandler_base::fstat_by_name, */
if (!NT_SUCCESS (status) && status != STATUS_BUFFER_OVERFLOW)
{
debug_printf ("%p = NtQueryDirectoryFile(%S)",
status, &dirname);
fileattr = 0; fileattr = 0;
}
else
fileattr = fdi.FileAttributes;
}
ext_tacked_on = !!*ext_here; ext_tacked_on = !!*ext_here;
goto file_not_symlink; goto file_not_symlink;
} }
if (set_error (geterrno_from_win_error (win_error, EACCES))) if (set_error (geterrno_from_win_error
(RtlNtStatusToDosError (status), EACCES)))
continue; continue;
} }