|
|
@ -489,6 +489,103 @@ void fs__readdir(uv_fs_t* req, const wchar_t* path, int flags) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#define IS_SLASH(c) \ |
|
|
|
((wchar_t) c == L'/' || (wchar_t) c == L'\\') |
|
|
|
#define IS_COLON(c) \ |
|
|
|
((wchar_t) c == L':') |
|
|
|
#define IS_LETTER(c) \ |
|
|
|
((((wchar_t) c >= L'a') && ((wchar_t) c <= L'z')) || \ |
|
|
|
(((wchar_t) c >= L'A') && ((wchar_t) c <= L'Z'))) |
|
|
|
#define IS_QUESTION(c) \ |
|
|
|
((wchar_t) c == L'?') |
|
|
|
|
|
|
|
|
|
|
|
static int uv__count_slash_separated_words(const wchar_t* pos, |
|
|
|
const wchar_t* end, |
|
|
|
int limit) { |
|
|
|
char last_was_slash = 1, count = 0; |
|
|
|
|
|
|
|
for (; pos < end; pos++) { |
|
|
|
if (IS_SLASH(*pos)) { |
|
|
|
/* Don't accept double slashes */ |
|
|
|
if (last_was_slash) { |
|
|
|
return 0; |
|
|
|
} else { |
|
|
|
last_was_slash = 1; |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (last_was_slash) { |
|
|
|
/* Found a new word */ |
|
|
|
count++; |
|
|
|
if (count > limit) { |
|
|
|
return -1; |
|
|
|
} |
|
|
|
last_was_slash = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return count; |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns true if the given path is a root directory. The following patterns |
|
|
|
* are recognized: |
|
|
|
* \ |
|
|
|
* c:\ (must have trailing slash) |
|
|
|
* \\server\share (trailing slash optional) |
|
|
|
* \\?\c: (trailing slash optional) |
|
|
|
* \\?\UNC\server\share (trailing slash optional) |
|
|
|
*/ |
|
|
|
static int uv__is_root(const wchar_t* path) { |
|
|
|
size_t len = wcslen(path); |
|
|
|
|
|
|
|
/* Test for \ */ |
|
|
|
if (len == 0 && IS_SLASH(path[0])) { |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
if (len < 3) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* Test for c:\ */ |
|
|
|
if (IS_LETTER(path[0]) && IS_COLON(path[1]) && IS_SLASH(path[2])) { |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
if (!IS_SLASH(path[0]) || !IS_SLASH(path[1])) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* Test for \\server\share */ |
|
|
|
if (!IS_QUESTION(path[2])) { |
|
|
|
return uv__count_slash_separated_words(path + 2, path + len, 2) == 2; |
|
|
|
} |
|
|
|
|
|
|
|
if (!IS_SLASH(path[3])) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
if ((len == 6 || len == 7) && |
|
|
|
IS_LETTER(path[4]) && IS_COLON(path[5]) && |
|
|
|
(len == 6 || IS_SLASH(path[6]))) { |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
/* Test for \\?\UNC\server\share */ |
|
|
|
if (len >= 8 && |
|
|
|
(path[4] == L'u' || path[4] == L'U') && |
|
|
|
(path[5] == L'n' || path[5] == L'N') && |
|
|
|
(path[6] == L'c' || path[6] == L'C') && |
|
|
|
IS_SLASH(path[7])) { |
|
|
|
return uv__count_slash_separated_words(path + 8, path + len, 2) == 2; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void fs__stat(uv_fs_t* req, const wchar_t* path) { |
|
|
|
HANDLE file; |
|
|
|
WIN32_FIND_DATAW ent; |
|
|
@ -496,6 +593,30 @@ void fs__stat(uv_fs_t* req, const wchar_t* path) { |
|
|
|
|
|
|
|
req->ptr = NULL; |
|
|
|
|
|
|
|
if (uv__is_root(path)) { |
|
|
|
/* We can't stat root directories like c:\. _wstati64 can't either, but */ |
|
|
|
/* it will make up something reasonable. */ |
|
|
|
DWORD drive_type = GetDriveTypeW(path); |
|
|
|
if (drive_type == DRIVE_UNKNOWN || drive_type == DRIVE_NO_ROOT_DIR) { |
|
|
|
req->last_error = ERROR_PATH_NOT_FOUND; |
|
|
|
req->errorno = UV_ENOENT; |
|
|
|
req->result = -1; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
memset(&req->stat, 0, sizeof req->stat); |
|
|
|
|
|
|
|
req->stat.st_nlink = 1; |
|
|
|
req->stat.st_mode = ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3) + |
|
|
|
((_S_IREAD|_S_IWRITE) >> 6)) | S_IFDIR; |
|
|
|
|
|
|
|
req->last_error = ERROR_SUCCESS; |
|
|
|
req->errorno = UV_OK; |
|
|
|
req->result = 0; |
|
|
|
req->ptr = &req->stat; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
file = FindFirstFileExW(path, FindExInfoStandard, &ent, |
|
|
|
FindExSearchNameMatch, NULL, 0); |
|
|
|
|
|
|
@ -516,7 +637,7 @@ void fs__stat(uv_fs_t* req, const wchar_t* path) { |
|
|
|
if (result != -1) { |
|
|
|
req->ptr = &req->stat; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
SET_REQ_RESULT(req, result); |
|
|
|
} |
|
|
|
|
|
|
|