Skip to content

Instantly share code, notes, and snippets.

@igorzi
Created November 22, 2011 18:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save igorzi/1386547 to your computer and use it in GitHub Desktop.
Save igorzi/1386547 to your computer and use it in GitHub Desktop.
From 33604b4f22879e3617a358ef944d5442c241b6bc Mon Sep 17 00:00:00 2001
From: Igor Zinkovsky <igorzi@microsoft.com>
Date: Tue, 22 Nov 2011 00:38:29 -0800
Subject: [PATCH] windows: enables uv_fs_open and uv_fs_stat to work with long paths
---
src/win/fs.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/src/win/fs.c b/src/win/fs.c
index c6d86b0..da089ca 100644
--- a/src/win/fs.c
+++ b/src/win/fs.c
@@ -492,7 +492,12 @@ void fs__readdir(uv_fs_t* req, const wchar_t* path, int flags) {
void fs__stat(uv_fs_t* req, const wchar_t* path) {
int result;
- result = _wstati64(path, &req->stat);
+ fs__open(req, path, _O_RDONLY, 0);
+ if (req->result == -1) {
+ return;
+ }
+
+ result = _fstati64(req->result, &req->stat);
if (result == -1) {
req->ptr = NULL;
} else {
@@ -500,6 +505,8 @@ void fs__stat(uv_fs_t* req, const wchar_t* path) {
}
SET_REQ_RESULT(req, result);
+
+ _close(req->result);
}
@@ -905,10 +912,47 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
int mode, uv_fs_cb cb) {
wchar_t* pathw;
- int size;
+ const wchar_t lfs_ext_len_prefix[] = L"\\\\?\\";
+ const wchar_t unc_ext_len_prefix[] = L"\\\\?\\UNC\\";
+ int size, offset = 0;
+ int convert_lfs_to_ext_len = 0, convert_unc_to_ext_len = 0;
+
+ size = uv_utf8_to_utf16(path, NULL, 0) * sizeof(wchar_t);
+
+ if (size >= 3) {
+ if (isalpha(path[0]) && path[1] == ':' && path[2] == '\\') {
+ /*
+ * path is local filesystem path, which needs to be converted
+ * to long UNC path.
+ */
+ convert_lfs_to_ext_len = 1;
+ offset = COUNTOF(lfs_ext_len_prefix);
+ } else if (memcmp(path, "\\\\", 2) == 0 &&
+ (size < 4 || memcmp(path + 2, "?\\", 2) != 0)) {
+ /*
+ * path is network UNC path, which needs to be converted
+ * to long UNC path.
+ */
+ convert_unc_to_ext_len = 1;
+ offset = COUNTOF(unc_ext_len_prefix);
+ }
+ }
- /* Convert to UTF16. */
- UTF8_TO_UTF16(path, pathw);
+ pathw = (wchar_t*)malloc(size + offset);
+ if (!pathw) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ }
+
+ if (!uv_utf8_to_utf16(path, pathw + offset, size / sizeof(wchar_t))) {
+ uv__set_sys_error(loop, GetLastError());
+ return -1;
+ }
+
+ if (convert_lfs_to_ext_len) {
+ memcpy(pathw, lfs_ext_len_prefix, sizeof(lfs_ext_len_prefix));
+ } else if (convert_unc_to_ext_len) {
+ memcpy(pathw, unc_ext_len_prefix, sizeof(unc_ext_len_prefix));
+ }
if (cb) {
uv_fs_req_init_async(loop, req, UV_FS_OPEN, path, pathw, cb);
@@ -1517,3 +1561,4 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
req->flags |= UV_FS_CLEANEDUP;
}
+
--
1.7.4.msysgit.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment