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