4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-21 16:26:12 +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 debug_printf ("%p = NtQueryAttributesFile (%S)", status, &upath);
treated as non-existant. */ fileattr = INVALID_FILE_ATTRIBUTES;
DWORD win_error = GetLastError ();
if (win_error == ERROR_INVALID_FUNCTION) /* One of the inner path components is invalid. Bail out. */
win_error = ERROR_FILE_NOT_FOUND; if (status == STATUS_OBJECT_PATH_NOT_FOUND)
else if (win_error == ERROR_SHARING_VIOLATION
|| win_error == ERROR_ACCESS_DENIED)
{ {
/* This is easily converted to NT functions at one point, set_error (ENOENT);
see fhandler_base::fstat_by_name. */ break;
WIN32_FIND_DATA data; }
HANDLE f = FindFirstFile (suffix.path, &data); if (status != STATUS_OBJECT_NAME_NOT_FOUND
if (f != INVALID_HANDLE_VALUE) && status != STATUS_NO_SUCH_FILE) /* File not found on 9x share */
{ {
FindClose (f); /* The file exists, but the user can't access it for one reason
fileattr = data.dwFileAttributes; 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
fileattr = 0; {
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;
}
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;
} }