34
37
static void uv_fs_event_init_handle(uv_loop_t* loop, uv_fs_event_t* handle,
35
38
const char* filename, uv_fs_event_cb cb) {
36
handle->type = UV_FS_EVENT;
39
uv__handle_init(loop, (uv_handle_t*) handle, UV_FS_EVENT);
40
41
handle->dir_handle = INVALID_HANDLE_VALUE;
41
42
handle->buffer = NULL;
53
54
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
56
loop->counters.handle_init++;
57
loop->counters.fs_event_init++;
57
uv__handle_start(handle);
93
static int uv_split_path(const wchar_t* filename, wchar_t** dir,
91
static int uv_split_path(const WCHAR* filename, WCHAR** dir,
95
93
int len = wcslen(filename);
97
95
while (i > 0 && filename[--i] != '\\' && filename[i] != '/');
101
*dir = (wchar_t*)malloc((MAX_PATH + 1) * sizeof(wchar_t));
99
*dir = (WCHAR*)malloc((MAX_PATH + 1) * sizeof(WCHAR));
103
101
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
113
111
*file = wcsdup(filename);
116
*dir = (wchar_t*)malloc((i + 1) * sizeof(wchar_t));
114
*dir = (WCHAR*)malloc((i + 1) * sizeof(WCHAR));
118
116
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
137
135
const char* filename, uv_fs_event_cb cb, int flags) {
138
136
int name_size, is_path_dir;
139
137
DWORD attr, last_error;
140
wchar_t* dir = NULL, *dir_to_watch, *filenamew = NULL;
141
wchar_t short_path[MAX_PATH];
143
/* We don't support any flags yet. */
138
WCHAR* dir = NULL, *dir_to_watch, *filenamew = NULL;
139
WCHAR short_path[MAX_PATH];
146
141
uv_fs_event_init_handle(loop, handle, filename, cb);
148
143
/* Convert name to UTF16. */
149
name_size = uv_utf8_to_utf16(filename, NULL, 0) * sizeof(wchar_t);
150
filenamew = (wchar_t*)malloc(name_size);
144
name_size = uv_utf8_to_utf16(filename, NULL, 0) * sizeof(WCHAR);
145
filenamew = (WCHAR*)malloc(name_size);
151
146
if (!filenamew) {
152
147
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
155
if (!uv_utf8_to_utf16(filename, filenamew,
156
name_size / sizeof(wchar_t))) {
150
if (!uv_utf8_to_utf16(filename, filenamew,
151
name_size / sizeof(WCHAR))) {
157
152
uv__set_sys_error(loop, GetLastError());
172
167
handle->dirw = filenamew;
173
168
dir_to_watch = filenamew;
176
171
* filename is a file. So we split filename into dir & file parts, and
177
172
* watch the dir directory.
180
175
/* Convert to short path. */
181
if (!GetShortPathNameW(filenamew, short_path, COUNTOF(short_path))) {
176
if (!GetShortPathNameW(filenamew, short_path, ARRAY_SIZE(short_path))) {
182
177
last_error = GetLastError();
229
handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size,
224
handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size,
231
226
if (!handle->buffer) {
232
227
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
294
289
FILE_NOTIFY_INFORMATION* file_info;
295
290
int sizew, size, result;
296
291
char* filename = NULL;
297
wchar_t* filenamew, *long_filenamew = NULL;
292
WCHAR* filenamew, *long_filenamew = NULL;
298
293
DWORD offset = 0;
300
295
assert(req->type == UV_FS_EVENT_REQ);
304
299
/* If we're closing, don't report any callbacks, and just push the handle */
305
300
/* onto the endgame queue. */
306
if (handle->flags & UV_HANDLE_CLOSING) {
301
if (handle->flags & UV__HANDLE_CLOSING) {
307
302
uv_want_endgame(loop, (uv_handle_t*) handle);
317
312
assert(!filename);
318
313
assert(!long_filenamew);
321
316
* Fire the event only if we were asked to watch a directory,
322
317
* or if the filename filter matches.
324
319
if (handle->dirw ||
325
320
_wcsnicmp(handle->filew, file_info->FileName,
326
file_info->FileNameLength / sizeof(wchar_t)) == 0 ||
321
file_info->FileNameLength / sizeof(WCHAR)) == 0 ||
327
322
_wcsnicmp(handle->short_filew, file_info->FileName,
328
file_info->FileNameLength / sizeof(wchar_t)) == 0) {
323
file_info->FileNameLength / sizeof(WCHAR)) == 0) {
330
325
if (handle->dirw) {
332
* We attempt to convert the file name to its long form for
327
* We attempt to convert the file name to its long form for
333
328
* events that still point to valid files on disk.
334
329
* For removed and renamed events, we do not provide the file name.
337
332
file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) {
338
333
/* Construct a full path to the file. */
339
334
size = wcslen(handle->dirw) +
340
file_info->FileNameLength / sizeof(wchar_t) + 2;
335
file_info->FileNameLength / sizeof(WCHAR) + 2;
342
filenamew = (wchar_t*)malloc(size * sizeof(wchar_t));
337
filenamew = (WCHAR*)malloc(size * sizeof(WCHAR));
343
338
if (!filenamew) {
344
339
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
353
348
size = GetLongPathNameW(filenamew, NULL, 0);
356
long_filenamew = (wchar_t*)malloc(size * sizeof(wchar_t));
351
long_filenamew = (WCHAR*)malloc(size * sizeof(WCHAR));
357
352
if (!long_filenamew) {
358
353
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
386
381
* If we couldn't get the long name - just use the name
387
382
* provided by ReadDirectoryChangesW.
389
384
if (!long_filenamew) {
390
385
filenamew = file_info->FileName;
391
sizew = file_info->FileNameLength / sizeof(wchar_t);
386
sizew = file_info->FileNameLength / sizeof(WCHAR);
394
389
/* Removed or renamed callbacks don't provide filename. */
447
442
offset = file_info->NextEntryOffset;
448
} while (offset && !(handle->flags & UV_HANDLE_CLOSING));
443
} while (offset && !(handle->flags & UV__HANDLE_CLOSING));
450
445
handle->cb(handle, NULL, UV_CHANGE, 0);
454
449
handle->cb(handle, NULL, 0, -1);
457
if (!(handle->flags & UV_HANDLE_CLOSING)) {
452
if (!(handle->flags & UV__HANDLE_CLOSING)) {
458
453
uv_fs_event_queue_readdirchanges(loop, handle);
460
455
uv_want_endgame(loop, (uv_handle_t*)handle);
471
466
if (!handle->req_pending) {
472
467
uv_want_endgame(loop, (uv_handle_t*)handle);
470
uv__handle_closing(handle);
477
474
void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
478
if (handle->flags & UV_HANDLE_CLOSING &&
475
if (handle->flags & UV__HANDLE_CLOSING &&
479
476
!handle->req_pending) {
480
477
assert(!(handle->flags & UV_HANDLE_CLOSED));
481
handle->flags |= UV_HANDLE_CLOSED;
483
479
if (handle->buffer) {
484
480
_aligned_free(handle->buffer);