Browse Source

Upgrade libuv to 142a702

Ryan Dahl 13 years ago
parent
commit
17021ea631
  1. 16
      deps/uv/common.gypi
  2. 1
      deps/uv/include/uv-private/uv-win.h
  3. 8
      deps/uv/include/uv.h
  4. 1
      deps/uv/src/unix/core.c
  5. 1
      deps/uv/src/unix/darwin.c
  6. 72
      deps/uv/src/unix/fs.c
  7. 217
      deps/uv/src/win/fs.c
  8. 4
      deps/uv/src/win/winapi.c
  9. 35
      deps/uv/src/win/winapi.h
  10. 236
      deps/uv/test/test-fs.c
  11. 4
      deps/uv/test/test-list.h
  12. 7
      src/node_file.cc

16
deps/uv/common.gypi

@ -1,5 +1,6 @@
{
'variables': {
'visibility%': 'hidden', # V8's visibility setting
'target_arch%': 'ia32', # set v8's target architecture
'host_arch%': 'ia32', # set v8's host architecture
'library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds
@ -87,6 +88,11 @@
'DataExecutionPrevention': 2, # enable DEP
'AllowIsolation': 'true',
'SuppressStartupBanner': 'true',
'target_conditions': [
['_type=="executable"', {
'SubSystem': 1, # console executable
}],
],
},
},
'conditions': [
@ -103,8 +109,8 @@
],
}],
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
'target_defaults': {
'cflags': [ '-Wall', '-pthread', '-fno-rtti', '-fno-exceptions' ],
'cflags': [ '-Wall', '-pthread', ],
'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ],
'ldflags': [ '-pthread', ],
'conditions': [
[ 'target_arch=="ia32"', {
@ -118,13 +124,10 @@
'cflags': [ '-fvisibility=hidden' ],
}],
],
},
}],
['OS=="mac"', {
'target_defaults': {
'xcode_settings': {
'ALWAYS_SEARCH_USER_PATHS': 'NO',
'GCC_C_LANGUAGE_STANDARD': 'ansi', # -ansi
'GCC_CW_ASM_SYNTAX': 'NO', # No -fasm-blocks
'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic
# (Equivalent to -fPIC)
@ -135,7 +138,6 @@
'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES', # -Werror
'GCC_VERSION': '4.2',
'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof
'MACOSX_DEPLOYMENT_TARGET': '10.4', # -mmacosx-version-min=10.4
@ -149,7 +151,6 @@
'-Wendif-labels',
'-W',
'-Wno-unused-parameter',
'-Wnon-virtual-dtor',
],
},
'target_conditions': [
@ -157,7 +158,6 @@
'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']},
}],
],
},
}],
],
},

1
deps/uv/include/uv-private/uv-win.h

@ -247,6 +247,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
#define UV_FS_PRIVATE_FIELDS \
int flags; \
int last_error; \
struct _stat stat; \
void* arg0; \
union { \

8
deps/uv/include/uv.h

@ -948,8 +948,14 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb);
/*
* This flag can be used with uv_fs_symlink on Windows
* to specify whether path argument points to a directory.
*/
#define UV_FS_SYMLINK_DIR 0x0001
int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb);
const char* new_path, int flags, uv_fs_cb cb);
int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb);

1
deps/uv/src/unix/core.c

@ -323,7 +323,6 @@ int64_t uv_now(uv_loop_t* loop) {
void uv__req_init(uv_req_t* req) {
/* loop->counters.req_init++; */
req->type = UV_UNKNOWN_REQ;
req->data = NULL;
}

1
deps/uv/src/unix/darwin.c

@ -24,6 +24,7 @@
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <mach-o/dyld.h> /* _NSGetExecutablePath */
uint64_t uv_hrtime() {

72
deps/uv/src/unix/fs.c

@ -112,7 +112,7 @@ static int uv__fs_after(eio_req* eio) {
case UV_FS_READDIR:
/*
* XXX This is pretty bad.
* We alloc and copy the large null termiated string list from libeio.
* We alloc and copy the large null terminated string list from libeio.
* This is done because libeio is going to free eio->ptr2 after this
* callback. We must keep it until uv_fs_req_cleanup. If we get rid of
* libeio this can be avoided.
@ -130,12 +130,31 @@ static int uv__fs_after(eio_req* eio) {
req->ptr = malloc(buflen);
memcpy(req->ptr, req->eio->ptr2, buflen);
break;
case UV_FS_STAT:
case UV_FS_LSTAT:
case UV_FS_FSTAT:
req->ptr = req->eio->ptr2;
break;
case UV_FS_READLINK:
if (req->result == -1) {
req->ptr = NULL;
} else {
assert(req->result > 0);
if ((name = realloc(req->eio->ptr2, req->result + 1)) == NULL) {
/* Not enough memory. Reuse buffer, chop off last byte. */
name = req->eio->ptr2;
req->result--;
}
name[req->result] = '\0';
req->ptr = name;
req->result = 0;
}
break;
default:
break;
}
@ -490,17 +509,64 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb) {
const char* new_path, int flags, uv_fs_cb cb) {
WRAP_EIO(UV_FS_SYMLINK, eio_symlink, symlink, ARGS2(path, new_path))
}
int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb) {
assert(0 && "implement me");
size_t size;
int status;
char* buf;
status = -1;
uv_fs_req_init(loop, req, UV_FS_READLINK, cb);
if (cb) {
if ((req->eio = eio_readlink(path, EIO_PRI_DEFAULT, uv__fs_after, req))) {
uv_ref(loop);
return 0;
} else {
uv_err_new(loop, ENOMEM);
return -1;
}
} else {
/* pathconf(_PC_PATH_MAX) may return -1 to signify that path
* lengths have no upper limit or aren't suitable for malloc'ing.
*/
if ((size = pathconf(path, _PC_PATH_MAX)) == -1) {
#if defined(PATH_MAX)
size = PATH_MAX;
#else
size = 4096;
#endif
}
if ((buf = malloc(size + 1)) == NULL) {
uv_err_new(loop, ENOMEM);
return -1;
}
if ((size = readlink(path, buf, size)) == -1) {
req->errorno = errno;
req->result = -1;
free(buf);
} else {
/* Cannot conceivably fail since it shrinks the buffer. */
buf = realloc(buf, size + 1);
buf[size] = '\0';
req->result = 0;
req->ptr = buf;
}
return 0;
}
assert(0 && "unreachable");
}
int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode,
uv_fs_cb cb) {

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

@ -22,6 +22,7 @@
#include <assert.h>
#include <malloc.h>
#include <direct.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
@ -36,6 +37,7 @@
#define UV_FS_FREE_ARG1 0x0004
#define UV_FS_FREE_PTR 0x0008
#define UV_FS_CLEANEDUP 0x0010
#define UV_FS_LAST_ERROR_SET 0x0020
#define STRDUP_ARG(req, i) \
req->arg##i = (void*)strdup((const char*)req->arg##i); \
@ -70,6 +72,16 @@
uv_ref((loop));
#define SET_UV_LAST_ERROR_FROM_REQ(req) \
if (req->flags & UV_FS_LAST_ERROR_SET) { \
uv_set_sys_error(req->loop, req->last_error); \
}
#define SET_REQ_LAST_ERROR(req, error) \
req->last_error = error; \
req->flags |= UV_FS_LAST_ERROR_SET;
void uv_fs_init() {
_fmode = _O_BINARY;
}
@ -86,6 +98,7 @@ static void uv_fs_req_init_async(uv_loop_t* loop, uv_fs_t* req,
req->result = 0;
req->ptr = NULL;
req->errorno = 0;
req->last_error = 0;
memset(&req->overlapped, 0, sizeof(req->overlapped));
}
@ -187,6 +200,7 @@ void fs__readdir(uv_fs_t* req, const char* path, int flags) {
if(dir == INVALID_HANDLE_VALUE) {
result = -1;
SET_REQ_LAST_ERROR(req, GetLastError());
goto done;
}
@ -267,6 +281,9 @@ void fs__rename(uv_fs_t* req, const char* path, const char* new_path) {
void fs__fsync(uv_fs_t* req, uv_file file) {
int result = FlushFileBuffers((HANDLE)_get_osfhandle(file)) ? 0 : -1;
if (result == -1) {
SET_REQ_LAST_ERROR(req, GetLastError());
}
SET_REQ_RESULT(req, result);
}
@ -383,6 +400,128 @@ void fs__futime(uv_fs_t* req, uv_file file, double atime, double mtime) {
}
void fs__link(uv_fs_t* req, const char* path, const char* new_path) {
int result = CreateHardLinkA(new_path, path, NULL) ? 0 : -1;
if (result == -1) {
SET_REQ_LAST_ERROR(req, GetLastError());
}
SET_REQ_RESULT(req, result);
}
void fs__symlink(uv_fs_t* req, const char* path, const char* new_path,
int flags) {
int result;
if (pCreateSymbolicLinkA) {
result = pCreateSymbolicLinkA(new_path,
path,
flags & UV_FS_SYMLINK_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) ? 0 : -1;
if (result == -1) {
SET_REQ_LAST_ERROR(req, GetLastError());
}
} else {
result = -1;
errno = ENOTSUP;
}
SET_REQ_RESULT(req, result);
}
void fs__readlink(uv_fs_t* req, const char* path) {
int result = -1;
BOOL rv;
HANDLE symlink;
void* buffer;
DWORD bytes_returned;
REPARSE_DATA_BUFFER* reparse_data;
int utf8size;
symlink = CreateFileA(path,
0,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (INVALID_HANDLE_VALUE == symlink) {
result = -1;
SET_REQ_LAST_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_LAST_ERROR(req, GetLastError());
goto done;
}
reparse_data = buffer;
if (reparse_data->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
result = -1;
/* something is seriously wrong */
SET_REQ_LAST_ERROR(req, GetLastError());
goto done;
}
utf8size = uv_utf16_to_utf8(reparse_data->SymbolicLinkReparseBuffer.PathBuffer + (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t)),
reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t),
NULL,
0);
if (!utf8size) {
result = -1;
SET_REQ_LAST_ERROR(req, GetLastError());
goto done;
}
req->ptr = malloc(utf8size + 1);
if (!req->ptr) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
req->flags |= UV_FS_FREE_PTR;
utf8size = uv_utf16_to_utf8(reparse_data->SymbolicLinkReparseBuffer.PathBuffer + (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t)),
reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t),
req->ptr,
utf8size);
if (!utf8size) {
result = -1;
SET_REQ_LAST_ERROR(req, GetLastError());
goto done;
}
((char*)req->ptr)[utf8size] = '\0';
result = 0;
done:
if (buffer) {
free(buffer);
}
if (symlink != INVALID_HANDLE_VALUE) {
CloseHandle(symlink);
}
SET_REQ_RESULT(req, result);
}
void fs__nop(uv_fs_t* req) {
req->result = 0;
}
@ -464,6 +603,15 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
case UV_FS_FUTIME:
fs__futime(req, (uv_file)req->arg0, req->arg4, req->arg5);
break;
case UV_FS_LINK:
fs__link(req, (const char*)req->arg0, (const char*)req->arg1);
break;
case UV_FS_SYMLINK:
fs__symlink(req, (const char*)req->arg0, (const char*)req->arg1, (int)req->arg2);
break;
case UV_FS_READLINK:
fs__readlink(req, (const char*)req->arg0);
break;
case UV_FS_CHOWN:
case UV_FS_FCHOWN:
fs__nop(req);
@ -488,6 +636,7 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_OPEN);
fs__open(req, path, flags, mode);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -502,6 +651,7 @@ int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
} else {
uv_fs_req_init_sync(loop, req, UV_FS_CLOSE);
fs__close(req, file);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -517,6 +667,7 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_READ);
fs__read(req, file, buf, length, offset);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -532,6 +683,7 @@ int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_WRITE);
fs__write(req, file, buf, length, offset);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -548,6 +700,7 @@ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_UNLINK);
fs__unlink(req, path);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -564,6 +717,7 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_MKDIR);
fs__mkdir(req, path, mode);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -579,6 +733,7 @@ int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
} else {
uv_fs_req_init_sync(loop, req, UV_FS_RMDIR);
fs__rmdir(req, path);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -595,6 +750,7 @@ int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_READDIR);
fs__readdir(req, path, flags);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -603,22 +759,54 @@ int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
if (cb) {
uv_fs_req_init_async(loop, req, UV_FS_LINK, cb);
WRAP_REQ_ARGS2(req, path, new_path);
STRDUP_ARG(req, 0);
STRDUP_ARG(req, 1);
QUEUE_FS_TP_JOB(loop, req);
} else {
uv_fs_req_init_sync(loop, req, UV_FS_LINK);
fs__link(req, path, new_path);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
}
int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
const char* new_path, int flags, uv_fs_cb cb) {
if (cb) {
uv_fs_req_init_async(loop, req, UV_FS_SYMLINK, cb);
WRAP_REQ_ARGS3(req, path, new_path, flags);
STRDUP_ARG(req, 0);
STRDUP_ARG(req, 1);
QUEUE_FS_TP_JOB(loop, req);
} else {
uv_fs_req_init_sync(loop, req, UV_FS_SYMLINK);
fs__symlink(req, path, new_path, flags);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
}
int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
if (cb) {
uv_fs_req_init_async(loop, req, UV_FS_READLINK, cb);
WRAP_REQ_ARGS1(req, path);
STRDUP_ARG(req, 0);
QUEUE_FS_TP_JOB(loop, req);
} else {
uv_fs_req_init_sync(loop, req, UV_FS_READLINK);
fs__readlink(req, path);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
}
@ -632,6 +820,7 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_CHOWN);
fs__nop(req);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -647,6 +836,7 @@ int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, int uid,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_FCHOWN);
fs__nop(req);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -684,6 +874,7 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
if (path2) {
free(path2);
}
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -722,6 +913,7 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
if (path2) {
free(path2);
}
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -736,6 +928,7 @@ int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
} else {
uv_fs_req_init_sync(loop, req, UV_FS_FSTAT);
fs__fstat(req, file);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -753,6 +946,7 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_RENAME);
fs__rename(req, path, new_path);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -767,6 +961,7 @@ int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
} else {
uv_fs_req_init_sync(loop, req, UV_FS_FDATASYNC);
fs__fsync(req, file);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -781,6 +976,7 @@ int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
} else {
uv_fs_req_init_sync(loop, req, UV_FS_FSYNC);
fs__fsync(req, file);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -796,6 +992,7 @@ int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_FTRUNCATE);
fs__ftruncate(req, file, offset);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -811,6 +1008,7 @@ int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_SENDFILE);
fs__sendfile(req, out_fd, in_fd, in_offset, length);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -827,6 +1025,7 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_CHMOD);
fs__chmod(req, path, mode);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -842,6 +1041,7 @@ int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_FCHMOD);
fs__fchmod(req, file, mode);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -860,6 +1060,7 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_UTIME);
fs__utime(req, path, atime, mtime);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -877,6 +1078,7 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime,
} else {
uv_fs_req_init_sync(loop, req, UV_FS_FUTIME);
fs__futime(req, file, atime, mtime);
SET_UV_LAST_ERROR_FROM_REQ(req);
}
return 0;
@ -885,6 +1087,7 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime,
void uv_process_fs_req(uv_loop_t* loop, uv_fs_t* req) {
assert(req->cb);
SET_UV_LAST_ERROR_FROM_REQ(req);
req->cb(req);
}

4
deps/uv/src/win/winapi.c

@ -31,6 +31,7 @@ sNtQueryInformationFile pNtQueryInformationFile;
sNtSetInformationFile pNtSetInformationFile;
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
sCreateSymbolicLinkA pCreateSymbolicLinkA;
void uv_winapi_init() {
@ -74,4 +75,7 @@ void uv_winapi_init() {
pSetFileCompletionNotificationModes = (sSetFileCompletionNotificationModes)
GetProcAddress(kernel32_module, "SetFileCompletionNotificationModes");
pCreateSymbolicLinkA = (sCreateSymbolicLinkA)
GetProcAddress(kernel32_module, "CreateSymbolicLinkA");
}

35
deps/uv/src/win/winapi.h

@ -4075,6 +4075,33 @@
(FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_ERROR)))
#endif
/* from ntifs.h */
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
@ -4186,6 +4213,8 @@ typedef NTSTATUS (NTAPI *sNtSetInformationFile)
#define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1
#define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2
#define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
#ifdef __MINGW32__
typedef struct _OVERLAPPED_ENTRY {
ULONG_PTR lpCompletionKey;
@ -4207,6 +4236,11 @@ typedef BOOL (WINAPI* sSetFileCompletionNotificationModes)
(HANDLE FileHandle,
UCHAR Flags);
typedef BOOLEAN (WINAPI* sCreateSymbolicLinkA)
(LPCSTR lpSymlinkFileName,
LPCSTR lpTargetFileName,
DWORD dwFlags);
/* Ntapi function pointers */
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
@ -4217,5 +4251,6 @@ extern sNtSetInformationFile pNtSetInformationFile;
/* Kernel32 function pointers */
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
extern sCreateSymbolicLinkA pCreateSymbolicLinkA;
#endif /* UV_WIN_WINAPI_H_ */

236
deps/uv/test/test-fs.c

@ -25,6 +25,7 @@
#include "uv.h"
#include "task.h"
#include <errno.h>
#include <string.h> /* memset */
#include <fcntl.h>
#include <sys/stat.h>
@ -62,6 +63,9 @@ static int chmod_cb_count;
static int fchmod_cb_count;
static int chown_cb_count;
static int fchown_cb_count;
static int link_cb_count;
static int symlink_cb_count;
static int readlink_cb_count;
static uv_loop_t* loop;
@ -109,6 +113,29 @@ void check_permission(const char* filename, int mode) {
}
static void link_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_LINK);
ASSERT(req->result == 0);
link_cb_count++;
uv_fs_req_cleanup(req);
}
static void symlink_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_SYMLINK);
ASSERT(req->result == 0);
symlink_cb_count++;
uv_fs_req_cleanup(req);
}
static void readlink_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_READLINK);
ASSERT(req->result == 0);
ASSERT(strcmp(req->ptr, "test_file_symlink2") == 0);
readlink_cb_count++;
uv_fs_req_cleanup(req);
}
static void fchmod_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_FCHMOD);
ASSERT(req->result == 0);
@ -297,9 +324,8 @@ static void readdir_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_READDIR);
ASSERT(req->result == 2);
ASSERT(req->ptr);
ASSERT(strcmp((const char*)req->ptr, "file1") == 0);
ASSERT(strcmp((char*)req->ptr + strlen((const char*)req->ptr) + 1,
"file2") == 0);
ASSERT(memcmp(req->ptr, "file1\0file2\0", 12) == 0
|| memcmp(req->ptr, "file2\0file1\0", 12) == 0);
readdir_cb_count++;
uv_fs_req_cleanup(req);
ASSERT(!req->ptr);
@ -734,6 +760,7 @@ TEST_IMPL(fs_chmod) {
ASSERT(r == 0);
uv_run(loop);
ASSERT(chmod_cb_count == 1);
chmod_cb_count = 0; /* reset for the next test */
#endif
/* async chmod */
@ -821,3 +848,206 @@ TEST_IMPL(fs_chown) {
return 0;
}
TEST_IMPL(fs_link) {
int r;
uv_fs_t req;
uv_file file;
uv_file link;
/* Setup. */
unlink("test_file");
unlink("test_file_link");
unlink("test_file_link2");
uv_init();
loop = uv_default_loop();
r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT,
S_IWRITE | S_IREAD, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
file = req.result;
uv_fs_req_cleanup(&req);
r = uv_fs_write(loop, &req, file, test_buf, sizeof(test_buf), -1, NULL);
ASSERT(r == 0);
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
close(file);
/* sync link */
r = uv_fs_link(loop, &req, "test_file", "test_file_link", NULL);
ASSERT(r == 0);
ASSERT(req.result == 0);
uv_fs_req_cleanup(&req);
r = uv_fs_open(loop, &req, "test_file_link", O_RDWR, 0, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
link = req.result;
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
ASSERT(strcmp(buf, test_buf) == 0);
close(link);
/* async link */
r = uv_fs_link(loop, &req, "test_file", "test_file_link2", link_cb);
ASSERT(r == 0);
uv_run(loop);
ASSERT(link_cb_count == 1);
r = uv_fs_open(loop, &req, "test_file_link2", O_RDWR, 0, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
link = req.result;
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
ASSERT(strcmp(buf, test_buf) == 0);
close(link);
/*
* Run the loop just to check we don't have make any extraneous uv_ref()
* calls. This should drop out immediately.
*/
uv_run(loop);
/* Cleanup. */
unlink("test_file");
unlink("test_file_link");
unlink("test_file_link2");
return 0;
}
TEST_IMPL(fs_symlink) {
int r;
uv_fs_t req;
uv_file file;
uv_file link;
/* Setup. */
unlink("test_file");
unlink("test_file_symlink");
unlink("test_file_symlink2");
unlink("test_file_symlink_symlink");
unlink("test_file_symlink2_symlink");
uv_init();
loop = uv_default_loop();
r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT,
S_IWRITE | S_IREAD, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
file = req.result;
uv_fs_req_cleanup(&req);
r = uv_fs_write(loop, &req, file, test_buf, sizeof(test_buf), -1, NULL);
ASSERT(r == 0);
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
close(file);
/* sync symlink */
r = uv_fs_symlink(loop, &req, "test_file", "test_file_symlink", 0, NULL);
ASSERT(r == 0);
#ifdef _WIN32
if (req.result == -1) {
if (req.errorno == ENOTSUP) {
/*
* Windows doesn't support symlinks on older versions.
* We just pass the test and bail out early if we get ENOTSUP.
*/
return 0;
} else if (uv_last_error(loop).sys_errno_ == ERROR_PRIVILEGE_NOT_HELD) {
/*
* Creating a symlink is only allowed when running elevated.
* We pass the test and bail out early if we get ERROR_PRIVILEGE_NOT_HELD.
*/
return 0;
}
}
#endif
ASSERT(req.result == 0);
uv_fs_req_cleanup(&req);
r = uv_fs_open(loop, &req, "test_file_symlink", O_RDWR, 0, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
link = req.result;
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
ASSERT(strcmp(buf, test_buf) == 0);
close(link);
r = uv_fs_symlink(loop, &req, "test_file_symlink", "test_file_symlink_symlink", 0, NULL);
ASSERT(r == 0);
r = uv_fs_readlink(loop, &req, "test_file_symlink_symlink", NULL);
ASSERT(r == 0);
ASSERT(strcmp(req.ptr, "test_file_symlink") == 0);
uv_fs_req_cleanup(&req);
/* async link */
r = uv_fs_symlink(loop, &req, "test_file", "test_file_symlink2", 0, symlink_cb);
ASSERT(r == 0);
uv_run(loop);
ASSERT(symlink_cb_count == 1);
r = uv_fs_open(loop, &req, "test_file_symlink2", O_RDWR, 0, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
link = req.result;
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
ASSERT(strcmp(buf, test_buf) == 0);
close(link);
r = uv_fs_symlink(loop, &req, "test_file_symlink2", "test_file_symlink2_symlink", 0, NULL);
ASSERT(r == 0);
r = uv_fs_readlink(loop, &req, "test_file_symlink2_symlink", readlink_cb);
ASSERT(r == 0);
uv_run(loop);
ASSERT(readlink_cb_count == 1);
/*
* Run the loop just to check we don't have make any extraneous uv_ref()
* calls. This should drop out immediately.
*/
uv_run(loop);
/* Cleanup. */
unlink("test_file");
unlink("test_file_symlink");
unlink("test_file_symlink_symlink");
unlink("test_file_symlink2");
unlink("test_file_symlink2_symlink");
return 0;
}

4
deps/uv/test/test-list.h

@ -79,6 +79,8 @@ TEST_DECLARE (fs_async_sendfile)
TEST_DECLARE (fs_fstat)
TEST_DECLARE (fs_chmod)
TEST_DECLARE (fs_chown)
TEST_DECLARE (fs_link)
TEST_DECLARE (fs_symlink)
TEST_DECLARE (threadpool_queue_work_simple)
#ifdef _WIN32
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
@ -185,6 +187,8 @@ TASK_LIST_START
TEST_ENTRY (fs_fstat)
TEST_ENTRY (fs_chmod)
TEST_ENTRY (fs_chown)
TEST_ENTRY (fs_link)
TEST_ENTRY (fs_symlink)
TEST_ENTRY (threadpool_queue_work_simple)

7
src/node_file.cc

@ -384,10 +384,13 @@ static Handle<Value> Symlink(const Arguments& args) {
String::Utf8Value dest(args[0]->ToString());
String::Utf8Value path(args[1]->ToString());
// Just set to zero for now. Support UV_FS_SYMLINK_DIR in the future.
int flags = 0;
if (args[2]->IsFunction()) {
ASYNC_CALL(symlink, args[2], *dest, *path)
ASYNC_CALL(symlink, args[2], *dest, *path, flags)
} else {
SYNC_CALL(symlink, *path, *dest, *path)
SYNC_CALL(symlink, *path, *dest, *path, flags)
return Undefined();
}
}

Loading…
Cancel
Save