win: compare entire filename in watch events
This commit causes Window file watching events to compare the entire file path when filtering events. This fixes a bug where incomplete path comparisons would cause invalid events to be raised. Refs: https://github.com/libuv/libuv/pull/682 PR-URL: https://github.com/libuv/libuv/pull/924 Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
parent
34ee25734f
commit
77c8abae33
@ -344,6 +344,22 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
|
||||
}
|
||||
|
||||
|
||||
static int file_info_cmp(WCHAR* str, WCHAR* file_name, int file_name_len) {
|
||||
int str_len;
|
||||
|
||||
str_len = wcslen(str);
|
||||
|
||||
/*
|
||||
Since we only care about equality, return early if the strings
|
||||
aren't the same length
|
||||
*/
|
||||
if (str_len != (file_name_len / sizeof(WCHAR)))
|
||||
return -1;
|
||||
|
||||
return _wcsnicmp(str, file_name, str_len);
|
||||
}
|
||||
|
||||
|
||||
void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
|
||||
uv_fs_event_t* handle) {
|
||||
FILE_NOTIFY_INFORMATION* file_info;
|
||||
@ -383,10 +399,12 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
|
||||
* or if the filename filter matches.
|
||||
*/
|
||||
if (handle->dirw ||
|
||||
_wcsnicmp(handle->filew, file_info->FileName,
|
||||
file_info->FileNameLength / sizeof(WCHAR)) == 0 ||
|
||||
_wcsnicmp(handle->short_filew, file_info->FileName,
|
||||
file_info->FileNameLength / sizeof(WCHAR)) == 0) {
|
||||
file_info_cmp(handle->filew,
|
||||
file_info->FileName,
|
||||
file_info->FileNameLength) == 0 ||
|
||||
file_info_cmp(handle->short_filew,
|
||||
file_info->FileName,
|
||||
file_info->FileNameLength) == 0) {
|
||||
|
||||
if (handle->dirw) {
|
||||
/*
|
||||
|
||||
@ -53,6 +53,14 @@ static char fs_event_filename[PATH_MAX];
|
||||
static char fs_event_filename[1024];
|
||||
#endif /* defined(PATH_MAX) */
|
||||
static int timer_cb_touch_called;
|
||||
static int timer_cb_exact_called;
|
||||
|
||||
static void fs_event_fail(uv_fs_event_t* handle,
|
||||
const char* filename,
|
||||
int events,
|
||||
int status) {
|
||||
ASSERT(0 && "should never be called");
|
||||
}
|
||||
|
||||
static void create_dir(const char* name) {
|
||||
int r;
|
||||
@ -345,6 +353,21 @@ static void timer_cb_touch(uv_timer_t* timer) {
|
||||
timer_cb_touch_called++;
|
||||
}
|
||||
|
||||
static void timer_cb_exact(uv_timer_t* handle) {
|
||||
int r;
|
||||
|
||||
if (timer_cb_exact_called == 0) {
|
||||
touch_file("watch_dir/file.js");
|
||||
} else {
|
||||
uv_close((uv_handle_t*)handle, NULL);
|
||||
r = uv_fs_event_stop(&fs_event);
|
||||
ASSERT(r == 0);
|
||||
uv_close((uv_handle_t*) &fs_event, NULL);
|
||||
}
|
||||
|
||||
++timer_cb_exact_called;
|
||||
}
|
||||
|
||||
static void timer_cb_watch_twice(uv_timer_t* handle) {
|
||||
uv_fs_event_t* handles = handle->data;
|
||||
uv_close((uv_handle_t*) (handles + 0), NULL);
|
||||
@ -467,6 +490,45 @@ TEST_IMPL(fs_event_watch_file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_event_watch_file_exact_path) {
|
||||
/*
|
||||
This test watches a file named "file.jsx" and modifies a file named
|
||||
"file.js". The test verifies that no events occur for file.jsx.
|
||||
*/
|
||||
uv_loop_t* loop;
|
||||
int r;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
/* Setup */
|
||||
remove("watch_dir/file.js");
|
||||
remove("watch_dir/file.jsx");
|
||||
remove("watch_dir/");
|
||||
create_dir("watch_dir");
|
||||
create_file("watch_dir/file.js");
|
||||
create_file("watch_dir/file.jsx");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir/file.jsx", 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_timer_init(loop, &timer);
|
||||
ASSERT(r == 0);
|
||||
r = uv_timer_start(&timer, timer_cb_exact, 100, 100);
|
||||
ASSERT(r == 0);
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(timer_cb_exact_called == 2);
|
||||
|
||||
/* Cleanup */
|
||||
remove("watch_dir/file.js");
|
||||
remove("watch_dir/file.jsx");
|
||||
remove("watch_dir/");
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_event_watch_file_twice) {
|
||||
const char path[] = "test/fixtures/empty_file";
|
||||
uv_fs_event_t watchers[2];
|
||||
@ -626,12 +688,6 @@ TEST_IMPL(fs_event_no_callback_on_close) {
|
||||
}
|
||||
|
||||
|
||||
static void fs_event_fail(uv_fs_event_t* handle, const char* filename,
|
||||
int events, int status) {
|
||||
ASSERT(0 && "should never be called");
|
||||
}
|
||||
|
||||
|
||||
static void timer_cb(uv_timer_t* handle) {
|
||||
int r;
|
||||
|
||||
|
||||
@ -275,6 +275,7 @@ TEST_DECLARE (fs_read_file_eof)
|
||||
TEST_DECLARE (fs_event_watch_dir)
|
||||
TEST_DECLARE (fs_event_watch_dir_recursive)
|
||||
TEST_DECLARE (fs_event_watch_file)
|
||||
TEST_DECLARE (fs_event_watch_file_exact_path)
|
||||
TEST_DECLARE (fs_event_watch_file_twice)
|
||||
TEST_DECLARE (fs_event_watch_file_current_dir)
|
||||
#ifdef _WIN32
|
||||
@ -724,6 +725,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (fs_event_watch_dir)
|
||||
TEST_ENTRY (fs_event_watch_dir_recursive)
|
||||
TEST_ENTRY (fs_event_watch_file)
|
||||
TEST_ENTRY (fs_event_watch_file_exact_path)
|
||||
TEST_ENTRY (fs_event_watch_file_twice)
|
||||
TEST_ENTRY (fs_event_watch_file_current_dir)
|
||||
#ifdef _WIN32
|
||||
|
||||
Loading…
Reference in New Issue
Block a user