From 855e63eb4b1ea80dd892309e2bcd214626a90611 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 16 Aug 2007 10:41:45 +0000 Subject: [PATCH] * ntdll.h (RtlCreateUnicodeStringFromAsciiz): Fix declaration. (RtlUpcaseUnicodeChar): Declare. * path.cc (hash_path_name): Split into three functions, taking the path as char *, PWCSTR, or PUNICODE_STRING. Move implementation into PUNICODE_STRING-based function. Drop old drive-relative path consideration. * winsup.h (iswdirsep): Like isdirsep but for WCHARs. (isabspath_u): Like isabspath, for PUNICODE_STRINGs. (iswabspath): Like isabspath, for PWCHARs. (hash_path_name): Add new declarations. --- winsup/cygwin/ChangeLog | 13 +++++++ winsup/cygwin/ntdll.h | 3 +- winsup/cygwin/path.cc | 78 ++++++++++++++++++----------------------- winsup/cygwin/winsup.h | 20 +++++++++++ 4 files changed, 69 insertions(+), 45 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 5b9ba01ff..9c953eb46 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,16 @@ +2007-08-16 Corinna Vinschen + + * ntdll.h (RtlCreateUnicodeStringFromAsciiz): Fix declaration. + (RtlUpcaseUnicodeChar): Declare. + * path.cc (hash_path_name): Split into three functions, taking + the path as char *, PWCSTR, or PUNICODE_STRING. Move implementation + into PUNICODE_STRING-based function. Drop old drive-relative path + consideration. + * winsup.h (iswdirsep): Like isdirsep but for WCHARs. + (isabspath_u): Like isabspath, for PUNICODE_STRINGs. + (iswabspath): Like isabspath, for PWCHARs. + (hash_path_name): Add new declarations. + 2007-08-15 Corinna Vinschen * path.cc (get_nt_native_path): Allow to convert special paths which diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 467c9e496..7b8c556b9 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -833,7 +833,7 @@ extern "C" BOOLEAN); NTSTATUS NTAPI RtlConvertSidToUnicodeString (PUNICODE_STRING, PSID, BOOLEAN); VOID NTAPI RtlCopyUnicodeString (PUNICODE_STRING, PUNICODE_STRING); - ULONG WINAPI RtlCreateUnicodeStringFromAsciiz (PUNICODE_STRING, PCSTR); + BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz (PUNICODE_STRING, PCSTR); BOOLEAN NTAPI RtlEqualUnicodeString (PUNICODE_STRING, PUNICODE_STRING, BOOLEAN); VOID NTAPI RtlFreeAnsiString (PANSI_STRING); @@ -853,6 +853,7 @@ extern "C" BOOLEAN); NTSTATUS NTAPI RtlUnicodeStringToOemString (PANSI_STRING, PUNICODE_STRING, BOOLEAN); + WCHAR NTAPI RtlUpcaseUnicodeChar (WCHAR); /* A few Rtl functions are either actually macros, or they just don't exist even though they would be a big help. We implement them here, diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 9b20322b8..5a0bc903b 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -80,6 +80,7 @@ details. */ #include #include #include +#include bool dos_file_warning = true; static int normalize_win32_path (const char *, char *, char *&); @@ -3740,62 +3741,51 @@ readlink (const char *path, char *buf, int buflen) done during the opendir call and the hash or the filename within the directory. FIXME: Not bullet-proof. */ /* Cygwin internal */ - __ino64_t __stdcall -hash_path_name (__ino64_t hash, const char *name) +hash_path_name (__ino64_t hash, PUNICODE_STRING name) { - if (!*name) + if (name->Length == 0) return hash; - /* Perform some initial permutations on the pathname if this is - not "seeded" */ - if (!hash) + /* Fill out the hashed path name with the current working directory if + this is not an absolute path and there is no pre-specified hash value. + Otherwise the inodes same will differ depending on whether a file is + referenced with an absolute value or relatively. */ + if (!hash && !isabspath_u (name)) { - /* Simplistic handling of drives. If there is a drive specified, - make sure that the initial letter is upper case. If there is - no \ after the ':' assume access through the root directory - of that drive. - FIXME: Should really honor MS-Windows convention of using - the environment to track current directory on various drives. */ - if (name[1] == ':') - { - char *nn, *newname = (char *) alloca (strlen (name) + 2); - nn = newname; - *nn = isupper (*name) ? cyg_tolower (*name) : *name; - *++nn = ':'; - name += 2; - if (*name != '\\') - *++nn = '\\'; - strcpy (++nn, name); - name = newname; - goto hashit; - } - - /* Fill out the hashed path name with the current working directory if - this is not an absolute path and there is no pre-specified hash value. - Otherwise the inodes same will differ depending on whether a file is - referenced with an absolute value or relatively. */ - - if (!hash && !isabspath (name)) - { - hash = cygheap->cwd.get_hash (); - if (name[0] == '.' && name[1] == '\0') - return hash; - hash = '\\' + (hash << 6) + (hash << 16) - hash; - } + hash = cygheap->cwd.get_hash (); + if (name->Length == sizeof (WCHAR) && name->Buffer[0] == L'.') + return hash; + hash = L'\\' + (hash << 6) + (hash << 16) - hash; } hashit: /* Build up hash. Name is already normalized */ - do - { - int ch = cyg_tolower (*name); - hash = ch + (hash << 6) + (hash << 16) - hash; - } - while (*++name != '\0'); + USHORT len = name->Length / sizeof (WCHAR); + for (USHORT idx = 0; idx < len; ++idx) + hash = RtlUpcaseUnicodeChar (name->Buffer[idx]) + + (hash << 6) + (hash << 16) - hash; return hash; } +__ino64_t __stdcall +hash_path_name (__ino64_t hash, PCWSTR name) +{ + UNICODE_STRING uname; + RtlInitUnicodeString (&uname, name); + return hash_path_name (hash, &uname); +} + +__ino64_t __stdcall +hash_path_name (__ino64_t hash, const char *name) +{ + UNICODE_STRING uname; + RtlCreateUnicodeStringFromAsciiz (&uname, name); + __ino64_t ret = hash_path_name (hash, &uname); + RtlFreeUnicodeString (&uname); + return ret; +} + char * getcwd (char *buf, size_t ulen) { diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 2d099304b..9e949e846 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -143,6 +143,12 @@ extern HANDLE tty_mutex; type flag () const { return (type) status.flag; } /* Used when treating / and \ as equivalent. */ +#define iswdirsep(ch) \ + ({ \ + WCHAR __c = (ch); \ + ((__c) == L'/' || (__c) == L'\\'); \ + }) + #define isdirsep(ch) \ ({ \ char __c = (ch); \ @@ -160,6 +166,18 @@ extern int __api_fatal_exit_val; #undef issep #define issep(ch) (strchr (" \t\n\r", (ch)) != NULL) +/* Every path beginning with / or \, as well as every path being X: + or starting with X:/ or X:\ */ +#define isabspath_u(p) \ + ((p)->Length && \ + (iswdirsep ((p)->Buffer[0]) || \ + ((p)->Length > sizeof (WCHAR) && iswalpha ((p)->Buffer[0]) \ + && (p)->Buffer[1] == L':' && \ + ((p)->Length == 2 * sizeof (WCHAR) || iswdirsep ((p)->Buffer[2]))))) + +#define iswabspath(p) \ + (iswdirsep (*(p)) || (iswalpha (*(p)) && (p)[1] == L':' && (!(p)[2] || iswdirsep ((p)[2])))) + #define isabspath(p) \ (isdirsep (*(p)) || (isalpha (*(p)) && (p)[1] == ':' && (!(p)[2] || isdirsep ((p)[2])))) @@ -239,6 +257,8 @@ extern bool cygwin_finished_initializing; void __stdcall set_std_handle (int); int __stdcall stat_dev (DWORD, int, unsigned long, struct __stat64 *); +__ino64_t __stdcall hash_path_name (__ino64_t hash, PUNICODE_STRING name) __attribute__ ((regparm(2))); +__ino64_t __stdcall hash_path_name (__ino64_t hash, PCWSTR name) __attribute__ ((regparm(2))); __ino64_t __stdcall hash_path_name (__ino64_t hash, const char *name) __attribute__ ((regparm(2))); void __stdcall nofinalslash (const char *src, char *dst) __attribute__ ((regparm(2))); extern "C" char *__stdcall rootdir (const char *full_path, char *root_path) __attribute__ ((regparm(2)));