Browse Source

uv: upgrade to 4a88b3b

v0.8.7-release
Bert Belder 13 years ago
parent
commit
3ea2a618ad
  1. 2
      deps/uv/src/unix/dl.c
  2. 2
      deps/uv/src/win/error.c
  3. 298
      deps/uv/src/win/fs.c

2
deps/uv/src/unix/dl.c

@ -34,7 +34,7 @@ int uv_dlopen(const char* filename, uv_lib_t* lib) {
dlerror(); /* Reset error status. */ dlerror(); /* Reset error status. */
lib->errmsg = NULL; lib->errmsg = NULL;
lib->handle = dlopen(filename, RTLD_LAZY); lib->handle = dlopen(filename, RTLD_LAZY);
return uv__dlerror(lib); return lib->handle ? 0 : uv__dlerror(lib);
} }

2
deps/uv/src/win/error.c

@ -83,6 +83,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
case ERROR_SIGNAL_REFUSED: return UV_EIO; case ERROR_SIGNAL_REFUSED: return UV_EIO;
case ERROR_FILE_NOT_FOUND: return UV_ENOENT; case ERROR_FILE_NOT_FOUND: return UV_ENOENT;
case ERROR_INVALID_NAME: return UV_ENOENT; case ERROR_INVALID_NAME: return UV_ENOENT;
case ERROR_INVALID_REPARSE_DATA: return UV_ENOENT;
case ERROR_MOD_NOT_FOUND: return UV_ENOENT; case ERROR_MOD_NOT_FOUND: return UV_ENOENT;
case ERROR_PATH_NOT_FOUND: return UV_ENOENT; case ERROR_PATH_NOT_FOUND: return UV_ENOENT;
case ERROR_ACCESS_DENIED: return UV_EPERM; case ERROR_ACCESS_DENIED: return UV_EPERM;
@ -111,6 +112,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
case ERROR_OPERATION_ABORTED: return UV_EINTR; case ERROR_OPERATION_ABORTED: return UV_EINTR;
case WSAEINTR: return UV_EINTR; case WSAEINTR: return UV_EINTR;
case ERROR_INVALID_DATA: return UV_EINVAL; case ERROR_INVALID_DATA: return UV_EINVAL;
case ERROR_SYMLINK_NOT_SUPPORTED: return UV_EINVAL;
case WSAEINVAL: return UV_EINVAL; case WSAEINVAL: return UV_EINVAL;
case ERROR_CANT_RESOLVE_FILENAME: return UV_ELOOP; case ERROR_CANT_RESOLVE_FILENAME: return UV_ELOOP;
case ERROR_TOO_MANY_OPEN_FILES: return UV_EMFILE; case ERROR_TOO_MANY_OPEN_FILES: return UV_EMFILE;

298
deps/uv/src/win/fs.c

@ -161,47 +161,147 @@ static int is_path_dir(const wchar_t* path) {
} }
static int get_reparse_point(HANDLE handle, int* target_length) { INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
void* buffer = NULL; int64_t* target_len_ptr) {
REPARSE_DATA_BUFFER* reparse_data; char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
DWORD bytes_returned; REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer;
int rv = 0; WCHAR *w_target;
DWORD w_target_len;
buffer = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); char* target;
if (!buffer) { int target_len;
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); DWORD bytes;
}
if (!DeviceIoControl(handle, if (!DeviceIoControl(handle,
FSCTL_GET_REPARSE_POINT, FSCTL_GET_REPARSE_POINT,
NULL, NULL,
0, 0,
buffer, buffer,
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, sizeof buffer,
&bytes_returned, &bytes,
NULL)) { NULL)) {
free(buffer); return -1;
return 0;
} }
reparse_data = (REPARSE_DATA_BUFFER*)buffer;
if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) { if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
rv = 1; /* Real symlink */
if (target_length) { w_target = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
*target_length = reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset /
sizeof(wchar_t); sizeof(WCHAR));
w_target_len =
reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
sizeof(WCHAR);
/* Real symlinks can contain pretty much everything, but the only thing */
/* we really care about is undoing the implicit conversion to an NT */
/* namespaced path that CreateSymbolicLink will perform on absolute */
/* paths. If the path is win32-namespaced then the user must have */
/* explicitly made it so, and we better just return the unmodified */
/* reparse data. */
if (w_target_len >= 4 &&
w_target[0] == L'\\' &&
w_target[1] == L'?' &&
w_target[2] == L'?' &&
w_target[3] == L'\\') {
/* Starts with \??\ */
if (w_target_len >= 6 &&
((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
(w_target[4] >= L'a' && w_target[4] <= L'z')) &&
w_target[5] == L':' &&
(w_target_len == 6 || w_target[6] == L'\\')) {
/* \??\«drive»:\ */
w_target += 4;
w_target_len -= 4;
} else if (w_target_len >= 8 &&
(w_target[4] == L'U' || w_target[4] == L'u') &&
(w_target[5] == L'N' || w_target[5] == L'n') &&
(w_target[6] == L'C' || w_target[6] == L'c') &&
w_target[7] == L'\\') {
/* \??\UNC\«server»\«share»\ - make sure the final path looks like */
/* \\«server»\«share»\ */
w_target += 6;
w_target[0] = L'\\';
w_target_len -= 6;
} }
}
} else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
rv = 1; /* Junction. */
if (target_length) { w_target = reparse_data->MountPointReparseBuffer.PathBuffer +
*target_length = reparse_data->MountPointReparseBuffer.SubstituteNameLength / (reparse_data->MountPointReparseBuffer.SubstituteNameOffset /
sizeof(WCHAR));
w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
sizeof(wchar_t); sizeof(wchar_t);
/* Only treat junctions that look like \??\«drive»:\ as symlink. */
/* Junctions can also be used as mount points, like \??\Volume{«guid»}, */
/* but that's confusing for programs since they wouldn't be able to */
/* actually understand such a path when returned by uv_readlink(). */
/* UNC paths are never valid for junctions so we don't care about them. */
if (!(w_target_len >= 6 &&
w_target[0] == L'\\' &&
w_target[1] == L'?' &&
w_target[2] == L'?' &&
w_target[3] == L'\\' &&
((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
(w_target[4] >= L'a' && w_target[4] <= L'z')) &&
w_target[5] == L':' &&
(w_target_len == 6 || w_target[6] == L'\\'))) {
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
return -1;
} }
/* Remove leading \??\ */
w_target += 4;
w_target_len -= 4;
} else {
/* Reparse tag does not indicate a symlink. */
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
return -1;
} }
free(buffer); /* Compute the length of the target. */
return rv; target_len = WideCharToMultiByte(CP_UTF8,
0,
w_target,
w_target_len,
NULL,
0,
NULL,
NULL);
if (target_len == 0) {
return -1;
}
/* If requested, allocate memory and convert to UTF8. */
if (target_ptr != NULL) {
int r;
target = (char*) malloc(target_len + 1);
if (target == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return -1;
}
r = WideCharToMultiByte(CP_UTF8,
0,
w_target,
w_target_len,
target,
target_len,
NULL,
NULL);
assert(r == target_len);
target[target_len] = '\0';
*target_ptr = target;
}
if (target_len_ptr != NULL) {
*target_len_ptr = target_len;
}
return 0;
} }
@ -455,11 +555,12 @@ void fs__unlink(uv_fs_t* req, const wchar_t* path) {
return; return;
} }
is_dir_symlink = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && is_dir_symlink = (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
get_reparse_point(handle, NULL); (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT);
CloseHandle(handle); CloseHandle(handle);
/* Todo: very inefficient; fix this. */
if (is_dir_symlink) { if (is_dir_symlink) {
fs__rmdir(req, path); fs__rmdir(req, path);
} else { } else {
@ -583,7 +684,6 @@ void fs__readdir(uv_fs_t* req, const wchar_t* path, int flags) {
INLINE static int fs__stat_handle(HANDLE handle, uv_statbuf_t* statbuf) { INLINE static int fs__stat_handle(HANDLE handle, uv_statbuf_t* statbuf) {
int target_length;
BY_HANDLE_FILE_INFORMATION info; BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle(handle, &info)) { if (!GetFileInformationByHandle(handle, &info)) {
@ -600,28 +700,25 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_statbuf_t* statbuf) {
statbuf->st_mode = 0; statbuf->st_mode = 0;
if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
get_reparse_point(handle, &target_length)) { if (fs__readlink_handle(handle, NULL, &statbuf->st_size) != 0) {
statbuf->st_mode = S_IFLNK; return -1;
/* Adjust for long path */
statbuf->st_size = target_length - JUNCTION_PREFIX_LEN;
} else {
if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
statbuf->st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
} else {
statbuf->st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3) +
((_S_IREAD|_S_IWRITE) >> 6));
} }
statbuf->st_mode |= S_IFLNK;
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { } else if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
statbuf->st_mode |= _S_IFDIR; statbuf->st_mode |= _S_IFDIR;
statbuf->st_size = 0;
} else { } else {
statbuf->st_mode |= _S_IFREG; statbuf->st_mode |= _S_IFREG;
}
statbuf->st_size = ((int64_t) info.nFileSizeHigh << 32) + statbuf->st_size = ((int64_t) info.nFileSizeHigh << 32) +
(int64_t) info.nFileSizeLow; (int64_t) info.nFileSizeLow;
}
if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
statbuf->st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
} else {
statbuf->st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3) +
((_S_IREAD|_S_IWRITE) >> 6));
} }
statbuf->st_mtime = FILETIME_TO_TIME_T(info.ftLastWriteTime); statbuf->st_mtime = FILETIME_TO_TIME_T(info.ftLastWriteTime);
@ -659,7 +756,16 @@ INLINE static void fs__stat(uv_fs_t* req, const wchar_t* path, int do_lstat) {
} }
if (fs__stat_handle(handle, &req->stat) != 0) { if (fs__stat_handle(handle, &req->stat) != 0) {
DWORD error = GetLastError();
if (do_lstat && error == ERROR_SYMLINK_NOT_SUPPORTED) {
/* We opened a reparse point but it was not a symlink. Try again. */
fs__stat(req, path, 0);
} else {
/* Stat failed. */
SET_REQ_WIN32_ERROR(req, GetLastError()); SET_REQ_WIN32_ERROR(req, GetLastError());
}
CloseHandle(handle); CloseHandle(handle);
return; return;
} }
@ -1099,17 +1205,9 @@ void fs__symlink(uv_fs_t* req, const wchar_t* path, const wchar_t* new_path,
void fs__readlink(uv_fs_t* req, const wchar_t* path) { void fs__readlink(uv_fs_t* req, const wchar_t* path) {
int result = -1; HANDLE handle;
BOOL rv;
HANDLE symlink; handle = CreateFileW(path,
void* buffer = NULL;
DWORD bytes_returned;
REPARSE_DATA_BUFFER* reparse_data;
int utf8size;
wchar_t* substitute_name;
int substitute_name_length;
symlink = CreateFileW(path,
0, 0,
0, 0,
NULL, NULL,
@ -1117,99 +1215,21 @@ void fs__readlink(uv_fs_t* req, const wchar_t* path) {
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
NULL); NULL);
if (INVALID_HANDLE_VALUE == symlink) { if (handle == INVALID_HANDLE_VALUE) {
result = -1;
SET_REQ_WIN32_ERROR(req, GetLastError());
goto done;
}
buffer = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
if (!buffer) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
rv = DeviceIoControl(symlink,
FSCTL_GET_REPARSE_POINT,
NULL,
0,
buffer,
MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
&bytes_returned,
NULL);
if (!rv) {
result = -1;
SET_REQ_WIN32_ERROR(req, GetLastError());
goto done;
}
reparse_data = (REPARSE_DATA_BUFFER*)buffer;
if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
substitute_name = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
(reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset /
sizeof(wchar_t));
substitute_name_length =
reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
sizeof(wchar_t);
} else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
substitute_name = reparse_data->MountPointReparseBuffer.PathBuffer +
(reparse_data->MountPointReparseBuffer.SubstituteNameOffset /
sizeof(wchar_t));
substitute_name_length =
reparse_data->MountPointReparseBuffer.SubstituteNameLength /
sizeof(wchar_t);
} else {
result = -1;
/* something is seriously wrong */
SET_REQ_WIN32_ERROR(req, GetLastError());
goto done;
}
/* Strip off the leading \??\ from the substitute name buffer.*/
if (wcsncmp(substitute_name, JUNCTION_PREFIX, JUNCTION_PREFIX_LEN) == 0) {
substitute_name += JUNCTION_PREFIX_LEN;
substitute_name_length -= JUNCTION_PREFIX_LEN;
}
utf8size = uv_utf16_to_utf8(substitute_name,
substitute_name_length,
NULL,
0);
if (!utf8size) {
result = -1;
SET_REQ_WIN32_ERROR(req, GetLastError()); SET_REQ_WIN32_ERROR(req, GetLastError());
goto done; return;
}
req->ptr = malloc(utf8size + 1);
if (!req->ptr) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
} }
utf8size = uv_utf16_to_utf8(substitute_name, if (fs__readlink_handle(handle, (char**) &req->ptr, NULL) != 0) {
substitute_name_length,
(char*)req->ptr,
utf8size);
if (!utf8size) {
result = -1;
SET_REQ_WIN32_ERROR(req, GetLastError()); SET_REQ_WIN32_ERROR(req, GetLastError());
goto done; CloseHandle(handle);
return;
} }
req->flags |= UV_FS_FREE_PTR; req->flags |= UV_FS_FREE_PTR;
((char*)req->ptr)[utf8size] = '\0'; SET_REQ_RESULT(req, 0);
result = 0;
done:
if (buffer) {
free(buffer);
}
if (symlink != INVALID_HANDLE_VALUE) {
CloseHandle(symlink);
}
SET_REQ_RESULT(req, result); CloseHandle(handle);
} }

Loading…
Cancel
Save