From 0df8ffe4728828c24a05b989007b5cc9bba1e365 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sun, 4 Sep 2011 02:31:12 +0200 Subject: [PATCH] uv: upgrade to 6422a14 --- deps/uv/Makefile | 2 +- deps/uv/config-mingw.mk | 12 +-- deps/uv/src/win/fs.c | 149 +++++++++++++++++++++++++++++---- deps/uv/src/win/loop-watcher.c | 2 +- deps/uv/src/win/winapi.c | 8 ++ deps/uv/src/win/winapi.h | 15 ++++ deps/uv/test/test-fs.c | 122 +++++++++++++++++++++++++-- deps/uv/test/test-list.h | 2 + 8 files changed, 276 insertions(+), 36 deletions(-) diff --git a/deps/uv/Makefile b/deps/uv/Makefile index d125271684..59be3de08f 100644 --- a/deps/uv/Makefile +++ b/deps/uv/Makefile @@ -80,7 +80,7 @@ endif TESTS=test/echo-server.c test/test-*.c BENCHMARKS=test/echo-server.c test/dns-server.c test/benchmark-*.c -all: uv.a test/run-tests test/run-benchmarks +all: uv.a test/run-tests$(E) test/run-benchmarks$(E) $(CARES_OBJS): %.o: %.c $(CC) -o $*.o -c $(CFLAGS) $(CPPFLAGS) $< -DHAVE_CONFIG_H diff --git a/deps/uv/config-mingw.mk b/deps/uv/config-mingw.mk index c7b5577f10..d4daca8a1f 100644 --- a/deps/uv/config-mingw.mk +++ b/deps/uv/config-mingw.mk @@ -36,25 +36,19 @@ RUNNER_LINKFLAGS=$(LINKFLAGS) RUNNER_LIBS=-lws2_32 RUNNER_SRC=test/runner-win.c -uv.a: $(WIN_OBJS) src/uv-common.o src/uv-eio.o src/eio/eio.o $(CARES_OBJS) - $(AR) rcs uv.a src/win/*.o src/uv-common.o src/uv-eio.o src/eio/eio.o $(CARES_OBJS) +uv.a: $(WIN_OBJS) src/uv-common.o $(CARES_OBJS) + $(AR) rcs uv.a src/win/*.o src/uv-common.o $(CARES_OBJS) src/win/%.o: src/win/%.c src/win/internal.h $(CC) $(CFLAGS) -o $@ -c $< -src/uv-common.o: src/uv-common.c include/uv.h include/uv-win.h +src/uv-common.o: src/uv-common.c include/uv.h include/uv-private/uv-win.h $(CC) $(CFLAGS) -c src/uv-common.c -o src/uv-common.o EIO_CPPFLAGS += $(CPPFLAGS) EIO_CPPFLAGS += -DEIO_STACKSIZE=65536 EIO_CPPFLAGS += -D_GNU_SOURCE -src/eio/eio.o: src/eio/eio.c - $(CC) $(EIO_CPPFLAGS) $(CFLAGS) -c src/eio/eio.c -o src/eio/eio.o - -src/uv-eio.o: src/uv-eio.c - $(CC) $(CPPFLAGS) -Isrc/eio/ $(CFLAGS) -c src/uv-eio.c -o src/uv-eio.o - clean-platform: -rm -f src/ares/*.o -rm -f src/eio/*.o diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index cd647181aa..63d569b4b0 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -323,6 +323,50 @@ void fs__chmod(uv_fs_t* req, const char* path, int mode) { } +void fs__fchmod(uv_fs_t* req, uv_file file, int mode) { + int result; + HANDLE handle; + NTSTATUS nt_status; + IO_STATUS_BLOCK io_status; + FILE_BASIC_INFORMATION file_info; + + handle = (HANDLE)_get_osfhandle(file); + + nt_status = pNtQueryInformationFile(handle, + &io_status, + &file_info, + sizeof file_info, + FileBasicInformation); + + if (nt_status != STATUS_SUCCESS) { + result = -1; + goto done; + } + + if (mode & _S_IWRITE) { + file_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; + } else { + file_info.FileAttributes |= FILE_ATTRIBUTE_READONLY; + } + + nt_status = pNtSetInformationFile(handle, + &io_status, + &file_info, + sizeof file_info, + FileBasicInformation); + + if (nt_status != STATUS_SUCCESS) { + result = -1; + goto done; + } + + result = 0; + +done: + SET_REQ_RESULT(req, result); +} + + void fs__utime(uv_fs_t* req, const char* path, double atime, double mtime) { int result; struct _utimbuf b = {(time_t)atime, (time_t)mtime}; @@ -339,6 +383,11 @@ void fs__futime(uv_fs_t* req, uv_file file, double atime, double mtime) { } +void fs__nop(uv_fs_t* req) { + req->result = 0; +} + + static DWORD WINAPI uv_fs_thread_proc(void* parameter) { uv_fs_t* req = (uv_fs_t*) parameter; uv_loop_t* loop = req->loop; @@ -380,6 +429,7 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) { fs__readdir(req, (const char*)req->arg0, (int)req->arg1); break; case UV_FS_STAT: + case UV_FS_LSTAT: fs__stat(req, (const char*)req->arg0); break; case UV_FS_FSTAT: @@ -405,12 +455,19 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) { case UV_FS_CHMOD: fs__chmod(req, (const char*)req->arg0, (int)req->arg1); break; + case UV_FS_FCHMOD: + fs__fchmod(req, (uv_file)req->arg0, (int)req->arg1); + break; case UV_FS_UTIME: fs__utime(req, (const char*)req->arg0, req->arg4, req->arg5); break; case UV_FS_FUTIME: fs__futime(req, (uv_file)req->arg0, req->arg4, req->arg5); break; + case UV_FS_CHOWN: + case UV_FS_FCHOWN: + fs__nop(req); + break; default: assert(!"bad uv_fs_type"); } @@ -544,13 +601,6 @@ int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, } -int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - assert(0 && "implement me"); - return -1; -} - - -// uv_fs_readlink, uv_fs_fchmod, uv_fs_chown, uv_fs_fchown 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"); @@ -572,24 +622,34 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, } -int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, - uv_fs_cb cb) { - assert(0 && "implement me"); - return -1; -} - - int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid, int gid, uv_fs_cb cb) { - assert(0 && "implement me"); - return -1; + if (cb) { + uv_fs_req_init_async(loop, req, UV_FS_CHOWN, cb); + WRAP_REQ_ARGS3(req, path, uid, gid); + STRDUP_ARG(req, 0); + QUEUE_FS_TP_JOB(loop, req); + } else { + uv_fs_req_init_sync(loop, req, UV_FS_CHOWN); + fs__nop(req); + } + + return 0; } int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, int uid, int gid, uv_fs_cb cb) { - assert(0 && "implement me"); - return -1; + if (cb) { + uv_fs_req_init_async(loop, req, UV_FS_FCHOWN, cb); + WRAP_REQ_ARGS3(req, file, uid, gid); + QUEUE_FS_TP_JOB(loop, req); + } else { + uv_fs_req_init_sync(loop, req, UV_FS_FCHOWN); + fs__nop(req); + } + + return 0; } @@ -630,6 +690,44 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { } +/* TODO: add support for links. */ +int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { + int len = strlen(path); + char* path2 = NULL; + int has_backslash = (path[len - 1] == '\\' || path[len - 1] == '/'); + + if (path[len - 1] == '\\' || path[len - 1] == '/') { + path2 = strdup(path); + if (!path2) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + } + + path2[len - 1] = '\0'; + } + + if (cb) { + uv_fs_req_init_async(loop, req, UV_FS_LSTAT, cb); + if (path2) { + WRAP_REQ_ARGS1(req, path2); + req->flags |= UV_FS_FREE_ARG0; + } else { + 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_LSTAT); + fs__stat(req, path2 ? path2 : path); + if (path2) { + free(path2); + } + } + + return 0; +} + + int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_FSTAT, cb); @@ -735,6 +833,21 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, } +int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, + uv_fs_cb cb) { + if (cb) { + uv_fs_req_init_async(loop, req, UV_FS_FCHMOD, cb); + WRAP_REQ_ARGS2(req, file, mode); + QUEUE_FS_TP_JOB(loop, req); + } else { + uv_fs_req_init_sync(loop, req, UV_FS_FCHMOD); + fs__fchmod(req, file, mode); + } + + return 0; +} + + int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb) { if (cb) { diff --git a/deps/uv/src/win/loop-watcher.c b/deps/uv/src/win/loop-watcher.c index 15bfae3693..c597cd99b1 100644 --- a/deps/uv/src/win/loop-watcher.c +++ b/deps/uv/src/win/loop-watcher.c @@ -49,7 +49,7 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) { uv_ref(loop); \ \ loop->counters.handle_init++; \ - loop->counters.##name##_init++; \ + loop->counters.name##_init++; \ \ return 0; \ } \ diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c index 739cb9c5cc..bf4d5e3896 100644 --- a/deps/uv/src/win/winapi.c +++ b/deps/uv/src/win/winapi.c @@ -28,6 +28,7 @@ sRtlNtStatusToDosError pRtlNtStatusToDosError; sNtQueryInformationFile pNtQueryInformationFile; +sNtSetInformationFile pNtSetInformationFile; sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; @@ -55,6 +56,13 @@ void uv_winapi_init() { uv_fatal_error(GetLastError(), "GetProcAddress"); } + pNtSetInformationFile = (sNtSetInformationFile) GetProcAddress( + ntdll_module, + "NtSetInformationFile"); + if (pNtSetInformationFile == NULL) { + uv_fatal_error(GetLastError(), "GetProcAddress"); + } + kernel32_module = GetModuleHandleA("kernel32.dll"); if (kernel32_module == NULL) { uv_fatal_error(GetLastError(), "GetModuleHandleA"); diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index 00eda7c60f..9feee8bb5c 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4096,6 +4096,14 @@ typedef struct _FILE_PIPE_LOCAL_INFORMATION { ULONG NamedPipeEnd; } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; +typedef struct _FILE_BASIC_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + DWORD FileAttributes; +} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; + typedef enum _FILE_INFORMATION_CLASS { FileDirectoryInformation = 1, FileFullDirectoryInformation, @@ -4165,6 +4173,12 @@ typedef NTSTATUS (NTAPI *sNtQueryInformationFile) ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); +typedef NTSTATUS (NTAPI *sNtSetInformationFile) + (HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass); /* * Kernel32 headers @@ -4197,6 +4211,7 @@ typedef BOOL (WINAPI* sSetFileCompletionNotificationModes) /* Ntapi function pointers */ extern sRtlNtStatusToDosError pRtlNtStatusToDosError; extern sNtQueryInformationFile pNtQueryInformationFile; +extern sNtSetInformationFile pNtSetInformationFile; /* Kernel32 function pointers */ diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 1d172e5eb3..27f91732f9 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -60,6 +60,8 @@ static int sendfile_cb_count; static int fstat_cb_count; static int chmod_cb_count; static int fchmod_cb_count; +static int chown_cb_count; +static int fchown_cb_count; static uv_loop_t* loop; @@ -93,7 +95,15 @@ void check_permission(const char* filename, int mode) { ASSERT(req.result == 0); s = req.ptr; +#ifdef _WIN32 + /* + * On Windows, chmod can only modify S_IWUSR (_S_IWRITE) bit, + * so only testing for the specified flags. + */ + ASSERT((s->st_mode & 0777) & mode); +#else ASSERT((s->st_mode & 0777) == mode); +#endif uv_fs_req_cleanup(&req); } @@ -104,7 +114,7 @@ static void fchmod_cb(uv_fs_t* req) { ASSERT(req->result == 0); fchmod_cb_count++; uv_fs_req_cleanup(req); - check_permission("test_file", 0600); + check_permission("test_file", (int)req->data); } @@ -113,7 +123,23 @@ static void chmod_cb(uv_fs_t* req) { ASSERT(req->result == 0); chmod_cb_count++; uv_fs_req_cleanup(req); - check_permission("test_file", 0200); + check_permission("test_file", (int)req->data); +} + + +static void fchown_cb(uv_fs_t* req) { + ASSERT(req->fs_type == UV_FS_FCHOWN); + ASSERT(req->result == 0); + fchown_cb_count++; + uv_fs_req_cleanup(req); +} + + +static void chown_cb(uv_fs_t* req) { + ASSERT(req->fs_type == UV_FS_CHOWN); + ASSERT(req->result == 0); + chown_cb_count++; + uv_fs_req_cleanup(req); } @@ -598,6 +624,7 @@ TEST_IMPL(fs_fstat) { int r; uv_fs_t req; uv_file file; + struct stat* s; /* Setup. */ unlink("test_file"); @@ -606,7 +633,8 @@ TEST_IMPL(fs_fstat) { loop = uv_default_loop(); - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, 0, NULL); + 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; @@ -620,7 +648,7 @@ TEST_IMPL(fs_fstat) { r = uv_fs_fstat(loop, &req, file, NULL); ASSERT(r == 0); ASSERT(req.result == 0); - struct stat* s = req.ptr; + s = req.ptr; ASSERT(s->st_size == sizeof(test_buf)); uv_fs_req_cleanup(&req); @@ -637,7 +665,7 @@ TEST_IMPL(fs_fstat) { uv_fs_req_cleanup(&req); /* - * Run the loop just to check we don't have make any extranious uv_ref() + * Run the loop just to check we don't have make any extraneous uv_ref() * calls. This should drop out immediately. */ uv_run(loop); @@ -661,7 +689,8 @@ TEST_IMPL(fs_chmod) { loop = uv_default_loop(); - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, 0, NULL); + 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; @@ -672,6 +701,7 @@ TEST_IMPL(fs_chmod) { ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); +#ifndef _WIN32 /* Make the file write-only */ r = uv_fs_chmod(loop, &req, "test_file", 0200, NULL); ASSERT(r == 0); @@ -679,6 +709,15 @@ TEST_IMPL(fs_chmod) { uv_fs_req_cleanup(&req); check_permission("test_file", 0200); +#endif + + /* Make the file read-only */ + r = uv_fs_chmod(loop, &req, "test_file", 0400, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + check_permission("test_file", 0400); /* Make the file read+write with sync uv_fs_fchmod */ r = uv_fs_fchmod(loop, &req, file, 0600, NULL); @@ -688,13 +727,24 @@ TEST_IMPL(fs_chmod) { check_permission("test_file", 0600); +#ifndef _WIN32 /* async chmod */ + req.data = (void*)0200; r = uv_fs_chmod(loop, &req, "test_file", 0200, chmod_cb); ASSERT(r == 0); uv_run(loop); ASSERT(chmod_cb_count == 1); +#endif + + /* async chmod */ + req.data = (void*)0400; + r = uv_fs_chmod(loop, &req, "test_file", 0400, chmod_cb); + ASSERT(r == 0); + uv_run(loop); + ASSERT(chmod_cb_count == 1); /* async fchmod */ + req.data = (void*)0600; r = uv_fs_fchmod(loop, &req, file, 0600, fchmod_cb); ASSERT(r == 0); uv_run(loop); @@ -703,7 +753,7 @@ TEST_IMPL(fs_chmod) { close(file); /* - * Run the loop just to check we don't have make any extranious uv_ref() + * Run the loop just to check we don't have make any extraneous uv_ref() * calls. This should drop out immediately. */ uv_run(loop); @@ -713,3 +763,61 @@ TEST_IMPL(fs_chmod) { return 0; } + + +TEST_IMPL(fs_chown) { + int r; + uv_fs_t req; + uv_file file; + + /* Setup. */ + unlink("test_file"); + + 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); + + /* sync chown */ + r = uv_fs_chown(loop, &req, "test_file", -1, -1, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + /* sync fchown */ + r = uv_fs_fchown(loop, &req, file, -1, -1, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + /* async chown */ + r = uv_fs_chown(loop, &req, "test_file", -1, -1, chown_cb); + ASSERT(r == 0); + uv_run(loop); + ASSERT(chown_cb_count == 1); + + /* async fchown */ + r = uv_fs_fchown(loop, &req, file, -1, -1, fchown_cb); + ASSERT(r == 0); + uv_run(loop); + ASSERT(fchown_cb_count == 1); + + close(file); + + /* + * 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"); + + return 0; +} \ No newline at end of file diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 032060d83d..94cf03c6bd 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -78,6 +78,7 @@ TEST_DECLARE (fs_async_dir) TEST_DECLARE (fs_async_sendfile) TEST_DECLARE (fs_fstat) TEST_DECLARE (fs_chmod) +TEST_DECLARE (fs_chown) TEST_DECLARE (threadpool_queue_work_simple) #ifdef _WIN32 TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) @@ -183,6 +184,7 @@ TASK_LIST_START TEST_ENTRY (fs_async_sendfile) TEST_ENTRY (fs_fstat) TEST_ENTRY (fs_chmod) + TEST_ENTRY (fs_chown) TEST_ENTRY (threadpool_queue_work_simple)