asyncengine 0.0.1.testing1 → 0.0.2.alpha1

Sign up to get free protection for your applications and to get access to all the features.
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