noderb 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ext/noderb_extension/extconf.rb +15 -11
- data/ext/noderb_extension/libuv/AUTHORS +3 -0
- data/ext/noderb_extension/libuv/{README → README.md} +48 -6
- data/ext/noderb_extension/libuv/common.gypi +6 -1
- data/ext/noderb_extension/libuv/config-unix.mk +1 -1
- data/ext/noderb_extension/libuv/include/uv-private/uv-linux.h +29 -0
- data/ext/noderb_extension/libuv/include/uv-private/uv-unix.h +9 -0
- data/ext/noderb_extension/libuv/include/uv-private/uv-win.h +38 -3
- data/ext/noderb_extension/libuv/include/uv.h +55 -3
- data/ext/noderb_extension/libuv/src/unix/cares.c +1 -0
- data/ext/noderb_extension/libuv/src/unix/core.c +20 -4
- data/ext/noderb_extension/libuv/src/unix/cygwin.c +16 -0
- data/ext/noderb_extension/libuv/src/unix/darwin.c +18 -0
- data/ext/noderb_extension/libuv/src/unix/freebsd.c +18 -1
- data/ext/noderb_extension/libuv/src/unix/fs.c +18 -9
- data/ext/noderb_extension/libuv/src/unix/internal.h +24 -0
- data/ext/noderb_extension/libuv/src/unix/linux.c +133 -1
- data/ext/noderb_extension/libuv/src/unix/netbsd.c +18 -1
- data/ext/noderb_extension/libuv/src/unix/stream.c +21 -7
- data/ext/noderb_extension/libuv/src/unix/sunos.c +18 -1
- data/ext/noderb_extension/libuv/src/unix/tty.c +41 -0
- data/ext/noderb_extension/libuv/src/unix/udp.c +1 -0
- data/ext/noderb_extension/libuv/src/win/core.c +3 -0
- data/ext/noderb_extension/libuv/src/win/fs-event.c +384 -0
- data/ext/noderb_extension/libuv/src/win/getaddrinfo.c +7 -2
- data/ext/noderb_extension/libuv/src/win/handle.c +41 -0
- data/ext/noderb_extension/libuv/src/win/internal.h +36 -0
- data/ext/noderb_extension/libuv/src/win/pipe.c +3 -0
- data/ext/noderb_extension/libuv/src/win/process.c +7 -2
- data/ext/noderb_extension/libuv/src/win/req.c +10 -0
- data/ext/noderb_extension/libuv/src/win/stream.c +10 -3
- data/ext/noderb_extension/libuv/src/win/tcp.c +3 -1
- data/ext/noderb_extension/libuv/src/win/tty.c +1559 -5
- data/ext/noderb_extension/libuv/test/benchmark-getaddrinfo.c +2 -0
- data/ext/noderb_extension/libuv/test/runner-unix.c +2 -0
- data/ext/noderb_extension/libuv/test/test-fs-event.c +217 -0
- data/ext/noderb_extension/libuv/test/test-fs.c +0 -4
- data/ext/noderb_extension/libuv/test/test-getaddrinfo.c +7 -3
- data/ext/noderb_extension/libuv/test/test-list.h +23 -0
- data/ext/noderb_extension/libuv/test/test-tcp-close.c +47 -0
- data/ext/noderb_extension/libuv/test/test-tcp-write-error.c +168 -0
- data/ext/noderb_extension/libuv/test/test-timer.c +40 -0
- data/ext/noderb_extension/libuv/test/test-tty.c +56 -0
- data/ext/noderb_extension/libuv/uv.gyp +17 -18
- data/ext/noderb_extension/noderb.c +0 -2
- data/ext/noderb_extension/noderb_dns.c +6 -7
- data/ext/noderb_extension/noderb_fs.c +11 -10
- data/ext/noderb_extension/noderb_timers.c +5 -5
- data/lib/noderb/version.rb +1 -1
- metadata +8 -3
@@ -0,0 +1,384 @@
|
|
1
|
+
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
2
|
+
*
|
3
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
* of this software and associated documentation files (the "Software"), to
|
5
|
+
* deal in the Software without restriction, including without limitation the
|
6
|
+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
* sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
* furnished to do so, subject to the following conditions:
|
9
|
+
*
|
10
|
+
* The above copyright notice and this permission notice shall be included in
|
11
|
+
* all copies or substantial portions of the Software.
|
12
|
+
*
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
18
|
+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
19
|
+
* IN THE SOFTWARE.
|
20
|
+
*/
|
21
|
+
|
22
|
+
#include <assert.h>
|
23
|
+
#include <malloc.h>
|
24
|
+
#include <errno.h>
|
25
|
+
#include <string.h>
|
26
|
+
#include "uv.h"
|
27
|
+
#include "internal.h"
|
28
|
+
|
29
|
+
|
30
|
+
const unsigned int uv_directory_watcher_buffer_size = 4096;
|
31
|
+
|
32
|
+
|
33
|
+
static void uv_fs_event_init_handle(uv_loop_t* loop, uv_fs_event_t* handle,
|
34
|
+
const char* filename, uv_fs_event_cb cb) {
|
35
|
+
handle->type = UV_FS_EVENT;
|
36
|
+
handle->loop = loop;
|
37
|
+
handle->flags = 0;
|
38
|
+
handle->cb = cb;
|
39
|
+
handle->is_path_dir = 0;
|
40
|
+
handle->dir_handle = INVALID_HANDLE_VALUE;
|
41
|
+
handle->buffer = NULL;
|
42
|
+
handle->req_pending = 0;
|
43
|
+
handle->filew = NULL;
|
44
|
+
|
45
|
+
uv_req_init(loop, (uv_req_t*)&handle->req);
|
46
|
+
handle->req.type = UV_FS_EVENT_REQ;
|
47
|
+
handle->req.data = (void*)handle;
|
48
|
+
|
49
|
+
handle->filename = strdup(filename);
|
50
|
+
if (!handle->filename) {
|
51
|
+
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
52
|
+
}
|
53
|
+
|
54
|
+
loop->counters.handle_init++;
|
55
|
+
loop->counters.fs_event_init++;
|
56
|
+
|
57
|
+
uv_ref(loop);
|
58
|
+
}
|
59
|
+
|
60
|
+
|
61
|
+
static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop,
|
62
|
+
uv_fs_event_t* handle) {
|
63
|
+
assert(handle->dir_handle != INVALID_HANDLE_VALUE);
|
64
|
+
assert(!handle->req_pending);
|
65
|
+
|
66
|
+
memset(&(handle->req.overlapped), 0, sizeof(handle->req.overlapped));
|
67
|
+
if (!ReadDirectoryChangesW(handle->dir_handle,
|
68
|
+
handle->buffer,
|
69
|
+
uv_directory_watcher_buffer_size,
|
70
|
+
FALSE,
|
71
|
+
FILE_NOTIFY_CHANGE_FILE_NAME |
|
72
|
+
FILE_NOTIFY_CHANGE_DIR_NAME |
|
73
|
+
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
74
|
+
FILE_NOTIFY_CHANGE_SIZE |
|
75
|
+
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
76
|
+
FILE_NOTIFY_CHANGE_LAST_ACCESS |
|
77
|
+
FILE_NOTIFY_CHANGE_CREATION |
|
78
|
+
FILE_NOTIFY_CHANGE_SECURITY,
|
79
|
+
NULL,
|
80
|
+
&handle->req.overlapped,
|
81
|
+
NULL)) {
|
82
|
+
/* Make this req pending reporting an error. */
|
83
|
+
SET_REQ_ERROR(&handle->req, GetLastError());
|
84
|
+
uv_insert_pending_req(loop, (uv_req_t*)&handle->req);
|
85
|
+
}
|
86
|
+
|
87
|
+
handle->req_pending = 1;
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
static int uv_split_path(const wchar_t* filename, wchar_t** dir,
|
92
|
+
wchar_t** file) {
|
93
|
+
int len = wcslen(filename);
|
94
|
+
int i = len;
|
95
|
+
while (i > 0 && filename[--i] != '\\' && filename[i] != '/');
|
96
|
+
|
97
|
+
if (i == 0) {
|
98
|
+
*dir = (wchar_t*)malloc((MAX_PATH + 1) * sizeof(wchar_t));
|
99
|
+
if (!*dir) {
|
100
|
+
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
101
|
+
}
|
102
|
+
|
103
|
+
if (!GetCurrentDirectoryW(MAX_PATH, *dir)) {
|
104
|
+
free(*dir);
|
105
|
+
*dir = NULL;
|
106
|
+
return -1;
|
107
|
+
}
|
108
|
+
|
109
|
+
*file = wcsdup(filename);
|
110
|
+
} else {
|
111
|
+
*dir = (wchar_t*)malloc((i + 1) * sizeof(wchar_t));
|
112
|
+
if (!*dir) {
|
113
|
+
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
114
|
+
}
|
115
|
+
wcsncpy(*dir, filename, i);
|
116
|
+
(*dir)[i] = L'\0';
|
117
|
+
|
118
|
+
*file = (wchar_t*)malloc((len - i) * sizeof(wchar_t));
|
119
|
+
if (!*file) {
|
120
|
+
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
121
|
+
}
|
122
|
+
wcsncpy(*file, filename + i + 1, len - i - 1);
|
123
|
+
(*file)[len - i - 1] = L'\0';
|
124
|
+
}
|
125
|
+
|
126
|
+
return 0;
|
127
|
+
}
|
128
|
+
|
129
|
+
|
130
|
+
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
|
131
|
+
const char* filename, uv_fs_event_cb cb) {
|
132
|
+
int name_size;
|
133
|
+
DWORD attr, last_error;
|
134
|
+
wchar_t* dir = NULL, *dir_to_watch, *filenamew;
|
135
|
+
|
136
|
+
uv_fs_event_init_handle(loop, handle, filename, cb);
|
137
|
+
|
138
|
+
/* Convert name to UTF16. */
|
139
|
+
name_size = uv_utf8_to_utf16(filename, NULL, 0) * sizeof(wchar_t);
|
140
|
+
filenamew = (wchar_t*)malloc(name_size);
|
141
|
+
if (!filenamew) {
|
142
|
+
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
143
|
+
}
|
144
|
+
|
145
|
+
if (!uv_utf8_to_utf16(filename, filenamew,
|
146
|
+
name_size / sizeof(wchar_t))) {
|
147
|
+
uv_set_sys_error(loop, GetLastError());
|
148
|
+
return -1;
|
149
|
+
}
|
150
|
+
|
151
|
+
/* Determine whether filename is a file or a directory. */
|
152
|
+
attr = GetFileAttributesW(filenamew);
|
153
|
+
if (attr == INVALID_FILE_ATTRIBUTES) {
|
154
|
+
last_error = GetLastError();
|
155
|
+
goto error;
|
156
|
+
}
|
157
|
+
|
158
|
+
handle->is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
|
159
|
+
|
160
|
+
if (handle->is_path_dir) {
|
161
|
+
/* filename is a directory, so that's the directory that we will watch. */
|
162
|
+
dir_to_watch = filenamew;
|
163
|
+
} else {
|
164
|
+
/*
|
165
|
+
* filename is a file. So we split filename into dir & file parts, and
|
166
|
+
* watch the dir directory.
|
167
|
+
*/
|
168
|
+
if (uv_split_path(filenamew, &dir, &handle->filew) != 0) {
|
169
|
+
last_error = GetLastError();
|
170
|
+
goto error;
|
171
|
+
}
|
172
|
+
|
173
|
+
dir_to_watch = dir;
|
174
|
+
}
|
175
|
+
|
176
|
+
handle->dir_handle = CreateFileW(dir_to_watch,
|
177
|
+
FILE_LIST_DIRECTORY,
|
178
|
+
FILE_SHARE_READ | FILE_SHARE_DELETE |
|
179
|
+
FILE_SHARE_WRITE,
|
180
|
+
NULL,
|
181
|
+
OPEN_EXISTING,
|
182
|
+
FILE_FLAG_BACKUP_SEMANTICS |
|
183
|
+
FILE_FLAG_OVERLAPPED,
|
184
|
+
NULL);
|
185
|
+
|
186
|
+
if (dir) {
|
187
|
+
free(dir);
|
188
|
+
dir = NULL;
|
189
|
+
}
|
190
|
+
|
191
|
+
if (handle->dir_handle == INVALID_HANDLE_VALUE) {
|
192
|
+
last_error = GetLastError();
|
193
|
+
goto error;
|
194
|
+
}
|
195
|
+
|
196
|
+
if (CreateIoCompletionPort(handle->dir_handle,
|
197
|
+
loop->iocp,
|
198
|
+
(ULONG_PTR)handle,
|
199
|
+
0) == NULL) {
|
200
|
+
last_error = GetLastError();
|
201
|
+
goto error;
|
202
|
+
}
|
203
|
+
|
204
|
+
handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size,
|
205
|
+
sizeof(DWORD));
|
206
|
+
if (!handle->buffer) {
|
207
|
+
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
208
|
+
}
|
209
|
+
|
210
|
+
memset(&(handle->req.overlapped), 0, sizeof(handle->req.overlapped));
|
211
|
+
|
212
|
+
if (!ReadDirectoryChangesW(handle->dir_handle,
|
213
|
+
handle->buffer,
|
214
|
+
uv_directory_watcher_buffer_size,
|
215
|
+
FALSE,
|
216
|
+
FILE_NOTIFY_CHANGE_FILE_NAME |
|
217
|
+
FILE_NOTIFY_CHANGE_DIR_NAME |
|
218
|
+
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
219
|
+
FILE_NOTIFY_CHANGE_SIZE |
|
220
|
+
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
221
|
+
FILE_NOTIFY_CHANGE_LAST_ACCESS |
|
222
|
+
FILE_NOTIFY_CHANGE_CREATION |
|
223
|
+
FILE_NOTIFY_CHANGE_SECURITY,
|
224
|
+
NULL,
|
225
|
+
&handle->req.overlapped,
|
226
|
+
NULL)) {
|
227
|
+
last_error = GetLastError();
|
228
|
+
goto error;
|
229
|
+
}
|
230
|
+
|
231
|
+
handle->req_pending = 1;
|
232
|
+
return 0;
|
233
|
+
|
234
|
+
error:
|
235
|
+
if (handle->filename) {
|
236
|
+
free(handle->filename);
|
237
|
+
handle->filename = NULL;
|
238
|
+
}
|
239
|
+
|
240
|
+
if (handle->filew) {
|
241
|
+
free(handle->filew);
|
242
|
+
handle->filew = NULL;
|
243
|
+
}
|
244
|
+
|
245
|
+
if (handle->dir_handle != INVALID_HANDLE_VALUE) {
|
246
|
+
CloseHandle(handle->dir_handle);
|
247
|
+
handle->dir_handle = INVALID_HANDLE_VALUE;
|
248
|
+
}
|
249
|
+
|
250
|
+
if (handle->buffer) {
|
251
|
+
_aligned_free(handle->buffer);
|
252
|
+
handle->buffer = NULL;
|
253
|
+
}
|
254
|
+
|
255
|
+
uv_set_sys_error(loop, last_error);
|
256
|
+
return -1;
|
257
|
+
}
|
258
|
+
|
259
|
+
|
260
|
+
void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
|
261
|
+
uv_fs_event_t* handle) {
|
262
|
+
FILE_NOTIFY_INFORMATION* file_info;
|
263
|
+
char* filename = NULL;
|
264
|
+
int utf8size;
|
265
|
+
DWORD offset = 0;
|
266
|
+
|
267
|
+
assert(req->type == UV_FS_EVENT_REQ);
|
268
|
+
assert(handle->req_pending);
|
269
|
+
handle->req_pending = 0;
|
270
|
+
|
271
|
+
file_info = (FILE_NOTIFY_INFORMATION*)(handle->buffer + offset);
|
272
|
+
|
273
|
+
if (REQ_SUCCESS(req)) {
|
274
|
+
if (req->overlapped.InternalHigh > 0) {
|
275
|
+
do {
|
276
|
+
file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset);
|
277
|
+
|
278
|
+
/*
|
279
|
+
* Fire the event only if we were asked to watch a directory,
|
280
|
+
* or if the filename filter matches.
|
281
|
+
*/
|
282
|
+
if (handle->is_path_dir || _wcsnicmp(handle->filew, file_info->FileName,
|
283
|
+
file_info->FileNameLength / sizeof(wchar_t)) == 0) {
|
284
|
+
|
285
|
+
/* Convert the filename to utf8. */
|
286
|
+
utf8size = uv_utf16_to_utf8(file_info->FileName,
|
287
|
+
file_info->FileNameLength /
|
288
|
+
sizeof(wchar_t),
|
289
|
+
NULL,
|
290
|
+
0);
|
291
|
+
if (utf8size) {
|
292
|
+
filename = (char*)malloc(utf8size + 1);
|
293
|
+
if (!filename) {
|
294
|
+
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
295
|
+
}
|
296
|
+
|
297
|
+
utf8size = uv_utf16_to_utf8(file_info->FileName,
|
298
|
+
file_info->FileNameLength /
|
299
|
+
sizeof(wchar_t),
|
300
|
+
filename,
|
301
|
+
utf8size);
|
302
|
+
if (utf8size) {
|
303
|
+
filename[utf8size] = L'\0';
|
304
|
+
} else {
|
305
|
+
free(filename);
|
306
|
+
filename = NULL;
|
307
|
+
}
|
308
|
+
}
|
309
|
+
|
310
|
+
switch (file_info->Action) {
|
311
|
+
case FILE_ACTION_ADDED:
|
312
|
+
case FILE_ACTION_REMOVED:
|
313
|
+
case FILE_ACTION_RENAMED_OLD_NAME:
|
314
|
+
case FILE_ACTION_RENAMED_NEW_NAME:
|
315
|
+
handle->cb(handle, filename, UV_RENAME, 0);
|
316
|
+
break;
|
317
|
+
|
318
|
+
case FILE_ACTION_MODIFIED:
|
319
|
+
handle->cb(handle, filename, UV_CHANGE, 0);
|
320
|
+
break;
|
321
|
+
}
|
322
|
+
|
323
|
+
free(filename);
|
324
|
+
filename = NULL;
|
325
|
+
}
|
326
|
+
|
327
|
+
offset = file_info->NextEntryOffset;
|
328
|
+
} while(offset);
|
329
|
+
} else {
|
330
|
+
handle->cb(handle, NULL, UV_CHANGE, 0);
|
331
|
+
}
|
332
|
+
} else {
|
333
|
+
loop->last_error = GET_REQ_UV_ERROR(req);
|
334
|
+
handle->cb(handle, NULL, 0, -1);
|
335
|
+
}
|
336
|
+
|
337
|
+
if (!(handle->flags & UV_HANDLE_CLOSING)) {
|
338
|
+
uv_fs_event_queue_readdirchanges(loop, handle);
|
339
|
+
} else {
|
340
|
+
uv_want_endgame(loop, (uv_handle_t*)handle);
|
341
|
+
}
|
342
|
+
}
|
343
|
+
|
344
|
+
|
345
|
+
void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) {
|
346
|
+
if (handle->dir_handle != INVALID_HANDLE_VALUE) {
|
347
|
+
CloseHandle(handle->dir_handle);
|
348
|
+
handle->dir_handle = INVALID_HANDLE_VALUE;
|
349
|
+
}
|
350
|
+
|
351
|
+
if (!handle->req_pending) {
|
352
|
+
uv_want_endgame(loop, (uv_handle_t*)handle);
|
353
|
+
}
|
354
|
+
}
|
355
|
+
|
356
|
+
|
357
|
+
void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
|
358
|
+
if (handle->flags & UV_HANDLE_CLOSING &&
|
359
|
+
!handle->req_pending) {
|
360
|
+
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
361
|
+
handle->flags |= UV_HANDLE_CLOSED;
|
362
|
+
|
363
|
+
if (handle->buffer) {
|
364
|
+
_aligned_free(handle->buffer);
|
365
|
+
handle->buffer = NULL;
|
366
|
+
}
|
367
|
+
|
368
|
+
if (handle->filew) {
|
369
|
+
free(handle->filew);
|
370
|
+
handle->filew = NULL;
|
371
|
+
}
|
372
|
+
|
373
|
+
if (handle->filename) {
|
374
|
+
free(handle->filename);
|
375
|
+
handle->filename = NULL;
|
376
|
+
}
|
377
|
+
|
378
|
+
if (handle->close_cb) {
|
379
|
+
handle->close_cb((uv_handle_t*)handle);
|
380
|
+
}
|
381
|
+
|
382
|
+
uv_unref(loop);
|
383
|
+
}
|
384
|
+
}
|
@@ -216,12 +216,17 @@ complete:
|
|
216
216
|
/* finally do callback with converted result */
|
217
217
|
handle->getaddrinfo_cb(handle, uv_ret, (struct addrinfo*)alloc_ptr);
|
218
218
|
|
219
|
+
uv_unref(loop);
|
220
|
+
}
|
221
|
+
|
222
|
+
|
223
|
+
void uv_freeaddrinfo(struct addrinfo* ai) {
|
224
|
+
char* alloc_ptr = (char*)ai;
|
225
|
+
|
219
226
|
/* release copied result memory */
|
220
227
|
if (alloc_ptr != NULL) {
|
221
228
|
free(alloc_ptr);
|
222
229
|
}
|
223
|
-
|
224
|
-
uv_unref(loop);
|
225
230
|
}
|
226
231
|
|
227
232
|
|
@@ -20,11 +20,36 @@
|
|
20
20
|
*/
|
21
21
|
|
22
22
|
#include <assert.h>
|
23
|
+
#include <io.h>
|
23
24
|
|
24
25
|
#include "uv.h"
|
25
26
|
#include "internal.h"
|
26
27
|
|
27
28
|
|
29
|
+
uv_handle_type uv_guess_handle(uv_file file) {
|
30
|
+
HANDLE handle = (HANDLE) _get_osfhandle(file);
|
31
|
+
DWORD mode;
|
32
|
+
|
33
|
+
switch (GetFileType(handle)) {
|
34
|
+
case FILE_TYPE_CHAR:
|
35
|
+
if (GetConsoleMode(handle, &mode)) {
|
36
|
+
return UV_TTY;
|
37
|
+
} else {
|
38
|
+
return UV_UNKNOWN_HANDLE;
|
39
|
+
}
|
40
|
+
|
41
|
+
case FILE_TYPE_PIPE:
|
42
|
+
return UV_NAMED_PIPE;
|
43
|
+
|
44
|
+
case FILE_TYPE_DISK:
|
45
|
+
return UV_FILE;
|
46
|
+
|
47
|
+
default:
|
48
|
+
return UV_UNKNOWN_HANDLE;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
|
28
53
|
int uv_is_active(uv_handle_t* handle) {
|
29
54
|
switch (handle->type) {
|
30
55
|
case UV_TIMER:
|
@@ -80,6 +105,10 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
|
|
80
105
|
}
|
81
106
|
return;
|
82
107
|
|
108
|
+
case UV_TTY:
|
109
|
+
uv_tty_close((uv_tty_t*) handle);
|
110
|
+
return;
|
111
|
+
|
83
112
|
case UV_UDP:
|
84
113
|
udp = (uv_udp_t*) handle;
|
85
114
|
uv_udp_recv_stop(udp);
|
@@ -120,6 +149,10 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
|
|
120
149
|
uv_process_close(loop, process);
|
121
150
|
return;
|
122
151
|
|
152
|
+
case UV_FS_EVENT:
|
153
|
+
uv_fs_event_close(loop, (uv_fs_event_t*)handle);
|
154
|
+
return;
|
155
|
+
|
123
156
|
default:
|
124
157
|
/* Not supported */
|
125
158
|
abort();
|
@@ -155,6 +188,10 @@ void uv_process_endgames(uv_loop_t* loop) {
|
|
155
188
|
uv_pipe_endgame(loop, (uv_pipe_t*) handle);
|
156
189
|
break;
|
157
190
|
|
191
|
+
case UV_TTY:
|
192
|
+
uv_tty_endgame(loop, (uv_tty_t*) handle);
|
193
|
+
break;
|
194
|
+
|
158
195
|
case UV_UDP:
|
159
196
|
uv_udp_endgame(loop, (uv_udp_t*) handle);
|
160
197
|
break;
|
@@ -177,6 +214,10 @@ void uv_process_endgames(uv_loop_t* loop) {
|
|
177
214
|
uv_process_endgame(loop, (uv_process_t*) handle);
|
178
215
|
break;
|
179
216
|
|
217
|
+
case UV_FS_EVENT:
|
218
|
+
uv_fs_event_endgame(loop, (uv_fs_event_t*) handle);
|
219
|
+
break;
|
220
|
+
|
180
221
|
default:
|
181
222
|
assert(0);
|
182
223
|
break;
|
@@ -64,6 +64,7 @@ void uv_process_timers(uv_loop_t* loop);
|
|
64
64
|
#define UV_HANDLE_UV_ALLOCED 0x20000
|
65
65
|
#define UV_HANDLE_SYNC_BYPASS_IOCP 0x40000
|
66
66
|
#define UV_HANDLE_ZERO_READ 0x80000
|
67
|
+
#define UV_HANDLE_TTY_RAW 0x100000
|
67
68
|
|
68
69
|
void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle);
|
69
70
|
void uv_process_endgames(uv_loop_t* loop);
|
@@ -173,6 +174,33 @@ void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
|
|
173
174
|
void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
|
174
175
|
uv_shutdown_t* req);
|
175
176
|
|
177
|
+
|
178
|
+
/*
|
179
|
+
* TTY
|
180
|
+
*/
|
181
|
+
void uv_console_init();
|
182
|
+
|
183
|
+
int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
|
184
|
+
uv_read_cb read_cb);
|
185
|
+
int uv_tty_read_stop(uv_tty_t* handle);
|
186
|
+
int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle,
|
187
|
+
uv_buf_t bufs[], int bufcnt, uv_write_cb cb);
|
188
|
+
void uv_tty_close(uv_tty_t* handle);
|
189
|
+
|
190
|
+
void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
|
191
|
+
uv_req_t* req);
|
192
|
+
void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
|
193
|
+
uv_write_t* req);
|
194
|
+
/* TODO: remove me */
|
195
|
+
void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
|
196
|
+
uv_req_t* raw_req);
|
197
|
+
/* TODO: remove me */
|
198
|
+
void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
|
199
|
+
uv_connect_t* req);
|
200
|
+
|
201
|
+
void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle);
|
202
|
+
|
203
|
+
|
176
204
|
/*
|
177
205
|
* Loop watchers
|
178
206
|
*/
|
@@ -231,6 +259,14 @@ void uv_process_fs_req(uv_loop_t* loop, uv_fs_t* req);
|
|
231
259
|
void uv_process_work_req(uv_loop_t* loop, uv_work_t* req);
|
232
260
|
|
233
261
|
|
262
|
+
/*
|
263
|
+
* FS Event
|
264
|
+
*/
|
265
|
+
void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle);
|
266
|
+
void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle);
|
267
|
+
void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle);
|
268
|
+
|
269
|
+
|
234
270
|
/*
|
235
271
|
* Error handling
|
236
272
|
*/
|
@@ -231,6 +231,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
|
|
231
231
|
if (result) {
|
232
232
|
/* Mark the handle as shut now to avoid going through this again. */
|
233
233
|
handle->flags |= UV_HANDLE_SHUT;
|
234
|
+
return;
|
234
235
|
|
235
236
|
} else {
|
236
237
|
/* Failure. */
|
@@ -678,6 +679,8 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {
|
|
678
679
|
/* Make this req pending reporting an error. */
|
679
680
|
SET_REQ_ERROR(req, WSAGetLastError());
|
680
681
|
uv_insert_pending_req(loop, req);
|
682
|
+
|
683
|
+
handle->flags |= UV_HANDLE_READ_PENDING;
|
681
684
|
handle->reqs_pending++;
|
682
685
|
return;
|
683
686
|
}
|
@@ -845,14 +845,19 @@ static int duplicate_std_handle(uv_loop_t* loop, DWORD id, HANDLE* dup) {
|
|
845
845
|
int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
846
846
|
uv_process_options_t options) {
|
847
847
|
int err = 0, keep_child_stdio_open = 0;
|
848
|
-
wchar_t* path;
|
848
|
+
wchar_t* path = NULL;
|
849
849
|
int size;
|
850
850
|
BOOL result;
|
851
|
-
wchar_t* application_path, *application, *arguments, *env, *cwd;
|
851
|
+
wchar_t* application_path = NULL, *application = NULL, *arguments = NULL, *env = NULL, *cwd = NULL;
|
852
852
|
HANDLE* child_stdio = process->child_stdio;
|
853
853
|
STARTUPINFOW startup;
|
854
854
|
PROCESS_INFORMATION info;
|
855
855
|
|
856
|
+
if (!options.file) {
|
857
|
+
uv_set_error(loop, UV_EINVAL, 0);
|
858
|
+
return -1;
|
859
|
+
}
|
860
|
+
|
856
861
|
uv_process_init(loop, process);
|
857
862
|
|
858
863
|
process->exit_cb = options.exit_cb;
|
@@ -87,6 +87,12 @@ static uv_req_t* uv_remove_pending_req(uv_loop_t* loop) {
|
|
87
87
|
req); \
|
88
88
|
break; \
|
89
89
|
\
|
90
|
+
case UV_TTY: \
|
91
|
+
uv_process_tty_##method##_req(loop, \
|
92
|
+
(uv_tty_t*) ((req)->handle_at), \
|
93
|
+
req); \
|
94
|
+
break; \
|
95
|
+
\
|
90
96
|
default: \
|
91
97
|
assert(0); \
|
92
98
|
} \
|
@@ -165,6 +171,10 @@ void uv_process_reqs(uv_loop_t* loop) {
|
|
165
171
|
uv_process_work_req(loop, (uv_work_t*) req);
|
166
172
|
break;
|
167
173
|
|
174
|
+
case UV_FS_EVENT_REQ:
|
175
|
+
uv_process_fs_event_req(loop, req, (uv_fs_event_t*) req->data);
|
176
|
+
break;
|
177
|
+
|
168
178
|
default:
|
169
179
|
assert(0);
|
170
180
|
}
|
@@ -83,6 +83,8 @@ int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,
|
|
83
83
|
return uv_tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb);
|
84
84
|
case UV_NAMED_PIPE:
|
85
85
|
return uv_pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb);
|
86
|
+
case UV_TTY:
|
87
|
+
return uv_tty_read_start((uv_tty_t*) handle, alloc_cb, read_cb);
|
86
88
|
default:
|
87
89
|
assert(0);
|
88
90
|
return -1;
|
@@ -91,9 +93,12 @@ int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,
|
|
91
93
|
|
92
94
|
|
93
95
|
int uv_read_stop(uv_stream_t* handle) {
|
94
|
-
handle->
|
95
|
-
|
96
|
-
|
96
|
+
if (handle->type = UV_TTY) {
|
97
|
+
return uv_tty_read_stop((uv_tty_t*) handle);
|
98
|
+
} else {
|
99
|
+
handle->flags &= ~UV_HANDLE_READING;
|
100
|
+
return 0;
|
101
|
+
}
|
97
102
|
}
|
98
103
|
|
99
104
|
|
@@ -106,6 +111,8 @@ int uv_write(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt,
|
|
106
111
|
return uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, bufcnt, cb);
|
107
112
|
case UV_NAMED_PIPE:
|
108
113
|
return uv_pipe_write(loop, req, (uv_pipe_t*) handle, bufs, bufcnt, cb);
|
114
|
+
case UV_TTY:
|
115
|
+
return uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, bufcnt, cb);
|
109
116
|
default:
|
110
117
|
assert(0);
|
111
118
|
uv_set_sys_error(loop, WSAEINVAL);
|
@@ -128,7 +128,9 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
|
128
128
|
}
|
129
129
|
handle->shutdown_req->cb(handle->shutdown_req, status);
|
130
130
|
}
|
131
|
-
|
131
|
+
|
132
|
+
DECREASE_PENDING_REQ_COUNT(handle);
|
133
|
+
return;
|
132
134
|
}
|
133
135
|
|
134
136
|
if (handle->flags & UV_HANDLE_CLOSING &&
|