diff options
author | wtc%google.com <devnull@localhost> | 2008-01-27 05:00:58 +0000 |
---|---|---|
committer | wtc%google.com <devnull@localhost> | 2008-01-27 05:00:58 +0000 |
commit | c13d5b09e1b66bb38510251d20f205a94d0c5dce (patch) | |
tree | e7cb0835cf94dceec3ab7ec2df26b2103a497e29 | |
parent | 85ed39d66675bd9394eb4cca5f7cea9ac5de0716 (diff) | |
download | nspr-hg-c13d5b09e1b66bb38510251d20f205a94d0c5dce.tar.gz |
Bug 285157: Use GetFileAttributesEx if it exists. GetFileAttributesEx is
much faster than FindFirstFile. The patch is contributed by Jim Mathies
<jmathies@mozilla.com>. r=wtc
Modified files: ntio.c w95io.c
-rw-r--r-- | pr/src/md/windows/ntio.c | 68 | ||||
-rw-r--r-- | pr/src/md/windows/w95io.c | 112 |
2 files changed, 86 insertions, 94 deletions
diff --git a/pr/src/md/windows/ntio.c b/pr/src/md/windows/ntio.c index 3e0d860f..afa867b3 100644 --- a/pr/src/md/windows/ntio.c +++ b/pr/src/md/windows/ntio.c @@ -3043,80 +3043,18 @@ IsRootDirectory(char *fn, size_t buflen) PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) { - HANDLE hFindFile; - WIN32_FIND_DATA findFileData; - char pathbuf[MAX_PATH + 1]; + WIN32_FILE_ATTRIBUTE_DATA findFileData; if (NULL == fn || '\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 != _mbspbrk(fn, "?*")) { - PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0); + if (!GetFileAttributesEx(fn, GetFileExInfoStandard, &findFileData)) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return -1; } - hFindFile = FindFirstFile(fn, &findFileData); - if (INVALID_HANDLE_VALUE == hFindFile) { - DWORD len; - char *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 == _mbspbrk(fn, ".\\/")) { - _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); - return -1; - } - len = GetFullPathName(fn, sizeof(pathbuf), pathbuf, - &filePart); - if (0 == len) { - _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); - return -1; - } - if (len > sizeof(pathbuf)) { - PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); - return -1; - } - if (IsRootDirectory(pathbuf, sizeof(pathbuf))) { - 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 (!IsPrevCharSlash(pathbuf, pathbuf + len)) { - _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); - return -1; - } else { - pathbuf[len - 1] = '\0'; - hFindFile = FindFirstFile(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 { diff --git a/pr/src/md/windows/w95io.c b/pr/src/md/windows/w95io.c index ccbec62a..8c7e56da 100644 --- a/pr/src/md/windows/w95io.c +++ b/pr/src/md/windows/w95io.c @@ -81,6 +81,12 @@ static const PRTime _pr_filetime_offset = 116444736000000000LL; static const PRTime _pr_filetime_offset = 116444736000000000i64; #endif +typedef BOOL (WINAPI *GetFileAttributesExFn)(LPCTSTR, + GET_FILEEX_INFO_LEVELS, + LPVOID); +static GetFileAttributesExFn getFileAttributesEx; +static void InitGetFileInfo(void); + static void InitUnicodeSupport(void); static PRBool IsPrevCharSlash(const char *str, const char *current); @@ -122,6 +128,8 @@ _PR_MD_INIT_IO() _PR_NT_InitSids(); + InitGetFileInfo(); + InitUnicodeSupport(); _PR_MD_InitSockets(); @@ -771,31 +779,52 @@ IsRootDirectory(char *fn, size_t buflen) return rv; } -PRInt32 -_PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) +/* + * InitGetFileInfo -- + * + * Called during IO init. Checks for the existence of the system function + * GetFileAttributeEx, which when available is used in GETFILEINFO calls. + * If the routine exists, then the address of the routine is stored in the + * variable getFileAttributesEx, which will be used to call the routine. + */ +static void InitGetFileInfo(void) { - HANDLE hFindFile; - WIN32_FIND_DATA findFileData; - char pathbuf[MAX_PATH + 1]; - - if (NULL == fn || '\0' == *fn) { - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - return -1; + HMODULE module; + module = GetModuleHandle("Kernel32.dll"); + if (!module) { + PR_LOG(_pr_io_lm, PR_LOG_DEBUG, + ("InitGetFileInfo: GetModuleHandle() failed: %d", + GetLastError())); + return; } + getFileAttributesEx = (GetFileAttributesExFn) + GetProcAddress(module, "GetFileAttributesExA"); +} + +/* + * If GetFileAttributeEx doesn't exist, we call FindFirstFile as a + * fallback. + */ +static BOOL +GetFileAttributesExFB(const char *fn, WIN32_FIND_DATA *findFileData) +{ + HANDLE hFindFile; + /* * FindFirstFile() expands wildcard characters. So * we make sure the pathname contains no wildcard. */ if (NULL != _mbspbrk(fn, "?*")) { - PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0); - return -1; + SetLastError(ERROR_INVALID_NAME); + return FALSE; } - hFindFile = FindFirstFile(fn, &findFileData); + hFindFile = FindFirstFile(fn, findFileData); if (INVALID_HANDLE_VALUE == hFindFile) { DWORD len; char *filePart; + char pathbuf[MAX_PATH + 1]; /* * FindFirstFile() does not work correctly on root directories. @@ -810,43 +839,68 @@ _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) * a root directory or a pathname that ends in a slash. */ if (NULL == _mbspbrk(fn, ".\\/")) { - _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); - return -1; + return FALSE; } len = GetFullPathName(fn, sizeof(pathbuf), pathbuf, &filePart); if (0 == len) { - _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); - return -1; + return FALSE; } if (len > sizeof(pathbuf)) { - PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); - return -1; + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return FALSE; } if (IsRootDirectory(pathbuf, sizeof(pathbuf))) { - info->type = PR_FILE_DIRECTORY; - info->size = 0; + findFileData->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; + /* The file size doesn't have a meaning for directories. */ + findFileData->nFileSizeHigh = 0; + findFileData->nFileSizeLow = 0; /* - * These timestamps don't make sense for root directories. + * For a directory, these timestamps all specify when the + * directory is created. The creation time doesn't make + * sense for root directories, so we set it to (NSPR) time 0. */ - info->modifyTime = 0; - info->creationTime = 0; - return 0; + memcpy(&findFileData->ftCreationTime, &_pr_filetime_offset, 8); + findFileData->ftLastAccessTime = findFileData->ftCreationTime; + findFileData->ftLastWriteTime = findFileData->ftCreationTime; + return TRUE; } if (!IsPrevCharSlash(pathbuf, pathbuf + len)) { - _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); - return -1; + return FALSE; } else { pathbuf[len - 1] = '\0'; - hFindFile = FindFirstFile(pathbuf, &findFileData); + hFindFile = FindFirstFile(pathbuf, findFileData); if (INVALID_HANDLE_VALUE == hFindFile) { - _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); - return -1; + return FALSE; } } } FindClose(hFindFile); + return TRUE; +} + +PRInt32 +_PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) +{ + WIN32_FIND_DATA findFileData; + BOOL rv; + + if (NULL == fn || '\0' == *fn) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return -1; + } + + /* GetFileAttributesEx is supported on Win 2K and up. */ + if (getFileAttributesEx) { + rv = getFileAttributesEx(fn, GetFileExInfoStandard, &findFileData); + } else { + rv = GetFileAttributesExFB(fn, &findFileData); + } + if (!rv) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { info->type = PR_FILE_DIRECTORY; |