asyncengine 0.0.1.testing1 → 0.0.2.alpha1

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.
Files changed (251) hide show
  1. data/README.markdown +3 -0
  2. data/Rakefile +38 -0
  3. data/asyncengine.gemspec +8 -4
  4. data/ext/asyncengine/ae_call_from_other_thread.c +106 -0
  5. data/ext/asyncengine/ae_call_from_other_thread.h +12 -0
  6. data/ext/asyncengine/ae_handle_common.c +193 -48
  7. data/ext/asyncengine/ae_handle_common.h +40 -13
  8. data/ext/asyncengine/ae_ip_utils.c +246 -0
  9. data/ext/asyncengine/ae_ip_utils.h +25 -0
  10. data/ext/asyncengine/ae_next_tick.c +81 -21
  11. data/ext/asyncengine/ae_next_tick.h +4 -2
  12. data/ext/asyncengine/ae_resolver.c +156 -0
  13. data/ext/asyncengine/ae_resolver.h +10 -0
  14. data/ext/asyncengine/ae_tcp.c +908 -0
  15. data/ext/asyncengine/ae_tcp.h +20 -0
  16. data/ext/asyncengine/ae_timer.c +355 -81
  17. data/ext/asyncengine/ae_timer.h +11 -4
  18. data/ext/asyncengine/ae_udp.c +579 -13
  19. data/ext/asyncengine/ae_udp.h +15 -2
  20. data/ext/asyncengine/ae_utils.c +192 -0
  21. data/ext/asyncengine/ae_utils.h +16 -0
  22. data/ext/asyncengine/asyncengine_ruby.c +469 -26
  23. data/ext/asyncengine/asyncengine_ruby.h +49 -11
  24. data/ext/asyncengine/debug.h +68 -0
  25. data/ext/asyncengine/extconf.rb +26 -2
  26. data/ext/asyncengine/ip_parser.c +5954 -0
  27. data/ext/asyncengine/ip_parser.h +16 -0
  28. data/ext/asyncengine/libuv/AUTHORS +16 -0
  29. data/ext/asyncengine/libuv/common.gypi +4 -4
  30. data/ext/asyncengine/libuv/config-mingw.mk +6 -6
  31. data/ext/asyncengine/libuv/config-unix.mk +13 -13
  32. data/ext/asyncengine/libuv/gyp_uv +5 -1
  33. data/ext/asyncengine/libuv/ibc_tests/exec_test.sh +8 -0
  34. data/ext/asyncengine/libuv/ibc_tests/uv_shutdown_write_issue.c +171 -0
  35. data/ext/asyncengine/libuv/ibc_tests/uv_tcp_close_while_connecting.c +102 -0
  36. data/ext/asyncengine/libuv/include/uv-private/ngx-queue.h +3 -1
  37. data/ext/asyncengine/libuv/include/uv-private/uv-unix.h +103 -50
  38. data/ext/asyncengine/libuv/include/uv-private/uv-win.h +76 -24
  39. data/ext/asyncengine/libuv/include/uv.h +353 -88
  40. data/ext/asyncengine/libuv/src/ares/ares__close_sockets.o +0 -0
  41. data/ext/asyncengine/libuv/src/ares/ares__get_hostent.o +0 -0
  42. data/ext/asyncengine/libuv/src/ares/ares__read_line.o +0 -0
  43. data/ext/asyncengine/libuv/src/ares/ares__timeval.o +0 -0
  44. data/ext/asyncengine/libuv/src/ares/ares_cancel.o +0 -0
  45. data/ext/asyncengine/libuv/src/ares/ares_data.o +0 -0
  46. data/ext/asyncengine/libuv/src/ares/ares_destroy.o +0 -0
  47. data/ext/asyncengine/libuv/src/ares/ares_expand_name.o +0 -0
  48. data/ext/asyncengine/libuv/src/ares/ares_expand_string.o +0 -0
  49. data/ext/asyncengine/libuv/src/ares/ares_fds.o +0 -0
  50. data/ext/asyncengine/libuv/src/ares/ares_free_hostent.o +0 -0
  51. data/ext/asyncengine/libuv/src/ares/ares_free_string.o +0 -0
  52. data/ext/asyncengine/libuv/src/ares/ares_gethostbyaddr.o +0 -0
  53. data/ext/asyncengine/libuv/src/ares/ares_gethostbyname.o +0 -0
  54. data/ext/asyncengine/libuv/src/ares/ares_getnameinfo.o +0 -0
  55. data/ext/asyncengine/libuv/src/ares/ares_getopt.o +0 -0
  56. data/ext/asyncengine/libuv/src/ares/ares_getsock.o +0 -0
  57. data/ext/asyncengine/libuv/src/ares/ares_init.o +0 -0
  58. data/ext/asyncengine/libuv/src/ares/ares_library_init.o +0 -0
  59. data/ext/asyncengine/libuv/src/ares/ares_llist.o +0 -0
  60. data/ext/asyncengine/libuv/src/ares/ares_mkquery.o +0 -0
  61. data/ext/asyncengine/libuv/src/ares/ares_nowarn.o +0 -0
  62. data/ext/asyncengine/libuv/src/ares/ares_options.o +0 -0
  63. data/ext/asyncengine/libuv/src/ares/ares_parse_a_reply.o +0 -0
  64. data/ext/asyncengine/libuv/src/ares/ares_parse_aaaa_reply.o +0 -0
  65. data/ext/asyncengine/libuv/src/ares/ares_parse_mx_reply.o +0 -0
  66. data/ext/asyncengine/libuv/src/ares/ares_parse_ns_reply.o +0 -0
  67. data/ext/asyncengine/libuv/src/ares/ares_parse_ptr_reply.o +0 -0
  68. data/ext/asyncengine/libuv/src/ares/ares_parse_srv_reply.o +0 -0
  69. data/ext/asyncengine/libuv/src/ares/ares_parse_txt_reply.o +0 -0
  70. data/ext/asyncengine/libuv/src/ares/ares_process.o +0 -0
  71. data/ext/asyncengine/libuv/src/ares/ares_query.o +0 -0
  72. data/ext/asyncengine/libuv/src/ares/ares_search.o +0 -0
  73. data/ext/asyncengine/libuv/src/ares/ares_send.o +0 -0
  74. data/ext/asyncengine/libuv/src/ares/ares_strcasecmp.o +0 -0
  75. data/ext/asyncengine/libuv/src/ares/ares_strdup.o +0 -0
  76. data/ext/asyncengine/libuv/src/ares/ares_strerror.o +0 -0
  77. data/ext/asyncengine/libuv/src/ares/ares_timeout.o +0 -0
  78. data/ext/asyncengine/libuv/src/ares/ares_version.o +0 -0
  79. data/ext/asyncengine/libuv/src/ares/ares_writev.o +0 -0
  80. data/ext/asyncengine/libuv/src/ares/bitncmp.o +0 -0
  81. data/ext/asyncengine/libuv/src/ares/inet_net_pton.o +0 -0
  82. data/ext/asyncengine/libuv/src/ares/inet_ntop.o +0 -0
  83. data/ext/asyncengine/libuv/src/cares.c +225 -0
  84. data/ext/asyncengine/libuv/src/cares.o +0 -0
  85. data/ext/asyncengine/libuv/src/fs-poll.c +237 -0
  86. data/ext/asyncengine/libuv/src/fs-poll.o +0 -0
  87. data/ext/asyncengine/libuv/src/unix/async.c +78 -17
  88. data/ext/asyncengine/libuv/src/unix/async.o +0 -0
  89. data/ext/asyncengine/libuv/src/unix/core.c +305 -213
  90. data/ext/asyncengine/libuv/src/unix/core.o +0 -0
  91. data/ext/asyncengine/libuv/src/unix/cygwin.c +1 -1
  92. data/ext/asyncengine/libuv/src/unix/darwin.c +2 -1
  93. data/ext/asyncengine/libuv/src/unix/dl.c +36 -44
  94. data/ext/asyncengine/libuv/src/unix/dl.o +0 -0
  95. data/ext/asyncengine/libuv/src/unix/eio/eio.o +0 -0
  96. data/ext/asyncengine/libuv/src/unix/error.c +6 -0
  97. data/ext/asyncengine/libuv/src/unix/error.o +0 -0
  98. data/ext/asyncengine/libuv/src/unix/ev/ev.c +8 -4
  99. data/ext/asyncengine/libuv/src/unix/ev/ev.o +0 -0
  100. data/ext/asyncengine/libuv/src/unix/freebsd.c +1 -1
  101. data/ext/asyncengine/libuv/src/unix/fs.c +25 -33
  102. data/ext/asyncengine/libuv/src/unix/fs.o +0 -0
  103. data/ext/asyncengine/libuv/src/unix/internal.h +50 -31
  104. data/ext/asyncengine/libuv/src/unix/kqueue.c +2 -7
  105. data/ext/asyncengine/libuv/src/unix/linux/core.o +0 -0
  106. data/ext/asyncengine/libuv/src/unix/linux/inotify.c +12 -14
  107. data/ext/asyncengine/libuv/src/unix/linux/inotify.o +0 -0
  108. data/ext/asyncengine/libuv/src/unix/linux/{core.c → linux-core.c} +1 -1
  109. data/ext/asyncengine/libuv/src/unix/linux/linux-core.o +0 -0
  110. data/ext/asyncengine/libuv/src/unix/linux/syscalls.c +147 -1
  111. data/ext/asyncengine/libuv/src/unix/linux/syscalls.h +39 -2
  112. data/ext/asyncengine/libuv/src/unix/linux/syscalls.o +0 -0
  113. data/ext/asyncengine/libuv/src/unix/loop-watcher.c +63 -0
  114. data/ext/asyncengine/libuv/src/unix/loop-watcher.o +0 -0
  115. data/ext/asyncengine/libuv/src/unix/loop.c +29 -6
  116. data/ext/asyncengine/libuv/src/unix/loop.o +0 -0
  117. data/ext/asyncengine/libuv/src/unix/netbsd.c +1 -1
  118. data/ext/asyncengine/libuv/src/unix/openbsd.c +1 -1
  119. data/ext/asyncengine/libuv/src/unix/pipe.c +31 -36
  120. data/ext/asyncengine/libuv/src/unix/pipe.o +0 -0
  121. data/ext/asyncengine/libuv/src/unix/poll.c +116 -0
  122. data/ext/asyncengine/libuv/src/unix/poll.o +0 -0
  123. data/ext/asyncengine/libuv/src/unix/process.c +193 -115
  124. data/ext/asyncengine/libuv/src/unix/process.o +0 -0
  125. data/ext/asyncengine/libuv/src/unix/stream.c +146 -153
  126. data/ext/asyncengine/libuv/src/unix/stream.o +0 -0
  127. data/ext/asyncengine/libuv/src/unix/sunos.c +45 -36
  128. data/ext/asyncengine/libuv/src/unix/tcp.c +6 -5
  129. data/ext/asyncengine/libuv/src/unix/tcp.o +0 -0
  130. data/ext/asyncengine/libuv/src/unix/thread.c +82 -25
  131. data/ext/asyncengine/libuv/src/unix/thread.o +0 -0
  132. data/ext/asyncengine/libuv/src/unix/timer.c +69 -58
  133. data/ext/asyncengine/libuv/src/unix/timer.o +0 -0
  134. data/ext/asyncengine/libuv/src/unix/tty.c +3 -3
  135. data/ext/asyncengine/libuv/src/unix/tty.o +0 -0
  136. data/ext/asyncengine/libuv/src/unix/udp.c +57 -66
  137. data/ext/asyncengine/libuv/src/unix/udp.o +0 -0
  138. data/ext/asyncengine/libuv/src/unix/uv-eio.c +33 -50
  139. data/ext/asyncengine/libuv/src/unix/uv-eio.o +0 -0
  140. data/ext/asyncengine/libuv/src/uv-common.c +68 -38
  141. data/ext/asyncengine/libuv/src/uv-common.h +104 -20
  142. data/ext/asyncengine/libuv/src/uv-common.o +0 -0
  143. data/ext/asyncengine/libuv/src/win/async.c +20 -17
  144. data/ext/asyncengine/libuv/src/win/core.c +44 -31
  145. data/ext/asyncengine/libuv/src/win/dl.c +40 -36
  146. data/ext/asyncengine/libuv/src/win/error.c +21 -1
  147. data/ext/asyncengine/libuv/src/win/fs-event.c +19 -21
  148. data/ext/asyncengine/libuv/src/win/fs.c +541 -189
  149. data/ext/asyncengine/libuv/src/win/getaddrinfo.c +56 -63
  150. data/ext/asyncengine/libuv/src/win/handle-inl.h +145 -0
  151. data/ext/asyncengine/libuv/src/win/handle.c +26 -101
  152. data/ext/asyncengine/libuv/src/win/internal.h +92 -107
  153. data/ext/asyncengine/libuv/src/win/loop-watcher.c +6 -14
  154. data/ext/asyncengine/libuv/src/win/pipe.c +78 -64
  155. data/ext/asyncengine/libuv/src/win/poll.c +618 -0
  156. data/ext/asyncengine/libuv/src/win/process-stdio.c +479 -0
  157. data/ext/asyncengine/libuv/src/win/process.c +147 -274
  158. data/ext/asyncengine/libuv/src/win/req-inl.h +225 -0
  159. data/ext/asyncengine/libuv/src/win/req.c +0 -149
  160. data/ext/asyncengine/libuv/src/{unix/check.c → win/stream-inl.h} +31 -42
  161. data/ext/asyncengine/libuv/src/win/stream.c +9 -43
  162. data/ext/asyncengine/libuv/src/win/tcp.c +200 -82
  163. data/ext/asyncengine/libuv/src/win/thread.c +42 -2
  164. data/ext/asyncengine/libuv/src/win/threadpool.c +3 -2
  165. data/ext/asyncengine/libuv/src/win/timer.c +13 -63
  166. data/ext/asyncengine/libuv/src/win/tty.c +26 -20
  167. data/ext/asyncengine/libuv/src/win/udp.c +26 -17
  168. data/ext/asyncengine/libuv/src/win/util.c +312 -167
  169. data/ext/asyncengine/libuv/src/win/winapi.c +16 -1
  170. data/ext/asyncengine/libuv/src/win/winapi.h +33 -9
  171. data/ext/asyncengine/libuv/src/win/winsock.c +88 -1
  172. data/ext/asyncengine/libuv/src/win/winsock.h +36 -3
  173. data/ext/asyncengine/libuv/test/benchmark-ares.c +16 -17
  174. data/ext/asyncengine/libuv/test/benchmark-fs-stat.c +164 -0
  175. data/ext/asyncengine/libuv/test/benchmark-list.h +9 -0
  176. data/ext/asyncengine/libuv/{src/unix/prepare.c → test/benchmark-loop-count.c} +42 -33
  177. data/ext/asyncengine/libuv/test/benchmark-million-timers.c +65 -0
  178. data/ext/asyncengine/libuv/test/benchmark-pound.c +1 -1
  179. data/ext/asyncengine/libuv/test/benchmark-sizes.c +2 -0
  180. data/ext/asyncengine/libuv/test/benchmark-spawn.c +7 -1
  181. data/ext/asyncengine/libuv/test/benchmark-udp-packet-storm.c +1 -1
  182. data/ext/asyncengine/libuv/test/echo-server.c +8 -0
  183. data/ext/asyncengine/libuv/test/run-tests.c +30 -0
  184. data/ext/asyncengine/libuv/test/runner-unix.c +6 -26
  185. data/ext/asyncengine/libuv/test/runner-win.c +5 -63
  186. data/ext/asyncengine/libuv/test/runner.c +10 -1
  187. data/ext/asyncengine/libuv/test/task.h +0 -8
  188. data/ext/asyncengine/libuv/test/test-async.c +43 -141
  189. data/ext/asyncengine/libuv/test/test-callback-order.c +76 -0
  190. data/ext/asyncengine/libuv/test/test-counters-init.c +2 -3
  191. data/ext/asyncengine/libuv/test/test-dlerror.c +17 -8
  192. data/ext/asyncengine/libuv/test/test-fs-event.c +31 -39
  193. data/ext/asyncengine/libuv/test/test-fs-poll.c +146 -0
  194. data/ext/asyncengine/libuv/test/test-fs.c +114 -2
  195. data/ext/asyncengine/libuv/test/test-gethostbyname.c +8 -8
  196. data/ext/asyncengine/libuv/test/test-hrtime.c +18 -15
  197. data/ext/asyncengine/libuv/test/test-ipc.c +8 -2
  198. data/ext/asyncengine/libuv/test/test-list.h +59 -9
  199. data/ext/asyncengine/libuv/test/test-loop-handles.c +2 -25
  200. data/ext/asyncengine/libuv/{src/unix/idle.c → test/test-poll-close.c} +37 -39
  201. data/ext/asyncengine/libuv/test/test-poll.c +573 -0
  202. data/ext/asyncengine/libuv/test/test-ref.c +79 -63
  203. data/ext/asyncengine/libuv/test/test-run-once.c +15 -11
  204. data/ext/asyncengine/libuv/test/test-semaphore.c +111 -0
  205. data/ext/asyncengine/libuv/test/test-spawn.c +368 -20
  206. data/ext/asyncengine/libuv/test/test-stdio-over-pipes.c +25 -35
  207. data/ext/asyncengine/libuv/test/test-tcp-close-while-connecting.c +80 -0
  208. data/ext/asyncengine/libuv/test/test-tcp-close.c +1 -1
  209. data/ext/asyncengine/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  210. data/ext/asyncengine/libuv/test/test-tcp-connect-timeout.c +85 -0
  211. data/ext/asyncengine/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  212. data/ext/asyncengine/libuv/test/test-tcp-write-error.c +2 -2
  213. data/ext/asyncengine/libuv/test/test-tcp-writealot.c +29 -54
  214. data/ext/asyncengine/libuv/test/test-timer-again.c +1 -1
  215. data/ext/asyncengine/libuv/test/test-timer.c +23 -1
  216. data/ext/asyncengine/libuv/test/test-udp-options.c +1 -1
  217. data/ext/asyncengine/libuv/test/{test-eio-overflow.c → test-walk-handles.c} +31 -44
  218. data/ext/asyncengine/libuv/uv.gyp +26 -9
  219. data/ext/asyncengine/rb_utilities.c +54 -0
  220. data/ext/asyncengine/rb_utilities.h +63 -0
  221. data/lib/asyncengine.rb +45 -38
  222. data/lib/asyncengine/asyncengine_ext.so +0 -0
  223. data/lib/asyncengine/debug.rb +37 -0
  224. data/lib/asyncengine/handle.rb +9 -0
  225. data/lib/asyncengine/tcp.rb +28 -0
  226. data/lib/asyncengine/timer.rb +18 -28
  227. data/lib/asyncengine/udp.rb +29 -0
  228. data/lib/asyncengine/utils.rb +32 -0
  229. data/lib/asyncengine/uv_error.rb +17 -0
  230. data/lib/asyncengine/version.rb +9 -1
  231. data/test/ae_test_helper.rb +62 -0
  232. data/test/test_basic.rb +169 -0
  233. data/test/test_call_from_other_thread.rb +55 -0
  234. data/test/test_error.rb +92 -0
  235. data/test/test_ip_utils.rb +44 -0
  236. data/test/test_next_tick.rb +37 -0
  237. data/test/test_resolver.rb +51 -0
  238. data/test/test_threads.rb +69 -0
  239. data/test/test_timer.rb +95 -0
  240. data/test/test_udp.rb +216 -0
  241. data/test/test_utils.rb +49 -0
  242. metadata +84 -57
  243. data/ext/asyncengine/libuv/mkmf.log +0 -24
  244. data/ext/asyncengine/libuv/src/unix/cares.c +0 -194
  245. data/ext/asyncengine/libuv/src/unix/cares.o +0 -0
  246. data/ext/asyncengine/libuv/src/unix/check.o +0 -0
  247. data/ext/asyncengine/libuv/src/unix/idle.o +0 -0
  248. data/ext/asyncengine/libuv/src/unix/prepare.o +0 -0
  249. data/ext/asyncengine/libuv/src/win/cares.c +0 -290
  250. data/lib/asyncengine/errors.rb +0 -5
  251. data/lib/asyncengine/next_tick.rb +0 -24
@@ -26,7 +26,6 @@
26
26
  #include <string.h>
27
27
 
28
28
  #include "uv.h"
29
- #include "../uv-common.h"
30
29
  #include "internal.h"
31
30
 
32
31
 
@@ -67,9 +66,27 @@ void uv_fatal_error(const int errorno, const char* syscall) {
67
66
  uv_err_code uv_translate_sys_error(int sys_errno) {
68
67
  switch (sys_errno) {
69
68
  case ERROR_SUCCESS: return UV_OK;
69
+ case ERROR_BEGINNING_OF_MEDIA: return UV_EIO;
70
+ case ERROR_BUS_RESET: return UV_EIO;
71
+ case ERROR_CRC: return UV_EIO;
72
+ case ERROR_DEVICE_DOOR_OPEN: return UV_EIO;
73
+ case ERROR_DEVICE_REQUIRES_CLEANING: return UV_EIO;
74
+ case ERROR_DISK_CORRUPT: return UV_EIO;
75
+ case ERROR_EOM_OVERFLOW: return UV_EIO;
76
+ case ERROR_FILEMARK_DETECTED: return UV_EIO;
77
+ case ERROR_INVALID_BLOCK_LENGTH: return UV_EIO;
78
+ case ERROR_IO_DEVICE: return UV_EIO;
79
+ case ERROR_NO_DATA_DETECTED: return UV_EIO;
80
+ case ERROR_NO_SIGNAL_SENT: return UV_EIO;
81
+ case ERROR_OPEN_FAILED: return UV_EIO;
82
+ case ERROR_SETMARK_DETECTED: return UV_EIO;
83
+ case ERROR_SIGNAL_REFUSED: return UV_EIO;
70
84
  case ERROR_FILE_NOT_FOUND: return UV_ENOENT;
85
+ case ERROR_INVALID_NAME: return UV_ENOENT;
86
+ case ERROR_MOD_NOT_FOUND: return UV_ENOENT;
71
87
  case ERROR_PATH_NOT_FOUND: return UV_ENOENT;
72
88
  case ERROR_ACCESS_DENIED: return UV_EPERM;
89
+ case ERROR_PRIVILEGE_NOT_HELD: return UV_EPERM;
73
90
  case ERROR_NOACCESS: return UV_EACCES;
74
91
  case WSAEACCES: return UV_EACCES;
75
92
  case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE;
@@ -109,12 +126,14 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
109
126
  case ERROR_EA_TABLE_FULL: return UV_ENOSPC;
110
127
  case ERROR_END_OF_MEDIA: return UV_ENOSPC;
111
128
  case ERROR_HANDLE_DISK_FULL: return UV_ENOSPC;
129
+ case ERROR_WRITE_PROTECT: return UV_EROFS;
112
130
  case ERROR_NOT_CONNECTED: return UV_ENOTCONN;
113
131
  case WSAENOTCONN: return UV_ENOTCONN;
114
132
  case ERROR_DIR_NOT_EMPTY: return UV_ENOTEMPTY;
115
133
  case ERROR_NOT_SUPPORTED: return UV_ENOTSUP;
116
134
  case ERROR_INSUFFICIENT_BUFFER: return UV_EINVAL;
117
135
  case ERROR_INVALID_FLAGS: return UV_EBADF;
136
+ case ERROR_INVALID_HANDLE: return UV_EBADF;
118
137
  case ERROR_INVALID_PARAMETER: return UV_EINVAL;
119
138
  case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET;
120
139
  case ERROR_BROKEN_PIPE: return UV_EOF;
@@ -126,6 +145,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
126
145
  case WSAETIMEDOUT: return UV_ETIMEDOUT;
127
146
  case WSAHOST_NOT_FOUND: return UV_ENOENT;
128
147
  case WSAENOTSOCK: return UV_ENOTSOCK;
148
+ case ERROR_NOT_SAME_DEVICE: return UV_EXDEV;
129
149
  default: return UV_UNKNOWN;
130
150
  }
131
151
  }
@@ -24,8 +24,11 @@
24
24
  #include <errno.h>
25
25
  #include <stdio.h>
26
26
  #include <string.h>
27
+
27
28
  #include "uv.h"
28
29
  #include "internal.h"
30
+ #include "handle-inl.h"
31
+ #include "req-inl.h"
29
32
 
30
33
 
31
34
  const unsigned int uv_directory_watcher_buffer_size = 4096;
@@ -33,9 +36,7 @@ const unsigned int uv_directory_watcher_buffer_size = 4096;
33
36
 
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;
37
- handle->loop = loop;
38
- handle->flags = 0;
39
+ uv__handle_init(loop, (uv_handle_t*) handle, UV_FS_EVENT);
39
40
  handle->cb = cb;
40
41
  handle->dir_handle = INVALID_HANDLE_VALUE;
41
42
  handle->buffer = NULL;
@@ -53,10 +54,9 @@ static void uv_fs_event_init_handle(uv_loop_t* loop, uv_fs_event_t* handle,
53
54
  uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
54
55
  }
55
56
 
56
- loop->counters.handle_init++;
57
- loop->counters.fs_event_init++;
57
+ uv__handle_start(handle);
58
58
 
59
- uv_ref(loop);
59
+ loop->counters.fs_event_init++;
60
60
  }
61
61
 
62
62
 
@@ -109,7 +109,7 @@ static int uv_split_path(const wchar_t* filename, wchar_t** dir,
109
109
  return -1;
110
110
  }
111
111
  }
112
-
112
+
113
113
  *file = wcsdup(filename);
114
114
  } else {
115
115
  if (dir) {
@@ -152,7 +152,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
152
152
  uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
153
153
  }
154
154
 
155
- if (!uv_utf8_to_utf16(filename, filenamew,
155
+ if (!uv_utf8_to_utf16(filename, filenamew,
156
156
  name_size / sizeof(wchar_t))) {
157
157
  uv__set_sys_error(loop, GetLastError());
158
158
  return -1;
@@ -172,11 +172,11 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
172
172
  handle->dirw = filenamew;
173
173
  dir_to_watch = filenamew;
174
174
  } else {
175
- /*
175
+ /*
176
176
  * filename is a file. So we split filename into dir & file parts, and
177
177
  * watch the dir directory.
178
178
  */
179
-
179
+
180
180
  /* Convert to short path. */
181
181
  if (!GetShortPathNameW(filenamew, short_path, ARRAY_SIZE(short_path))) {
182
182
  last_error = GetLastError();
@@ -226,7 +226,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
226
226
  goto error;
227
227
  }
228
228
 
229
- handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size,
229
+ handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size,
230
230
  sizeof(DWORD));
231
231
  if (!handle->buffer) {
232
232
  uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
@@ -317,7 +317,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
317
317
  assert(!filename);
318
318
  assert(!long_filenamew);
319
319
 
320
- /*
320
+ /*
321
321
  * Fire the event only if we were asked to watch a directory,
322
322
  * or if the filename filter matches.
323
323
  */
@@ -328,8 +328,8 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
328
328
  file_info->FileNameLength / sizeof(wchar_t)) == 0) {
329
329
 
330
330
  if (handle->dirw) {
331
- /*
332
- * We attempt to convert the file name to its long form for
331
+ /*
332
+ * We attempt to convert the file name to its long form for
333
333
  * events that still point to valid files on disk.
334
334
  * For removed and renamed events, we do not provide the file name.
335
335
  */
@@ -382,7 +382,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
382
382
  }
383
383
  }
384
384
 
385
- /*
385
+ /*
386
386
  * If we couldn't get the long name - just use the name
387
387
  * provided by ReadDirectoryChangesW.
388
388
  */
@@ -471,6 +471,8 @@ void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) {
471
471
  if (!handle->req_pending) {
472
472
  uv_want_endgame(loop, (uv_handle_t*)handle);
473
473
  }
474
+
475
+ uv__handle_start(handle);
474
476
  }
475
477
 
476
478
 
@@ -478,7 +480,7 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
478
480
  if (handle->flags & UV_HANDLE_CLOSING &&
479
481
  !handle->req_pending) {
480
482
  assert(!(handle->flags & UV_HANDLE_CLOSED));
481
- handle->flags |= UV_HANDLE_CLOSED;
483
+ uv__handle_stop(handle);
482
484
 
483
485
  if (handle->buffer) {
484
486
  _aligned_free(handle->buffer);
@@ -505,10 +507,6 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
505
507
  handle->dirw = NULL;
506
508
  }
507
509
 
508
- if (handle->close_cb) {
509
- handle->close_cb((uv_handle_t*)handle);
510
- }
511
-
512
- uv_unref(loop);
510
+ uv__handle_close(handle);
513
511
  }
514
512
  }
@@ -32,10 +32,12 @@
32
32
 
33
33
  #include "uv.h"
34
34
  #include "internal.h"
35
+ #include "req-inl.h"
36
+
35
37
 
36
38
  #define UV_FS_ASYNC_QUEUED 0x0001
37
- #define UV_FS_FREE_ARG0 0x0002
38
- #define UV_FS_FREE_ARG1 0x0004
39
+ #define UV_FS_FREE_PATH 0x0002
40
+ #define UV_FS_FREE_NEW_PATH 0x0004
39
41
  #define UV_FS_FREE_PTR 0x0008
40
42
  #define UV_FS_CLEANEDUP 0x0010
41
43
 
@@ -51,40 +53,15 @@
51
53
  return -1; \
52
54
  }
53
55
 
54
- #define STRDUP_ARG(req, i) \
55
- req->arg##i = (void*)strdup((const char*)req->arg##i); \
56
- if (!req->arg##i) { \
57
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); \
58
- } \
59
- req->flags |= UV_FS_FREE_ARG##i;
60
-
61
- #define SET_ALLOCED_ARG(req, i) \
62
- req->flags |= UV_FS_FREE_ARG##i;
63
-
64
- #define WRAP_REQ_ARGS1(req, a0) \
65
- req->arg0 = (void*)a0;
66
-
67
- #define WRAP_REQ_ARGS2(req, a0, a1) \
68
- WRAP_REQ_ARGS1(req, a0) \
69
- req->arg1 = (void*)a1;
70
-
71
- #define WRAP_REQ_ARGS3(req, a0, a1, a2) \
72
- WRAP_REQ_ARGS2(req, a0, a1) \
73
- req->arg2 = (void*)a2;
74
-
75
- #define WRAP_REQ_ARGS4(req, a0, a1, a2, a3) \
76
- WRAP_REQ_ARGS3(req, a0, a1, a2) \
77
- req->arg3 = (void*)a3;
78
-
79
56
  #define QUEUE_FS_TP_JOB(loop, req) \
80
57
  if (!QueueUserWorkItem(&uv_fs_thread_proc, \
81
58
  req, \
82
- WT_EXECUTELONGFUNCTION)) { \
59
+ WT_EXECUTEDEFAULT)) { \
83
60
  uv__set_sys_error((loop), GetLastError()); \
84
61
  return -1; \
85
62
  } \
86
63
  req->flags |= UV_FS_ASYNC_QUEUED; \
87
- uv_ref((loop));
64
+ uv__req_register(loop, req);
88
65
 
89
66
  #define SET_UV_LAST_ERROR_FROM_REQ(req) \
90
67
  uv__set_error(req->loop, req->errorno, req->sys_errno_);
@@ -110,10 +87,30 @@
110
87
  if (file == -1) { \
111
88
  req->result = -1; \
112
89
  req->errorno = UV_EBADF; \
113
- req->sys_errno_ = ERROR_SUCCESS; \
90
+ req->sys_errno_ = ERROR_INVALID_HANDLE; \
114
91
  return; \
115
92
  }
116
93
 
94
+ #define FILETIME_TO_TIME_T(filetime) \
95
+ ((*((uint64_t*) &(filetime)) - 116444736000000000ULL) / 10000000ULL);
96
+
97
+ #define TIME_T_TO_FILETIME(time, filetime_ptr) \
98
+ do { \
99
+ *(uint64_t*) (filetime_ptr) = ((int64_t) (time) * 10000000LL) + \
100
+ 116444736000000000ULL; \
101
+ } while(0)
102
+
103
+
104
+ #define IS_SLASH(c) ((c) == L'\\' || (c) == L'/')
105
+ #define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \
106
+ ((c) >= L'A' && (c) <= L'Z'))
107
+
108
+ const wchar_t JUNCTION_PREFIX[] = L"\\??\\";
109
+ const wchar_t JUNCTION_PREFIX_LEN = 4;
110
+
111
+ const wchar_t LONG_PATH_PREFIX[] = L"\\\\?\\";
112
+ const wchar_t LONG_PATH_PREFIX_LEN = 4;
113
+
117
114
 
118
115
  void uv_fs_init() {
119
116
  _fmode = _O_BINARY;
@@ -153,6 +150,61 @@ static void uv_fs_req_init_sync(uv_loop_t* loop, uv_fs_t* req,
153
150
  }
154
151
 
155
152
 
153
+ static int is_path_dir(const wchar_t* path) {
154
+ DWORD attr = GetFileAttributesW(path);
155
+
156
+ if (attr != INVALID_FILE_ATTRIBUTES) {
157
+ return attr & FILE_ATTRIBUTE_DIRECTORY ? 1 : 0;
158
+ } else {
159
+ return 0;
160
+ }
161
+ }
162
+
163
+
164
+ static int get_reparse_point(HANDLE handle, int* target_length) {
165
+ void* buffer = NULL;
166
+ REPARSE_DATA_BUFFER* reparse_data;
167
+ DWORD bytes_returned;
168
+ int rv = 0;
169
+
170
+ buffer = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
171
+ if (!buffer) {
172
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
173
+ }
174
+
175
+ if (!DeviceIoControl(handle,
176
+ FSCTL_GET_REPARSE_POINT,
177
+ NULL,
178
+ 0,
179
+ buffer,
180
+ MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
181
+ &bytes_returned,
182
+ NULL)) {
183
+ free(buffer);
184
+ return 0;
185
+ }
186
+
187
+ reparse_data = (REPARSE_DATA_BUFFER*)buffer;
188
+
189
+ if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
190
+ rv = 1;
191
+ if (target_length) {
192
+ *target_length = reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
193
+ sizeof(wchar_t);
194
+ }
195
+ } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
196
+ rv = 1;
197
+ if (target_length) {
198
+ *target_length = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
199
+ sizeof(wchar_t);
200
+ }
201
+ }
202
+
203
+ free(buffer);
204
+ return rv;
205
+ }
206
+
207
+
156
208
  void fs__open(uv_fs_t* req, const wchar_t* path, int flags, int mode) {
157
209
  DWORD access;
158
210
  DWORD share;
@@ -249,10 +301,8 @@ void fs__open(uv_fs_t* req, const wchar_t* path, int flags, int mode) {
249
301
  goto end;
250
302
  }
251
303
 
252
- /* Figure out whether path is a file or a directory. */
253
- if (GetFileAttributesW(path) & FILE_ATTRIBUTE_DIRECTORY) {
254
- attributes |= FILE_FLAG_BACKUP_SEMANTICS;
255
- }
304
+ /* Setting this flag makes it possible to open a directory. */
305
+ attributes |= FILE_FLAG_BACKUP_SEMANTICS;
256
306
 
257
307
  file = CreateFileW(path,
258
308
  access,
@@ -289,7 +339,7 @@ void fs__close(uv_fs_t* req, uv_file file) {
289
339
 
290
340
 
291
341
  void fs__read(uv_fs_t* req, uv_file file, void *buf, size_t length,
292
- off_t offset) {
342
+ int64_t offset) {
293
343
  HANDLE handle;
294
344
  OVERLAPPED overlapped, *overlapped_ptr;
295
345
  LARGE_INTEGER offset_;
@@ -335,7 +385,7 @@ void fs__read(uv_fs_t* req, uv_file file, void *buf, size_t length,
335
385
 
336
386
 
337
387
  void fs__write(uv_fs_t* req, uv_file file, void *buf, size_t length,
338
- off_t offset) {
388
+ int64_t offset) {
339
389
  HANDLE handle;
340
390
  OVERLAPPED overlapped, *overlapped_ptr;
341
391
  LARGE_INTEGER offset_;
@@ -374,20 +424,53 @@ void fs__write(uv_fs_t* req, uv_file file, void *buf, size_t length,
374
424
  }
375
425
 
376
426
 
377
- void fs__unlink(uv_fs_t* req, const wchar_t* path) {
378
- int result = _wunlink(path);
427
+ void fs__rmdir(uv_fs_t* req, const wchar_t* path) {
428
+ int result = _wrmdir(path);
379
429
  SET_REQ_RESULT(req, result);
380
430
  }
381
431
 
382
432
 
383
- void fs__mkdir(uv_fs_t* req, const wchar_t* path, int mode) {
384
- int result = _wmkdir(path);
385
- SET_REQ_RESULT(req, result);
433
+ void fs__unlink(uv_fs_t* req, const wchar_t* path) {
434
+ int result;
435
+ HANDLE handle;
436
+ BY_HANDLE_FILE_INFORMATION info;
437
+ int is_dir_symlink;
438
+
439
+ handle = CreateFileW(path,
440
+ 0,
441
+ 0,
442
+ NULL,
443
+ OPEN_EXISTING,
444
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
445
+ NULL);
446
+
447
+ if (handle == INVALID_HANDLE_VALUE) {
448
+ SET_REQ_WIN32_ERROR(req, GetLastError());
449
+ return;
450
+ }
451
+
452
+ if (!GetFileInformationByHandle(handle, &info)) {
453
+ SET_REQ_WIN32_ERROR(req, GetLastError());
454
+ CloseHandle(handle);
455
+ return;
456
+ }
457
+
458
+ is_dir_symlink = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
459
+ get_reparse_point(handle, NULL);
460
+
461
+ CloseHandle(handle);
462
+
463
+ if (is_dir_symlink) {
464
+ fs__rmdir(req, path);
465
+ } else {
466
+ result = _wunlink(path);
467
+ SET_REQ_RESULT(req, result);
468
+ }
386
469
  }
387
470
 
388
471
 
389
- void fs__rmdir(uv_fs_t* req, const wchar_t* path) {
390
- int result = _wrmdir(path);
472
+ void fs__mkdir(uv_fs_t* req, const wchar_t* path, int mode) {
473
+ int result = _wmkdir(path);
391
474
  SET_REQ_RESULT(req, result);
392
475
  }
393
476
 
@@ -499,77 +582,115 @@ void fs__readdir(uv_fs_t* req, const wchar_t* path, int flags) {
499
582
  }
500
583
 
501
584
 
502
- static void fs__stat(uv_fs_t* req, const wchar_t* path) {
503
- HANDLE handle;
585
+ INLINE static int fs__stat_handle(HANDLE handle, uv_statbuf_t* statbuf) {
586
+ int target_length;
504
587
  BY_HANDLE_FILE_INFORMATION info;
505
588
 
589
+ if (!GetFileInformationByHandle(handle, &info)) {
590
+ return -1;
591
+ }
592
+
593
+ /* TODO: set st_dev, st_rdev and st_ino to something meaningful. */
594
+ statbuf->st_ino = 0;
595
+ statbuf->st_dev = 0;
596
+ statbuf->st_rdev = 0;
597
+
598
+ statbuf->st_gid = 0;
599
+ statbuf->st_uid = 0;
600
+
601
+ statbuf->st_mode = 0;
602
+
603
+ if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
604
+ get_reparse_point(handle, &target_length)) {
605
+ statbuf->st_mode = S_IFLNK;
606
+ /* Adjust for long path */
607
+ statbuf->st_size = target_length - JUNCTION_PREFIX_LEN;
608
+ } else {
609
+ if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
610
+ statbuf->st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
611
+ } else {
612
+ statbuf->st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3) +
613
+ ((_S_IREAD|_S_IWRITE) >> 6));
614
+ }
615
+
616
+ if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
617
+ statbuf->st_mode |= _S_IFDIR;
618
+ } else {
619
+ statbuf->st_mode |= _S_IFREG;
620
+ }
621
+
622
+ statbuf->st_size = ((int64_t) info.nFileSizeHigh << 32) +
623
+ (int64_t) info.nFileSizeLow;
624
+
625
+ }
626
+
627
+ statbuf->st_mtime = FILETIME_TO_TIME_T(info.ftLastWriteTime);
628
+ statbuf->st_atime = FILETIME_TO_TIME_T(info.ftLastAccessTime);
629
+ statbuf->st_ctime = FILETIME_TO_TIME_T(info.ftCreationTime);
630
+
631
+ statbuf->st_nlink = (info.nNumberOfLinks <= SHRT_MAX) ?
632
+ (short) info.nNumberOfLinks : SHRT_MAX;
633
+
634
+ return 0;
635
+ }
636
+
637
+
638
+ INLINE static void fs__stat(uv_fs_t* req, const wchar_t* path, int do_lstat) {
639
+ HANDLE handle;
640
+ DWORD flags;
641
+
506
642
  req->ptr = NULL;
643
+ flags = FILE_FLAG_BACKUP_SEMANTICS;
644
+
645
+ if (do_lstat) {
646
+ flags |= FILE_FLAG_OPEN_REPARSE_POINT;
647
+ }
507
648
 
508
649
  handle = CreateFileW(path,
509
650
  FILE_READ_ATTRIBUTES,
510
651
  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
511
652
  NULL,
512
653
  OPEN_EXISTING,
513
- FILE_FLAG_BACKUP_SEMANTICS,
654
+ flags,
514
655
  NULL);
515
656
  if (handle == INVALID_HANDLE_VALUE) {
516
657
  SET_REQ_WIN32_ERROR(req, GetLastError());
517
658
  return;
518
659
  }
519
660
 
520
- if (!GetFileInformationByHandle(handle, &info)) {
661
+ if (fs__stat_handle(handle, &req->stat) != 0) {
521
662
  SET_REQ_WIN32_ERROR(req, GetLastError());
522
663
  CloseHandle(handle);
523
664
  return;
524
665
  }
525
666
 
526
- memset(&req->stat, 0, sizeof req->stat);
527
-
528
- /* TODO: set st_dev and st_ino? */
529
-
530
- if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
531
- req->stat.st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
532
- } else {
533
- req->stat.st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3) +
534
- ((_S_IREAD|_S_IWRITE) >> 6));
535
- }
536
-
537
- if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
538
- req->stat.st_mode |= _S_IFDIR;
539
- } else {
540
- req->stat.st_mode |= _S_IFREG;
541
- }
542
-
543
- uv_filetime_to_time_t(&info.ftLastWriteTime, &(req->stat.st_mtime));
544
- uv_filetime_to_time_t(&info.ftLastAccessTime, &(req->stat.st_atime));
545
- uv_filetime_to_time_t(&info.ftCreationTime, &(req->stat.st_ctime));
546
-
547
- req->stat.st_size = ((int64_t) info.nFileSizeHigh << 32) +
548
- (int64_t) info.nFileSizeLow;
549
-
550
- req->stat.st_nlink = (info.nNumberOfLinks <= SHRT_MAX) ?
551
- (short) info.nNumberOfLinks : SHRT_MAX;
552
-
553
667
  req->ptr = &req->stat;
554
668
  req->result = 0;
555
-
556
669
  CloseHandle(handle);
557
670
  }
558
671
 
559
672
 
560
673
  void fs__fstat(uv_fs_t* req, uv_file file) {
561
- int result;
674
+ HANDLE handle;
675
+
676
+ req->ptr = NULL;
562
677
 
563
678
  VERIFY_UV_FILE(file, req);
564
679
 
565
- result = _fstati64(file, &req->stat);
566
- if (result == -1) {
567
- req->ptr = NULL;
568
- } else {
569
- req->ptr = &req->stat;
680
+ handle = (HANDLE) _get_osfhandle(file);
681
+
682
+ if (handle == INVALID_HANDLE_VALUE) {
683
+ SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
684
+ return;
570
685
  }
571
686
 
572
- SET_REQ_RESULT(req, result);
687
+ if (fs__stat_handle(handle, &req->stat) != 0) {
688
+ SET_REQ_WIN32_ERROR(req, GetLastError());
689
+ return;
690
+ }
691
+
692
+ req->ptr = &req->stat;
693
+ req->result = 0;
573
694
  }
574
695
 
575
696
 
@@ -597,31 +718,50 @@ void fs__fsync(uv_fs_t* req, uv_file file) {
597
718
  }
598
719
 
599
720
 
600
- void fs__ftruncate(uv_fs_t* req, uv_file file, off_t offset) {
601
- int result;
721
+ void fs__ftruncate(uv_fs_t* req, uv_file file, int64_t offset) {
722
+ HANDLE handle;
723
+ NTSTATUS status;
724
+ IO_STATUS_BLOCK io_status;
725
+ FILE_END_OF_FILE_INFORMATION eof_info;
602
726
 
603
727
  VERIFY_UV_FILE(file, req);
604
728
 
605
- result = _chsize(file, offset);
606
- SET_REQ_RESULT(req, result);
729
+ handle = (HANDLE)_get_osfhandle(file);
730
+
731
+ eof_info.EndOfFile.QuadPart = offset;
732
+
733
+ status = pNtSetInformationFile(handle,
734
+ &io_status,
735
+ &eof_info,
736
+ sizeof eof_info,
737
+ FileEndOfFileInformation);
738
+
739
+ if (NT_SUCCESS(status)) {
740
+ SET_REQ_RESULT(req, 0);
741
+ } else {
742
+ SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
743
+ }
607
744
  }
608
745
 
609
746
 
610
747
  void fs__sendfile(uv_fs_t* req, uv_file out_file, uv_file in_file,
611
- off_t in_offset, size_t length) {
748
+ int64_t in_offset, size_t length) {
612
749
  const size_t max_buf_size = 65536;
613
750
  size_t buf_size = length < max_buf_size ? length : max_buf_size;
614
751
  int n, result = 0;
752
+ int64_t result_offset = 0;
615
753
  char* buf = (char*)malloc(buf_size);
616
754
  if (!buf) {
617
755
  uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
618
756
  }
619
757
 
620
758
  if (in_offset != -1) {
621
- result = _lseek(in_file, in_offset, SEEK_SET);
759
+ result_offset = _lseeki64(in_file, in_offset, SEEK_SET);
622
760
  }
623
761
 
624
- if (result != -1) {
762
+ if (result_offset == -1) {
763
+ result = -1;
764
+ } else {
625
765
  while (length > 0) {
626
766
  n = _read(in_file, buf, length < buf_size ? length : buf_size);
627
767
  if (n == 0) {
@@ -699,22 +839,62 @@ done:
699
839
  }
700
840
 
701
841
 
842
+ INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
843
+ FILETIME filetime_a, filetime_m;
844
+
845
+ TIME_T_TO_FILETIME((time_t) atime, &filetime_a);
846
+ TIME_T_TO_FILETIME((time_t) mtime, &filetime_m);
847
+
848
+ if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) {
849
+ return -1;
850
+ }
851
+
852
+ return 0;
853
+ }
854
+
855
+
702
856
  void fs__utime(uv_fs_t* req, const wchar_t* path, double atime, double mtime) {
703
- int result;
704
- struct _utimbuf b = {(time_t)atime, (time_t)mtime};
705
- result = _wutime(path, &b);
706
- SET_REQ_RESULT(req, result);
857
+ HANDLE handle;
858
+
859
+ handle = CreateFileW(path,
860
+ FILE_WRITE_ATTRIBUTES,
861
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
862
+ NULL,
863
+ OPEN_EXISTING,
864
+ FILE_FLAG_BACKUP_SEMANTICS,
865
+ NULL);
866
+
867
+ if (handle == INVALID_HANDLE_VALUE) {
868
+ SET_REQ_WIN32_ERROR(req, GetLastError());
869
+ return;
870
+ }
871
+
872
+ if (fs__utime_handle(handle, atime, mtime) != 0) {
873
+ SET_REQ_WIN32_ERROR(req, GetLastError());
874
+ return;
875
+ }
876
+
877
+ req->result = 0;
707
878
  }
708
879
 
709
880
 
710
881
  void fs__futime(uv_fs_t* req, uv_file file, double atime, double mtime) {
711
- int result;
712
- struct _utimbuf b = {(time_t)atime, (time_t)mtime};
713
-
882
+ HANDLE handle;
714
883
  VERIFY_UV_FILE(file, req);
715
884
 
716
- result = _futime(file, &b);
717
- SET_REQ_RESULT(req, result);
885
+ handle = (HANDLE) _get_osfhandle(file);
886
+
887
+ if (handle == INVALID_HANDLE_VALUE) {
888
+ SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
889
+ return;
890
+ }
891
+
892
+ if (fs__utime_handle(handle, atime, mtime) != 0) {
893
+ SET_REQ_WIN32_ERROR(req, GetLastError());
894
+ return;
895
+ }
896
+
897
+ req->result = 0;
718
898
  }
719
899
 
720
900
 
@@ -728,23 +908,193 @@ void fs__link(uv_fs_t* req, const wchar_t* path, const wchar_t* new_path) {
728
908
  }
729
909
 
730
910
 
911
+ void fs__create_junction(uv_fs_t* req, const wchar_t* path, const wchar_t* new_path) {
912
+ HANDLE handle = INVALID_HANDLE_VALUE;
913
+ REPARSE_DATA_BUFFER *buffer = NULL;
914
+ int created = 0;
915
+ int target_len;
916
+ int is_absolute, is_long_path;
917
+ int needed_buf_size, used_buf_size, used_data_size, path_buf_len;
918
+ int start, len, i;
919
+ int add_slash;
920
+ DWORD bytes;
921
+ wchar_t* path_buf;
922
+
923
+ target_len = wcslen(path);
924
+ is_long_path = wcsncmp(path, LONG_PATH_PREFIX, LONG_PATH_PREFIX_LEN) == 0;
925
+
926
+ if (is_long_path) {
927
+ is_absolute = 1;
928
+ } else {
929
+ is_absolute = target_len >= 3 && IS_LETTER(path[0]) &&
930
+ path[1] == L':' && IS_SLASH(path[2]);
931
+ }
932
+
933
+ if (!is_absolute) {
934
+ /* Not supporting relative paths */
935
+ SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_NOT_SUPPORTED);
936
+ return;
937
+ }
938
+
939
+ // Do a pessimistic calculation of the required buffer size
940
+ needed_buf_size =
941
+ FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
942
+ JUNCTION_PREFIX_LEN * sizeof(wchar_t) +
943
+ 2 * (target_len + 2) * sizeof(wchar_t);
944
+
945
+ // Allocate the buffer
946
+ buffer = (REPARSE_DATA_BUFFER*)malloc(needed_buf_size);
947
+ if (!buffer) {
948
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
949
+ }
950
+
951
+ // Grab a pointer to the part of the buffer where filenames go
952
+ path_buf = (wchar_t*)&(buffer->MountPointReparseBuffer.PathBuffer);
953
+ path_buf_len = 0;
954
+
955
+ // Copy the substitute (internal) target path
956
+ start = path_buf_len;
957
+
958
+ wcsncpy((wchar_t*)&path_buf[path_buf_len], JUNCTION_PREFIX,
959
+ JUNCTION_PREFIX_LEN);
960
+ path_buf_len += JUNCTION_PREFIX_LEN;
961
+
962
+ add_slash = 0;
963
+ for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
964
+ if (IS_SLASH(path[i])) {
965
+ add_slash = 1;
966
+ continue;
967
+ }
968
+
969
+ if (add_slash) {
970
+ path_buf[path_buf_len++] = L'\\';
971
+ add_slash = 0;
972
+ }
973
+
974
+ path_buf[path_buf_len++] = path[i];
975
+ }
976
+ path_buf[path_buf_len++] = L'\\';
977
+ len = path_buf_len - start;
978
+
979
+ // Set the info about the substitute name
980
+ buffer->MountPointReparseBuffer.SubstituteNameOffset = start * sizeof(wchar_t);
981
+ buffer->MountPointReparseBuffer.SubstituteNameLength = len * sizeof(wchar_t);
982
+
983
+ // Insert null terminator
984
+ path_buf[path_buf_len++] = L'\0';
985
+
986
+ // Copy the print name of the target path
987
+ start = path_buf_len;
988
+ add_slash = 0;
989
+ for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
990
+ if (IS_SLASH(path[i])) {
991
+ add_slash = 1;
992
+ continue;
993
+ }
994
+
995
+ if (add_slash) {
996
+ path_buf[path_buf_len++] = L'\\';
997
+ add_slash = 0;
998
+ }
999
+
1000
+ path_buf[path_buf_len++] = path[i];
1001
+ }
1002
+ len = path_buf_len - start;
1003
+ if (len == 2) {
1004
+ path_buf[path_buf_len++] = L'\\';
1005
+ len++;
1006
+ }
1007
+
1008
+ // Set the info about the print name
1009
+ buffer->MountPointReparseBuffer.PrintNameOffset = start * sizeof(wchar_t);
1010
+ buffer->MountPointReparseBuffer.PrintNameLength = len * sizeof(wchar_t);
1011
+
1012
+ // Insert another null terminator
1013
+ path_buf[path_buf_len++] = L'\0';
1014
+
1015
+ // Calculate how much buffer space was actually used
1016
+ used_buf_size = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
1017
+ path_buf_len * sizeof(wchar_t);
1018
+ used_data_size = used_buf_size -
1019
+ FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer);
1020
+
1021
+ // Put general info in the data buffer
1022
+ buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
1023
+ buffer->ReparseDataLength = used_data_size;
1024
+ buffer->Reserved = 0;
1025
+
1026
+ // Create a new directory
1027
+ if (!CreateDirectoryW(new_path, NULL)) {
1028
+ SET_REQ_WIN32_ERROR(req, GetLastError());
1029
+ goto error;
1030
+ }
1031
+ created = 1;
1032
+
1033
+ // Open the directory
1034
+ handle = CreateFileW(new_path,
1035
+ GENERIC_ALL,
1036
+ 0,
1037
+ NULL,
1038
+ OPEN_EXISTING,
1039
+ FILE_FLAG_BACKUP_SEMANTICS |
1040
+ FILE_FLAG_OPEN_REPARSE_POINT,
1041
+ NULL);
1042
+ if (handle == INVALID_HANDLE_VALUE) {
1043
+ SET_REQ_WIN32_ERROR(req, GetLastError());
1044
+ goto error;
1045
+ }
1046
+
1047
+ // Create the actual reparse point
1048
+ if (!DeviceIoControl(handle,
1049
+ FSCTL_SET_REPARSE_POINT,
1050
+ buffer,
1051
+ used_buf_size,
1052
+ NULL,
1053
+ 0,
1054
+ &bytes,
1055
+ NULL)) {
1056
+ SET_REQ_WIN32_ERROR(req, GetLastError());
1057
+ goto error;
1058
+ }
1059
+
1060
+ // Clean up
1061
+ CloseHandle(handle);
1062
+ free(buffer);
1063
+
1064
+ SET_REQ_RESULT(req, 0);
1065
+ return;
1066
+
1067
+ error:
1068
+ free(buffer);
1069
+
1070
+ if (handle != INVALID_HANDLE_VALUE) {
1071
+ CloseHandle(handle);
1072
+ }
1073
+
1074
+ if (created) {
1075
+ RemoveDirectoryW(new_path);
1076
+ }
1077
+ }
1078
+
1079
+
731
1080
  void fs__symlink(uv_fs_t* req, const wchar_t* path, const wchar_t* new_path,
732
1081
  int flags) {
733
1082
  int result;
734
- if (pCreateSymbolicLinkW) {
1083
+
1084
+ if (flags & UV_FS_SYMLINK_JUNCTION) {
1085
+ fs__create_junction(req, path, new_path);
1086
+ } else if (pCreateSymbolicLinkW) {
735
1087
  result = pCreateSymbolicLinkW(new_path,
736
1088
  path,
737
1089
  flags & UV_FS_SYMLINK_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) ? 0 : -1;
738
1090
  if (result == -1) {
739
1091
  SET_REQ_WIN32_ERROR(req, GetLastError());
740
- return;
1092
+ } else {
1093
+ SET_REQ_RESULT(req, result);
741
1094
  }
742
1095
  } else {
743
1096
  SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
744
- return;
745
1097
  }
746
-
747
- SET_REQ_RESULT(req, result);
748
1098
  }
749
1099
 
750
1100
 
@@ -794,22 +1144,31 @@ void fs__readlink(uv_fs_t* req, const wchar_t* path) {
794
1144
  }
795
1145
 
796
1146
  reparse_data = (REPARSE_DATA_BUFFER*)buffer;
797
- if (reparse_data->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
1147
+ if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
1148
+ substitute_name = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
1149
+ (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset /
1150
+ sizeof(wchar_t));
1151
+ substitute_name_length =
1152
+ reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
1153
+ sizeof(wchar_t);
1154
+ } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
1155
+ substitute_name = reparse_data->MountPointReparseBuffer.PathBuffer +
1156
+ (reparse_data->MountPointReparseBuffer.SubstituteNameOffset /
1157
+ sizeof(wchar_t));
1158
+ substitute_name_length =
1159
+ reparse_data->MountPointReparseBuffer.SubstituteNameLength /
1160
+ sizeof(wchar_t);
1161
+ } else {
798
1162
  result = -1;
799
1163
  /* something is seriously wrong */
800
1164
  SET_REQ_WIN32_ERROR(req, GetLastError());
801
1165
  goto done;
802
1166
  }
803
1167
 
804
- substitute_name = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
805
- (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t));
806
- substitute_name_length =
807
- reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
808
-
809
1168
  /* Strip off the leading \??\ from the substitute name buffer.*/
810
- if (memcmp(substitute_name, L"\\??\\", 8) == 0) {
811
- substitute_name += 4;
812
- substitute_name_length -= 4;
1169
+ if (wcsncmp(substitute_name, JUNCTION_PREFIX, JUNCTION_PREFIX_LEN) == 0) {
1170
+ substitute_name += JUNCTION_PREFIX_LEN;
1171
+ substitute_name_length -= JUNCTION_PREFIX_LEN;
813
1172
  }
814
1173
 
815
1174
  utf8size = uv_utf16_to_utf8(substitute_name,
@@ -868,78 +1227,68 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
868
1227
 
869
1228
  switch (req->fs_type) {
870
1229
  case UV_FS_OPEN:
871
- fs__open(req, req->pathw, (int)req->arg0, (int)req->arg1);
1230
+ fs__open(req, req->pathw, req->file_flags, (int)req->mode);
872
1231
  break;
873
1232
  case UV_FS_CLOSE:
874
- fs__close(req, (uv_file)req->arg0);
1233
+ fs__close(req, req->file);
875
1234
  break;
876
1235
  case UV_FS_READ:
877
- fs__read(req,
878
- (uv_file) req->arg0,
879
- req->arg1,
880
- (size_t) req->arg2,
881
- (off_t) req->arg3);
1236
+ fs__read(req, req->file, req->buf, req->length, req->offset);
882
1237
  break;
883
1238
  case UV_FS_WRITE:
884
- fs__write(req,
885
- (uv_file)req->arg0,
886
- req->arg1,
887
- (size_t) req->arg2,
888
- (off_t) req->arg3);
1239
+ fs__write(req, req->file, req->buf, req->length, req->offset);
889
1240
  break;
890
1241
  case UV_FS_UNLINK:
891
1242
  fs__unlink(req, req->pathw);
892
1243
  break;
893
1244
  case UV_FS_MKDIR:
894
- fs__mkdir(req, req->pathw, (int)req->arg0);
1245
+ fs__mkdir(req, req->pathw, req->mode);
895
1246
  break;
896
1247
  case UV_FS_RMDIR:
897
1248
  fs__rmdir(req, req->pathw);
898
1249
  break;
899
1250
  case UV_FS_READDIR:
900
- fs__readdir(req, req->pathw, (int)req->arg0);
1251
+ fs__readdir(req, req->pathw, req->file_flags);
901
1252
  break;
902
1253
  case UV_FS_STAT:
1254
+ fs__stat(req, req->pathw, 0);
1255
+ break;
903
1256
  case UV_FS_LSTAT:
904
- fs__stat(req, req->pathw);
1257
+ fs__stat(req, req->pathw, 1);
905
1258
  break;
906
1259
  case UV_FS_FSTAT:
907
- fs__fstat(req, (uv_file)req->arg0);
1260
+ fs__fstat(req, req->file);
908
1261
  break;
909
1262
  case UV_FS_RENAME:
910
- fs__rename(req, req->pathw, (const wchar_t*)req->arg0);
1263
+ fs__rename(req, req->pathw, req->new_pathw);
911
1264
  break;
912
1265
  case UV_FS_FSYNC:
913
1266
  case UV_FS_FDATASYNC:
914
- fs__fsync(req, (uv_file)req->arg0);
1267
+ fs__fsync(req, req->file);
915
1268
  break;
916
1269
  case UV_FS_FTRUNCATE:
917
- fs__ftruncate(req, (uv_file)req->arg0, (off_t)req->arg1);
1270
+ fs__ftruncate(req, req->file, req->offset);
918
1271
  break;
919
1272
  case UV_FS_SENDFILE:
920
- fs__sendfile(req,
921
- (uv_file) req->arg0,
922
- (uv_file) req->arg1,
923
- (off_t) req->arg2,
924
- (size_t) req->arg3);
1273
+ fs__sendfile(req, req->file_out, req->file, req->offset, req->length);
925
1274
  break;
926
1275
  case UV_FS_CHMOD:
927
- fs__chmod(req, req->pathw, (int)req->arg0);
1276
+ fs__chmod(req, req->pathw, req->mode);
928
1277
  break;
929
1278
  case UV_FS_FCHMOD:
930
- fs__fchmod(req, (uv_file)req->arg0, (int)req->arg1);
1279
+ fs__fchmod(req, req->file, req->mode);
931
1280
  break;
932
1281
  case UV_FS_UTIME:
933
- fs__utime(req, req->pathw, req->arg4, req->arg5);
1282
+ fs__utime(req, req->pathw, req->atime, req->mtime);
934
1283
  break;
935
1284
  case UV_FS_FUTIME:
936
- fs__futime(req, (uv_file)req->arg0, req->arg4, req->arg5);
1285
+ fs__futime(req, req->file, req->atime, req->mtime);
937
1286
  break;
938
1287
  case UV_FS_LINK:
939
- fs__link(req, req->pathw, (const wchar_t*)req->arg0);
1288
+ fs__link(req, req->pathw, req->new_pathw);
940
1289
  break;
941
1290
  case UV_FS_SYMLINK:
942
- fs__symlink(req, req->pathw, (const wchar_t*)req->arg0, (int)req->arg1);
1291
+ fs__symlink(req, req->pathw, req->new_pathw, req->file_flags);
943
1292
  break;
944
1293
  case UV_FS_READLINK:
945
1294
  fs__readlink(req, req->pathw);
@@ -968,7 +1317,8 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
968
1317
 
969
1318
  if (cb) {
970
1319
  uv_fs_req_init_async(loop, req, UV_FS_OPEN, path, pathw, cb);
971
- WRAP_REQ_ARGS2(req, flags, mode);
1320
+ req->file_flags = flags;
1321
+ req->mode = mode;
972
1322
  QUEUE_FS_TP_JOB(loop, req);
973
1323
  } else {
974
1324
  uv_fs_req_init_sync(loop, req, UV_FS_OPEN);
@@ -985,7 +1335,7 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
985
1335
  int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
986
1336
  if (cb) {
987
1337
  uv_fs_req_init_async(loop, req, UV_FS_CLOSE, NULL, NULL, cb);
988
- WRAP_REQ_ARGS1(req, file);
1338
+ req->file = file;
989
1339
  QUEUE_FS_TP_JOB(loop, req);
990
1340
  } else {
991
1341
  uv_fs_req_init_sync(loop, req, UV_FS_CLOSE);
@@ -999,10 +1349,13 @@ int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
999
1349
 
1000
1350
 
1001
1351
  int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf,
1002
- size_t length, off_t offset, uv_fs_cb cb) {
1352
+ size_t length, int64_t offset, uv_fs_cb cb) {
1003
1353
  if (cb) {
1004
1354
  uv_fs_req_init_async(loop, req, UV_FS_READ, NULL, NULL, cb);
1005
- WRAP_REQ_ARGS4(req, file, buf, length, offset);
1355
+ req->file = file;
1356
+ req->buf = buf;
1357
+ req->length = length;
1358
+ req->offset = offset;
1006
1359
  QUEUE_FS_TP_JOB(loop, req);
1007
1360
  } else {
1008
1361
  uv_fs_req_init_sync(loop, req, UV_FS_READ);
@@ -1016,10 +1369,13 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf,
1016
1369
 
1017
1370
 
1018
1371
  int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf,
1019
- size_t length, off_t offset, uv_fs_cb cb) {
1372
+ size_t length, int64_t offset, uv_fs_cb cb) {
1020
1373
  if (cb) {
1021
1374
  uv_fs_req_init_async(loop, req, UV_FS_WRITE, NULL, NULL, cb);
1022
- WRAP_REQ_ARGS4(req, file, buf, length, offset);
1375
+ req->file = file;
1376
+ req->buf = buf;
1377
+ req->length = length;
1378
+ req->offset = offset;
1023
1379
  QUEUE_FS_TP_JOB(loop, req);
1024
1380
  } else {
1025
1381
  uv_fs_req_init_sync(loop, req, UV_FS_WRITE);
@@ -1065,7 +1421,7 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
1065
1421
 
1066
1422
  if (cb) {
1067
1423
  uv_fs_req_init_async(loop, req, UV_FS_MKDIR, path, pathw, cb);
1068
- WRAP_REQ_ARGS1(req, mode);
1424
+ req->mode = mode;
1069
1425
  QUEUE_FS_TP_JOB(loop, req);
1070
1426
  } else {
1071
1427
  uv_fs_req_init_sync(loop, req, UV_FS_MKDIR);
@@ -1111,7 +1467,7 @@ int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
1111
1467
 
1112
1468
  if (cb) {
1113
1469
  uv_fs_req_init_async(loop, req, UV_FS_READDIR, path, pathw, cb);
1114
- WRAP_REQ_ARGS1(req, flags);
1470
+ req->file_flags = flags;
1115
1471
  QUEUE_FS_TP_JOB(loop, req);
1116
1472
  } else {
1117
1473
  uv_fs_req_init_sync(loop, req, UV_FS_READDIR);
@@ -1137,8 +1493,8 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
1137
1493
 
1138
1494
  if (cb) {
1139
1495
  uv_fs_req_init_async(loop, req, UV_FS_LINK, path, pathw, cb);
1140
- WRAP_REQ_ARGS1(req, new_pathw);
1141
- SET_ALLOCED_ARG(req, 0);
1496
+ req->new_pathw = new_pathw;
1497
+ req->flags |= UV_FS_FREE_NEW_PATH;
1142
1498
  QUEUE_FS_TP_JOB(loop, req);
1143
1499
  } else {
1144
1500
  uv_fs_req_init_sync(loop, req, UV_FS_LINK);
@@ -1165,8 +1521,9 @@ int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
1165
1521
 
1166
1522
  if (cb) {
1167
1523
  uv_fs_req_init_async(loop, req, UV_FS_SYMLINK, path, pathw, cb);
1168
- WRAP_REQ_ARGS2(req, new_pathw, flags);
1169
- SET_ALLOCED_ARG(req, 0);
1524
+ req->new_pathw = new_pathw;
1525
+ req->file_flags = flags;
1526
+ req->flags |= UV_FS_FREE_NEW_PATH;
1170
1527
  QUEUE_FS_TP_JOB(loop, req);
1171
1528
  } else {
1172
1529
  uv_fs_req_init_sync(loop, req, UV_FS_SYMLINK);
@@ -1214,7 +1571,6 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid,
1214
1571
 
1215
1572
  if (cb) {
1216
1573
  uv_fs_req_init_async(loop, req, UV_FS_CHOWN, path, pathw, cb);
1217
- WRAP_REQ_ARGS2(req, uid, gid);
1218
1574
  QUEUE_FS_TP_JOB(loop, req);
1219
1575
  } else {
1220
1576
  uv_fs_req_init_sync(loop, req, UV_FS_CHOWN);
@@ -1232,7 +1588,6 @@ int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, int uid,
1232
1588
  int gid, uv_fs_cb cb) {
1233
1589
  if (cb) {
1234
1590
  uv_fs_req_init_async(loop, req, UV_FS_FCHOWN, NULL, NULL, cb);
1235
- WRAP_REQ_ARGS3(req, file, uid, gid);
1236
1591
  QUEUE_FS_TP_JOB(loop, req);
1237
1592
  } else {
1238
1593
  uv_fs_req_init_sync(loop, req, UV_FS_FCHOWN);
@@ -1275,7 +1630,7 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
1275
1630
  } else {
1276
1631
  uv_fs_req_init_sync(loop, req, UV_FS_STAT);
1277
1632
  UTF8_TO_UTF16(path2 ? path2 : path, pathw);
1278
- fs__stat(req, pathw);
1633
+ fs__stat(req, pathw, 0);
1279
1634
  if (path2) {
1280
1635
  free(path2);
1281
1636
  }
@@ -1319,7 +1674,7 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
1319
1674
  } else {
1320
1675
  uv_fs_req_init_sync(loop, req, UV_FS_LSTAT);
1321
1676
  UTF8_TO_UTF16(path2 ? path2 : path, pathw);
1322
- fs__stat(req, pathw);
1677
+ fs__stat(req, pathw, 1);
1323
1678
  if (path2) {
1324
1679
  free(path2);
1325
1680
  }
@@ -1335,7 +1690,7 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
1335
1690
  int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1336
1691
  if (cb) {
1337
1692
  uv_fs_req_init_async(loop, req, UV_FS_FSTAT, NULL, NULL, cb);
1338
- WRAP_REQ_ARGS1(req, file);
1693
+ req->file = file;
1339
1694
  QUEUE_FS_TP_JOB(loop, req);
1340
1695
  } else {
1341
1696
  uv_fs_req_init_sync(loop, req, UV_FS_FSTAT);
@@ -1360,8 +1715,8 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
1360
1715
 
1361
1716
  if (cb) {
1362
1717
  uv_fs_req_init_async(loop, req, UV_FS_RENAME, path, pathw, cb);
1363
- WRAP_REQ_ARGS1(req, new_pathw);
1364
- SET_ALLOCED_ARG(req, 0);
1718
+ req->new_pathw = new_pathw;
1719
+ req->flags |= UV_FS_FREE_NEW_PATH;
1365
1720
  QUEUE_FS_TP_JOB(loop, req);
1366
1721
  } else {
1367
1722
  uv_fs_req_init_sync(loop, req, UV_FS_RENAME);
@@ -1379,7 +1734,7 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
1379
1734
  int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1380
1735
  if (cb) {
1381
1736
  uv_fs_req_init_async(loop, req, UV_FS_FDATASYNC, NULL, NULL, cb);
1382
- WRAP_REQ_ARGS1(req, file);
1737
+ req->file = file;
1383
1738
  QUEUE_FS_TP_JOB(loop, req);
1384
1739
  } else {
1385
1740
  uv_fs_req_init_sync(loop, req, UV_FS_FDATASYNC);
@@ -1395,7 +1750,7 @@ int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1395
1750
  int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1396
1751
  if (cb) {
1397
1752
  uv_fs_req_init_async(loop, req, UV_FS_FSYNC, NULL, NULL, cb);
1398
- WRAP_REQ_ARGS1(req, file);
1753
+ req->file = file;
1399
1754
  QUEUE_FS_TP_JOB(loop, req);
1400
1755
  } else {
1401
1756
  uv_fs_req_init_sync(loop, req, UV_FS_FSYNC);
@@ -1409,10 +1764,11 @@ int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1409
1764
 
1410
1765
 
1411
1766
  int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file,
1412
- off_t offset, uv_fs_cb cb) {
1767
+ int64_t offset, uv_fs_cb cb) {
1413
1768
  if (cb) {
1414
1769
  uv_fs_req_init_async(loop, req, UV_FS_FTRUNCATE, NULL, NULL, cb);
1415
- WRAP_REQ_ARGS2(req, file, offset);
1770
+ req->file = file;
1771
+ req->offset = offset;
1416
1772
  QUEUE_FS_TP_JOB(loop, req);
1417
1773
  } else {
1418
1774
  uv_fs_req_init_sync(loop, req, UV_FS_FTRUNCATE);
@@ -1426,10 +1782,13 @@ int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file,
1426
1782
 
1427
1783
 
1428
1784
  int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd,
1429
- uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb) {
1785
+ uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb) {
1430
1786
  if (cb) {
1431
1787
  uv_fs_req_init_async(loop, req, UV_FS_SENDFILE, NULL, NULL, cb);
1432
- WRAP_REQ_ARGS4(req, out_fd, in_fd, in_offset, length);
1788
+ req->file_out = out_fd;
1789
+ req->file = in_fd;
1790
+ req->offset = in_offset;
1791
+ req->length = length;
1433
1792
  QUEUE_FS_TP_JOB(loop, req);
1434
1793
  } else {
1435
1794
  uv_fs_req_init_sync(loop, req, UV_FS_SENDFILE);
@@ -1452,7 +1811,7 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
1452
1811
 
1453
1812
  if (cb) {
1454
1813
  uv_fs_req_init_async(loop, req, UV_FS_CHMOD, path, pathw, cb);
1455
- WRAP_REQ_ARGS1(req, mode);
1814
+ req->mode = mode;
1456
1815
  QUEUE_FS_TP_JOB(loop, req);
1457
1816
  } else {
1458
1817
  uv_fs_req_init_sync(loop, req, UV_FS_CHMOD);
@@ -1470,7 +1829,8 @@ int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode,
1470
1829
  uv_fs_cb cb) {
1471
1830
  if (cb) {
1472
1831
  uv_fs_req_init_async(loop, req, UV_FS_FCHMOD, NULL, NULL, cb);
1473
- WRAP_REQ_ARGS2(req, file, mode);
1832
+ req->file = file;
1833
+ req->mode = mode;
1474
1834
  QUEUE_FS_TP_JOB(loop, req);
1475
1835
  } else {
1476
1836
  uv_fs_req_init_sync(loop, req, UV_FS_FCHMOD);
@@ -1493,8 +1853,8 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
1493
1853
 
1494
1854
  if (cb) {
1495
1855
  uv_fs_req_init_async(loop, req, UV_FS_UTIME, path, pathw, cb);
1496
- req->arg4 = (ssize_t)atime;
1497
- req->arg5 = (ssize_t)mtime;
1856
+ req->atime = atime;
1857
+ req->mtime = mtime;
1498
1858
  QUEUE_FS_TP_JOB(loop, req);
1499
1859
  } else {
1500
1860
  uv_fs_req_init_sync(loop, req, UV_FS_UTIME);
@@ -1512,9 +1872,9 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime,
1512
1872
  double mtime, uv_fs_cb cb) {
1513
1873
  if (cb) {
1514
1874
  uv_fs_req_init_async(loop, req, UV_FS_FUTIME, NULL, NULL, cb);
1515
- WRAP_REQ_ARGS1(req, file);
1516
- req->arg4 = (ssize_t)atime;
1517
- req->arg5 = (ssize_t)mtime;
1875
+ req->file = file;
1876
+ req->atime = atime;
1877
+ req->mtime = mtime;
1518
1878
  QUEUE_FS_TP_JOB(loop, req);
1519
1879
  } else {
1520
1880
  uv_fs_req_init_sync(loop, req, UV_FS_FUTIME);
@@ -1529,6 +1889,7 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime,
1529
1889
 
1530
1890
  void uv_process_fs_req(uv_loop_t* loop, uv_fs_t* req) {
1531
1891
  assert(req->cb);
1892
+ uv__req_unregister(loop, req);
1532
1893
  SET_UV_LAST_ERROR_FROM_REQ(req);
1533
1894
  req->cb(req);
1534
1895
  }
@@ -1541,14 +1902,14 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
1541
1902
  return;
1542
1903
  }
1543
1904
 
1544
- if (req->flags & UV_FS_FREE_ARG0 && req->arg0) {
1545
- free(req->arg0);
1546
- req->arg0 = NULL;
1905
+ if (req->flags & UV_FS_FREE_PATH && req->pathw) {
1906
+ free(req->pathw);
1907
+ req->pathw = NULL;
1547
1908
  }
1548
1909
 
1549
- if (req->flags & UV_FS_FREE_ARG1 && req->arg1) {
1550
- free(req->arg1);
1551
- req->arg1 = NULL;
1910
+ if (req->flags & UV_FS_FREE_NEW_PATH && req->new_pathw) {
1911
+ free(req->new_pathw);
1912
+ req->new_pathw = NULL;
1552
1913
  }
1553
1914
 
1554
1915
  if (req->flags & UV_FS_FREE_PTR && req->ptr) {
@@ -1562,15 +1923,6 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
1562
1923
  req->path = NULL;
1563
1924
  }
1564
1925
 
1565
- if (req->pathw) {
1566
- free(req->pathw);
1567
- req->pathw = NULL;
1568
- }
1569
-
1570
- if (req->flags & UV_FS_ASYNC_QUEUED) {
1571
- uv_unref(loop);
1572
- }
1573
-
1574
1926
  req->flags |= UV_FS_CLEANEDUP;
1575
1927
  }
1576
1928