diff options
author | wtc%netscape.com <devnull@localhost> | 2002-11-27 02:40:33 +0000 |
---|---|---|
committer | wtc%netscape.com <devnull@localhost> | 2002-11-27 02:40:33 +0000 |
commit | 3f571ec63595c1613e3aabdaa7615bb509f2ef88 (patch) | |
tree | d50784f1ca7d3b54a9dc05da7dd1d0a9d6c9998f | |
parent | bf748184e5384b1ae279039e2fb4c474831ada13 (diff) | |
download | nspr-hg-3f571ec63595c1613e3aabdaa7615bb509f2ef88.tar.gz |
Looked up the W functions at runtime.NSPR_UNICODE_PATHNAME_BRANCH
-rw-r--r-- | pr/include/md/_win95.h | 7 | ||||
-rw-r--r-- | pr/include/prio.h | 7 | ||||
-rw-r--r-- | pr/include/private/primpl.h | 3 | ||||
-rw-r--r-- | pr/src/io/prfile.c | 16 | ||||
-rw-r--r-- | pr/src/md/windows/w95io.c | 258 | ||||
-rw-r--r-- | pr/src/pthreads/ptio.c | 6 |
6 files changed, 290 insertions, 7 deletions
diff --git a/pr/include/md/_win95.h b/pr/include/md/_win95.h index 3a314eaf..5060be6f 100644 --- a/pr/include/md/_win95.h +++ b/pr/include/md/_win95.h @@ -225,10 +225,11 @@ extern PRInt32 _MD_CloseFile(PRInt32 osfd); #ifdef MOZ_UNICODE /* --- UTF16 IO stuff --- */ -#define _MD_OPEN_FILE_UTF16 _PR_MD_OPEN_FILE_UTF16 -#define _MD_OPEN_DIR_UTF16 _PR_MD_OPEN_DIR_UTF16 -#define _MD_READ_DIR_UTF16 _PR_MD_READ_DIR_UTF16 +#define _MD_OPEN_FILE_UTF16 _PR_MD_OPEN_FILE_UTF16 +#define _MD_OPEN_DIR_UTF16 _PR_MD_OPEN_DIR_UTF16 +#define _MD_READ_DIR_UTF16 _PR_MD_READ_DIR_UTF16 #define _MD_CLOSE_DIR_UTF16 _PR_MD_CLOSE_DIR_UTF16 +#define _MD_GETFILEINFO64_UTF16 _PR_MD_GETFILEINFO64_UTF16 #endif /* MOZ_UNICODE */ /* --- Socket IO stuff --- */ diff --git a/pr/include/prio.h b/pr/include/prio.h index 215885c8..42beca33 100644 --- a/pr/include/prio.h +++ b/pr/include/prio.h @@ -842,6 +842,13 @@ struct PRFileInfo64 { NSPR_API(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info); NSPR_API(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info); +#ifdef MOZ_UNICODE +/* + * EXPERIMENTAL: This function may be removed in a future release. + */ +NSPR_API(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info); +#endif /* MOZ_UNICODE */ + /* ************************************************************************** * FUNCTION: PR_GetOpenFileInfo, PR_GetOpenFileInfo64 diff --git a/pr/include/private/primpl.h b/pr/include/private/primpl.h index 8eacbd5a..180c4073 100644 --- a/pr/include/private/primpl.h +++ b/pr/include/private/primpl.h @@ -1160,6 +1160,9 @@ extern PRUnichar * _PR_MD_READ_DIR_UTF16(_MDDirUTF16 *md, PRIntn flags); extern PRInt32 _PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *md); #define _PR_MD_CLOSE_DIR_UTF16 _MD_CLOSE_DIR_UTF16 + +extern PRInt32 _PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info); +#define _PR_MD_GETFILEINFO64_UTF16 _MD_GETFILEINFO64_UTF16 #endif /* MOZ_UNICODE */ /* Socket I/O related */ diff --git a/pr/src/io/prfile.c b/pr/src/io/prfile.c index a56c84d6..1b3acaec 100644 --- a/pr/src/io/prfile.c +++ b/pr/src/io/prfile.c @@ -809,5 +809,21 @@ PR_IMPLEMENT(PRFileDesc*) PR_OpenFileUTF16( return fd; } +PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info) +{ +#ifdef XP_MAC +#pragma unused (fn, info) +#endif + PRInt32 rv; + + if (!_pr_initialized) _PR_ImplicitInitialization(); + rv = _PR_MD_GETFILEINFO64_UTF16(fn, info); + if (rv < 0) { + return PR_FAILURE; + } else { + return PR_SUCCESS; + } +} + /* ================ UTF16 Interfaces ================================ */ #endif /* MOZ_UNICODE */ diff --git a/pr/src/md/windows/w95io.c b/pr/src/md/windows/w95io.c index 8f6789dd..99b1a0b6 100644 --- a/pr/src/md/windows/w95io.c +++ b/pr/src/md/windows/w95io.c @@ -42,7 +42,7 @@ #include <direct.h> #include <mbstring.h> #ifdef MOZ_UNICODE -#include <tchar.h> +#include <wchar.h> #endif /* MOZ_UNICODE */ @@ -77,6 +77,10 @@ static const PRTime _pr_filetime_offset = 116444736000000000LL; static const PRTime _pr_filetime_offset = 116444736000000000i64; #endif +#ifdef MOZ_UNICODE +static void InitUnicodeSupport(void); +#endif + void _PR_MD_INIT_IO() { @@ -113,6 +117,10 @@ _PR_MD_INIT_IO() #endif /* DEBUG */ _PR_NT_InitSids(); + +#ifdef MOZ_UNICODE + InitUnicodeSupport(); +#endif } PRStatus @@ -1093,6 +1101,40 @@ _PR_MD_PIPEAVAILABLE(PRFileDesc *fd) } #ifdef MOZ_UNICODE + +typedef HANDLE (WINAPI *CreateFileWFn) (LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); +static CreateFileWFn createFileW = NULL; +typedef HANDLE (WINAPI *FindFirstFileWFn) (LPCWSTR, LPWIN32_FIND_DATAW); +static FindFirstFileWFn findFirstFileW = NULL; +typedef BOOL (WINAPI *FindNextFileWFn) (HANDLE, LPWIN32_FIND_DATAW); +static FindNextFileWFn findNextFileW = NULL; +typedef DWORD (WINAPI *GetFullPathNameWFn) (LPCWSTR, DWORD, LPWSTR, LPWSTR *); +static GetFullPathNameWFn getFullPathNameW = NULL; +typedef UINT (WINAPI *GetDriveTypeWFn) (LPCWSTR); +static GetDriveTypeWFn getDriveTypeW = NULL; + +static void InitUnicodeSupport(void) +{ + HMODULE module; + + /* + * The W functions do not exist on Win9x. NSPR won't run on Win9x + * if we call the W functions directly. Use GetProcAddress() to + * look up their addresses at run time. + */ + + module = GetModuleHandle("Kernel32.dll"); + if (!module) { + return; + } + + createFileW = (CreateFileWFn)GetProcAddress(module, "CreateFileW"); + findFirstFileW = (FindFirstFileWFn)GetProcAddress(module, "FindFirstFileW"); + findNextFileW = (FindNextFileWFn)GetProcAddress(module, "FindNextFileW"); + getDriveTypeW = (GetDriveTypeWFn)GetProcAddress(module, "GetDriveTypeW"); + getFullPathNameW = (GetFullPathNameWFn)GetProcAddress(module, "GetFullPathNameW"); +} + /* ================ UTF16 Interfaces ================================ */ void FlipSlashesW(PRUnichar *cp, int len) { @@ -1115,6 +1157,11 @@ _PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, int mode) LPSECURITY_ATTRIBUTES lpSA = NULL; PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; + + if (!createFileW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return -1; + } if (osflags & PR_CREATE_FILE) { if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, @@ -1147,7 +1194,7 @@ _PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, int mode) flags = OPEN_EXISTING; } - file = CreateFileW(name, + file = createFileW(name, access, FILE_SHARE_READ|FILE_SHARE_WRITE, lpSA, @@ -1171,6 +1218,11 @@ _PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *d, const PRUnichar *name) PRUnichar filename[ MAX_PATH ]; int len; + if (!findFirstFileW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return PR_FAILURE; + } + len = wcslen(name); /* Need 5 bytes for \*.* and the trailing null byte. */ if (len + 5 > MAX_PATH) { @@ -1189,7 +1241,7 @@ _PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *d, const PRUnichar *name) wcscpy(&filename[len], L"\\*.*"); FlipSlashesW( filename, wcslen(filename) ); - d->d_hdl = FindFirstFileW( filename, &(d->d_entry) ); + d->d_hdl = findFirstFileW( filename, &(d->d_entry) ); if ( d->d_hdl == INVALID_HANDLE_VALUE ) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return PR_FAILURE; @@ -1206,13 +1258,18 @@ _PR_MD_READ_DIR_UTF16(_MDDirUTF16 *d, PRIntn flags) BOOL rv; PRUnichar *fileName; + if (!findNextFileW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return NULL; + } + if ( d ) { while (1) { if (d->firstEntry) { d->firstEntry = PR_FALSE; rv = 1; } else { - rv = FindNextFileW(d->d_hdl, &(d->d_entry)); + rv = findNextFileW(d->d_hdl, &(d->d_entry)); } if (rv == 0) { break; @@ -1254,5 +1311,198 @@ _PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *d) return PR_FAILURE; } +#define _PR_IS_W_SLASH(ch) ((ch) == L'/' || (ch) == L'\\') + +/* + * IsRootDirectoryW -- + * + * Return PR_TRUE if the pathname 'fn' is a valid root directory, + * else return PR_FALSE. The PRUnichar buffer pointed to by 'fn' must + * be writable. During the execution of this function, the contents + * of the buffer pointed to by 'fn' may be modified, but on return + * the original contents will be restored. 'buflen' is the size of + * the buffer pointed to by 'fn', in PRUnichars. + * + * Root directories come in three formats: + * 1. / or \, meaning the root directory of the current drive. + * 2. C:/ or C:\, where C is a drive letter. + * 3. \\<server name>\<share point name>\ or + * \\<server name>\<share point name>, meaning the root directory + * of a UNC (Universal Naming Convention) name. + */ + +static PRBool +IsRootDirectoryW(PRUnichar *fn, size_t buflen) +{ + PRUnichar *p; + PRBool slashAdded = PR_FALSE; + PRBool rv = PR_FALSE; + + if (_PR_IS_W_SLASH(fn[0]) && fn[1] == L'\0') { + return PR_TRUE; + } + + if (iswalpha(fn[0]) && fn[1] == L':' && _PR_IS_W_SLASH(fn[2]) + && fn[3] == L'\0') { + rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE; + return rv; + } + + /* The UNC root directory */ + + if (_PR_IS_W_SLASH(fn[0]) && _PR_IS_W_SLASH(fn[1])) { + /* The 'server' part should have at least one character. */ + p = &fn[2]; + if (*p == L'\0' || _PR_IS_W_SLASH(*p)) { + return PR_FALSE; + } + + /* look for the next slash */ + do { + p++; + } while (*p != L'\0' && !_PR_IS_W_SLASH(*p)); + if (*p == L'\0') { + return PR_FALSE; + } + + /* The 'share' part should have at least one character. */ + p++; + if (*p == L'\0' || _PR_IS_W_SLASH(*p)) { + return PR_FALSE; + } + + /* look for the final slash */ + do { + p++; + } while (*p != L'\0' && !_PR_IS_W_SLASH(*p)); + if (_PR_IS_W_SLASH(*p) && p[1] != L'\0') { + return PR_FALSE; + } + if (*p == L'\0') { + /* + * GetDriveType() doesn't work correctly if the + * path is of the form \\server\share, so we add + * a final slash temporarily. + */ + if ((p + 1) < (fn + buflen)) { + *p++ = L'\\'; + *p = L'\0'; + slashAdded = PR_TRUE; + } else { + return PR_FALSE; /* name too long */ + } + } + rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE; + /* restore the 'fn' buffer */ + if (slashAdded) { + *--p = L'\0'; + } + } + return rv; +} + +PRInt32 +_PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info) +{ + HANDLE hFindFile; + WIN32_FIND_DATAW findFileData; + PRUnichar pathbuf[MAX_PATH + 1]; + + if (!findFirstFileW || !getFullPathNameW || !getDriveTypeW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return -1; + } + + if (NULL == fn || L'\0' == *fn) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return -1; + } + + /* + * FindFirstFile() expands wildcard characters. So + * we make sure the pathname contains no wildcard. + */ + if (NULL != wcspbrk(fn, L"?*")) { + PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0); + return -1; + } + + hFindFile = findFirstFileW(fn, &findFileData); + if (INVALID_HANDLE_VALUE == hFindFile) { + DWORD len; + PRUnichar *filePart; + + /* + * FindFirstFile() does not work correctly on root directories. + * It also doesn't work correctly on a pathname that ends in a + * slash. So we first check to see if the pathname specifies a + * root directory. If not, and if the pathname ends in a slash, + * we remove the final slash and try again. + */ + + /* + * If the pathname does not contain ., \, and /, it cannot be + * a root directory or a pathname that ends in a slash. + */ + if (NULL == wcspbrk(fn, L".\\/")) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } + len = getFullPathNameW(fn, sizeof(pathbuf)/sizeof(pathbuf[0]), pathbuf, + &filePart); + if (0 == len) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } + if (len > sizeof(pathbuf)/sizeof(pathbuf[0])) { + PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); + return -1; + } + if (IsRootDirectoryW(pathbuf, sizeof(pathbuf)/sizeof(pathbuf[0]))) { + info->type = PR_FILE_DIRECTORY; + info->size = 0; + /* + * These timestamps don't make sense for root directories. + */ + info->modifyTime = 0; + info->creationTime = 0; + return 0; + } + if (!_PR_IS_W_SLASH(pathbuf[len - 1])) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } else { + pathbuf[len - 1] = L'\0'; + hFindFile = findFirstFileW(pathbuf, &findFileData); + if (INVALID_HANDLE_VALUE == hFindFile) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } + } + } + + FindClose(hFindFile); + + if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + info->type = PR_FILE_DIRECTORY; + } else { + info->type = PR_FILE_FILE; + } + + info->size = findFileData.nFileSizeHigh; + info->size = (info->size << 32) + findFileData.nFileSizeLow; + + _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime); + + if (0 == findFileData.ftCreationTime.dwLowDateTime && + 0 == findFileData.ftCreationTime.dwHighDateTime) { + info->creationTime = info->modifyTime; + } else { + _PR_FileTimeToPRTime(&findFileData.ftCreationTime, + &info->creationTime); + } + + return 0; +} /* ================ end of UTF16 Interfaces ================================ */ #endif /* MOZ_UNICODE */ diff --git a/pr/src/pthreads/ptio.c b/pr/src/pthreads/ptio.c index d42e7974..8a19b91d 100644 --- a/pr/src/pthreads/ptio.c +++ b/pr/src/pthreads/ptio.c @@ -4812,6 +4812,12 @@ PR_IMPLEMENT(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } + +PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info) +{ + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return PR_FAILURE; +} /* ================ UTF16 Interfaces ================================ */ #endif /* MOZ_UNICODE */ |