Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2007-08-23 11:43:24 +0400
committerCorinna Vinschen <corinna@vinschen.de>2007-08-23 11:43:24 +0400
commita888c0799c04d0ce6f1cce94b12675343ee7c516 (patch)
treeabc2fba107f54dd4785feb32090cdf6a1b3218e9
parente1e4b104b6610b4e7bbf70d7759f0e08bfae6fa6 (diff)
* 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.
-rw-r--r--winsup/cygwin/ChangeLog7
-rw-r--r--winsup/cygwin/ntdll.h1
-rw-r--r--winsup/cygwin/path.cc107
3 files changed, 84 insertions, 31 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 4b0ce4eb1..06411906c 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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>
* uinfo.cc (pwdgrp::load): Use NT native functions.
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index f5c079767..b676ce797 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -15,6 +15,7 @@
#endif
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
+#define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xc000000f)
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xc0000010)
#define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xc0000013)
#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xc0000022)
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 8dcccc847..9934fa4fe 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -545,6 +545,7 @@ path_conv::set_normalized_path (const char *path_copy, bool strip_tail)
PUNICODE_STRING
get_nt_native_path (const char *path, UNICODE_STRING &upath)
{
+ upath.Length = 0;
if (path[0] == '/') /* special path w/o NT path representation. */
str2uni_cat (upath, path);
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);
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 ())
{
+ FILE_BASIC_INFORMATION fbi;
+ NTSTATUS status;
+
error = 0;
- fileattr = GetFileAttributes (suffix.path);
- if (fileattr == INVALID_FILE_ATTRIBUTES)
+ get_nt_native_path (suffix.path, upath);
+ status = NtQueryAttributesFile (&attr, &fbi);
+ if (NT_SUCCESS (status))
+ fileattr = fbi.FileAttributes;
+ else
{
- /* 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
- GetFileAttributes for a non-existant file an a Win9x share,
- GetLastError returns ERROR_INVALID_FUNCTION. Go figure!
- Also, GetFileAttributes fails with ERROR_SHARING_VIOLATION
- if the file is locked exclusively by another process, or with
- ERROR_ACCESS_DENIED if the file exists but the user has no right
- 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)
+ debug_printf ("%p = NtQueryAttributesFile (%S)", status, &upath);
+ fileattr = INVALID_FILE_ATTRIBUTES;
+
+ /* One of the inner path components is invalid. Bail out. */
+ if (status == STATUS_OBJECT_PATH_NOT_FOUND)
{
- /* This is easily converted to NT functions at one point,
- see fhandler_base::fstat_by_name. */
- WIN32_FIND_DATA data;
- HANDLE f = FindFirstFile (suffix.path, &data);
- if (f != INVALID_HANDLE_VALUE)
- {
- FindClose (f);
- fileattr = data.dwFileAttributes;
+ set_error (ENOENT);
+ 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
- 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;
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;
}