Rizin
unix-like reverse engineering framework and cli tools
fs.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <direct.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <io.h>
28 #include <limits.h>
29 #include <sys/stat.h>
30 #include <sys/utime.h>
31 #include <stdio.h>
32 
33 #include "uv.h"
34 #include "internal.h"
35 #include "req-inl.h"
36 #include "handle-inl.h"
37 #include "fs-fd-hash-inl.h"
38 
39 
40 #define UV_FS_FREE_PATHS 0x0002
41 #define UV_FS_FREE_PTR 0x0008
42 #define UV_FS_CLEANEDUP 0x0010
43 
44 
45 #define INIT(subtype) \
46  do { \
47  if (req == NULL) \
48  return UV_EINVAL; \
49  uv_fs_req_init(loop, req, subtype, cb); \
50  } \
51  while (0)
52 
53 #define POST \
54  do { \
55  if (cb != NULL) { \
56  uv__req_register(loop, req); \
57  uv__work_submit(loop, \
58  &req->work_req, \
59  UV__WORK_FAST_IO, \
60  uv__fs_work, \
61  uv__fs_done); \
62  return 0; \
63  } else { \
64  uv__fs_work(&req->work_req); \
65  return req->result; \
66  } \
67  } \
68  while (0)
69 
70 #define SET_REQ_RESULT(req, result_value) \
71  do { \
72  req->result = (result_value); \
73  assert(req->result != -1); \
74  } while (0)
75 
76 #define SET_REQ_WIN32_ERROR(req, sys_errno) \
77  do { \
78  req->sys_errno_ = (sys_errno); \
79  req->result = uv_translate_sys_error(req->sys_errno_); \
80  } while (0)
81 
82 #define SET_REQ_UV_ERROR(req, uv_errno, sys_errno) \
83  do { \
84  req->result = (uv_errno); \
85  req->sys_errno_ = (sys_errno); \
86  } while (0)
87 
88 #define VERIFY_FD(fd, req) \
89  if (fd == -1) { \
90  req->result = UV_EBADF; \
91  req->sys_errno_ = ERROR_INVALID_HANDLE; \
92  return; \
93  }
94 
95 #define MILLIONu (1000U * 1000U)
96 #define BILLIONu (1000U * 1000U * 1000U)
97 
98 #define FILETIME_TO_UINT(filetime) \
99  (*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu)
100 
101 #define FILETIME_TO_TIME_T(filetime) \
102  (FILETIME_TO_UINT(filetime) / (10u * MILLIONu))
103 
104 #define FILETIME_TO_TIME_NS(filetime, secs) \
105  ((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U)
106 
107 #define FILETIME_TO_TIMESPEC(ts, filetime) \
108  do { \
109  (ts).tv_sec = (long) FILETIME_TO_TIME_T(filetime); \
110  (ts).tv_nsec = (long) FILETIME_TO_TIME_NS(filetime, (ts).tv_sec); \
111  } while(0)
112 
113 #define TIME_T_TO_FILETIME(time, filetime_ptr) \
114  do { \
115  uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) + \
116  (uint64_t) 116444736 * BILLIONu; \
117  (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \
118  (filetime_ptr)->dwHighDateTime = bigtime >> 32; \
119  } while(0)
120 
121 #define IS_SLASH(c) ((c) == L'\\' || (c) == L'/')
122 #define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \
123  ((c) >= L'A' && (c) <= L'Z'))
124 
125 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
126 
127 const WCHAR JUNCTION_PREFIX[] = L"\\??\\";
128 const WCHAR JUNCTION_PREFIX_LEN = 4;
129 
130 const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\";
131 const WCHAR LONG_PATH_PREFIX_LEN = 4;
132 
133 const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
134 const WCHAR UNC_PATH_PREFIX_LEN = 8;
135 
137 
139 
140 
141 void uv_fs_init(void) {
142  SYSTEM_INFO system_info;
143 
144  GetSystemInfo(&system_info);
145  uv__allocation_granularity = system_info.dwAllocationGranularity;
146 
148 }
149 
150 
151 INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
152  const char* new_path, const int copy_path) {
153  char* buf;
154  char* pos;
155  ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0;
156 
157  /* new_path can only be set if path is also set. */
158  assert(new_path == NULL || path != NULL);
159 
160  if (path != NULL) {
161  pathw_len = MultiByteToWideChar(CP_UTF8,
162  0,
163  path,
164  -1,
165  NULL,
166  0);
167  if (pathw_len == 0) {
168  return GetLastError();
169  }
170 
171  buf_sz += pathw_len * sizeof(WCHAR);
172  }
173 
174  if (path != NULL && copy_path) {
175  path_len = 1 + strlen(path);
176  buf_sz += path_len;
177  }
178 
179  if (new_path != NULL) {
180  new_pathw_len = MultiByteToWideChar(CP_UTF8,
181  0,
182  new_path,
183  -1,
184  NULL,
185  0);
186  if (new_pathw_len == 0) {
187  return GetLastError();
188  }
189 
190  buf_sz += new_pathw_len * sizeof(WCHAR);
191  }
192 
193 
194  if (buf_sz == 0) {
195  req->file.pathw = NULL;
196  req->fs.info.new_pathw = NULL;
197  req->path = NULL;
198  return 0;
199  }
200 
201  buf = (char*) uv__malloc(buf_sz);
202  if (buf == NULL) {
203  return ERROR_OUTOFMEMORY;
204  }
205 
206  pos = buf;
207 
208  if (path != NULL) {
209  DWORD r = MultiByteToWideChar(CP_UTF8,
210  0,
211  path,
212  -1,
213  (WCHAR*) pos,
214  pathw_len);
215  assert(r == (DWORD) pathw_len);
216  req->file.pathw = (WCHAR*) pos;
217  pos += r * sizeof(WCHAR);
218  } else {
219  req->file.pathw = NULL;
220  }
221 
222  if (new_path != NULL) {
223  DWORD r = MultiByteToWideChar(CP_UTF8,
224  0,
225  new_path,
226  -1,
227  (WCHAR*) pos,
228  new_pathw_len);
229  assert(r == (DWORD) new_pathw_len);
230  req->fs.info.new_pathw = (WCHAR*) pos;
231  pos += r * sizeof(WCHAR);
232  } else {
233  req->fs.info.new_pathw = NULL;
234  }
235 
236  req->path = path;
237  if (path != NULL && copy_path) {
238  memcpy(pos, path, path_len);
239  assert(path_len == buf_sz - (pos - buf));
240  req->path = pos;
241  }
242 
243  req->flags |= UV_FS_FREE_PATHS;
244 
245  return 0;
246 }
247 
248 
249 
251  uv_fs_type fs_type, const uv_fs_cb cb) {
252  uv__once_init();
253  UV_REQ_INIT(req, UV_FS);
254  req->loop = loop;
255  req->flags = 0;
256  req->fs_type = fs_type;
257  req->sys_errno_ = 0;
258  req->result = 0;
259  req->ptr = NULL;
260  req->path = NULL;
261  req->cb = cb;
262  memset(&req->fs, 0, sizeof(req->fs));
263 }
264 
265 
266 static int fs__wide_to_utf8(WCHAR* w_source_ptr,
267  DWORD w_source_len,
268  char** target_ptr,
269  uint64_t* target_len_ptr) {
270  int r;
271  int target_len;
272  char* target;
273  target_len = WideCharToMultiByte(CP_UTF8,
274  0,
275  w_source_ptr,
276  w_source_len,
277  NULL,
278  0,
279  NULL,
280  NULL);
281 
282  if (target_len == 0) {
283  return -1;
284  }
285 
286  if (target_len_ptr != NULL) {
287  *target_len_ptr = target_len;
288  }
289 
290  if (target_ptr == NULL) {
291  return 0;
292  }
293 
294  target = uv__malloc(target_len + 1);
295  if (target == NULL) {
296  SetLastError(ERROR_OUTOFMEMORY);
297  return -1;
298  }
299 
300  r = WideCharToMultiByte(CP_UTF8,
301  0,
302  w_source_ptr,
303  w_source_len,
304  target,
305  target_len,
306  NULL,
307  NULL);
308  assert(r == target_len);
309  target[target_len] = '\0';
310  *target_ptr = target;
311  return 0;
312 }
313 
314 
315 INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
316  uint64_t* target_len_ptr) {
317  char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
318  REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer;
319  WCHAR* w_target;
320  DWORD w_target_len;
321  DWORD bytes;
322  size_t i;
323  size_t len;
324 
325  if (!DeviceIoControl(handle,
327  NULL,
328  0,
329  buffer,
330  sizeof buffer,
331  &bytes,
332  NULL)) {
333  return -1;
334  }
335 
336  if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
337  /* Real symlink */
338  w_target = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
339  (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset /
340  sizeof(WCHAR));
341  w_target_len =
342  reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
343  sizeof(WCHAR);
344 
345  /* Real symlinks can contain pretty much everything, but the only thing we
346  * really care about is undoing the implicit conversion to an NT namespaced
347  * path that CreateSymbolicLink will perform on absolute paths. If the path
348  * is win32-namespaced then the user must have explicitly made it so, and
349  * we better just return the unmodified reparse data. */
350  if (w_target_len >= 4 &&
351  w_target[0] == L'\\' &&
352  w_target[1] == L'?' &&
353  w_target[2] == L'?' &&
354  w_target[3] == L'\\') {
355  /* Starts with \??\ */
356  if (w_target_len >= 6 &&
357  ((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
358  (w_target[4] >= L'a' && w_target[4] <= L'z')) &&
359  w_target[5] == L':' &&
360  (w_target_len == 6 || w_target[6] == L'\\')) {
361  /* \??<drive>:\ */
362  w_target += 4;
363  w_target_len -= 4;
364 
365  } else if (w_target_len >= 8 &&
366  (w_target[4] == L'U' || w_target[4] == L'u') &&
367  (w_target[5] == L'N' || w_target[5] == L'n') &&
368  (w_target[6] == L'C' || w_target[6] == L'c') &&
369  w_target[7] == L'\\') {
370  /* \??\UNC<server><share>\ - make sure the final path looks like
371  * \<server><share>\ */
372  w_target += 6;
373  w_target[0] = L'\\';
374  w_target_len -= 6;
375  }
376  }
377 
378  } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
379  /* Junction. */
380  w_target = reparse_data->MountPointReparseBuffer.PathBuffer +
381  (reparse_data->MountPointReparseBuffer.SubstituteNameOffset /
382  sizeof(WCHAR));
383  w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
384  sizeof(WCHAR);
385 
386  /* Only treat junctions that look like \??<drive>:\ as symlink. Junctions
387  * can also be used as mount points, like \??\Volume{<guid>}, but that's
388  * confusing for programs since they wouldn't be able to actually
389  * understand such a path when returned by uv_readlink(). UNC paths are
390  * never valid for junctions so we don't care about them. */
391  if (!(w_target_len >= 6 &&
392  w_target[0] == L'\\' &&
393  w_target[1] == L'?' &&
394  w_target[2] == L'?' &&
395  w_target[3] == L'\\' &&
396  ((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
397  (w_target[4] >= L'a' && w_target[4] <= L'z')) &&
398  w_target[5] == L':' &&
399  (w_target_len == 6 || w_target[6] == L'\\'))) {
400  SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
401  return -1;
402  }
403 
404  /* Remove leading \??\ */
405  w_target += 4;
406  w_target_len -= 4;
407 
408  } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) {
409  /* String #3 in the list has the target filename. */
410  if (reparse_data->AppExecLinkReparseBuffer.StringCount < 3) {
411  SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
412  return -1;
413  }
414  w_target = reparse_data->AppExecLinkReparseBuffer.StringList;
415  /* The StringList buffer contains a list of strings separated by "\0", */
416  /* with "\0\0" terminating the list. Move to the 3rd string in the list: */
417  for (i = 0; i < 2; ++i) {
418  len = wcslen(w_target);
419  if (len == 0) {
420  SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
421  return -1;
422  }
423  w_target += len + 1;
424  }
425  w_target_len = wcslen(w_target);
426  if (w_target_len == 0) {
427  SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
428  return -1;
429  }
430  /* Make sure it is an absolute path. */
431  if (!(w_target_len >= 3 &&
432  ((w_target[0] >= L'a' && w_target[0] <= L'z') ||
433  (w_target[0] >= L'A' && w_target[0] <= L'Z')) &&
434  w_target[1] == L':' &&
435  w_target[2] == L'\\')) {
436  SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
437  return -1;
438  }
439 
440  } else {
441  /* Reparse tag does not indicate a symlink. */
442  SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
443  return -1;
444  }
445 
446  return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr);
447 }
448 
449 
451  DWORD access;
452  DWORD share;
453  DWORD disposition;
454  DWORD attributes = 0;
455  HANDLE file;
456  int fd, current_umask;
457  int flags = req->fs.info.file_flags;
458  struct uv__fd_info_s fd_info;
459 
460  /* Adjust flags to be compatible with the memory file mapping. Save the
461  * original flags to emulate the correct behavior. */
462  if (flags & UV_FS_O_FILEMAP) {
463  fd_info.flags = flags;
464  fd_info.current_pos.QuadPart = 0;
465 
467  UV_FS_O_WRONLY) {
468  /* CreateFileMapping always needs read access */
470  }
471 
472  if (flags & UV_FS_O_APPEND) {
473  /* Clear the append flag and ensure RDRW mode */
474  flags &= ~UV_FS_O_APPEND;
476  flags |= UV_FS_O_RDWR;
477  }
478  }
479 
480  /* Obtain the active umask. umask() never fails and returns the previous
481  * umask. */
482  current_umask = umask(0);
483  umask(current_umask);
484 
485  /* convert flags and mode to CreateFile parameters */
487  case UV_FS_O_RDONLY:
488  access = FILE_GENERIC_READ;
489  break;
490  case UV_FS_O_WRONLY:
491  access = FILE_GENERIC_WRITE;
492  break;
493  case UV_FS_O_RDWR:
494  access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
495  break;
496  default:
497  goto einval;
498  }
499 
500  if (flags & UV_FS_O_APPEND) {
501  access &= ~FILE_WRITE_DATA;
502  access |= FILE_APPEND_DATA;
503  }
504 
505  /*
506  * Here is where we deviate significantly from what CRT's _open()
507  * does. We indiscriminately use all the sharing modes, to match
508  * UNIX semantics. In particular, this ensures that the file can
509  * be deleted even whilst it's open, fixing issue
510  * https://github.com/nodejs/node-v0.x-archive/issues/1449.
511  * We still support exclusive sharing mode, since it is necessary
512  * for opening raw block devices, otherwise Windows will prevent
513  * any attempt to write past the master boot record.
514  */
515  if (flags & UV_FS_O_EXLOCK) {
516  share = 0;
517  } else {
518  share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
519  }
520 
521  switch (flags & (UV_FS_O_CREAT | UV_FS_O_EXCL | UV_FS_O_TRUNC)) {
522  case 0:
523  case UV_FS_O_EXCL:
524  disposition = OPEN_EXISTING;
525  break;
526  case UV_FS_O_CREAT:
527  disposition = OPEN_ALWAYS;
528  break;
531  disposition = CREATE_NEW;
532  break;
533  case UV_FS_O_TRUNC:
535  disposition = TRUNCATE_EXISTING;
536  break;
538  disposition = CREATE_ALWAYS;
539  break;
540  default:
541  goto einval;
542  }
543 
544  attributes |= FILE_ATTRIBUTE_NORMAL;
545  if (flags & UV_FS_O_CREAT) {
546  if (!((req->fs.info.mode & ~current_umask) & _S_IWRITE)) {
547  attributes |= FILE_ATTRIBUTE_READONLY;
548  }
549  }
550 
551  if (flags & UV_FS_O_TEMPORARY ) {
552  attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
553  access |= DELETE;
554  }
555 
556  if (flags & UV_FS_O_SHORT_LIVED) {
557  attributes |= FILE_ATTRIBUTE_TEMPORARY;
558  }
559 
560  switch (flags & (UV_FS_O_SEQUENTIAL | UV_FS_O_RANDOM)) {
561  case 0:
562  break;
563  case UV_FS_O_SEQUENTIAL:
564  attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
565  break;
566  case UV_FS_O_RANDOM:
567  attributes |= FILE_FLAG_RANDOM_ACCESS;
568  break;
569  default:
570  goto einval;
571  }
572 
573  if (flags & UV_FS_O_DIRECT) {
574  /*
575  * FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually exclusive.
576  * Windows returns 87, ERROR_INVALID_PARAMETER if these are combined.
577  *
578  * FILE_APPEND_DATA is included in FILE_GENERIC_WRITE:
579  *
580  * FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE |
581  * FILE_WRITE_DATA |
582  * FILE_WRITE_ATTRIBUTES |
583  * FILE_WRITE_EA |
584  * FILE_APPEND_DATA |
585  * SYNCHRONIZE
586  *
587  * Note: Appends are also permitted by FILE_WRITE_DATA.
588  *
589  * In order for direct writes and direct appends to succeed, we therefore
590  * exclude FILE_APPEND_DATA if FILE_WRITE_DATA is specified, and otherwise
591  * fail if the user's sole permission is a direct append, since this
592  * particular combination is invalid.
593  */
594  if (access & FILE_APPEND_DATA) {
595  if (access & FILE_WRITE_DATA) {
596  access &= ~FILE_APPEND_DATA;
597  } else {
598  goto einval;
599  }
600  }
601  attributes |= FILE_FLAG_NO_BUFFERING;
602  }
603 
604  switch (flags & (UV_FS_O_DSYNC | UV_FS_O_SYNC)) {
605  case 0:
606  break;
607  case UV_FS_O_DSYNC:
608  case UV_FS_O_SYNC:
609  attributes |= FILE_FLAG_WRITE_THROUGH;
610  break;
611  default:
612  goto einval;
613  }
614 
615  /* Setting this flag makes it possible to open a directory. */
616  attributes |= FILE_FLAG_BACKUP_SEMANTICS;
617 
618  file = CreateFileW(req->file.pathw,
619  access,
620  share,
621  NULL,
622  disposition,
623  attributes,
624  NULL);
625  if (file == INVALID_HANDLE_VALUE) {
626  DWORD error = GetLastError();
627  if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&
628  !(flags & UV_FS_O_EXCL)) {
629  /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was
630  * specified, it means the path referred to a directory. */
631  SET_REQ_UV_ERROR(req, UV_EISDIR, error);
632  } else {
633  SET_REQ_WIN32_ERROR(req, GetLastError());
634  }
635  return;
636  }
637 
638  fd = _open_osfhandle((intptr_t) file, flags);
639  if (fd < 0) {
640  /* The only known failure mode for _open_osfhandle() is EMFILE, in which
641  * case GetLastError() will return zero. However we'll try to handle other
642  * errors as well, should they ever occur.
643  */
644  if (errno == EMFILE)
645  SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES);
646  else if (GetLastError() != ERROR_SUCCESS)
647  SET_REQ_WIN32_ERROR(req, GetLastError());
648  else
649  SET_REQ_WIN32_ERROR(req, (DWORD) UV_UNKNOWN);
650  CloseHandle(file);
651  return;
652  }
653 
654  if (flags & UV_FS_O_FILEMAP) {
655  FILE_STANDARD_INFO file_info;
656  if (!GetFileInformationByHandleEx(file,
657  FileStandardInfo,
658  &file_info,
659  sizeof file_info)) {
660  SET_REQ_WIN32_ERROR(req, GetLastError());
661  CloseHandle(file);
662  return;
663  }
664  fd_info.is_directory = file_info.Directory;
665 
666  if (fd_info.is_directory) {
667  fd_info.size.QuadPart = 0;
668  fd_info.mapping = INVALID_HANDLE_VALUE;
669  } else {
670  if (!GetFileSizeEx(file, &fd_info.size)) {
671  SET_REQ_WIN32_ERROR(req, GetLastError());
672  CloseHandle(file);
673  return;
674  }
675 
676  if (fd_info.size.QuadPart == 0) {
677  fd_info.mapping = INVALID_HANDLE_VALUE;
678  } else {
679  DWORD flProtect = (fd_info.flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY |
680  UV_FS_O_RDWR)) == UV_FS_O_RDONLY ? PAGE_READONLY : PAGE_READWRITE;
681  fd_info.mapping = CreateFileMapping(file,
682  NULL,
683  flProtect,
684  fd_info.size.HighPart,
685  fd_info.size.LowPart,
686  NULL);
687  if (fd_info.mapping == NULL) {
688  SET_REQ_WIN32_ERROR(req, GetLastError());
689  CloseHandle(file);
690  return;
691  }
692  }
693  }
694 
695  uv__fd_hash_add(fd, &fd_info);
696  }
697 
699  return;
700 
701  einval:
702  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
703 }
704 
706  int fd = req->file.fd;
707  int result;
708  struct uv__fd_info_s fd_info;
709 
710  VERIFY_FD(fd, req);
711 
712  if (uv__fd_hash_remove(fd, &fd_info)) {
713  if (fd_info.mapping != INVALID_HANDLE_VALUE) {
714  CloseHandle(fd_info.mapping);
715  }
716  }
717 
718  if (fd > 2)
719  result = _close(fd);
720  else
721  result = 0;
722 
723  /* _close doesn't set _doserrno on failure, but it does always set errno
724  * to EBADF on failure.
725  */
726  if (result == -1) {
727  assert(errno == EBADF);
728  SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE);
729  } else {
730  SET_REQ_RESULT(req, 0);
731  }
732 }
733 
734 
735 LONG fs__filemap_ex_filter(LONG excode, PEXCEPTION_POINTERS pep,
736  int* perror) {
737  if (excode != (LONG)EXCEPTION_IN_PAGE_ERROR) {
738  return EXCEPTION_CONTINUE_SEARCH;
739  }
740 
741  assert(perror != NULL);
742  if (pep != NULL && pep->ExceptionRecord != NULL &&
743  pep->ExceptionRecord->NumberParameters >= 3) {
744  NTSTATUS status = (NTSTATUS)pep->ExceptionRecord->ExceptionInformation[3];
745  *perror = pRtlNtStatusToDosError(status);
746  if (*perror != ERROR_SUCCESS) {
747  return EXCEPTION_EXECUTE_HANDLER;
748  }
749  }
750  *perror = UV_UNKNOWN;
751  return EXCEPTION_EXECUTE_HANDLER;
752 }
753 
754 
755 void fs__read_filemap(uv_fs_t* req, struct uv__fd_info_s* fd_info) {
756  int fd = req->file.fd; /* VERIFY_FD done in fs__read */
757  int rw_flags = fd_info->flags &
759  size_t read_size, done_read;
760  unsigned int index;
761  LARGE_INTEGER pos, end_pos;
762  size_t view_offset;
763  LARGE_INTEGER view_base;
764  void* view;
765 
766  if (rw_flags == UV_FS_O_WRONLY) {
767  SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
768  return;
769  }
770  if (fd_info->is_directory) {
771  SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FUNCTION);
772  return;
773  }
774 
775  if (req->fs.info.offset == -1) {
776  pos = fd_info->current_pos;
777  } else {
778  pos.QuadPart = req->fs.info.offset;
779  }
780 
781  /* Make sure we wont read past EOF. */
782  if (pos.QuadPart >= fd_info->size.QuadPart) {
783  SET_REQ_RESULT(req, 0);
784  return;
785  }
786 
787  read_size = 0;
788  for (index = 0; index < req->fs.info.nbufs; ++index) {
789  read_size += req->fs.info.bufs[index].len;
790  }
791  read_size = (size_t) MIN((LONGLONG) read_size,
792  fd_info->size.QuadPart - pos.QuadPart);
793  if (read_size == 0) {
794  SET_REQ_RESULT(req, 0);
795  return;
796  }
797 
798  end_pos.QuadPart = pos.QuadPart + read_size;
799 
800  view_offset = pos.QuadPart % uv__allocation_granularity;
801  view_base.QuadPart = pos.QuadPart - view_offset;
802  view = MapViewOfFile(fd_info->mapping,
803  FILE_MAP_READ,
804  view_base.HighPart,
805  view_base.LowPart,
806  view_offset + read_size);
807  if (view == NULL) {
808  SET_REQ_WIN32_ERROR(req, GetLastError());
809  return;
810  }
811 
812  done_read = 0;
813  for (index = 0;
814  index < req->fs.info.nbufs && done_read < read_size;
815  ++index) {
816  size_t this_read_size = MIN(req->fs.info.bufs[index].len,
817  read_size - done_read);
818 #ifdef _MSC_VER
819  int err = 0;
820  __try {
821 #endif
822  memcpy(req->fs.info.bufs[index].base,
823  (char*)view + view_offset + done_read,
824  this_read_size);
825 #ifdef _MSC_VER
826  }
827  __except (fs__filemap_ex_filter(GetExceptionCode(),
828  GetExceptionInformation(), &err)) {
830  UnmapViewOfFile(view);
831  return;
832  }
833 #endif
834  done_read += this_read_size;
835  }
836  assert(done_read == read_size);
837 
838  if (!UnmapViewOfFile(view)) {
839  SET_REQ_WIN32_ERROR(req, GetLastError());
840  return;
841  }
842 
843  if (req->fs.info.offset == -1) {
844  fd_info->current_pos = end_pos;
845  uv__fd_hash_add(fd, fd_info);
846  }
847 
848  SET_REQ_RESULT(req, read_size);
849  return;
850 }
851 
853  int fd = req->file.fd;
854  int64_t offset = req->fs.info.offset;
855  HANDLE handle;
856  OVERLAPPED overlapped, *overlapped_ptr;
857  LARGE_INTEGER offset_;
858  DWORD bytes;
859  DWORD error;
860  int result;
861  unsigned int index;
862  LARGE_INTEGER original_position;
863  LARGE_INTEGER zero_offset;
864  int restore_position;
865  struct uv__fd_info_s fd_info;
866 
867  VERIFY_FD(fd, req);
868 
869  if (uv__fd_hash_get(fd, &fd_info)) {
870  fs__read_filemap(req, &fd_info);
871  return;
872  }
873 
874  zero_offset.QuadPart = 0;
875  restore_position = 0;
877 
878  if (handle == INVALID_HANDLE_VALUE) {
879  SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
880  return;
881  }
882 
883  if (offset != -1) {
884  memset(&overlapped, 0, sizeof overlapped);
885  overlapped_ptr = &overlapped;
886  if (SetFilePointerEx(handle, zero_offset, &original_position,
887  FILE_CURRENT)) {
888  restore_position = 1;
889  }
890  } else {
891  overlapped_ptr = NULL;
892  }
893 
894  index = 0;
895  bytes = 0;
896  do {
897  DWORD incremental_bytes;
898 
899  if (offset != -1) {
900  offset_.QuadPart = offset + bytes;
901  overlapped.Offset = offset_.LowPart;
902  overlapped.OffsetHigh = offset_.HighPart;
903  }
904 
905  result = ReadFile(handle,
906  req->fs.info.bufs[index].base,
907  req->fs.info.bufs[index].len,
908  &incremental_bytes,
909  overlapped_ptr);
910  bytes += incremental_bytes;
911  ++index;
912  } while (result && index < req->fs.info.nbufs);
913 
914  if (restore_position)
915  SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
916 
917  if (result || bytes > 0) {
919  } else {
920  error = GetLastError();
921  if (error == ERROR_HANDLE_EOF) {
923  } else {
925  }
926  }
927 }
928 
929 
931  struct uv__fd_info_s* fd_info) {
932  int fd = req->file.fd; /* VERIFY_FD done in fs__write */
933  int force_append = fd_info->flags & UV_FS_O_APPEND;
934  int rw_flags = fd_info->flags &
936  size_t write_size, done_write;
937  unsigned int index;
938  LARGE_INTEGER pos, end_pos;
939  size_t view_offset;
940  LARGE_INTEGER view_base;
941  void* view;
942  FILETIME ft;
943 
944  if (rw_flags == UV_FS_O_RDONLY) {
945  SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
946  return;
947  }
948  if (fd_info->is_directory) {
949  SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FUNCTION);
950  return;
951  }
952 
953  write_size = 0;
954  for (index = 0; index < req->fs.info.nbufs; ++index) {
955  write_size += req->fs.info.bufs[index].len;
956  }
957 
958  if (write_size == 0) {
959  SET_REQ_RESULT(req, 0);
960  return;
961  }
962 
963  if (force_append) {
964  pos = fd_info->size;
965  } else if (req->fs.info.offset == -1) {
966  pos = fd_info->current_pos;
967  } else {
968  pos.QuadPart = req->fs.info.offset;
969  }
970 
971  end_pos.QuadPart = pos.QuadPart + write_size;
972 
973  /* Recreate the mapping to enlarge the file if needed */
974  if (end_pos.QuadPart > fd_info->size.QuadPart) {
975  if (fd_info->mapping != INVALID_HANDLE_VALUE) {
976  CloseHandle(fd_info->mapping);
977  }
978 
979  fd_info->mapping = CreateFileMapping(file,
980  NULL,
981  PAGE_READWRITE,
982  end_pos.HighPart,
983  end_pos.LowPart,
984  NULL);
985  if (fd_info->mapping == NULL) {
986  SET_REQ_WIN32_ERROR(req, GetLastError());
987  CloseHandle(file);
988  fd_info->mapping = INVALID_HANDLE_VALUE;
989  fd_info->size.QuadPart = 0;
990  fd_info->current_pos.QuadPart = 0;
991  uv__fd_hash_add(fd, fd_info);
992  return;
993  }
994 
995  fd_info->size = end_pos;
996  uv__fd_hash_add(fd, fd_info);
997  }
998 
999  view_offset = pos.QuadPart % uv__allocation_granularity;
1000  view_base.QuadPart = pos.QuadPart - view_offset;
1001  view = MapViewOfFile(fd_info->mapping,
1002  FILE_MAP_WRITE,
1003  view_base.HighPart,
1004  view_base.LowPart,
1005  view_offset + write_size);
1006  if (view == NULL) {
1007  SET_REQ_WIN32_ERROR(req, GetLastError());
1008  return;
1009  }
1010 
1011  done_write = 0;
1012  for (index = 0; index < req->fs.info.nbufs; ++index) {
1013 #ifdef _MSC_VER
1014  int err = 0;
1015  __try {
1016 #endif
1017  memcpy((char*)view + view_offset + done_write,
1018  req->fs.info.bufs[index].base,
1019  req->fs.info.bufs[index].len);
1020 #ifdef _MSC_VER
1021  }
1022  __except (fs__filemap_ex_filter(GetExceptionCode(),
1023  GetExceptionInformation(), &err)) {
1025  UnmapViewOfFile(view);
1026  return;
1027  }
1028 #endif
1029  done_write += req->fs.info.bufs[index].len;
1030  }
1031  assert(done_write == write_size);
1032 
1033  if (!FlushViewOfFile(view, 0)) {
1034  SET_REQ_WIN32_ERROR(req, GetLastError());
1035  UnmapViewOfFile(view);
1036  return;
1037  }
1038  if (!UnmapViewOfFile(view)) {
1039  SET_REQ_WIN32_ERROR(req, GetLastError());
1040  return;
1041  }
1042 
1043  if (req->fs.info.offset == -1) {
1044  fd_info->current_pos = end_pos;
1045  uv__fd_hash_add(fd, fd_info);
1046  }
1047 
1048  GetSystemTimeAsFileTime(&ft);
1049  SetFileTime(file, NULL, NULL, &ft);
1050 
1051  SET_REQ_RESULT(req, done_write);
1052 }
1053 
1055  int fd = req->file.fd;
1056  int64_t offset = req->fs.info.offset;
1057  HANDLE handle;
1058  OVERLAPPED overlapped, *overlapped_ptr;
1059  LARGE_INTEGER offset_;
1060  DWORD bytes;
1061  int result;
1062  unsigned int index;
1063  LARGE_INTEGER original_position;
1064  LARGE_INTEGER zero_offset;
1065  int restore_position;
1066  struct uv__fd_info_s fd_info;
1067 
1068  VERIFY_FD(fd, req);
1069 
1070  zero_offset.QuadPart = 0;
1071  restore_position = 0;
1073  if (handle == INVALID_HANDLE_VALUE) {
1074  SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
1075  return;
1076  }
1077 
1078  if (uv__fd_hash_get(fd, &fd_info)) {
1079  fs__write_filemap(req, handle, &fd_info);
1080  return;
1081  }
1082 
1083  if (offset != -1) {
1084  memset(&overlapped, 0, sizeof overlapped);
1085  overlapped_ptr = &overlapped;
1086  if (SetFilePointerEx(handle, zero_offset, &original_position,
1087  FILE_CURRENT)) {
1088  restore_position = 1;
1089  }
1090  } else {
1091  overlapped_ptr = NULL;
1092  }
1093 
1094  index = 0;
1095  bytes = 0;
1096  do {
1097  DWORD incremental_bytes;
1098 
1099  if (offset != -1) {
1100  offset_.QuadPart = offset + bytes;
1101  overlapped.Offset = offset_.LowPart;
1102  overlapped.OffsetHigh = offset_.HighPart;
1103  }
1104 
1105  result = WriteFile(handle,
1106  req->fs.info.bufs[index].base,
1107  req->fs.info.bufs[index].len,
1108  &incremental_bytes,
1109  overlapped_ptr);
1110  bytes += incremental_bytes;
1111  ++index;
1112  } while (result && index < req->fs.info.nbufs);
1113 
1114  if (restore_position)
1115  SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
1116 
1117  if (result || bytes > 0) {
1119  } else {
1120  SET_REQ_WIN32_ERROR(req, GetLastError());
1121  }
1122 }
1123 
1124 
1126  int result = _wrmdir(req->file.pathw);
1127  if (result == -1)
1128  SET_REQ_WIN32_ERROR(req, _doserrno);
1129  else
1130  SET_REQ_RESULT(req, 0);
1131 }
1132 
1133 
1135  const WCHAR* pathw = req->file.pathw;
1136  HANDLE handle;
1137  BY_HANDLE_FILE_INFORMATION info;
1138  FILE_DISPOSITION_INFORMATION disposition;
1139  IO_STATUS_BLOCK iosb;
1140  NTSTATUS status;
1141 
1142  handle = CreateFileW(pathw,
1143  FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE,
1144  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1145  NULL,
1146  OPEN_EXISTING,
1147  FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
1148  NULL);
1149 
1150  if (handle == INVALID_HANDLE_VALUE) {
1151  SET_REQ_WIN32_ERROR(req, GetLastError());
1152  return;
1153  }
1154 
1155  if (!GetFileInformationByHandle(handle, &info)) {
1156  SET_REQ_WIN32_ERROR(req, GetLastError());
1157  CloseHandle(handle);
1158  return;
1159  }
1160 
1161  if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1162  /* Do not allow deletion of directories, unless it is a symlink. When the
1163  * path refers to a non-symlink directory, report EPERM as mandated by
1164  * POSIX.1. */
1165 
1166  /* Check if it is a reparse point. If it's not, it's a normal directory. */
1167  if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
1168  SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
1169  CloseHandle(handle);
1170  return;
1171  }
1172 
1173  /* Read the reparse point and check if it is a valid symlink. If not, don't
1174  * unlink. */
1175  if (fs__readlink_handle(handle, NULL, NULL) < 0) {
1176  DWORD error = GetLastError();
1178  error = ERROR_ACCESS_DENIED;
1180  CloseHandle(handle);
1181  return;
1182  }
1183  }
1184 
1185  if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
1186  /* Remove read-only attribute */
1187  FILE_BASIC_INFORMATION basic = { 0 };
1188 
1189  basic.FileAttributes = (info.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY) |
1190  FILE_ATTRIBUTE_ARCHIVE;
1191 
1193  &iosb,
1194  &basic,
1195  sizeof basic,
1197  if (!NT_SUCCESS(status)) {
1199  CloseHandle(handle);
1200  return;
1201  }
1202  }
1203 
1204  /* Try to set the delete flag. */
1205  disposition.DeleteFile = TRUE;
1207  &iosb,
1208  &disposition,
1209  sizeof disposition,
1211  if (NT_SUCCESS(status)) {
1213  } else {
1215  }
1216 
1217  CloseHandle(handle);
1218 }
1219 
1220 
1222  /* TODO: use req->mode. */
1223  if (CreateDirectoryW(req->file.pathw, NULL)) {
1224  SET_REQ_RESULT(req, 0);
1225  } else {
1226  SET_REQ_WIN32_ERROR(req, GetLastError());
1227  if (req->sys_errno_ == ERROR_INVALID_NAME)
1228  req->result = UV_EINVAL;
1229  }
1230 }
1231 
1233 
1234 /* OpenBSD original: lib/libc/stdio/mktemp.c */
1236  static const WCHAR *tempchars =
1237  L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1238  static const size_t num_chars = 62;
1239  static const size_t num_x = 6;
1240  WCHAR *cp, *ep;
1241  unsigned int tries, i;
1242  size_t len;
1243  uint64_t v;
1244  char* path;
1245 
1246  path = req->path;
1247  len = wcslen(req->file.pathw);
1248  ep = req->file.pathw + len;
1249  if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) {
1250  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
1251  goto clobber;
1252  }
1253 
1254  tries = TMP_MAX;
1255  do {
1256  if (uv__random_rtlgenrandom((void *)&v, sizeof(v)) < 0) {
1257  SET_REQ_UV_ERROR(req, UV_EIO, ERROR_IO_DEVICE);
1258  goto clobber;
1259  }
1260 
1261  cp = ep - num_x;
1262  for (i = 0; i < num_x; i++) {
1263  *cp++ = tempchars[v % num_chars];
1264  v /= num_chars;
1265  }
1266 
1267  if (func(req)) {
1268  if (req->result >= 0) {
1269  len = strlen(path);
1270  wcstombs(path + len - num_x, ep - num_x, num_x);
1271  }
1272  return;
1273  }
1274  } while (--tries);
1275 
1276  SET_REQ_WIN32_ERROR(req, GetLastError());
1277 
1278 clobber:
1279  path[0] = '\0';
1280 }
1281 
1282 
1284  DWORD error;
1285  if (CreateDirectoryW(req->file.pathw, NULL)) {
1286  SET_REQ_RESULT(req, 0);
1287  return 1;
1288  }
1289  error = GetLastError();
1290  if (error != ERROR_ALREADY_EXISTS) {
1292  return 1;
1293  }
1294 
1295  return 0;
1296 }
1297 
1298 
1301 }
1302 
1303 
1305  HANDLE file;
1306  int fd;
1307 
1308  file = CreateFileW(req->file.pathw,
1309  GENERIC_READ | GENERIC_WRITE,
1310  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1311  NULL,
1312  CREATE_NEW,
1313  FILE_ATTRIBUTE_NORMAL,
1314  NULL);
1315 
1316  if (file == INVALID_HANDLE_VALUE) {
1317  DWORD error;
1318  error = GetLastError();
1319 
1320  /* If the file exists, the main fs__mktemp() function
1321  will retry. If it's another error, we want to stop. */
1322  if (error != ERROR_FILE_EXISTS) {
1324  return 1;
1325  }
1326 
1327  return 0;
1328  }
1329 
1330  fd = _open_osfhandle((intptr_t) file, 0);
1331  if (fd < 0) {
1332  /* The only known failure mode for _open_osfhandle() is EMFILE, in which
1333  * case GetLastError() will return zero. However we'll try to handle other
1334  * errors as well, should they ever occur.
1335  */
1336  if (errno == EMFILE)
1337  SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES);
1338  else if (GetLastError() != ERROR_SUCCESS)
1339  SET_REQ_WIN32_ERROR(req, GetLastError());
1340  else
1341  SET_REQ_WIN32_ERROR(req, UV_UNKNOWN);
1342  CloseHandle(file);
1343  return 1;
1344  }
1345 
1346  SET_REQ_RESULT(req, fd);
1347 
1348  return 1;
1349 }
1350 
1351 
1354 }
1355 
1356 
1358  static const size_t dirents_initial_size = 32;
1359 
1360  HANDLE dir_handle = INVALID_HANDLE_VALUE;
1361 
1362  uv__dirent_t** dirents = NULL;
1363  size_t dirents_size = 0;
1364  size_t dirents_used = 0;
1365 
1366  IO_STATUS_BLOCK iosb;
1367  NTSTATUS status;
1368 
1369  /* Buffer to hold directory entries returned by NtQueryDirectoryFile.
1370  * It's important that this buffer can hold at least one entry, regardless
1371  * of the length of the file names present in the enumerated directory.
1372  * A file name is at most 256 WCHARs long.
1373  * According to MSDN, the buffer must be aligned at an 8-byte boundary.
1374  */
1375 #if _MSC_VER
1376  __declspec(align(8)) char buffer[8192];
1377 #else
1378  __attribute__ ((aligned (8))) char buffer[8192];
1379 #endif
1380 
1381  STATIC_ASSERT(sizeof buffer >=
1382  sizeof(FILE_DIRECTORY_INFORMATION) + 256 * sizeof(WCHAR));
1383 
1384  /* Open the directory. */
1385  dir_handle =
1386  CreateFileW(req->file.pathw,
1387  FILE_LIST_DIRECTORY | SYNCHRONIZE,
1388  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1389  NULL,
1390  OPEN_EXISTING,
1391  FILE_FLAG_BACKUP_SEMANTICS,
1392  NULL);
1393  if (dir_handle == INVALID_HANDLE_VALUE)
1394  goto win32_error;
1395 
1396  /* Read the first chunk. */
1397  status = pNtQueryDirectoryFile(dir_handle,
1398  NULL,
1399  NULL,
1400  NULL,
1401  &iosb,
1402  &buffer,
1403  sizeof buffer,
1405  FALSE,
1406  NULL,
1407  TRUE);
1408 
1409  /* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER.
1410  * This should be reported back as UV_ENOTDIR.
1411  */
1413  goto not_a_directory_error;
1414 
1415  while (NT_SUCCESS(status)) {
1416  char* position = buffer;
1417  size_t next_entry_offset = 0;
1418 
1419  do {
1422 
1423  size_t wchar_len;
1424  size_t utf8_len;
1425 
1426  /* Obtain a pointer to the current directory entry. */
1427  position += next_entry_offset;
1428  info = (FILE_DIRECTORY_INFORMATION*) position;
1429 
1430  /* Fetch the offset to the next directory entry. */
1431  next_entry_offset = info->NextEntryOffset;
1432 
1433  /* Compute the length of the filename in WCHARs. */
1434  wchar_len = info->FileNameLength / sizeof info->FileName[0];
1435 
1436  /* Skip over '.' and '..' entries. It has been reported that
1437  * the SharePoint driver includes the terminating zero byte in
1438  * the filename length. Strip those first.
1439  */
1440  while (wchar_len > 0 && info->FileName[wchar_len - 1] == L'\0')
1441  wchar_len -= 1;
1442 
1443  if (wchar_len == 0)
1444  continue;
1445  if (wchar_len == 1 && info->FileName[0] == L'.')
1446  continue;
1447  if (wchar_len == 2 && info->FileName[0] == L'.' &&
1448  info->FileName[1] == L'.')
1449  continue;
1450 
1451  /* Compute the space required to store the filename as UTF-8. */
1452  utf8_len = WideCharToMultiByte(
1453  CP_UTF8, 0, &info->FileName[0], wchar_len, NULL, 0, NULL, NULL);
1454  if (utf8_len == 0)
1455  goto win32_error;
1456 
1457  /* Resize the dirent array if needed. */
1458  if (dirents_used >= dirents_size) {
1459  size_t new_dirents_size =
1460  dirents_size == 0 ? dirents_initial_size : dirents_size << 1;
1461  uv__dirent_t** new_dirents =
1462  uv__realloc(dirents, new_dirents_size * sizeof *dirents);
1463 
1464  if (new_dirents == NULL)
1465  goto out_of_memory_error;
1466 
1467  dirents_size = new_dirents_size;
1468  dirents = new_dirents;
1469  }
1470 
1471  /* Allocate space for the uv dirent structure. The dirent structure
1472  * includes room for the first character of the filename, but `utf8_len`
1473  * doesn't count the NULL terminator at this point.
1474  */
1475  dirent = uv__malloc(sizeof *dirent + utf8_len);
1476  if (dirent == NULL)
1477  goto out_of_memory_error;
1478 
1479  dirents[dirents_used++] = dirent;
1480 
1481  /* Convert file name to UTF-8. */
1482  if (WideCharToMultiByte(CP_UTF8,
1483  0,
1484  &info->FileName[0],
1485  wchar_len,
1486  &dirent->d_name[0],
1487  utf8_len,
1488  NULL,
1489  NULL) == 0)
1490  goto win32_error;
1491 
1492  /* Add a null terminator to the filename. */
1493  dirent->d_name[utf8_len] = '\0';
1494 
1495  /* Fill out the type field. */
1496  if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE)
1497  dirent->d_type = UV__DT_CHAR;
1498  else if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1499  dirent->d_type = UV__DT_LINK;
1500  else if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1501  dirent->d_type = UV__DT_DIR;
1502  else
1503  dirent->d_type = UV__DT_FILE;
1504  } while (next_entry_offset != 0);
1505 
1506  /* Read the next chunk. */
1507  status = pNtQueryDirectoryFile(dir_handle,
1508  NULL,
1509  NULL,
1510  NULL,
1511  &iosb,
1512  &buffer,
1513  sizeof buffer,
1515  FALSE,
1516  NULL,
1517  FALSE);
1518 
1519  /* After the first pNtQueryDirectoryFile call, the function may return
1520  * STATUS_SUCCESS even if the buffer was too small to hold at least one
1521  * directory entry.
1522  */
1523  if (status == STATUS_SUCCESS && iosb.Information == 0)
1525  }
1526 
1528  goto nt_error;
1529 
1530  CloseHandle(dir_handle);
1531 
1532  /* Store the result in the request object. */
1533  req->ptr = dirents;
1534  if (dirents != NULL)
1535  req->flags |= UV_FS_FREE_PTR;
1536 
1537  SET_REQ_RESULT(req, dirents_used);
1538 
1539  /* `nbufs` will be used as index by uv_fs_scandir_next. */
1540  req->fs.info.nbufs = 0;
1541 
1542  return;
1543 
1544 nt_error:
1546  goto cleanup;
1547 
1548 win32_error:
1549  SET_REQ_WIN32_ERROR(req, GetLastError());
1550  goto cleanup;
1551 
1552 not_a_directory_error:
1553  SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
1554  goto cleanup;
1555 
1556 out_of_memory_error:
1557  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
1558  goto cleanup;
1559 
1560 cleanup:
1561  if (dir_handle != INVALID_HANDLE_VALUE)
1562  CloseHandle(dir_handle);
1563  while (dirents_used > 0)
1564  uv__free(dirents[--dirents_used]);
1565  if (dirents != NULL)
1566  uv__free(dirents);
1567 }
1568 
1570  WCHAR* pathw;
1571  size_t len;
1572  const WCHAR* fmt;
1573  WCHAR* find_path;
1574  uv_dir_t* dir;
1575 
1576  pathw = req->file.pathw;
1577  dir = NULL;
1578  find_path = NULL;
1579 
1580  /* Figure out whether path is a file or a directory. */
1581  if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) {
1582  SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
1583  goto error;
1584  }
1585 
1586  dir = uv__malloc(sizeof(*dir));
1587  if (dir == NULL) {
1588  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
1589  goto error;
1590  }
1591 
1592  len = wcslen(pathw);
1593 
1594  if (len == 0)
1595  fmt = L"./*";
1596  else if (IS_SLASH(pathw[len - 1]))
1597  fmt = L"%s*";
1598  else
1599  fmt = L"%s\\*";
1600 
1601  find_path = uv__malloc(sizeof(WCHAR) * (len + 4));
1602  if (find_path == NULL) {
1603  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
1604  goto error;
1605  }
1606 
1607  _snwprintf(find_path, len + 3, fmt, pathw);
1608  dir->dir_handle = FindFirstFileW(find_path, &dir->find_data);
1610  find_path = NULL;
1611  if (dir->dir_handle == INVALID_HANDLE_VALUE &&
1612  GetLastError() != ERROR_FILE_NOT_FOUND) {
1613  SET_REQ_WIN32_ERROR(req, GetLastError());
1614  goto error;
1615  }
1616 
1617  dir->need_find_call = FALSE;
1618  req->ptr = dir;
1619  SET_REQ_RESULT(req, 0);
1620  return;
1621 
1622 error:
1623  uv__free(dir);
1625  req->ptr = NULL;
1626 }
1627 
1629  uv_dir_t* dir;
1630  uv_dirent_t* dirents;
1631  uv__dirent_t dent;
1632  unsigned int dirent_idx;
1633  PWIN32_FIND_DATAW find_data;
1634  unsigned int i;
1635  int r;
1636 
1637  req->flags |= UV_FS_FREE_PTR;
1638  dir = req->ptr;
1639  dirents = dir->dirents;
1640  memset(dirents, 0, dir->nentries * sizeof(*dir->dirents));
1641  find_data = &dir->find_data;
1642  dirent_idx = 0;
1643 
1644  while (dirent_idx < dir->nentries) {
1645  if (dir->need_find_call && FindNextFileW(dir->dir_handle, find_data) == 0) {
1646  if (GetLastError() == ERROR_NO_MORE_FILES)
1647  break;
1648  goto error;
1649  }
1650 
1651  /* Skip "." and ".." entries. */
1652  if (find_data->cFileName[0] == L'.' &&
1653  (find_data->cFileName[1] == L'\0' ||
1654  (find_data->cFileName[1] == L'.' &&
1655  find_data->cFileName[2] == L'\0'))) {
1656  dir->need_find_call = TRUE;
1657  continue;
1658  }
1659 
1660  r = uv__convert_utf16_to_utf8((const WCHAR*) &find_data->cFileName,
1661  -1,
1662  (char**) &dirents[dirent_idx].name);
1663  if (r != 0)
1664  goto error;
1665 
1666  /* Copy file type. */
1667  if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
1668  dent.d_type = UV__DT_DIR;
1669  else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
1670  dent.d_type = UV__DT_LINK;
1671  else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0)
1672  dent.d_type = UV__DT_CHAR;
1673  else
1674  dent.d_type = UV__DT_FILE;
1675 
1676  dirents[dirent_idx].type = uv__fs_get_dirent_type(&dent);
1677  dir->need_find_call = TRUE;
1678  ++dirent_idx;
1679  }
1680 
1681  SET_REQ_RESULT(req, dirent_idx);
1682  return;
1683 
1684 error:
1685  SET_REQ_WIN32_ERROR(req, GetLastError());
1686  for (i = 0; i < dirent_idx; ++i) {
1687  uv__free((char*) dirents[i].name);
1688  dirents[i].name = NULL;
1689  }
1690 }
1691 
1693  uv_dir_t* dir;
1694 
1695  dir = req->ptr;
1696  FindClose(dir->dir_handle);
1697  uv__free(req->ptr);
1698  SET_REQ_RESULT(req, 0);
1699 }
1700 
1702  int do_lstat) {
1703  FILE_ALL_INFORMATION file_info;
1704  FILE_FS_VOLUME_INFORMATION volume_info;
1705  NTSTATUS nt_status;
1706  IO_STATUS_BLOCK io_status;
1707 
1708  nt_status = pNtQueryInformationFile(handle,
1709  &io_status,
1710  &file_info,
1711  sizeof file_info,
1713 
1714  /* Buffer overflow (a warning status code) is expected here. */
1715  if (NT_ERROR(nt_status)) {
1716  SetLastError(pRtlNtStatusToDosError(nt_status));
1717  return -1;
1718  }
1719 
1721  &io_status,
1722  &volume_info,
1723  sizeof volume_info,
1725 
1726  /* Buffer overflow (a warning status code) is expected here. */
1727  if (io_status.Status == STATUS_NOT_IMPLEMENTED) {
1728  statbuf->st_dev = 0;
1729  } else if (NT_ERROR(nt_status)) {
1730  SetLastError(pRtlNtStatusToDosError(nt_status));
1731  return -1;
1732  } else {
1733  statbuf->st_dev = volume_info.VolumeSerialNumber;
1734  }
1735 
1736  /* Todo: st_mode should probably always be 0666 for everyone. We might also
1737  * want to report 0777 if the file is a .exe or a directory.
1738  *
1739  * Currently it's based on whether the 'readonly' attribute is set, which
1740  * makes little sense because the semantics are so different: the 'read-only'
1741  * flag is just a way for a user to protect against accidental deletion, and
1742  * serves no security purpose. Windows uses ACLs for that.
1743  *
1744  * Also people now use uv_fs_chmod() to take away the writable bit for good
1745  * reasons. Windows however just makes the file read-only, which makes it
1746  * impossible to delete the file afterwards, since read-only files can't be
1747  * deleted.
1748  *
1749  * IOW it's all just a clusterfuck and we should think of something that
1750  * makes slightly more sense.
1751  *
1752  * And uv_fs_chmod should probably just fail on windows or be a total no-op.
1753  * There's nothing sensible it can do anyway.
1754  */
1755  statbuf->st_mode = 0;
1756 
1757  /*
1758  * On Windows, FILE_ATTRIBUTE_REPARSE_POINT is a general purpose mechanism
1759  * by which filesystem drivers can intercept and alter file system requests.
1760  *
1761  * The only reparse points we care about are symlinks and mount points, both
1762  * of which are treated as POSIX symlinks. Further, we only care when
1763  * invoked via lstat, which seeks information about the link instead of its
1764  * target. Otherwise, reparse points must be treated as regular files.
1765  */
1766  if (do_lstat &&
1767  (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
1768  /*
1769  * If reading the link fails, the reparse point is not a symlink and needs
1770  * to be treated as a regular file. The higher level lstat function will
1771  * detect this failure and retry without do_lstat if appropriate.
1772  */
1773  if (fs__readlink_handle(handle, NULL, &statbuf->st_size) != 0)
1774  return -1;
1775  statbuf->st_mode |= S_IFLNK;
1776  }
1777 
1778  if (statbuf->st_mode == 0) {
1779  if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1780  statbuf->st_mode |= _S_IFDIR;
1781  statbuf->st_size = 0;
1782  } else {
1783  statbuf->st_mode |= _S_IFREG;
1784  statbuf->st_size = file_info.StandardInformation.EndOfFile.QuadPart;
1785  }
1786  }
1787 
1788  if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY)
1789  statbuf->st_mode |= _S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6);
1790  else
1791  statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) |
1792  ((_S_IREAD | _S_IWRITE) >> 6);
1793 
1798 
1799  statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart;
1800 
1801  /* st_blocks contains the on-disk allocation size in 512-byte units. */
1802  statbuf->st_blocks =
1803  (uint64_t) file_info.StandardInformation.AllocationSize.QuadPart >> 9;
1804 
1805  statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks;
1806 
1807  /* The st_blksize is supposed to be the 'optimal' number of bytes for reading
1808  * and writing to the disk. That is, for any definition of 'optimal' - it's
1809  * supposed to at least avoid read-update-write behavior when writing to the
1810  * disk.
1811  *
1812  * However nobody knows this and even fewer people actually use this value,
1813  * and in order to fill it out we'd have to make another syscall to query the
1814  * volume for FILE_FS_SECTOR_SIZE_INFORMATION.
1815  *
1816  * Therefore we'll just report a sensible value that's quite commonly okay
1817  * on modern hardware.
1818  *
1819  * 4096 is the minimum required to be compatible with newer Advanced Format
1820  * drives (which have 4096 bytes per physical sector), and to be backwards
1821  * compatible with older drives (which have 512 bytes per physical sector).
1822  */
1823  statbuf->st_blksize = 4096;
1824 
1825  /* Todo: set st_flags to something meaningful. Also provide a wrapper for
1826  * chattr(2).
1827  */
1828  statbuf->st_flags = 0;
1829 
1830  /* Windows has nothing sensible to say about these values, so they'll just
1831  * remain empty.
1832  */
1833  statbuf->st_gid = 0;
1834  statbuf->st_uid = 0;
1835  statbuf->st_rdev = 0;
1836  statbuf->st_gen = 0;
1837 
1838  return 0;
1839 }
1840 
1841 
1842 INLINE static void fs__stat_prepare_path(WCHAR* pathw) {
1843  size_t len = wcslen(pathw);
1844 
1845  /* TODO: ignore namespaced paths. */
1846  if (len > 1 && pathw[len - 2] != L':' &&
1847  (pathw[len - 1] == L'\\' || pathw[len - 1] == L'/')) {
1848  pathw[len - 1] = '\0';
1849  }
1850 }
1851 
1852 
1854  int do_lstat,
1855  uv_stat_t* statbuf) {
1856  HANDLE handle;
1857  DWORD flags;
1858  DWORD ret;
1859 
1860  flags = FILE_FLAG_BACKUP_SEMANTICS;
1861  if (do_lstat)
1862  flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1863 
1864  handle = CreateFileW(path,
1865  FILE_READ_ATTRIBUTES,
1866  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1867  NULL,
1868  OPEN_EXISTING,
1869  flags,
1870  NULL);
1871 
1873  ret = GetLastError();
1874  else if (fs__stat_handle(handle, statbuf, do_lstat) != 0)
1875  ret = GetLastError();
1876  else
1877  ret = 0;
1878 
1879  CloseHandle(handle);
1880  return ret;
1881 }
1882 
1883 
1884 INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {
1885  DWORD error;
1886 
1887  error = fs__stat_impl_from_path(req->file.pathw, do_lstat, &req->statbuf);
1888  if (error != 0) {
1889  if (do_lstat &&
1891  error == ERROR_NOT_A_REPARSE_POINT)) {
1892  /* We opened a reparse point but it was not a symlink. Try again. */
1893  fs__stat_impl(req, 0);
1894  } else {
1895  /* Stat failed. */
1897  }
1898 
1899  return;
1900  }
1901 
1902  req->ptr = &req->statbuf;
1903  SET_REQ_RESULT(req, 0);
1904 }
1905 
1906 
1907 static void fs__stat(uv_fs_t* req) {
1908  fs__stat_prepare_path(req->file.pathw);
1909  fs__stat_impl(req, 0);
1910 }
1911 
1912 
1913 static void fs__lstat(uv_fs_t* req) {
1914  fs__stat_prepare_path(req->file.pathw);
1915  fs__stat_impl(req, 1);
1916 }
1917 
1918 
1919 static void fs__fstat(uv_fs_t* req) {
1920  int fd = req->file.fd;
1921  HANDLE handle;
1922 
1923  VERIFY_FD(fd, req);
1924 
1926 
1927  if (handle == INVALID_HANDLE_VALUE) {
1928  SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
1929  return;
1930  }
1931 
1932  if (fs__stat_handle(handle, &req->statbuf, 0) != 0) {
1933  SET_REQ_WIN32_ERROR(req, GetLastError());
1934  return;
1935  }
1936 
1937  req->ptr = &req->statbuf;
1938  SET_REQ_RESULT(req, 0);
1939 }
1940 
1941 
1942 static void fs__rename(uv_fs_t* req) {
1943  if (!MoveFileExW(req->file.pathw, req->fs.info.new_pathw, MOVEFILE_REPLACE_EXISTING)) {
1944  SET_REQ_WIN32_ERROR(req, GetLastError());
1945  return;
1946  }
1947 
1948  SET_REQ_RESULT(req, 0);
1949 }
1950 
1951 
1953  int fd = req->file.fd;
1954  int result;
1955 
1956  VERIFY_FD(fd, req);
1957 
1958  result = FlushFileBuffers(uv__get_osfhandle(fd)) ? 0 : -1;
1959  if (result == -1) {
1960  SET_REQ_WIN32_ERROR(req, GetLastError());
1961  } else {
1962  SET_REQ_RESULT(req, result);
1963  }
1964 }
1965 
1966 
1967 static void fs__fsync(uv_fs_t* req) {
1968  fs__sync_impl(req);
1969 }
1970 
1971 
1972 static void fs__fdatasync(uv_fs_t* req) {
1973  fs__sync_impl(req);
1974 }
1975 
1976 
1977 static void fs__ftruncate(uv_fs_t* req) {
1978  int fd = req->file.fd;
1979  HANDLE handle;
1980  struct uv__fd_info_s fd_info = { 0 };
1981  NTSTATUS status;
1982  IO_STATUS_BLOCK io_status;
1984 
1985  VERIFY_FD(fd, req);
1986 
1988 
1989  if (uv__fd_hash_get(fd, &fd_info)) {
1990  if (fd_info.is_directory) {
1991  SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
1992  return;
1993  }
1994 
1995  if (fd_info.mapping != INVALID_HANDLE_VALUE) {
1996  CloseHandle(fd_info.mapping);
1997  }
1998  }
1999 
2000  eof_info.EndOfFile.QuadPart = req->fs.info.offset;
2001 
2003  &io_status,
2004  &eof_info,
2005  sizeof eof_info,
2007 
2008  if (NT_SUCCESS(status)) {
2009  SET_REQ_RESULT(req, 0);
2010  } else {
2012 
2013  if (fd_info.flags) {
2014  CloseHandle(handle);
2015  fd_info.mapping = INVALID_HANDLE_VALUE;
2016  fd_info.size.QuadPart = 0;
2017  fd_info.current_pos.QuadPart = 0;
2018  uv__fd_hash_add(fd, &fd_info);
2019  return;
2020  }
2021  }
2022 
2023  if (fd_info.flags) {
2024  fd_info.size = eof_info.EndOfFile;
2025 
2026  if (fd_info.size.QuadPart == 0) {
2027  fd_info.mapping = INVALID_HANDLE_VALUE;
2028  } else {
2029  DWORD flProtect = (fd_info.flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY |
2030  UV_FS_O_RDWR)) == UV_FS_O_RDONLY ? PAGE_READONLY : PAGE_READWRITE;
2031  fd_info.mapping = CreateFileMapping(handle,
2032  NULL,
2033  flProtect,
2034  fd_info.size.HighPart,
2035  fd_info.size.LowPart,
2036  NULL);
2037  if (fd_info.mapping == NULL) {
2038  SET_REQ_WIN32_ERROR(req, GetLastError());
2039  CloseHandle(handle);
2040  fd_info.mapping = INVALID_HANDLE_VALUE;
2041  fd_info.size.QuadPart = 0;
2042  fd_info.current_pos.QuadPart = 0;
2043  uv__fd_hash_add(fd, &fd_info);
2044  return;
2045  }
2046  }
2047 
2048  uv__fd_hash_add(fd, &fd_info);
2049  }
2050 }
2051 
2052 
2053 static void fs__copyfile(uv_fs_t* req) {
2054  int flags;
2055  int overwrite;
2056  uv_stat_t statbuf;
2057  uv_stat_t new_statbuf;
2058 
2059  flags = req->fs.info.file_flags;
2060 
2062  SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
2063  return;
2064  }
2065 
2066  overwrite = flags & UV_FS_COPYFILE_EXCL;
2067 
2068  if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) != 0) {
2069  SET_REQ_RESULT(req, 0);
2070  return;
2071  }
2072 
2073  SET_REQ_WIN32_ERROR(req, GetLastError());
2074  if (req->result != UV_EBUSY)
2075  return;
2076 
2077  /* if error UV_EBUSY check if src and dst file are the same */
2078  if (fs__stat_impl_from_path(req->file.pathw, 0, &statbuf) != 0 ||
2079  fs__stat_impl_from_path(req->fs.info.new_pathw, 0, &new_statbuf) != 0) {
2080  return;
2081  }
2082 
2083  if (statbuf.st_dev == new_statbuf.st_dev &&
2084  statbuf.st_ino == new_statbuf.st_ino) {
2085  SET_REQ_RESULT(req, 0);
2086  }
2087 }
2088 
2089 
2090 static void fs__sendfile(uv_fs_t* req) {
2091  int fd_in = req->file.fd, fd_out = req->fs.info.fd_out;
2092  size_t length = req->fs.info.bufsml[0].len;
2093  int64_t offset = req->fs.info.offset;
2094  const size_t max_buf_size = 65536;
2095  size_t buf_size = length < max_buf_size ? length : max_buf_size;
2096  int n, result = 0;
2097  int64_t result_offset = 0;
2098  char* buf = (char*) uv__malloc(buf_size);
2099  if (!buf) {
2100  uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
2101  }
2102 
2103  if (offset != -1) {
2104  result_offset = _lseeki64(fd_in, offset, SEEK_SET);
2105  }
2106 
2107  if (result_offset == -1) {
2108  result = -1;
2109  } else {
2110  while (length > 0) {
2111  n = _read(fd_in, buf, length < buf_size ? length : buf_size);
2112  if (n == 0) {
2113  break;
2114  } else if (n == -1) {
2115  result = -1;
2116  break;
2117  }
2118 
2119  length -= n;
2120 
2121  n = _write(fd_out, buf, n);
2122  if (n == -1) {
2123  result = -1;
2124  break;
2125  }
2126 
2127  result += n;
2128  }
2129  }
2130 
2131  uv__free(buf);
2132 
2133  SET_REQ_RESULT(req, result);
2134 }
2135 
2136 
2137 static void fs__access(uv_fs_t* req) {
2138  DWORD attr = GetFileAttributesW(req->file.pathw);
2139 
2140  if (attr == INVALID_FILE_ATTRIBUTES) {
2141  SET_REQ_WIN32_ERROR(req, GetLastError());
2142  return;
2143  }
2144 
2145  /*
2146  * Access is possible if
2147  * - write access wasn't requested,
2148  * - or the file isn't read-only,
2149  * - or it's a directory.
2150  * (Directories cannot be read-only on Windows.)
2151  */
2152  if (!(req->fs.info.mode & W_OK) ||
2153  !(attr & FILE_ATTRIBUTE_READONLY) ||
2154  (attr & FILE_ATTRIBUTE_DIRECTORY)) {
2155  SET_REQ_RESULT(req, 0);
2156  } else {
2157  SET_REQ_WIN32_ERROR(req, UV_EPERM);
2158  }
2159 
2160 }
2161 
2162 
2163 static void fs__chmod(uv_fs_t* req) {
2164  int result = _wchmod(req->file.pathw, req->fs.info.mode);
2165  if (result == -1)
2166  SET_REQ_WIN32_ERROR(req, _doserrno);
2167  else
2168  SET_REQ_RESULT(req, 0);
2169 }
2170 
2171 
2172 static void fs__fchmod(uv_fs_t* req) {
2173  int fd = req->file.fd;
2174  int clear_archive_flag;
2175  HANDLE handle;
2176  NTSTATUS nt_status;
2177  IO_STATUS_BLOCK io_status;
2178  FILE_BASIC_INFORMATION file_info;
2179 
2180  VERIFY_FD(fd, req);
2181 
2182  handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0);
2183  if (handle == INVALID_HANDLE_VALUE) {
2184  SET_REQ_WIN32_ERROR(req, GetLastError());
2185  return;
2186  }
2187 
2188  nt_status = pNtQueryInformationFile(handle,
2189  &io_status,
2190  &file_info,
2191  sizeof file_info,
2193 
2194  if (!NT_SUCCESS(nt_status)) {
2196  goto fchmod_cleanup;
2197  }
2198 
2199  /* Test if the Archive attribute is cleared */
2200  if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) {
2201  /* Set Archive flag, otherwise setting or clearing the read-only
2202  flag will not work */
2203  file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
2204  nt_status = pNtSetInformationFile(handle,
2205  &io_status,
2206  &file_info,
2207  sizeof file_info,
2209  if (!NT_SUCCESS(nt_status)) {
2211  goto fchmod_cleanup;
2212  }
2213  /* Remeber to clear the flag later on */
2214  clear_archive_flag = 1;
2215  } else {
2216  clear_archive_flag = 0;
2217  }
2218 
2219  if (req->fs.info.mode & _S_IWRITE) {
2220  file_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
2221  } else {
2222  file_info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
2223  }
2224 
2225  nt_status = pNtSetInformationFile(handle,
2226  &io_status,
2227  &file_info,
2228  sizeof file_info,
2230 
2231  if (!NT_SUCCESS(nt_status)) {
2233  goto fchmod_cleanup;
2234  }
2235 
2236  if (clear_archive_flag) {
2237  file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
2238  if (file_info.FileAttributes == 0) {
2239  file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2240  }
2241  nt_status = pNtSetInformationFile(handle,
2242  &io_status,
2243  &file_info,
2244  sizeof file_info,
2246  if (!NT_SUCCESS(nt_status)) {
2248  goto fchmod_cleanup;
2249  }
2250  }
2251 
2253 fchmod_cleanup:
2254  CloseHandle(handle);
2255 }
2256 
2257 
2258 INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
2259  FILETIME filetime_a, filetime_m;
2260 
2261  TIME_T_TO_FILETIME(atime, &filetime_a);
2262  TIME_T_TO_FILETIME(mtime, &filetime_m);
2263 
2264  if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) {
2265  return -1;
2266  }
2267 
2268  return 0;
2269 }
2270 
2272  double atime,
2273  double mtime,
2274  int do_lutime) {
2275  HANDLE handle;
2276  DWORD flags;
2277  DWORD ret;
2278 
2279  flags = FILE_FLAG_BACKUP_SEMANTICS;
2280  if (do_lutime) {
2281  flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2282  }
2283 
2284  handle = CreateFileW(path,
2285  FILE_WRITE_ATTRIBUTES,
2286  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2287  NULL,
2288  OPEN_EXISTING,
2289  flags,
2290  NULL);
2291 
2292  if (handle == INVALID_HANDLE_VALUE) {
2293  ret = GetLastError();
2294  } else if (fs__utime_handle(handle, atime, mtime) != 0) {
2295  ret = GetLastError();
2296  } else {
2297  ret = 0;
2298  }
2299 
2300  CloseHandle(handle);
2301  return ret;
2302 }
2303 
2304 INLINE static void fs__utime_impl(uv_fs_t* req, int do_lutime) {
2305  DWORD error;
2306 
2307  error = fs__utime_impl_from_path(req->file.pathw,
2308  req->fs.time.atime,
2309  req->fs.time.mtime,
2310  do_lutime);
2311 
2312  if (error != 0) {
2313  if (do_lutime &&
2315  error == ERROR_NOT_A_REPARSE_POINT)) {
2316  /* Opened file is a reparse point but not a symlink. Try again. */
2317  fs__utime_impl(req, 0);
2318  } else {
2319  /* utime failed. */
2321  }
2322 
2323  return;
2324  }
2325 
2326  SET_REQ_RESULT(req, 0);
2327 }
2328 
2329 static void fs__utime(uv_fs_t* req) {
2330  fs__utime_impl(req, /* do_lutime */ 0);
2331 }
2332 
2333 
2334 static void fs__futime(uv_fs_t* req) {
2335  int fd = req->file.fd;
2336  HANDLE handle;
2337  VERIFY_FD(fd, req);
2338 
2340 
2341  if (handle == INVALID_HANDLE_VALUE) {
2342  SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
2343  return;
2344  }
2345 
2346  if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {
2347  SET_REQ_WIN32_ERROR(req, GetLastError());
2348  return;
2349  }
2350 
2351  SET_REQ_RESULT(req, 0);
2352 }
2353 
2354 static void fs__lutime(uv_fs_t* req) {
2355  fs__utime_impl(req, /* do_lutime */ 1);
2356 }
2357 
2358 
2359 static void fs__link(uv_fs_t* req) {
2360  DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL);
2361  if (r == 0)
2362  SET_REQ_WIN32_ERROR(req, GetLastError());
2363  else
2364  SET_REQ_RESULT(req, 0);
2365 }
2366 
2367 
2368 static void fs__create_junction(uv_fs_t* req, const WCHAR* path,
2369  const WCHAR* new_path) {
2371  REPARSE_DATA_BUFFER *buffer = NULL;
2372  int created = 0;
2373  int target_len;
2374  int is_absolute, is_long_path;
2375  int needed_buf_size, used_buf_size, used_data_size, path_buf_len;
2376  int start, len, i;
2377  int add_slash;
2378  DWORD bytes;
2379  WCHAR* path_buf;
2380 
2381  target_len = wcslen(path);
2382  is_long_path = wcsncmp(path, LONG_PATH_PREFIX, LONG_PATH_PREFIX_LEN) == 0;
2383 
2384  if (is_long_path) {
2385  is_absolute = 1;
2386  } else {
2387  is_absolute = target_len >= 3 && IS_LETTER(path[0]) &&
2388  path[1] == L':' && IS_SLASH(path[2]);
2389  }
2390 
2391  if (!is_absolute) {
2392  /* Not supporting relative paths */
2393  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_NOT_SUPPORTED);
2394  return;
2395  }
2396 
2397  /* Do a pessimistic calculation of the required buffer size */
2398  needed_buf_size =
2399  FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
2400  JUNCTION_PREFIX_LEN * sizeof(WCHAR) +
2401  2 * (target_len + 2) * sizeof(WCHAR);
2402 
2403  /* Allocate the buffer */
2404  buffer = (REPARSE_DATA_BUFFER*)uv__malloc(needed_buf_size);
2405  if (!buffer) {
2406  uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
2407  }
2408 
2409  /* Grab a pointer to the part of the buffer where filenames go */
2410  path_buf = (WCHAR*)&(buffer->MountPointReparseBuffer.PathBuffer);
2411  path_buf_len = 0;
2412 
2413  /* Copy the substitute (internal) target path */
2414  start = path_buf_len;
2415 
2416  wcsncpy((WCHAR*)&path_buf[path_buf_len], JUNCTION_PREFIX,
2418  path_buf_len += JUNCTION_PREFIX_LEN;
2419 
2420  add_slash = 0;
2421  for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
2422  if (IS_SLASH(path[i])) {
2423  add_slash = 1;
2424  continue;
2425  }
2426 
2427  if (add_slash) {
2428  path_buf[path_buf_len++] = L'\\';
2429  add_slash = 0;
2430  }
2431 
2432  path_buf[path_buf_len++] = path[i];
2433  }
2434  path_buf[path_buf_len++] = L'\\';
2435  len = path_buf_len - start;
2436 
2437  /* Set the info about the substitute name */
2438  buffer->MountPointReparseBuffer.SubstituteNameOffset = start * sizeof(WCHAR);
2439  buffer->MountPointReparseBuffer.SubstituteNameLength = len * sizeof(WCHAR);
2440 
2441  /* Insert null terminator */
2442  path_buf[path_buf_len++] = L'\0';
2443 
2444  /* Copy the print name of the target path */
2445  start = path_buf_len;
2446  add_slash = 0;
2447  for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
2448  if (IS_SLASH(path[i])) {
2449  add_slash = 1;
2450  continue;
2451  }
2452 
2453  if (add_slash) {
2454  path_buf[path_buf_len++] = L'\\';
2455  add_slash = 0;
2456  }
2457 
2458  path_buf[path_buf_len++] = path[i];
2459  }
2460  len = path_buf_len - start;
2461  if (len == 2) {
2462  path_buf[path_buf_len++] = L'\\';
2463  len++;
2464  }
2465 
2466  /* Set the info about the print name */
2467  buffer->MountPointReparseBuffer.PrintNameOffset = start * sizeof(WCHAR);
2468  buffer->MountPointReparseBuffer.PrintNameLength = len * sizeof(WCHAR);
2469 
2470  /* Insert another null terminator */
2471  path_buf[path_buf_len++] = L'\0';
2472 
2473  /* Calculate how much buffer space was actually used */
2474  used_buf_size = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
2475  path_buf_len * sizeof(WCHAR);
2476  used_data_size = used_buf_size -
2477  FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer);
2478 
2479  /* Put general info in the data buffer */
2480  buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
2481  buffer->ReparseDataLength = used_data_size;
2482  buffer->Reserved = 0;
2483 
2484  /* Create a new directory */
2485  if (!CreateDirectoryW(new_path, NULL)) {
2486  SET_REQ_WIN32_ERROR(req, GetLastError());
2487  goto error;
2488  }
2489  created = 1;
2490 
2491  /* Open the directory */
2492  handle = CreateFileW(new_path,
2493  GENERIC_WRITE,
2494  0,
2495  NULL,
2496  OPEN_EXISTING,
2497  FILE_FLAG_BACKUP_SEMANTICS |
2498  FILE_FLAG_OPEN_REPARSE_POINT,
2499  NULL);
2500  if (handle == INVALID_HANDLE_VALUE) {
2501  SET_REQ_WIN32_ERROR(req, GetLastError());
2502  goto error;
2503  }
2504 
2505  /* Create the actual reparse point */
2506  if (!DeviceIoControl(handle,
2508  buffer,
2509  used_buf_size,
2510  NULL,
2511  0,
2512  &bytes,
2513  NULL)) {
2514  SET_REQ_WIN32_ERROR(req, GetLastError());
2515  goto error;
2516  }
2517 
2518  /* Clean up */
2519  CloseHandle(handle);
2520  uv__free(buffer);
2521 
2522  SET_REQ_RESULT(req, 0);
2523  return;
2524 
2525 error:
2526  uv__free(buffer);
2527 
2528  if (handle != INVALID_HANDLE_VALUE) {
2529  CloseHandle(handle);
2530  }
2531 
2532  if (created) {
2533  RemoveDirectoryW(new_path);
2534  }
2535 }
2536 
2537 
2538 static void fs__symlink(uv_fs_t* req) {
2539  WCHAR* pathw;
2540  WCHAR* new_pathw;
2541  int flags;
2542  int err;
2543 
2544  pathw = req->file.pathw;
2545  new_pathw = req->fs.info.new_pathw;
2546 
2547  if (req->fs.info.file_flags & UV_FS_SYMLINK_JUNCTION) {
2548  fs__create_junction(req, pathw, new_pathw);
2549  return;
2550  }
2551 
2552  if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
2554  else
2556 
2557  if (CreateSymbolicLinkW(new_pathw, pathw, flags)) {
2558  SET_REQ_RESULT(req, 0);
2559  return;
2560  }
2561 
2562  /* Something went wrong. We will test if it is because of user-mode
2563  * symlinks.
2564  */
2565  err = GetLastError();
2566  if (err == ERROR_INVALID_PARAMETER &&
2568  /* This system does not support user-mode symlinks. We will clear the
2569  * unsupported flag and retry.
2570  */
2572  fs__symlink(req);
2573  } else {
2575  }
2576 }
2577 
2578 
2579 static void fs__readlink(uv_fs_t* req) {
2580  HANDLE handle;
2581 
2582  handle = CreateFileW(req->file.pathw,
2583  0,
2584  0,
2585  NULL,
2586  OPEN_EXISTING,
2587  FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
2588  NULL);
2589 
2590  if (handle == INVALID_HANDLE_VALUE) {
2591  SET_REQ_WIN32_ERROR(req, GetLastError());
2592  return;
2593  }
2594 
2595  if (fs__readlink_handle(handle, (char**) &req->ptr, NULL) != 0) {
2596  SET_REQ_WIN32_ERROR(req, GetLastError());
2597  CloseHandle(handle);
2598  return;
2599  }
2600 
2601  req->flags |= UV_FS_FREE_PTR;
2602  SET_REQ_RESULT(req, 0);
2603 
2604  CloseHandle(handle);
2605 }
2606 
2607 
2608 static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
2609  int r;
2610  DWORD w_realpath_len;
2611  WCHAR* w_realpath_ptr = NULL;
2612  WCHAR* w_realpath_buf;
2613 
2614  w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
2615  if (w_realpath_len == 0) {
2616  return -1;
2617  }
2618 
2619  w_realpath_buf = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR));
2620  if (w_realpath_buf == NULL) {
2621  SetLastError(ERROR_OUTOFMEMORY);
2622  return -1;
2623  }
2624  w_realpath_ptr = w_realpath_buf;
2625 
2626  if (GetFinalPathNameByHandleW(
2627  handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) {
2628  uv__free(w_realpath_buf);
2629  SetLastError(ERROR_INVALID_HANDLE);
2630  return -1;
2631  }
2632 
2633  /* convert UNC path to long path */
2634  if (wcsncmp(w_realpath_ptr,
2636  UNC_PATH_PREFIX_LEN) == 0) {
2637  w_realpath_ptr += 6;
2638  *w_realpath_ptr = L'\\';
2639  w_realpath_len -= 6;
2640  } else if (wcsncmp(w_realpath_ptr,
2642  LONG_PATH_PREFIX_LEN) == 0) {
2643  w_realpath_ptr += 4;
2644  w_realpath_len -= 4;
2645  } else {
2646  uv__free(w_realpath_buf);
2647  SetLastError(ERROR_INVALID_HANDLE);
2648  return -1;
2649  }
2650 
2651  r = fs__wide_to_utf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL);
2652  uv__free(w_realpath_buf);
2653  return r;
2654 }
2655 
2656 static void fs__realpath(uv_fs_t* req) {
2657  HANDLE handle;
2658 
2659  handle = CreateFileW(req->file.pathw,
2660  0,
2661  0,
2662  NULL,
2663  OPEN_EXISTING,
2664  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
2665  NULL);
2666  if (handle == INVALID_HANDLE_VALUE) {
2667  SET_REQ_WIN32_ERROR(req, GetLastError());
2668  return;
2669  }
2670 
2671  if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) {
2672  CloseHandle(handle);
2673  SET_REQ_WIN32_ERROR(req, GetLastError());
2674  return;
2675  }
2676 
2677  CloseHandle(handle);
2678  req->flags |= UV_FS_FREE_PTR;
2679  SET_REQ_RESULT(req, 0);
2680 }
2681 
2682 
2683 static void fs__chown(uv_fs_t* req) {
2684  SET_REQ_RESULT(req, 0);
2685 }
2686 
2687 
2688 static void fs__fchown(uv_fs_t* req) {
2689  SET_REQ_RESULT(req, 0);
2690 }
2691 
2692 
2693 static void fs__lchown(uv_fs_t* req) {
2694  SET_REQ_RESULT(req, 0);
2695 }
2696 
2697 
2698 static void fs__statfs(uv_fs_t* req) {
2699  uv_statfs_t* stat_fs;
2700  DWORD sectors_per_cluster;
2701  DWORD bytes_per_sector;
2702  DWORD free_clusters;
2703  DWORD total_clusters;
2704  WCHAR* pathw;
2705 
2706  pathw = req->file.pathw;
2707 retry_get_disk_free_space:
2708  if (0 == GetDiskFreeSpaceW(pathw,
2709  &sectors_per_cluster,
2710  &bytes_per_sector,
2711  &free_clusters,
2712  &total_clusters)) {
2713  DWORD err;
2714  WCHAR* fpart;
2715  size_t len;
2716  DWORD ret;
2717  BOOL is_second;
2718 
2719  err = GetLastError();
2720  is_second = pathw != req->file.pathw;
2721  if (err != ERROR_DIRECTORY || is_second) {
2722  if (is_second)
2723  uv__free(pathw);
2724 
2726  return;
2727  }
2728 
2729  len = MAX_PATH + 1;
2730  pathw = uv__malloc(len * sizeof(*pathw));
2731  if (pathw == NULL) {
2732  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
2733  return;
2734  }
2735 retry_get_full_path_name:
2736  ret = GetFullPathNameW(req->file.pathw,
2737  len,
2738  pathw,
2739  &fpart);
2740  if (ret == 0) {
2741  uv__free(pathw);
2743  return;
2744  } else if (ret > len) {
2745  len = ret;
2746  pathw = uv__reallocf(pathw, len * sizeof(*pathw));
2747  if (pathw == NULL) {
2748  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
2749  return;
2750  }
2751  goto retry_get_full_path_name;
2752  }
2753  if (fpart != 0)
2754  *fpart = L'\0';
2755 
2756  goto retry_get_disk_free_space;
2757  }
2758  if (pathw != req->file.pathw) {
2759  uv__free(pathw);
2760  }
2761 
2762  stat_fs = uv__malloc(sizeof(*stat_fs));
2763  if (stat_fs == NULL) {
2764  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
2765  return;
2766  }
2767 
2768  stat_fs->f_type = 0;
2769  stat_fs->f_bsize = bytes_per_sector * sectors_per_cluster;
2770  stat_fs->f_blocks = total_clusters;
2771  stat_fs->f_bfree = free_clusters;
2772  stat_fs->f_bavail = free_clusters;
2773  stat_fs->f_files = 0;
2774  stat_fs->f_ffree = 0;
2775  req->ptr = stat_fs;
2776  req->flags |= UV_FS_FREE_PTR;
2777  SET_REQ_RESULT(req, 0);
2778 }
2779 
2780 
2781 static void uv__fs_work(struct uv__work* w) {
2782  uv_fs_t* req;
2783 
2784  req = container_of(w, uv_fs_t, work_req);
2785  assert(req->type == UV_FS);
2786 
2787 #define XX(uc, lc) case UV_FS_##uc: fs__##lc(req); break;
2788  switch (req->fs_type) {
2789  XX(OPEN, open)
2790  XX(CLOSE, close)
2791  XX(READ, read)
2792  XX(WRITE, write)
2793  XX(COPYFILE, copyfile)
2794  XX(SENDFILE, sendfile)
2795  XX(STAT, stat)
2796  XX(LSTAT, lstat)
2797  XX(FSTAT, fstat)
2798  XX(FTRUNCATE, ftruncate)
2799  XX(UTIME, utime)
2800  XX(FUTIME, futime)
2801  XX(LUTIME, lutime)
2802  XX(ACCESS, access)
2803  XX(CHMOD, chmod)
2804  XX(FCHMOD, fchmod)
2805  XX(FSYNC, fsync)
2806  XX(FDATASYNC, fdatasync)
2807  XX(UNLINK, unlink)
2808  XX(RMDIR, rmdir)
2809  XX(MKDIR, mkdir)
2810  XX(MKDTEMP, mkdtemp)
2811  XX(MKSTEMP, mkstemp)
2812  XX(RENAME, rename)
2813  XX(SCANDIR, scandir)
2814  XX(READDIR, readdir)
2815  XX(OPENDIR, opendir)
2816  XX(CLOSEDIR, closedir)
2817  XX(LINK, link)
2818  XX(SYMLINK, symlink)
2819  XX(READLINK, readlink)
2820  XX(REALPATH, realpath)
2821  XX(CHOWN, chown)
2822  XX(FCHOWN, fchown)
2823  XX(LCHOWN, lchown)
2824  XX(STATFS, statfs)
2825  default:
2826  assert(!"bad uv_fs_type");
2827  }
2828 }
2829 
2830 
2831 static void uv__fs_done(struct uv__work* w, int status) {
2832  uv_fs_t* req;
2833 
2834  req = container_of(w, uv_fs_t, work_req);
2835  uv__req_unregister(req->loop, req);
2836 
2837  if (status == UV_ECANCELED) {
2838  assert(req->result == 0);
2839  SET_REQ_UV_ERROR(req, UV_ECANCELED, 0);
2840  }
2841 
2842  req->cb(req);
2843 }
2844 
2845 
2847  if (req == NULL)
2848  return;
2849 
2850  if (req->flags & UV_FS_CLEANEDUP)
2851  return;
2852 
2853  if (req->flags & UV_FS_FREE_PATHS)
2854  uv__free(req->file.pathw);
2855 
2856  if (req->flags & UV_FS_FREE_PTR) {
2857  if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
2859  else if (req->fs_type == UV_FS_READDIR)
2861  else
2862  uv__free(req->ptr);
2863  }
2864 
2865  if (req->fs.info.bufs != req->fs.info.bufsml)
2866  uv__free(req->fs.info.bufs);
2867 
2868  req->path = NULL;
2869  req->file.pathw = NULL;
2870  req->fs.info.new_pathw = NULL;
2871  req->fs.info.bufs = NULL;
2872  req->ptr = NULL;
2873 
2874  req->flags |= UV_FS_CLEANEDUP;
2875 }
2876 
2877 
2878 int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
2879  int mode, uv_fs_cb cb) {
2880  int err;
2881 
2882  INIT(UV_FS_OPEN);
2883  err = fs__capture_path(req, path, NULL, cb != NULL);
2884  if (err) {
2886  return req->result;
2887  }
2888 
2889  req->fs.info.file_flags = flags;
2890  req->fs.info.mode = mode;
2891  POST;
2892 }
2893 
2894 
2896  INIT(UV_FS_CLOSE);
2897  req->file.fd = fd;
2898  POST;
2899 }
2900 
2901 
2903  uv_fs_t* req,
2904  uv_file fd,
2905  const uv_buf_t bufs[],
2906  unsigned int nbufs,
2907  int64_t offset,
2908  uv_fs_cb cb) {
2909  INIT(UV_FS_READ);
2910 
2911  if (bufs == NULL || nbufs == 0) {
2912  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
2913  return UV_EINVAL;
2914  }
2915 
2916  req->file.fd = fd;
2917 
2918  req->fs.info.nbufs = nbufs;
2919  req->fs.info.bufs = req->fs.info.bufsml;
2920  if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
2921  req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
2922 
2923  if (req->fs.info.bufs == NULL) {
2924  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
2925  return UV_ENOMEM;
2926  }
2927 
2928  memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
2929 
2930  req->fs.info.offset = offset;
2931  POST;
2932 }
2933 
2934 
2936  uv_fs_t* req,
2937  uv_file fd,
2938  const uv_buf_t bufs[],
2939  unsigned int nbufs,
2940  int64_t offset,
2941  uv_fs_cb cb) {
2942  INIT(UV_FS_WRITE);
2943 
2944  if (bufs == NULL || nbufs == 0) {
2945  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
2946  return UV_EINVAL;
2947  }
2948 
2949  req->file.fd = fd;
2950 
2951  req->fs.info.nbufs = nbufs;
2952  req->fs.info.bufs = req->fs.info.bufsml;
2953  if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
2954  req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
2955 
2956  if (req->fs.info.bufs == NULL) {
2957  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
2958  return UV_ENOMEM;
2959  }
2960 
2961  memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
2962 
2963  req->fs.info.offset = offset;
2964  POST;
2965 }
2966 
2967 
2969  uv_fs_cb cb) {
2970  int err;
2971 
2972  INIT(UV_FS_UNLINK);
2973  err = fs__capture_path(req, path, NULL, cb != NULL);
2974  if (err) {
2976  return req->result;
2977  }
2978 
2979  POST;
2980 }
2981 
2982 
2983 int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
2984  uv_fs_cb cb) {
2985  int err;
2986 
2987  INIT(UV_FS_MKDIR);
2988  err = fs__capture_path(req, path, NULL, cb != NULL);
2989  if (err) {
2991  return req->result;
2992  }
2993 
2994  req->fs.info.mode = mode;
2995  POST;
2996 }
2997 
2998 
3000  uv_fs_t* req,
3001  const char* tpl,
3002  uv_fs_cb cb) {
3003  int err;
3004 
3006  err = fs__capture_path(req, tpl, NULL, TRUE);
3007  if (err) {
3009  return req->result;
3010  }
3011 
3012  POST;
3013 }
3014 
3015 
3017  uv_fs_t* req,
3018  const char* tpl,
3019  uv_fs_cb cb) {
3020  int err;
3021 
3023  err = fs__capture_path(req, tpl, NULL, TRUE);
3024  if (err) {
3026  return req->result;
3027  }
3028 
3029  POST;
3030 }
3031 
3032 
3034  int err;
3035 
3036  INIT(UV_FS_RMDIR);
3037  err = fs__capture_path(req, path, NULL, cb != NULL);
3038  if (err) {
3040  return req->result;
3041  }
3042 
3043  POST;
3044 }
3045 
3046 
3047 int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
3048  uv_fs_cb cb) {
3049  int err;
3050 
3052  err = fs__capture_path(req, path, NULL, cb != NULL);
3053  if (err) {
3055  return req->result;
3056  }
3057 
3058  req->fs.info.file_flags = flags;
3059  POST;
3060 }
3061 
3063  uv_fs_t* req,
3064  const char* path,
3065  uv_fs_cb cb) {
3066  int err;
3067 
3069  err = fs__capture_path(req, path, NULL, cb != NULL);
3070  if (err) {
3072  return req->result;
3073  }
3074  POST;
3075 }
3076 
3078  uv_fs_t* req,
3079  uv_dir_t* dir,
3080  uv_fs_cb cb) {
3082 
3083  if (dir == NULL ||
3084  dir->dirents == NULL ||
3085  dir->dir_handle == INVALID_HANDLE_VALUE) {
3086  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
3087  return UV_EINVAL;
3088  }
3089 
3090  req->ptr = dir;
3091  POST;
3092 }
3093 
3095  uv_fs_t* req,
3096  uv_dir_t* dir,
3097  uv_fs_cb cb) {
3099  if (dir == NULL) {
3100  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
3101  return UV_EINVAL;
3102  }
3103  req->ptr = dir;
3104  POST;
3105 }
3106 
3107 int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
3108  const char* new_path, uv_fs_cb cb) {
3109  int err;
3110 
3111  INIT(UV_FS_LINK);
3112  err = fs__capture_path(req, path, new_path, cb != NULL);
3113  if (err) {
3115  return req->result;
3116  }
3117 
3118  POST;
3119 }
3120 
3121 
3123  const char* new_path, int flags, uv_fs_cb cb) {
3124  int err;
3125 
3127  err = fs__capture_path(req, path, new_path, cb != NULL);
3128  if (err) {
3130  return req->result;
3131  }
3132 
3133  req->fs.info.file_flags = flags;
3134  POST;
3135 }
3136 
3137 
3139  uv_fs_cb cb) {
3140  int err;
3141 
3143  err = fs__capture_path(req, path, NULL, cb != NULL);
3144  if (err) {
3146  return req->result;
3147  }
3148 
3149  POST;
3150 }
3151 
3152 
3154  uv_fs_cb cb) {
3155  int err;
3156 
3158 
3159  if (!path) {
3160  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
3161  return UV_EINVAL;
3162  }
3163 
3164  err = fs__capture_path(req, path, NULL, cb != NULL);
3165  if (err) {
3167  return req->result;
3168  }
3169 
3170  POST;
3171 }
3172 
3173 
3174 int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
3175  uv_gid_t gid, uv_fs_cb cb) {
3176  int err;
3177 
3178  INIT(UV_FS_CHOWN);
3179  err = fs__capture_path(req, path, NULL, cb != NULL);
3180  if (err) {
3182  return req->result;
3183  }
3184 
3185  POST;
3186 }
3187 
3188 
3190  uv_gid_t gid, uv_fs_cb cb) {
3191  INIT(UV_FS_FCHOWN);
3192  POST;
3193 }
3194 
3195 
3197  uv_gid_t gid, uv_fs_cb cb) {
3198  int err;
3199 
3200  INIT(UV_FS_LCHOWN);
3201  err = fs__capture_path(req, path, NULL, cb != NULL);
3202  if (err) {
3204  return req->result;
3205  }
3206 
3207  POST;
3208 }
3209 
3210 
3212  int err;
3213 
3214  INIT(UV_FS_STAT);
3215  err = fs__capture_path(req, path, NULL, cb != NULL);
3216  if (err) {
3218  return req->result;
3219  }
3220 
3221  POST;
3222 }
3223 
3224 
3226  int err;
3227 
3228  INIT(UV_FS_LSTAT);
3229  err = fs__capture_path(req, path, NULL, cb != NULL);
3230  if (err) {
3232  return req->result;
3233  }
3234 
3235  POST;
3236 }
3237 
3238 
3240  INIT(UV_FS_FSTAT);
3241  req->file.fd = fd;
3242  POST;
3243 }
3244 
3245 
3247  const char* new_path, uv_fs_cb cb) {
3248  int err;
3249 
3250  INIT(UV_FS_RENAME);
3251  err = fs__capture_path(req, path, new_path, cb != NULL);
3252  if (err) {
3254  return req->result;
3255  }
3256 
3257  POST;
3258 }
3259 
3260 
3262  INIT(UV_FS_FSYNC);
3263  req->file.fd = fd;
3264  POST;
3265 }
3266 
3267 
3270  req->file.fd = fd;
3271  POST;
3272 }
3273 
3274 
3278  req->file.fd = fd;
3279  req->fs.info.offset = offset;
3280  POST;
3281 }
3282 
3283 
3285  uv_fs_t* req,
3286  const char* path,
3287  const char* new_path,
3288  int flags,
3289  uv_fs_cb cb) {
3290  int err;
3291 
3293 
3294  if (flags & ~(UV_FS_COPYFILE_EXCL |
3297  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
3298  return UV_EINVAL;
3299  }
3300 
3301  err = fs__capture_path(req, path, new_path, cb != NULL);
3302  if (err) {
3304  return req->result;
3305  }
3306 
3307  req->fs.info.file_flags = flags;
3308  POST;
3309 }
3310 
3311 
3313  uv_file fd_in, int64_t in_offset, size_t length, uv_fs_cb cb) {
3315  req->file.fd = fd_in;
3316  req->fs.info.fd_out = fd_out;
3317  req->fs.info.offset = in_offset;
3318  req->fs.info.bufsml[0].len = length;
3319  POST;
3320 }
3321 
3322 
3324  uv_fs_t* req,
3325  const char* path,
3326  int flags,
3327  uv_fs_cb cb) {
3328  int err;
3329 
3330  INIT(UV_FS_ACCESS);
3331  err = fs__capture_path(req, path, NULL, cb != NULL);
3332  if (err) {
3334  return req->result;
3335  }
3336 
3337  req->fs.info.mode = flags;
3338  POST;
3339 }
3340 
3341 
3342 int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
3343  uv_fs_cb cb) {
3344  int err;
3345 
3346  INIT(UV_FS_CHMOD);
3347  err = fs__capture_path(req, path, NULL, cb != NULL);
3348  if (err) {
3350  return req->result;
3351  }
3352 
3353  req->fs.info.mode = mode;
3354  POST;
3355 }
3356 
3357 
3359  uv_fs_cb cb) {
3360  INIT(UV_FS_FCHMOD);
3361  req->file.fd = fd;
3362  req->fs.info.mode = mode;
3363  POST;
3364 }
3365 
3366 
3367 int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
3368  double mtime, uv_fs_cb cb) {
3369  int err;
3370 
3371  INIT(UV_FS_UTIME);
3372  err = fs__capture_path(req, path, NULL, cb != NULL);
3373  if (err) {
3375  return req->result;
3376  }
3377 
3378  req->fs.time.atime = atime;
3379  req->fs.time.mtime = mtime;
3380  POST;
3381 }
3382 
3383 
3385  double mtime, uv_fs_cb cb) {
3386  INIT(UV_FS_FUTIME);
3387  req->file.fd = fd;
3388  req->fs.time.atime = atime;
3389  req->fs.time.mtime = mtime;
3390  POST;
3391 }
3392 
3393 int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
3394  double mtime, uv_fs_cb cb) {
3395  int err;
3396 
3397  INIT(UV_FS_LUTIME);
3398  err = fs__capture_path(req, path, NULL, cb != NULL);
3399  if (err) {
3401  return req->result;
3402  }
3403 
3404  req->fs.time.atime = atime;
3405  req->fs.time.mtime = mtime;
3406  POST;
3407 }
3408 
3409 
3411  uv_fs_t* req,
3412  const char* path,
3413  uv_fs_cb cb) {
3414  int err;
3415 
3416  INIT(UV_FS_STATFS);
3417  err = fs__capture_path(req, path, NULL, cb != NULL);
3418  if (err) {
3420  return req->result;
3421  }
3422 
3423  POST;
3424 }
3425 
3427  return req->sys_errno_;
3428 }
size_t len
Definition: 6502dis.c:15
#define ARRAY_SIZE(a)
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
static ut8 bytes[32]
Definition: asm_arc.c:23
static mcore_handle handle
Definition: asm_mcore.c:8
#define READ(x, i)
Definition: bflt.c:22
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
struct buffer buffer
#define EXCEPTION_IN_PAGE_ERROR
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
#define w
Definition: crypto_rc6.c:13
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence ftruncate
Definition: sflib.h:113
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count fchmod
Definition: sflib.h:84
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec req
Definition: sflib.h:128
static static fork write
Definition: sflib.h:33
static static fork const void static count close
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen rmdir
Definition: sflib.h:90
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
static static sync static getppid static getegid const char static filename char static len readlink
Definition: sflib.h:65
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset fstat
Definition: sflib.h:107
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz umask
Definition: sflib.h:65
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg fsync
Definition: sflib.h:79
static static fork const void static count static fd const char const char static newpath const char static path chmod
Definition: sflib.h:35
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem lchown
Definition: sflib.h:133
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
static static fork const void static count static fd link
Definition: sflib.h:33
static int buf_size
Definition: debug_qnx.c:35
const char * v
Definition: dsignal.c:12
@ INLINE
Definition: egg_lang.c:67
void cleanup(void)
Definition: enough.c:244
void uv_fatal_error(const int errorno, const char *syscall)
Definition: error.c:35
static INLINE void uv__fd_hash_add(int fd, struct uv__fd_info_s *info)
static INLINE int uv__fd_hash_get(int fd, struct uv__fd_info_s *info)
static INLINE void uv__fd_hash_init(void)
static INLINE int uv__fd_hash_remove(int fd, struct uv__fd_info_s *info)
static INLINE HANDLE uv__get_osfhandle(int fd)
Definition: handle-inl.h:166
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21
#define LONG
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define __attribute__(x)
Definition: ansidecl.h:266
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig mkdir
Definition: sflib.h:66
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds utime
Definition: sflib.h:57
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause access
Definition: sflib.h:64
static const char struct stat static buf struct stat static buf static vhangup int struct rusage static rusage struct sysinfo static info unsigned static __unused struct utsname static buf const char static size const char static name static pid unsigned static persona static fsgid const void static flags const struct iovec static count fdatasync
Definition: sflib.h:177
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment static handler static getegid char static len static pgid const char static path static newfd static getpgrp static euid const sigset_t static mask const char static len const gid_t static list symlink
Definition: sflib.h:114
static static fork const void static count static fd const char static mode unlink
Definition: sflib.h:41
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment static handler static getegid char static len static pgid const char static path static newfd static getpgrp static euid const sigset_t static mask const char static len const gid_t static list const char const char static newpath const char static library readdir
Definition: sflib.h:120
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
static const char struct stat static buf struct stat static buf static vhangup int struct rusage static rusage struct sysinfo static info unsigned static __unused struct utsname static buf const char static size const char static name static pid unsigned static persona static fsgid const void static flags const struct iovec static count static fd const void static len static munlockall struct sched_param static p static sched_yield static policy const struct timespec struct timespec static rem uid_t uid_t uid_t static suid struct pollfd unsigned static timeout chown
Definition: sflib.h:210
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync rename
Definition: sflib.h:69
assert(limit<=UINT32_MAX/2)
int n
Definition: mipsasm.c:19
#define TRUE
Definition: mybfd.h:103
#define FALSE
Definition: mybfd.h:102
int scandir(const char *maindir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const struct dirent **, const struct dirent **))
char * mkdtemp(char *path)
#define SET_REQ_SUCCESS(req)
Definition: req-inl.h:40
#define container_of(ptr, type, member)
Definition: rz_types.h:650
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
static int
Definition: sfsocketcall.h:114
long int64_t
Definition: sftypes.h:32
int size_t
Definition: sftypes.h:40
#define EMFILE
Definition: sftypes.h:134
unsigned long uint64_t
Definition: sftypes.h:28
#define EBADF
Definition: sftypes.h:119
int ssize_t
Definition: sftypes.h:39
_W64 signed int intptr_t
FILE_STANDARD_INFORMATION StandardInformation
Definition: winapi.h:4312
FILE_INTERNAL_INFORMATION InternalInformation
Definition: winapi.h:4313
FILE_BASIC_INFORMATION BasicInformation
Definition: winapi.h:4311
LARGE_INTEGER LastWriteTime
Definition: winapi.h:4264
LARGE_INTEGER CreationTime
Definition: winapi.h:4262
LARGE_INTEGER ChangeTime
Definition: winapi.h:4265
LARGE_INTEGER LastAccessTime
Definition: winapi.h:4263
LARGE_INTEGER IndexNumber
Definition: winapi.h:4278
LARGE_INTEGER EndOfFile
Definition: winapi.h:4271
LARGE_INTEGER AllocationSize
Definition: winapi.h:4270
NTSTATUS Status
Definition: winapi.h:4165
ULONG_PTR Information
Definition: winapi.h:4168
Definition: buffer.h:15
Definition: sftypes.h:48
char d_name[256]
Definition: sftypes.h:52
Definition: gzappend.c:170
Definition: z80asm.h:102
Definition: sftypes.h:80
Definition: sftypes.h:74
LARGE_INTEGER size
BOOLEAN is_directory
LARGE_INTEGER current_pos
Definition: unix.h:123
Definition: uv.h:1298
uv_dirent_t * dirents
Definition: uv.h:1299
size_t nentries
Definition: uv.h:1300
uv_dirent_type_t type
Definition: uv.h:1152
const char * name
Definition: uv.h:1151
Definition: uv.h:1306
Definition: uv.h:1780
Definition: uv.h:349
uint64_t st_nlink
Definition: uv.h:352
uint64_t st_ino
Definition: uv.h:356
uint64_t st_flags
Definition: uv.h:360
uint64_t st_mode
Definition: uv.h:351
uv_timespec_t st_birthtim
Definition: uv.h:365
uint64_t st_size
Definition: uv.h:357
uv_timespec_t st_ctim
Definition: uv.h:364
uint64_t st_blocks
Definition: uv.h:359
uv_timespec_t st_mtim
Definition: uv.h:363
uv_timespec_t st_atim
Definition: uv.h:362
uint64_t st_gid
Definition: uv.h:354
uint64_t st_gen
Definition: uv.h:361
uint64_t st_dev
Definition: uv.h:350
uint64_t st_uid
Definition: uv.h:353
uint64_t st_rdev
Definition: uv.h:355
uint64_t st_blksize
Definition: uv.h:358
uint64_t f_files
Definition: uv.h:1134
uint64_t f_type
Definition: uv.h:1129
uint64_t f_bsize
Definition: uv.h:1130
uint64_t f_bfree
Definition: uv.h:1132
uint64_t f_ffree
Definition: uv.h:1135
uint64_t f_bavail
Definition: uv.h:1133
uint64_t f_blocks
Definition: uv.h:1131
uv_loop_t * loop
Definition: main.c:7
int pos
Definition: main.c:11
void uv__once_init(void)
Definition: core.c:329
__declspec(noreturn) void uv_fatal_error(const int errorno
int uv__convert_utf16_to_utf8(const WCHAR *utf16, int utf16len, char **utf8)
Definition: util.c:1280
int uv__random_rtlgenrandom(void *buf, size_t buflen)
Definition: util.c:1965
static char bufs[4][128]
Buffers for uint64_to_str() and uint64_to_nicestr()
Definition: util.c:18
int uv_fs_fstat(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb)
Definition: fs.c:1751
int uv_fs_closedir(uv_loop_t *loop, uv_fs_t *req, uv_dir_t *dir, uv_fs_cb cb)
Definition: fs.c:1933
int uv_fs_scandir(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, uv_fs_cb cb)
Definition: fs.c:1900
int uv_fs_fchown(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
Definition: fs.c:1716
int uv_fs_rename(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *new_path, uv_fs_cb cb)
Definition: fs.c:1966
int uv_fs_access(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, uv_fs_cb cb)
Definition: fs.c:1659
int uv_fs_close(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb)
Definition: fs.c:1697
int uv_fs_stat(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: fs.c:2000
int uv_fs_ftruncate(uv_loop_t *loop, uv_fs_t *req, uv_file file, int64_t off, uv_fs_cb cb)
Definition: fs.c:1765
int uv_fs_open(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, int mode, uv_fs_cb cb)
Definition: fs.c:1858
int uv_fs_utime(uv_loop_t *loop, uv_fs_t *req, const char *path, double atime, double mtime, uv_fs_cb cb)
Definition: fs.c:2027
int uv_fs_opendir(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: fs.c:1911
int uv_fs_mkstemp(uv_loop_t *loop, uv_fs_t *req, const char *tpl, uv_fs_cb cb)
Definition: fs.c:1846
int uv_fs_futime(uv_loop_t *loop, uv_fs_t *req, uv_file file, double atime, double mtime, uv_fs_cb cb)
Definition: fs.c:1777
int uv_fs_symlink(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *new_path, int flags, uv_fs_cb cb)
Definition: fs.c:2007
int uv_fs_sendfile(uv_loop_t *loop, uv_fs_t *req, uv_file out_fd, uv_file in_fd, int64_t off, size_t len, uv_fs_cb cb)
Definition: fs.c:1984
int uv_fs_get_system_error(const uv_fs_t *req)
Definition: fs.c:2132
int uv_fs_unlink(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: fs.c:2020
int uv_fs_mkdir(uv_loop_t *loop, uv_fs_t *req, const char *path, int mode, uv_fs_cb cb)
Definition: fs.c:1822
int uv_fs_mkdtemp(uv_loop_t *loop, uv_fs_t *req, const char *tpl, uv_fs_cb cb)
Definition: fs.c:1834
int uv_fs_chown(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
Definition: fs.c:1683
int uv_fs_copyfile(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *new_path, int flags, uv_fs_cb cb)
Definition: fs.c:2103
int uv_fs_lutime(uv_loop_t *loop, uv_fs_t *req, const char *path, double atime, double mtime, uv_fs_cb cb)
Definition: fs.c:1790
void uv_fs_req_cleanup(uv_fs_t *req)
Definition: fs.c:2070
int uv_fs_lstat(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: fs.c:1804
int uv_fs_read(uv_loop_t *loop, uv_fs_t *req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t off, uv_fs_cb cb)
Definition: fs.c:1872
int uv_fs_chmod(uv_loop_t *loop, uv_fs_t *req, const char *path, int mode, uv_fs_cb cb)
Definition: fs.c:1671
int uv_fs_lchown(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
Definition: fs.c:1730
int uv_fs_link(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *new_path, uv_fs_cb cb)
Definition: fs.c:1811
int uv_fs_realpath(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: fs.c:1956
int uv_fs_fdatasync(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb)
Definition: fs.c:1744
int uv_fs_statfs(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: fs.c:2123
int uv_fs_fsync(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb)
Definition: fs.c:1758
int uv_fs_fchmod(uv_loop_t *loop, uv_fs_t *req, uv_file file, int mode, uv_fs_cb cb)
Definition: fs.c:1704
int uv_fs_write(uv_loop_t *loop, uv_fs_t *req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t off, uv_fs_cb cb)
Definition: fs.c:2041
int uv_fs_rmdir(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: fs.c:1977
int uv_fs_readdir(uv_loop_t *loop, uv_fs_t *req, uv_dir_t *dir, uv_fs_cb cb)
Definition: fs.c:1920
int uv_fs_readlink(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: fs.c:1946
#define UV_FS_O_SEQUENTIAL
Definition: unix.h:504
#define UV_FS_O_TEMPORARY
Definition: unix.h:505
uid_t uv_uid_t
Definition: unix.h:169
#define UV_FS_O_CREAT
Definition: unix.h:408
#define UV_FS_O_RANDOM
Definition: unix.h:502
int uv_file
Definition: unix.h:128
#define UV_FS_O_RDONLY
Definition: unix.h:472
#define UV_FS_O_APPEND
Definition: unix.h:403
#define UV_FS_O_SHORT_LIVED
Definition: unix.h:503
#define UV_FS_O_SYNC
Definition: unix.h:487
#define UV_FS_O_DSYNC
Definition: unix.h:437
#define UV_FS_O_DIRECT
Definition: unix.h:426
#define UV_FS_O_EXLOCK
Definition: unix.h:447
#define UV_FS_O_WRONLY
Definition: unix.h:497
#define UV_FS_O_EXCL
Definition: unix.h:442
#define UV_FS_O_TRUNC
Definition: unix.h:492
#define UV_FS_O_RDWR
Definition: unix.h:477
#define UV_FS_O_FILEMAP
Definition: unix.h:501
gid_t uv_gid_t
Definition: unix.h:168
void error(const char *msg)
Definition: untgz.c:593
void * uv__reallocf(void *ptr, size_t size)
Definition: uv-common.c:103
void * uv__realloc(void *ptr, size_t size)
Definition: uv-common.c:96
void uv__fs_scandir_cleanup(uv_fs_t *req)
Definition: uv-common.c:635
void * uv__malloc(size_t size)
Definition: uv-common.c:75
void uv__fs_readdir_cleanup(uv_fs_t *req)
Definition: uv-common.c:724
uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t *dent)
Definition: uv-common.c:688
void uv__free(void *ptr)
Definition: uv-common.c:81
#define UV_REQ_INIT(req, typ)
Definition: uv-common.h:322
#define STATIC_ASSERT(expr)
Definition: uv-common.h:60
#define uv__req_unregister(loop, req)
Definition: uv-common.h:230
#define UV_FS_SYMLINK_DIR
Definition: uv.h:1489
uv_fs_type
Definition: uv.h:1257
@ UV_FS_STATFS
Definition: uv.h:1293
@ UV_FS_SYMLINK
Definition: uv.h:1283
@ UV_FS_FDATASYNC
Definition: uv.h:1275
@ UV_FS_FCHMOD
Definition: uv.h:1273
@ UV_FS_SCANDIR
Definition: uv.h:1281
@ UV_FS_FTRUNCATE
Definition: uv.h:1268
@ UV_FS_READDIR
Definition: uv.h:1291
@ UV_FS_SENDFILE
Definition: uv.h:1264
@ UV_FS_OPENDIR
Definition: uv.h:1290
@ UV_FS_RENAME
Definition: uv.h:1280
@ UV_FS_READLINK
Definition: uv.h:1284
@ UV_FS_LUTIME
Definition: uv.h:1295
@ UV_FS_STAT
Definition: uv.h:1265
@ UV_FS_CHOWN
Definition: uv.h:1285
@ UV_FS_FUTIME
Definition: uv.h:1270
@ UV_FS_CHMOD
Definition: uv.h:1272
@ UV_FS_REALPATH
Definition: uv.h:1287
@ UV_FS_UNLINK
Definition: uv.h:1276
@ UV_FS_MKSTEMP
Definition: uv.h:1294
@ UV_FS_RMDIR
Definition: uv.h:1277
@ UV_FS_CLOSEDIR
Definition: uv.h:1292
@ UV_FS_MKDTEMP
Definition: uv.h:1279
@ UV_FS_CLOSE
Definition: uv.h:1261
@ UV_FS_FSYNC
Definition: uv.h:1274
@ UV_FS_FCHOWN
Definition: uv.h:1286
@ UV_FS_READ
Definition: uv.h:1262
@ UV_FS_COPYFILE
Definition: uv.h:1288
@ UV_FS_MKDIR
Definition: uv.h:1278
@ UV_FS_UTIME
Definition: uv.h:1269
@ UV_FS_ACCESS
Definition: uv.h:1271
@ UV_FS_FSTAT
Definition: uv.h:1267
@ UV_FS_LCHOWN
Definition: uv.h:1289
@ UV_FS_LSTAT
Definition: uv.h:1266
@ UV_FS_OPEN
Definition: uv.h:1260
@ UV_FS_WRITE
Definition: uv.h:1263
@ UV_FS_LINK
Definition: uv.h:1282
#define UV_FS_COPYFILE_FICLONE_FORCE
Definition: uv.h:1370
void(* uv_fs_cb)(uv_fs_t *req)
Definition: uv.h:328
#define UV_FS_COPYFILE_EXCL
Definition: uv.h:1358
#define UV_FS_COPYFILE_FICLONE
Definition: uv.h:1364
#define UV_FS_SYMLINK_JUNCTION
Definition: uv.h:1495
static INLINE void fs__utime_impl(uv_fs_t *req, int do_lutime)
Definition: fs.c:2304
static void fs__chmod(uv_fs_t *req)
Definition: fs.c:2163
static void fs__utime(uv_fs_t *req)
Definition: fs.c:2329
#define IS_SLASH(c)
Definition: fs.c:121
void fs__opendir(uv_fs_t *req)
Definition: fs.c:1569
const WCHAR UNC_PATH_PREFIX_LEN
Definition: fs.c:134
static void fs__fchown(uv_fs_t *req)
Definition: fs.c:2688
static INLINE void fs__sync_impl(uv_fs_t *req)
Definition: fs.c:1952
#define VERIFY_FD(fd, req)
Definition: fs.c:88
static INLINE int fs__utime_handle(HANDLE handle, double atime, double mtime)
Definition: fs.c:2258
void fs__read(uv_fs_t *req)
Definition: fs.c:852
static void fs__readlink(uv_fs_t *req)
Definition: fs.c:2579
static int fs__mkdtemp_func(uv_fs_t *req)
Definition: fs.c:1283
LONG fs__filemap_ex_filter(LONG excode, PEXCEPTION_POINTERS pep, int *perror)
Definition: fs.c:735
static void fs__copyfile(uv_fs_t *req)
Definition: fs.c:2053
static void fs__link(uv_fs_t *req)
Definition: fs.c:2359
void fs__open(uv_fs_t *req)
Definition: fs.c:450
void fs__mktemp(uv_fs_t *req, uv__fs_mktemp_func func)
Definition: fs.c:1235
#define MIN(a, b)
Definition: fs.c:125
void fs__write(uv_fs_t *req)
Definition: fs.c:1054
#define UV_FS_FREE_PTR
Definition: fs.c:41
void fs__closedir(uv_fs_t *req)
Definition: fs.c:1692
void fs__read_filemap(uv_fs_t *req, struct uv__fd_info_s *fd_info)
Definition: fs.c:755
static void fs__symlink(uv_fs_t *req)
Definition: fs.c:2538
static INLINE int fs__capture_path(uv_fs_t *req, const char *path, const char *new_path, const int copy_path)
Definition: fs.c:151
#define SET_REQ_UV_ERROR(req, uv_errno, sys_errno)
Definition: fs.c:82
static void fs__sendfile(uv_fs_t *req)
Definition: fs.c:2090
static void fs__lstat(uv_fs_t *req)
Definition: fs.c:1913
static void fs__ftruncate(uv_fs_t *req)
Definition: fs.c:1977
static void uv__fs_done(struct uv__work *w, int status)
Definition: fs.c:2831
#define XX(uc, lc)
const WCHAR JUNCTION_PREFIX_LEN
Definition: fs.c:128
static void fs__futime(uv_fs_t *req)
Definition: fs.c:2334
const WCHAR LONG_PATH_PREFIX[]
Definition: fs.c:130
static void fs__statfs(uv_fs_t *req)
Definition: fs.c:2698
static void fs__fchmod(uv_fs_t *req)
Definition: fs.c:2172
static void fs__access(uv_fs_t *req)
Definition: fs.c:2137
void fs__readdir(uv_fs_t *req)
Definition: fs.c:1628
static void fs__fdatasync(uv_fs_t *req)
Definition: fs.c:1972
int(* uv__fs_mktemp_func)(uv_fs_t *req)
Definition: fs.c:1232
static INLINE DWORD fs__utime_impl_from_path(WCHAR *path, double atime, double mtime, int do_lutime)
Definition: fs.c:2271
static void fs__stat(uv_fs_t *req)
Definition: fs.c:1907
void fs__write_filemap(uv_fs_t *req, HANDLE file, struct uv__fd_info_s *fd_info)
Definition: fs.c:930
void fs__close(uv_fs_t *req)
Definition: fs.c:705
const WCHAR UNC_PATH_PREFIX[]
Definition: fs.c:133
const WCHAR LONG_PATH_PREFIX_LEN
Definition: fs.c:131
static ssize_t fs__realpath_handle(HANDLE handle, char **realpath_ptr)
Definition: fs.c:2608
#define IS_LETTER(c)
Definition: fs.c:122
static void fs__realpath(uv_fs_t *req)
Definition: fs.c:2656
static void fs__rename(uv_fs_t *req)
Definition: fs.c:1942
void fs__scandir(uv_fs_t *req)
Definition: fs.c:1357
static int fs__wide_to_utf8(WCHAR *w_source_ptr, DWORD w_source_len, char **target_ptr, uint64_t *target_len_ptr)
Definition: fs.c:266
#define POST
Definition: fs.c:53
static int fs__mkstemp_func(uv_fs_t *req)
Definition: fs.c:1304
static INLINE DWORD fs__stat_impl_from_path(WCHAR *path, int do_lstat, uv_stat_t *statbuf)
Definition: fs.c:1853
static int uv__file_symlink_usermode_flag
Definition: fs.c:136
#define UV_FS_FREE_PATHS
Definition: fs.c:40
void fs__rmdir(uv_fs_t *req)
Definition: fs.c:1125
static void fs__chown(uv_fs_t *req)
Definition: fs.c:2683
#define INIT(subtype)
Definition: fs.c:45
void fs__mkdir(uv_fs_t *req)
Definition: fs.c:1221
#define SET_REQ_WIN32_ERROR(req, sys_errno)
Definition: fs.c:76
static void fs__lchown(uv_fs_t *req)
Definition: fs.c:2693
static INLINE void fs__stat_prepare_path(WCHAR *pathw)
Definition: fs.c:1842
static void uv__fs_work(struct uv__work *w)
Definition: fs.c:2781
static void fs__create_junction(uv_fs_t *req, const WCHAR *path, const WCHAR *new_path)
Definition: fs.c:2368
const WCHAR JUNCTION_PREFIX[]
Definition: fs.c:127
static void fs__fstat(uv_fs_t *req)
Definition: fs.c:1919
static INLINE int fs__stat_handle(HANDLE handle, uv_stat_t *statbuf, int do_lstat)
Definition: fs.c:1701
void fs__mkstemp(uv_fs_t *req)
Definition: fs.c:1352
#define SET_REQ_RESULT(req, result_value)
Definition: fs.c:70
static DWORD uv__allocation_granularity
Definition: fs.c:138
#define UV_FS_CLEANEDUP
Definition: fs.c:42
static INLINE int fs__readlink_handle(HANDLE handle, char **target_ptr, uint64_t *target_len_ptr)
Definition: fs.c:315
static INLINE void uv_fs_req_init(uv_loop_t *loop, uv_fs_t *req, uv_fs_type fs_type, const uv_fs_cb cb)
Definition: fs.c:250
static INLINE void fs__stat_impl(uv_fs_t *req, int do_lstat)
Definition: fs.c:1884
void uv_fs_init(void)
Definition: fs.c:141
#define FILETIME_TO_TIMESPEC(ts, filetime)
Definition: fs.c:107
void fs__unlink(uv_fs_t *req)
Definition: fs.c:1134
static void fs__lutime(uv_fs_t *req)
Definition: fs.c:2354
void fs__mkdtemp(uv_fs_t *req)
Definition: fs.c:1299
static void fs__fsync(uv_fs_t *req)
Definition: fs.c:1967
#define TIME_T_TO_FILETIME(time, filetime_ptr)
Definition: fs.c:113
static WCHAR * find_path(WCHAR *env)
Definition: process.c:831
LONG NTSTATUS
Definition: win.h:198
#define UV__DT_FILE
Definition: win.h:311
#define UV__DT_CHAR
Definition: win.h:315
#define UV__DT_DIR
Definition: win.h:310
#define UV__DT_LINK
Definition: win.h:312
#define W_OK
Definition: win.h:661
#define S_IFLNK
Definition: win.h:68
sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile
Definition: winapi.c:34
sNtQueryDirectoryFile pNtQueryDirectoryFile
Definition: winapi.c:35
sNtSetInformationFile pNtSetInformationFile
Definition: winapi.c:33
sNtQueryInformationFile pNtQueryInformationFile
Definition: winapi.c:32
sRtlNtStatusToDosError pRtlNtStatusToDosError
Definition: winapi.c:30
#define NT_ERROR(status)
Definition: winapi.h:64
@ FileEndOfFileInformation
Definition: winapi.h:4191
@ FileAllInformation
Definition: winapi.h:4189
@ FileDirectoryInformation
Definition: winapi.h:4172
@ FileBasicInformation
Definition: winapi.h:4175
@ FileDispositionInformation
Definition: winapi.h:4184
#define FSCTL_GET_REPARSE_POINT
Definition: winapi.h:4508
#define FSCTL_SET_REPARSE_POINT
Definition: winapi.h:4501
#define SYMBOLIC_LINK_FLAG_DIRECTORY
Definition: winapi.h:4611
#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
Definition: winapi.h:4108
#define STATUS_INVALID_PARAMETER
Definition: winapi.h:728
#define ERROR_SYMLINK_NOT_SUPPORTED
Definition: winapi.h:4642
#define NT_SUCCESS(status)
Definition: winapi.h:52
#define IO_REPARSE_TAG_APPEXECLINK
Definition: winapi.h:4525
#define STATUS_NOT_IMPLEMENTED
Definition: winapi.h:684
#define IO_REPARSE_TAG_SYMLINK
Definition: winapi.h:4522
#define STATUS_BUFFER_OVERFLOW
Definition: winapi.h:520
#define STATUS_SUCCESS
Definition: winapi.h:68
#define STATUS_NO_MORE_FILES
Definition: winapi.h:524
@ FileFsVolumeInformation
Definition: winapi.h:4343
DWORD * HANDLE
DWORD
static const z80_opcode fd[]
Definition: z80_tab.h:997
static const char * cb[]
Definition: z80_tab.h:176
static int file
Definition: z80asm.c:58
#define SEEK_SET
Definition: zip.c:88
#define L
Definition: zip_err_str.c:7
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115