Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Merge remote branch 'origin/v0.6'

  • Loading branch information...
ry committed Jan 9, 2012
2 parents 4ad33e9 + 803f5a0 commit 51ea46de45db94bdb0e6af24ee8e3102e292598b
Showing with 254 additions and 38 deletions.
  1. +2 −0 LICENSE
  2. +1 −1 include/uv-private/uv-win.h
  3. +2 −1 include/uv.h
  4. +17 −5 src/unix/dl.c
  5. +12 −0 src/unix/internal.h
  6. +2 −0 src/unix/kqueue.c
  7. +2 −0 src/unix/linux.c
  8. +2 −0 src/unix/sunos.c
  9. +117 −28 src/win/fs-event.c
  10. +6 −2 src/win/fs.c
  11. +19 −1 test/test-fs-event.c
  12. +68 −0 test/test-fs.c
  13. +4 −0 test/test-list.h
@@ -33,6 +33,8 @@ The externally maintained libraries used by libuv are:

- ngx_queue.h (from Nginx), copyright Igor Sysoev. Two clause BSD license.

- c-ares, copyright Daniel Stenberg and others. MIT licensed.

- libev, located at ev/ is copyright Marc Alexander Lehmann, and
dual-licensed under the MIT license and GPL2.

@@ -439,7 +439,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
uv_fs_event_cb cb; \
wchar_t* filew; \
wchar_t* short_filew; \
int is_path_dir; \
wchar_t* dirw; \
char* buffer;

int uv_utf16_to_utf8(const wchar_t* utf16Buffer, size_t utf16Size,
@@ -1313,7 +1313,8 @@ UV_EXTERN uv_err_t uv_dlopen(const char* filename, uv_lib_t* library);
UV_EXTERN uv_err_t uv_dlclose(uv_lib_t library);

/*
* Retrieves a data pointer from a dynamic library.
* Retrieves a data pointer from a dynamic library. It is legal for a symbol to
* map to NULL.
*/
UV_EXTERN uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr);

@@ -25,11 +25,17 @@
#include <dlfcn.h>
#include <errno.h>

/* The dl family of functions don't set errno. We need a good way to communicate
* errors to the caller but there is only dlerror() and that returns a string -
* a string that may or may not be safe to keep a reference to...
*/
static const uv_err_t uv_inval_ = { UV_EINVAL, EINVAL };


uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) {
void* handle = dlopen(filename, RTLD_LAZY);
if (handle == NULL) {
return uv__new_sys_error(errno);
return uv_inval_;
}

*library = handle;
@@ -39,17 +45,23 @@ uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) {

uv_err_t uv_dlclose(uv_lib_t library) {
if (dlclose(library) != 0) {
return uv__new_sys_error(errno);
return uv_inval_;
}

return uv_ok_;
}


uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr) {
void* address = dlsym(library, name);
if (address == NULL) {
return uv__new_sys_error(errno);
void* address;

/* Reset error status. */
dlerror();

address = dlsym(library, name);

if (dlerror()) {
return uv_inval_;
}

*ptr = (void*) address;
@@ -59,6 +59,18 @@
# define HAVE_SYS_ACCEPT4 1
# endif

# ifndef O_CLOEXEC
# define O_CLOEXEC 02000000
# endif

# ifndef SOCK_CLOEXEC
# define SOCK_CLOEXEC O_CLOEXEC
# endif

# ifndef SOCK_NONBLOCK
# define SOCK_NONBLOCK O_NONBLOCK
# endif

# if HAVE_SYS_UTIMESAT
inline static int sys_utimesat(int dirfd,
const char* path,
@@ -43,10 +43,12 @@ static void uv__fs_event_start(uv_fs_event_t* handle) {
handle->fd,
EV_LIBUV_KQUEUE_HACK);
ev_io_start(handle->loop->ev, &handle->event_watcher);
ev_unref(handle->loop->ev);
}


static void uv__fs_event_stop(uv_fs_event_t* handle) {
ev_ref(handle->loop->ev);
ev_io_stop(handle->loop->ev, &handle->event_watcher);
}

@@ -650,12 +650,14 @@ int uv_fs_event_init(uv_loop_t* loop,

ev_io_init(&handle->read_watcher, uv__inotify_read, fd, EV_READ);
ev_io_start(loop->ev, &handle->read_watcher);
ev_unref(loop->ev);

return 0;
}


void uv__fs_event_destroy(uv_fs_event_t* handle) {
ev_ref(handle->loop->ev);
ev_io_stop(handle->loop->ev, &handle->read_watcher);
uv__close(handle->fd);
handle->fd = -1;
@@ -184,12 +184,14 @@ int uv_fs_event_init(uv_loop_t* loop,

ev_io_init(&handle->event_watcher, uv__fs_event_read, portfd, EV_READ);
ev_io_start(loop->ev, &handle->event_watcher);
ev_unref(loop->ev);

return 0;
}


void uv__fs_event_destroy(uv_fs_event_t* handle) {
ev_ref(handle->loop->ev);
ev_io_stop(handle->loop->ev, &handle->event_watcher);
uv__close(handle->fd);
handle->fd = -1;
@@ -22,6 +22,7 @@
#include <assert.h>
#include <malloc.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "uv.h"
#include "internal.h"
@@ -36,12 +37,12 @@ static void uv_fs_event_init_handle(uv_loop_t* loop, uv_fs_event_t* handle,
handle->loop = loop;
handle->flags = 0;
handle->cb = cb;
handle->is_path_dir = 0;
handle->dir_handle = INVALID_HANDLE_VALUE;
handle->buffer = NULL;
handle->req_pending = 0;
handle->filew = NULL;
handle->short_filew = NULL;
handle->dirw = NULL;

uv_req_init(loop, (uv_req_t*)&handle->req);
handle->req.type = UV_FS_EVENT_REQ;
@@ -134,9 +135,9 @@ static int uv_split_path(const wchar_t* filename, wchar_t** dir,

int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
const char* filename, uv_fs_event_cb cb, int flags) {
int name_size;
int name_size, is_path_dir;
DWORD attr, last_error;
wchar_t* dir = NULL, *dir_to_watch, *filenamew;
wchar_t* dir = NULL, *dir_to_watch, *filenamew = NULL;
wchar_t short_path[MAX_PATH];

/* We don't support any flags yet. */
@@ -164,10 +165,11 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
goto error;
}

handle->is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;

if (handle->is_path_dir) {
if (is_path_dir) {
/* filename is a directory, so that's the directory that we will watch. */
handle->dirw = filenamew;
dir_to_watch = filenamew;
} else {
/*
@@ -192,6 +194,8 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
}

dir_to_watch = dir;
free(filenamew);
filenamew = NULL;
}

handle->dir_handle = CreateFileW(dir_to_watch,
@@ -268,6 +272,8 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
handle->short_filew = NULL;
}

free(filenamew);

if (handle->dir_handle != INVALID_HANDLE_VALUE) {
CloseHandle(handle->dir_handle);
handle->dir_handle = INVALID_HANDLE_VALUE;
@@ -286,8 +292,9 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
uv_fs_event_t* handle) {
FILE_NOTIFY_INFORMATION* file_info;
int sizew, size, result;
char* filename = NULL;
int utf8size;
wchar_t* filenamew, *long_filenamew = NULL;
DWORD offset = 0;

assert(req->type == UV_FS_EVENT_REQ);
@@ -300,39 +307,114 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
if (req->overlapped.InternalHigh > 0) {
do {
file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset);
assert(!filename);
assert(!long_filenamew);

/*
* Fire the event only if we were asked to watch a directory,
* or if the filename filter matches.
*/
if (handle->is_path_dir ||
if (handle->dirw ||
_wcsnicmp(handle->filew, file_info->FileName,
file_info->FileNameLength / sizeof(wchar_t)) == 0 ||
_wcsnicmp(handle->short_filew, file_info->FileName,
file_info->FileNameLength / sizeof(wchar_t)) == 0) {

/* Convert the filename to utf8. */
utf8size = uv_utf16_to_utf8(file_info->FileName,
file_info->FileNameLength /
sizeof(wchar_t),
NULL,
0);
if (utf8size) {
filename = (char*)malloc(utf8size + 1);
if (!filename) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}

utf8size = uv_utf16_to_utf8(file_info->FileName,
file_info->FileNameLength /
sizeof(wchar_t),
filename,
utf8size);
if (utf8size) {
filename[utf8size] = '\0';
if (handle->dirw) {
/*
* We attempt to convert the file name to its long form for
* events that still point to valid files on disk.
* For removed and renamed events, we do not provide the file name.
*/
if (file_info->Action != FILE_ACTION_REMOVED &&
file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) {
/* Construct a full path to the file. */
size = wcslen(handle->dirw) +
file_info->FileNameLength / sizeof(wchar_t) + 2;

filenamew = (wchar_t*)malloc(size * sizeof(wchar_t));
if (!filenamew) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}

_snwprintf(filenamew, size, L"%s\\%s", handle->dirw,
file_info->FileName);

filenamew[size - 1] = L'\0';

/* Convert to long name. */
size = GetLongPathNameW(filenamew, NULL, 0);

if (size) {
long_filenamew = (wchar_t*)malloc(size * sizeof(wchar_t));
if (!long_filenamew) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}

size = GetLongPathNameW(filenamew, long_filenamew, size);
if (size) {
long_filenamew[size] = '\0';
} else {
free(long_filenamew);
long_filenamew = NULL;
}
}

free(filenamew);

if (long_filenamew) {
/* Get the file name out of the long path. */
result = uv_split_path(long_filenamew, NULL, &filenamew);
free(long_filenamew);

if (result == 0) {
long_filenamew = filenamew;
sizew = -1;
} else {
long_filenamew = NULL;
}
}

/*
* If we couldn't get the long name - just use the name
* provided by ReadDirectoryChangesW.
*/
if (!long_filenamew) {
filenamew = file_info->FileName;
sizew = file_info->FileNameLength / sizeof(wchar_t);
}
} else {
free(filename);
filename = NULL;
/* Removed or renamed callbacks don't provide filename. */
filenamew = NULL;
}
} else {
/* We already have the long name of the file, so just use it. */
filenamew = handle->filew;
sizew = -1;
}

if (filenamew) {
/* Convert the filename to utf8. */
size = uv_utf16_to_utf8(filenamew,
sizew,
NULL,
0);
if (size) {
filename = (char*)malloc(size + 1);
if (!filename) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}

size = uv_utf16_to_utf8(filenamew,
sizew,
filename,
size);
if (size) {
filename[size] = '\0';
} else {
free(filename);
filename = NULL;
}
}
}

@@ -351,6 +433,8 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,

free(filename);
filename = NULL;
free(long_filenamew);
long_filenamew = NULL;
}

offset = file_info->NextEntryOffset;
@@ -411,6 +495,11 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
handle->filename = NULL;
}

if (handle->dirw) {
free(handle->dirw);
handle->dirw = NULL;
}

if (handle->close_cb) {
handle->close_cb((uv_handle_t*)handle);
}
@@ -542,8 +542,12 @@ void fs__fstat(uv_fs_t* req, uv_file file) {


void fs__rename(uv_fs_t* req, const wchar_t* path, const wchar_t* new_path) {
int result = _wrename(path, new_path);
SET_REQ_RESULT(req, result);
if (!MoveFileExW(path, new_path, MOVEFILE_REPLACE_EXISTING)) {
SET_REQ_RESULT_WIN32_ERROR(req, GetLastError());
return;
}

SET_REQ_RESULT(req, 0);
}


0 comments on commit 51ea46d

Please sign in to comment.
You can’t perform that action at this time.