summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%google.com <devnull@localhost>2008-01-27 05:00:58 +0000
committerwtc%google.com <devnull@localhost>2008-01-27 05:00:58 +0000
commitc13d5b09e1b66bb38510251d20f205a94d0c5dce (patch)
treee7cb0835cf94dceec3ab7ec2df26b2103a497e29
parent85ed39d66675bd9394eb4cca5f7cea9ac5de0716 (diff)
downloadnspr-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.c68
-rw-r--r--pr/src/md/windows/w95io.c112
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;