11cb0ef41Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
41cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
51cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the
61cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
71cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
81cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
91cb0ef41Sopenharmony_ci *
101cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
111cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software.
121cb0ef41Sopenharmony_ci *
131cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
141cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
151cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
161cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
171cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
181cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
191cb0ef41Sopenharmony_ci * IN THE SOFTWARE.
201cb0ef41Sopenharmony_ci */
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#include <assert.h>
231cb0ef41Sopenharmony_ci#include <stdlib.h>
241cb0ef41Sopenharmony_ci#include <direct.h>
251cb0ef41Sopenharmony_ci#include <errno.h>
261cb0ef41Sopenharmony_ci#include <fcntl.h>
271cb0ef41Sopenharmony_ci#include <io.h>
281cb0ef41Sopenharmony_ci#include <limits.h>
291cb0ef41Sopenharmony_ci#include <sys/stat.h>
301cb0ef41Sopenharmony_ci#include <sys/utime.h>
311cb0ef41Sopenharmony_ci#include <stdio.h>
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci#include "uv.h"
341cb0ef41Sopenharmony_ci#include "internal.h"
351cb0ef41Sopenharmony_ci#include "req-inl.h"
361cb0ef41Sopenharmony_ci#include "handle-inl.h"
371cb0ef41Sopenharmony_ci#include "fs-fd-hash-inl.h"
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci#define UV_FS_FREE_PATHS         0x0002
411cb0ef41Sopenharmony_ci#define UV_FS_FREE_PTR           0x0008
421cb0ef41Sopenharmony_ci#define UV_FS_CLEANEDUP          0x0010
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci#define INIT(subtype)                                                         \
461cb0ef41Sopenharmony_ci  do {                                                                        \
471cb0ef41Sopenharmony_ci    if (req == NULL)                                                          \
481cb0ef41Sopenharmony_ci      return UV_EINVAL;                                                       \
491cb0ef41Sopenharmony_ci    uv__fs_req_init(loop, req, subtype, cb);                                  \
501cb0ef41Sopenharmony_ci  }                                                                           \
511cb0ef41Sopenharmony_ci  while (0)
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci#define POST                                                                  \
541cb0ef41Sopenharmony_ci  do {                                                                        \
551cb0ef41Sopenharmony_ci    if (cb != NULL) {                                                         \
561cb0ef41Sopenharmony_ci      uv__req_register(loop, req);                                            \
571cb0ef41Sopenharmony_ci      uv__work_submit(loop,                                                   \
581cb0ef41Sopenharmony_ci                      &req->work_req,                                         \
591cb0ef41Sopenharmony_ci                      UV__WORK_FAST_IO,                                       \
601cb0ef41Sopenharmony_ci                      uv__fs_work,                                            \
611cb0ef41Sopenharmony_ci                      uv__fs_done);                                           \
621cb0ef41Sopenharmony_ci      return 0;                                                               \
631cb0ef41Sopenharmony_ci    } else {                                                                  \
641cb0ef41Sopenharmony_ci      uv__fs_work(&req->work_req);                                            \
651cb0ef41Sopenharmony_ci      return req->result;                                                     \
661cb0ef41Sopenharmony_ci    }                                                                         \
671cb0ef41Sopenharmony_ci  }                                                                           \
681cb0ef41Sopenharmony_ci  while (0)
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci#define SET_REQ_RESULT(req, result_value)                                   \
711cb0ef41Sopenharmony_ci  do {                                                                      \
721cb0ef41Sopenharmony_ci    req->result = (result_value);                                           \
731cb0ef41Sopenharmony_ci    assert(req->result != -1);                                              \
741cb0ef41Sopenharmony_ci  } while (0)
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci#define SET_REQ_WIN32_ERROR(req, sys_errno)                                 \
771cb0ef41Sopenharmony_ci  do {                                                                      \
781cb0ef41Sopenharmony_ci    req->sys_errno_ = (sys_errno);                                          \
791cb0ef41Sopenharmony_ci    req->result = uv_translate_sys_error(req->sys_errno_);                  \
801cb0ef41Sopenharmony_ci  } while (0)
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci#define SET_REQ_UV_ERROR(req, uv_errno, sys_errno)                          \
831cb0ef41Sopenharmony_ci  do {                                                                      \
841cb0ef41Sopenharmony_ci    req->result = (uv_errno);                                               \
851cb0ef41Sopenharmony_ci    req->sys_errno_ = (sys_errno);                                          \
861cb0ef41Sopenharmony_ci  } while (0)
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci#define VERIFY_FD(fd, req)                                                  \
891cb0ef41Sopenharmony_ci  if (fd == -1) {                                                           \
901cb0ef41Sopenharmony_ci    req->result = UV_EBADF;                                                 \
911cb0ef41Sopenharmony_ci    req->sys_errno_ = ERROR_INVALID_HANDLE;                                 \
921cb0ef41Sopenharmony_ci    return;                                                                 \
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci#define MILLION ((int64_t) 1000 * 1000)
961cb0ef41Sopenharmony_ci#define BILLION ((int64_t) 1000 * 1000 * 1000)
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_cistatic void uv__filetime_to_timespec(uv_timespec_t *ts, int64_t filetime) {
991cb0ef41Sopenharmony_ci  filetime -= 116444736 * BILLION;
1001cb0ef41Sopenharmony_ci  ts->tv_sec = (long) (filetime / (10 * MILLION));
1011cb0ef41Sopenharmony_ci  ts->tv_nsec = (long) ((filetime - ts->tv_sec * 10 * MILLION) * 100U);
1021cb0ef41Sopenharmony_ci  if (ts->tv_nsec < 0) {
1031cb0ef41Sopenharmony_ci    ts->tv_sec -= 1;
1041cb0ef41Sopenharmony_ci    ts->tv_nsec += 1e9;
1051cb0ef41Sopenharmony_ci  }
1061cb0ef41Sopenharmony_ci}
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci#define TIME_T_TO_FILETIME(time, filetime_ptr)                              \
1091cb0ef41Sopenharmony_ci  do {                                                                      \
1101cb0ef41Sopenharmony_ci    int64_t bigtime = ((time) * 10 * MILLION + 116444736 * BILLION);        \
1111cb0ef41Sopenharmony_ci    (filetime_ptr)->dwLowDateTime = (uint64_t) bigtime & 0xFFFFFFFF;        \
1121cb0ef41Sopenharmony_ci    (filetime_ptr)->dwHighDateTime = (uint64_t) bigtime >> 32;              \
1131cb0ef41Sopenharmony_ci  } while(0)
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci#define IS_SLASH(c) ((c) == L'\\' || (c) == L'/')
1161cb0ef41Sopenharmony_ci#define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \
1171cb0ef41Sopenharmony_ci  ((c) >= L'A' && (c) <= L'Z'))
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci#define MIN(a,b) (((a) < (b)) ? (a) : (b))
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ciconst WCHAR JUNCTION_PREFIX[] = L"\\??\\";
1221cb0ef41Sopenharmony_ciconst WCHAR JUNCTION_PREFIX_LEN = 4;
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ciconst WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\";
1251cb0ef41Sopenharmony_ciconst WCHAR LONG_PATH_PREFIX_LEN = 4;
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ciconst WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
1281cb0ef41Sopenharmony_ciconst WCHAR UNC_PATH_PREFIX_LEN = 8;
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_cistatic int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_cistatic DWORD uv__allocation_granularity;
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_civoid uv__fs_init(void) {
1361cb0ef41Sopenharmony_ci  SYSTEM_INFO system_info;
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  GetSystemInfo(&system_info);
1391cb0ef41Sopenharmony_ci  uv__allocation_granularity = system_info.dwAllocationGranularity;
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci  uv__fd_hash_init();
1421cb0ef41Sopenharmony_ci}
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ciINLINE static int fs__capture_path(uv_fs_t* req, const char* path,
1461cb0ef41Sopenharmony_ci    const char* new_path, const int copy_path) {
1471cb0ef41Sopenharmony_ci  char* buf;
1481cb0ef41Sopenharmony_ci  char* pos;
1491cb0ef41Sopenharmony_ci  ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0;
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  /* new_path can only be set if path is also set. */
1521cb0ef41Sopenharmony_ci  assert(new_path == NULL || path != NULL);
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  if (path != NULL) {
1551cb0ef41Sopenharmony_ci    pathw_len = MultiByteToWideChar(CP_UTF8,
1561cb0ef41Sopenharmony_ci                                    0,
1571cb0ef41Sopenharmony_ci                                    path,
1581cb0ef41Sopenharmony_ci                                    -1,
1591cb0ef41Sopenharmony_ci                                    NULL,
1601cb0ef41Sopenharmony_ci                                    0);
1611cb0ef41Sopenharmony_ci    if (pathw_len == 0) {
1621cb0ef41Sopenharmony_ci      return GetLastError();
1631cb0ef41Sopenharmony_ci    }
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci    buf_sz += pathw_len * sizeof(WCHAR);
1661cb0ef41Sopenharmony_ci  }
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci  if (path != NULL && copy_path) {
1691cb0ef41Sopenharmony_ci    path_len = 1 + strlen(path);
1701cb0ef41Sopenharmony_ci    buf_sz += path_len;
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  if (new_path != NULL) {
1741cb0ef41Sopenharmony_ci    new_pathw_len = MultiByteToWideChar(CP_UTF8,
1751cb0ef41Sopenharmony_ci                                        0,
1761cb0ef41Sopenharmony_ci                                        new_path,
1771cb0ef41Sopenharmony_ci                                        -1,
1781cb0ef41Sopenharmony_ci                                        NULL,
1791cb0ef41Sopenharmony_ci                                        0);
1801cb0ef41Sopenharmony_ci    if (new_pathw_len == 0) {
1811cb0ef41Sopenharmony_ci      return GetLastError();
1821cb0ef41Sopenharmony_ci    }
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci    buf_sz += new_pathw_len * sizeof(WCHAR);
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  if (buf_sz == 0) {
1891cb0ef41Sopenharmony_ci    req->file.pathw = NULL;
1901cb0ef41Sopenharmony_ci    req->fs.info.new_pathw = NULL;
1911cb0ef41Sopenharmony_ci    req->path = NULL;
1921cb0ef41Sopenharmony_ci    return 0;
1931cb0ef41Sopenharmony_ci  }
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci  buf = (char*) uv__malloc(buf_sz);
1961cb0ef41Sopenharmony_ci  if (buf == NULL) {
1971cb0ef41Sopenharmony_ci    return ERROR_OUTOFMEMORY;
1981cb0ef41Sopenharmony_ci  }
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  pos = buf;
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  if (path != NULL) {
2031cb0ef41Sopenharmony_ci    DWORD r = MultiByteToWideChar(CP_UTF8,
2041cb0ef41Sopenharmony_ci                                  0,
2051cb0ef41Sopenharmony_ci                                  path,
2061cb0ef41Sopenharmony_ci                                  -1,
2071cb0ef41Sopenharmony_ci                                  (WCHAR*) pos,
2081cb0ef41Sopenharmony_ci                                  pathw_len);
2091cb0ef41Sopenharmony_ci    assert(r == (DWORD) pathw_len);
2101cb0ef41Sopenharmony_ci    req->file.pathw = (WCHAR*) pos;
2111cb0ef41Sopenharmony_ci    pos += r * sizeof(WCHAR);
2121cb0ef41Sopenharmony_ci  } else {
2131cb0ef41Sopenharmony_ci    req->file.pathw = NULL;
2141cb0ef41Sopenharmony_ci  }
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  if (new_path != NULL) {
2171cb0ef41Sopenharmony_ci    DWORD r = MultiByteToWideChar(CP_UTF8,
2181cb0ef41Sopenharmony_ci                                  0,
2191cb0ef41Sopenharmony_ci                                  new_path,
2201cb0ef41Sopenharmony_ci                                  -1,
2211cb0ef41Sopenharmony_ci                                  (WCHAR*) pos,
2221cb0ef41Sopenharmony_ci                                  new_pathw_len);
2231cb0ef41Sopenharmony_ci    assert(r == (DWORD) new_pathw_len);
2241cb0ef41Sopenharmony_ci    req->fs.info.new_pathw = (WCHAR*) pos;
2251cb0ef41Sopenharmony_ci    pos += r * sizeof(WCHAR);
2261cb0ef41Sopenharmony_ci  } else {
2271cb0ef41Sopenharmony_ci    req->fs.info.new_pathw = NULL;
2281cb0ef41Sopenharmony_ci  }
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci  req->path = path;
2311cb0ef41Sopenharmony_ci  if (path != NULL && copy_path) {
2321cb0ef41Sopenharmony_ci    memcpy(pos, path, path_len);
2331cb0ef41Sopenharmony_ci    assert(path_len == buf_sz - (pos - buf));
2341cb0ef41Sopenharmony_ci    req->path = pos;
2351cb0ef41Sopenharmony_ci  }
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  req->flags |= UV_FS_FREE_PATHS;
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  return 0;
2401cb0ef41Sopenharmony_ci}
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ciINLINE static void uv__fs_req_init(uv_loop_t* loop, uv_fs_t* req,
2451cb0ef41Sopenharmony_ci    uv_fs_type fs_type, const uv_fs_cb cb) {
2461cb0ef41Sopenharmony_ci  uv__once_init();
2471cb0ef41Sopenharmony_ci  UV_REQ_INIT(req, UV_FS);
2481cb0ef41Sopenharmony_ci  req->loop = loop;
2491cb0ef41Sopenharmony_ci  req->flags = 0;
2501cb0ef41Sopenharmony_ci  req->fs_type = fs_type;
2511cb0ef41Sopenharmony_ci  req->sys_errno_ = 0;
2521cb0ef41Sopenharmony_ci  req->result = 0;
2531cb0ef41Sopenharmony_ci  req->ptr = NULL;
2541cb0ef41Sopenharmony_ci  req->path = NULL;
2551cb0ef41Sopenharmony_ci  req->cb = cb;
2561cb0ef41Sopenharmony_ci  memset(&req->fs, 0, sizeof(req->fs));
2571cb0ef41Sopenharmony_ci}
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_cistatic int fs__wide_to_utf8(WCHAR* w_source_ptr,
2611cb0ef41Sopenharmony_ci                               DWORD w_source_len,
2621cb0ef41Sopenharmony_ci                               char** target_ptr,
2631cb0ef41Sopenharmony_ci                               uint64_t* target_len_ptr) {
2641cb0ef41Sopenharmony_ci  int r;
2651cb0ef41Sopenharmony_ci  int target_len;
2661cb0ef41Sopenharmony_ci  char* target;
2671cb0ef41Sopenharmony_ci  target_len = WideCharToMultiByte(CP_UTF8,
2681cb0ef41Sopenharmony_ci                                   0,
2691cb0ef41Sopenharmony_ci                                   w_source_ptr,
2701cb0ef41Sopenharmony_ci                                   w_source_len,
2711cb0ef41Sopenharmony_ci                                   NULL,
2721cb0ef41Sopenharmony_ci                                   0,
2731cb0ef41Sopenharmony_ci                                   NULL,
2741cb0ef41Sopenharmony_ci                                   NULL);
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  if (target_len == 0) {
2771cb0ef41Sopenharmony_ci    return -1;
2781cb0ef41Sopenharmony_ci  }
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ci  if (target_len_ptr != NULL) {
2811cb0ef41Sopenharmony_ci    *target_len_ptr = target_len;
2821cb0ef41Sopenharmony_ci  }
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci  if (target_ptr == NULL) {
2851cb0ef41Sopenharmony_ci    return 0;
2861cb0ef41Sopenharmony_ci  }
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci  target = uv__malloc(target_len + 1);
2891cb0ef41Sopenharmony_ci  if (target == NULL) {
2901cb0ef41Sopenharmony_ci    SetLastError(ERROR_OUTOFMEMORY);
2911cb0ef41Sopenharmony_ci    return -1;
2921cb0ef41Sopenharmony_ci  }
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_ci  r = WideCharToMultiByte(CP_UTF8,
2951cb0ef41Sopenharmony_ci                          0,
2961cb0ef41Sopenharmony_ci                          w_source_ptr,
2971cb0ef41Sopenharmony_ci                          w_source_len,
2981cb0ef41Sopenharmony_ci                          target,
2991cb0ef41Sopenharmony_ci                          target_len,
3001cb0ef41Sopenharmony_ci                          NULL,
3011cb0ef41Sopenharmony_ci                          NULL);
3021cb0ef41Sopenharmony_ci  assert(r == target_len);
3031cb0ef41Sopenharmony_ci  target[target_len] = '\0';
3041cb0ef41Sopenharmony_ci  *target_ptr = target;
3051cb0ef41Sopenharmony_ci  return 0;
3061cb0ef41Sopenharmony_ci}
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ciINLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
3101cb0ef41Sopenharmony_ci    uint64_t* target_len_ptr) {
3111cb0ef41Sopenharmony_ci  char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
3121cb0ef41Sopenharmony_ci  REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer;
3131cb0ef41Sopenharmony_ci  WCHAR* w_target;
3141cb0ef41Sopenharmony_ci  DWORD w_target_len;
3151cb0ef41Sopenharmony_ci  DWORD bytes;
3161cb0ef41Sopenharmony_ci  size_t i;
3171cb0ef41Sopenharmony_ci  size_t len;
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ci  if (!DeviceIoControl(handle,
3201cb0ef41Sopenharmony_ci                       FSCTL_GET_REPARSE_POINT,
3211cb0ef41Sopenharmony_ci                       NULL,
3221cb0ef41Sopenharmony_ci                       0,
3231cb0ef41Sopenharmony_ci                       buffer,
3241cb0ef41Sopenharmony_ci                       sizeof buffer,
3251cb0ef41Sopenharmony_ci                       &bytes,
3261cb0ef41Sopenharmony_ci                       NULL)) {
3271cb0ef41Sopenharmony_ci    return -1;
3281cb0ef41Sopenharmony_ci  }
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci  if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
3311cb0ef41Sopenharmony_ci    /* Real symlink */
3321cb0ef41Sopenharmony_ci    w_target = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
3331cb0ef41Sopenharmony_ci        (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset /
3341cb0ef41Sopenharmony_ci        sizeof(WCHAR));
3351cb0ef41Sopenharmony_ci    w_target_len =
3361cb0ef41Sopenharmony_ci        reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
3371cb0ef41Sopenharmony_ci        sizeof(WCHAR);
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ci    /* Real symlinks can contain pretty much everything, but the only thing we
3401cb0ef41Sopenharmony_ci     * really care about is undoing the implicit conversion to an NT namespaced
3411cb0ef41Sopenharmony_ci     * path that CreateSymbolicLink will perform on absolute paths. If the path
3421cb0ef41Sopenharmony_ci     * is win32-namespaced then the user must have explicitly made it so, and
3431cb0ef41Sopenharmony_ci     * we better just return the unmodified reparse data. */
3441cb0ef41Sopenharmony_ci    if (w_target_len >= 4 &&
3451cb0ef41Sopenharmony_ci        w_target[0] == L'\\' &&
3461cb0ef41Sopenharmony_ci        w_target[1] == L'?' &&
3471cb0ef41Sopenharmony_ci        w_target[2] == L'?' &&
3481cb0ef41Sopenharmony_ci        w_target[3] == L'\\') {
3491cb0ef41Sopenharmony_ci      /* Starts with \??\ */
3501cb0ef41Sopenharmony_ci      if (w_target_len >= 6 &&
3511cb0ef41Sopenharmony_ci          ((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
3521cb0ef41Sopenharmony_ci           (w_target[4] >= L'a' && w_target[4] <= L'z')) &&
3531cb0ef41Sopenharmony_ci          w_target[5] == L':' &&
3541cb0ef41Sopenharmony_ci          (w_target_len == 6 || w_target[6] == L'\\')) {
3551cb0ef41Sopenharmony_ci        /* \??\<drive>:\ */
3561cb0ef41Sopenharmony_ci        w_target += 4;
3571cb0ef41Sopenharmony_ci        w_target_len -= 4;
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci      } else if (w_target_len >= 8 &&
3601cb0ef41Sopenharmony_ci                 (w_target[4] == L'U' || w_target[4] == L'u') &&
3611cb0ef41Sopenharmony_ci                 (w_target[5] == L'N' || w_target[5] == L'n') &&
3621cb0ef41Sopenharmony_ci                 (w_target[6] == L'C' || w_target[6] == L'c') &&
3631cb0ef41Sopenharmony_ci                 w_target[7] == L'\\') {
3641cb0ef41Sopenharmony_ci        /* \??\UNC\<server>\<share>\ - make sure the final path looks like
3651cb0ef41Sopenharmony_ci         * \\<server>\<share>\ */
3661cb0ef41Sopenharmony_ci        w_target += 6;
3671cb0ef41Sopenharmony_ci        w_target[0] = L'\\';
3681cb0ef41Sopenharmony_ci        w_target_len -= 6;
3691cb0ef41Sopenharmony_ci      }
3701cb0ef41Sopenharmony_ci    }
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_ci  } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
3731cb0ef41Sopenharmony_ci    /* Junction. */
3741cb0ef41Sopenharmony_ci    w_target = reparse_data->MountPointReparseBuffer.PathBuffer +
3751cb0ef41Sopenharmony_ci        (reparse_data->MountPointReparseBuffer.SubstituteNameOffset /
3761cb0ef41Sopenharmony_ci        sizeof(WCHAR));
3771cb0ef41Sopenharmony_ci    w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
3781cb0ef41Sopenharmony_ci        sizeof(WCHAR);
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci    /* Only treat junctions that look like \??\<drive>:\ as symlink. Junctions
3811cb0ef41Sopenharmony_ci     * can also be used as mount points, like \??\Volume{<guid>}, but that's
3821cb0ef41Sopenharmony_ci     * confusing for programs since they wouldn't be able to actually
3831cb0ef41Sopenharmony_ci     * understand such a path when returned by uv_readlink(). UNC paths are
3841cb0ef41Sopenharmony_ci     * never valid for junctions so we don't care about them. */
3851cb0ef41Sopenharmony_ci    if (!(w_target_len >= 6 &&
3861cb0ef41Sopenharmony_ci          w_target[0] == L'\\' &&
3871cb0ef41Sopenharmony_ci          w_target[1] == L'?' &&
3881cb0ef41Sopenharmony_ci          w_target[2] == L'?' &&
3891cb0ef41Sopenharmony_ci          w_target[3] == L'\\' &&
3901cb0ef41Sopenharmony_ci          ((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
3911cb0ef41Sopenharmony_ci           (w_target[4] >= L'a' && w_target[4] <= L'z')) &&
3921cb0ef41Sopenharmony_ci          w_target[5] == L':' &&
3931cb0ef41Sopenharmony_ci          (w_target_len == 6 || w_target[6] == L'\\'))) {
3941cb0ef41Sopenharmony_ci      SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
3951cb0ef41Sopenharmony_ci      return -1;
3961cb0ef41Sopenharmony_ci    }
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_ci    /* Remove leading \??\ */
3991cb0ef41Sopenharmony_ci    w_target += 4;
4001cb0ef41Sopenharmony_ci    w_target_len -= 4;
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) {
4031cb0ef41Sopenharmony_ci    /* String #3 in the list has the target filename. */
4041cb0ef41Sopenharmony_ci    if (reparse_data->AppExecLinkReparseBuffer.StringCount < 3) {
4051cb0ef41Sopenharmony_ci      SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
4061cb0ef41Sopenharmony_ci      return -1;
4071cb0ef41Sopenharmony_ci    }
4081cb0ef41Sopenharmony_ci    w_target = reparse_data->AppExecLinkReparseBuffer.StringList;
4091cb0ef41Sopenharmony_ci    /* The StringList buffer contains a list of strings separated by "\0",   */
4101cb0ef41Sopenharmony_ci    /* with "\0\0" terminating the list. Move to the 3rd string in the list: */
4111cb0ef41Sopenharmony_ci    for (i = 0; i < 2; ++i) {
4121cb0ef41Sopenharmony_ci      len = wcslen(w_target);
4131cb0ef41Sopenharmony_ci      if (len == 0) {
4141cb0ef41Sopenharmony_ci        SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
4151cb0ef41Sopenharmony_ci        return -1;
4161cb0ef41Sopenharmony_ci      }
4171cb0ef41Sopenharmony_ci      w_target += len + 1;
4181cb0ef41Sopenharmony_ci    }
4191cb0ef41Sopenharmony_ci    w_target_len = wcslen(w_target);
4201cb0ef41Sopenharmony_ci    if (w_target_len == 0) {
4211cb0ef41Sopenharmony_ci      SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
4221cb0ef41Sopenharmony_ci      return -1;
4231cb0ef41Sopenharmony_ci    }
4241cb0ef41Sopenharmony_ci    /* Make sure it is an absolute path. */
4251cb0ef41Sopenharmony_ci    if (!(w_target_len >= 3 &&
4261cb0ef41Sopenharmony_ci         ((w_target[0] >= L'a' && w_target[0] <= L'z') ||
4271cb0ef41Sopenharmony_ci          (w_target[0] >= L'A' && w_target[0] <= L'Z')) &&
4281cb0ef41Sopenharmony_ci         w_target[1] == L':' &&
4291cb0ef41Sopenharmony_ci         w_target[2] == L'\\')) {
4301cb0ef41Sopenharmony_ci      SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
4311cb0ef41Sopenharmony_ci      return -1;
4321cb0ef41Sopenharmony_ci    }
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci  } else {
4351cb0ef41Sopenharmony_ci    /* Reparse tag does not indicate a symlink. */
4361cb0ef41Sopenharmony_ci    SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
4371cb0ef41Sopenharmony_ci    return -1;
4381cb0ef41Sopenharmony_ci  }
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ci  return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr);
4411cb0ef41Sopenharmony_ci}
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_civoid fs__open(uv_fs_t* req) {
4451cb0ef41Sopenharmony_ci  DWORD access;
4461cb0ef41Sopenharmony_ci  DWORD share;
4471cb0ef41Sopenharmony_ci  DWORD disposition;
4481cb0ef41Sopenharmony_ci  DWORD attributes = 0;
4491cb0ef41Sopenharmony_ci  HANDLE file;
4501cb0ef41Sopenharmony_ci  int fd, current_umask;
4511cb0ef41Sopenharmony_ci  int flags = req->fs.info.file_flags;
4521cb0ef41Sopenharmony_ci  struct uv__fd_info_s fd_info;
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ci  /* Adjust flags to be compatible with the memory file mapping. Save the
4551cb0ef41Sopenharmony_ci   * original flags to emulate the correct behavior. */
4561cb0ef41Sopenharmony_ci  if (flags & UV_FS_O_FILEMAP) {
4571cb0ef41Sopenharmony_ci    fd_info.flags = flags;
4581cb0ef41Sopenharmony_ci    fd_info.current_pos.QuadPart = 0;
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_ci    if ((flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) ==
4611cb0ef41Sopenharmony_ci        UV_FS_O_WRONLY) {
4621cb0ef41Sopenharmony_ci      /* CreateFileMapping always needs read access */
4631cb0ef41Sopenharmony_ci      flags = (flags & ~UV_FS_O_WRONLY) | UV_FS_O_RDWR;
4641cb0ef41Sopenharmony_ci    }
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci    if (flags & UV_FS_O_APPEND) {
4671cb0ef41Sopenharmony_ci      /* Clear the append flag and ensure RDRW mode */
4681cb0ef41Sopenharmony_ci      flags &= ~UV_FS_O_APPEND;
4691cb0ef41Sopenharmony_ci      flags &= ~(UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
4701cb0ef41Sopenharmony_ci      flags |= UV_FS_O_RDWR;
4711cb0ef41Sopenharmony_ci    }
4721cb0ef41Sopenharmony_ci  }
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_ci  /* Obtain the active umask. umask() never fails and returns the previous
4751cb0ef41Sopenharmony_ci   * umask. */
4761cb0ef41Sopenharmony_ci  current_umask = umask(0);
4771cb0ef41Sopenharmony_ci  umask(current_umask);
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci  /* convert flags and mode to CreateFile parameters */
4801cb0ef41Sopenharmony_ci  switch (flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) {
4811cb0ef41Sopenharmony_ci  case UV_FS_O_RDONLY:
4821cb0ef41Sopenharmony_ci    access = FILE_GENERIC_READ;
4831cb0ef41Sopenharmony_ci    break;
4841cb0ef41Sopenharmony_ci  case UV_FS_O_WRONLY:
4851cb0ef41Sopenharmony_ci    access = FILE_GENERIC_WRITE;
4861cb0ef41Sopenharmony_ci    break;
4871cb0ef41Sopenharmony_ci  case UV_FS_O_RDWR:
4881cb0ef41Sopenharmony_ci    access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
4891cb0ef41Sopenharmony_ci    break;
4901cb0ef41Sopenharmony_ci  default:
4911cb0ef41Sopenharmony_ci    goto einval;
4921cb0ef41Sopenharmony_ci  }
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci  if (flags & UV_FS_O_APPEND) {
4951cb0ef41Sopenharmony_ci    access &= ~FILE_WRITE_DATA;
4961cb0ef41Sopenharmony_ci    access |= FILE_APPEND_DATA;
4971cb0ef41Sopenharmony_ci  }
4981cb0ef41Sopenharmony_ci
4991cb0ef41Sopenharmony_ci  /*
5001cb0ef41Sopenharmony_ci   * Here is where we deviate significantly from what CRT's _open()
5011cb0ef41Sopenharmony_ci   * does. We indiscriminately use all the sharing modes, to match
5021cb0ef41Sopenharmony_ci   * UNIX semantics. In particular, this ensures that the file can
5031cb0ef41Sopenharmony_ci   * be deleted even whilst it's open, fixing issue
5041cb0ef41Sopenharmony_ci   * https://github.com/nodejs/node-v0.x-archive/issues/1449.
5051cb0ef41Sopenharmony_ci   * We still support exclusive sharing mode, since it is necessary
5061cb0ef41Sopenharmony_ci   * for opening raw block devices, otherwise Windows will prevent
5071cb0ef41Sopenharmony_ci   * any attempt to write past the master boot record.
5081cb0ef41Sopenharmony_ci   */
5091cb0ef41Sopenharmony_ci  if (flags & UV_FS_O_EXLOCK) {
5101cb0ef41Sopenharmony_ci    share = 0;
5111cb0ef41Sopenharmony_ci  } else {
5121cb0ef41Sopenharmony_ci    share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
5131cb0ef41Sopenharmony_ci  }
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ci  switch (flags & (UV_FS_O_CREAT | UV_FS_O_EXCL | UV_FS_O_TRUNC)) {
5161cb0ef41Sopenharmony_ci  case 0:
5171cb0ef41Sopenharmony_ci  case UV_FS_O_EXCL:
5181cb0ef41Sopenharmony_ci    disposition = OPEN_EXISTING;
5191cb0ef41Sopenharmony_ci    break;
5201cb0ef41Sopenharmony_ci  case UV_FS_O_CREAT:
5211cb0ef41Sopenharmony_ci    disposition = OPEN_ALWAYS;
5221cb0ef41Sopenharmony_ci    break;
5231cb0ef41Sopenharmony_ci  case UV_FS_O_CREAT | UV_FS_O_EXCL:
5241cb0ef41Sopenharmony_ci  case UV_FS_O_CREAT | UV_FS_O_TRUNC | UV_FS_O_EXCL:
5251cb0ef41Sopenharmony_ci    disposition = CREATE_NEW;
5261cb0ef41Sopenharmony_ci    break;
5271cb0ef41Sopenharmony_ci  case UV_FS_O_TRUNC:
5281cb0ef41Sopenharmony_ci  case UV_FS_O_TRUNC | UV_FS_O_EXCL:
5291cb0ef41Sopenharmony_ci    disposition = TRUNCATE_EXISTING;
5301cb0ef41Sopenharmony_ci    break;
5311cb0ef41Sopenharmony_ci  case UV_FS_O_CREAT | UV_FS_O_TRUNC:
5321cb0ef41Sopenharmony_ci    disposition = CREATE_ALWAYS;
5331cb0ef41Sopenharmony_ci    break;
5341cb0ef41Sopenharmony_ci  default:
5351cb0ef41Sopenharmony_ci    goto einval;
5361cb0ef41Sopenharmony_ci  }
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ci  attributes |= FILE_ATTRIBUTE_NORMAL;
5391cb0ef41Sopenharmony_ci  if (flags & UV_FS_O_CREAT) {
5401cb0ef41Sopenharmony_ci    if (!((req->fs.info.mode & ~current_umask) & _S_IWRITE)) {
5411cb0ef41Sopenharmony_ci      attributes |= FILE_ATTRIBUTE_READONLY;
5421cb0ef41Sopenharmony_ci    }
5431cb0ef41Sopenharmony_ci  }
5441cb0ef41Sopenharmony_ci
5451cb0ef41Sopenharmony_ci  if (flags & UV_FS_O_TEMPORARY ) {
5461cb0ef41Sopenharmony_ci    attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
5471cb0ef41Sopenharmony_ci    access |= DELETE;
5481cb0ef41Sopenharmony_ci  }
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_ci  if (flags & UV_FS_O_SHORT_LIVED) {
5511cb0ef41Sopenharmony_ci    attributes |= FILE_ATTRIBUTE_TEMPORARY;
5521cb0ef41Sopenharmony_ci  }
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  switch (flags & (UV_FS_O_SEQUENTIAL | UV_FS_O_RANDOM)) {
5551cb0ef41Sopenharmony_ci  case 0:
5561cb0ef41Sopenharmony_ci    break;
5571cb0ef41Sopenharmony_ci  case UV_FS_O_SEQUENTIAL:
5581cb0ef41Sopenharmony_ci    attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
5591cb0ef41Sopenharmony_ci    break;
5601cb0ef41Sopenharmony_ci  case UV_FS_O_RANDOM:
5611cb0ef41Sopenharmony_ci    attributes |= FILE_FLAG_RANDOM_ACCESS;
5621cb0ef41Sopenharmony_ci    break;
5631cb0ef41Sopenharmony_ci  default:
5641cb0ef41Sopenharmony_ci    goto einval;
5651cb0ef41Sopenharmony_ci  }
5661cb0ef41Sopenharmony_ci
5671cb0ef41Sopenharmony_ci  if (flags & UV_FS_O_DIRECT) {
5681cb0ef41Sopenharmony_ci    /*
5691cb0ef41Sopenharmony_ci     * FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually exclusive.
5701cb0ef41Sopenharmony_ci     * Windows returns 87, ERROR_INVALID_PARAMETER if these are combined.
5711cb0ef41Sopenharmony_ci     *
5721cb0ef41Sopenharmony_ci     * FILE_APPEND_DATA is included in FILE_GENERIC_WRITE:
5731cb0ef41Sopenharmony_ci     *
5741cb0ef41Sopenharmony_ci     * FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE |
5751cb0ef41Sopenharmony_ci     *                      FILE_WRITE_DATA |
5761cb0ef41Sopenharmony_ci     *                      FILE_WRITE_ATTRIBUTES |
5771cb0ef41Sopenharmony_ci     *                      FILE_WRITE_EA |
5781cb0ef41Sopenharmony_ci     *                      FILE_APPEND_DATA |
5791cb0ef41Sopenharmony_ci     *                      SYNCHRONIZE
5801cb0ef41Sopenharmony_ci     *
5811cb0ef41Sopenharmony_ci     * Note: Appends are also permitted by FILE_WRITE_DATA.
5821cb0ef41Sopenharmony_ci     *
5831cb0ef41Sopenharmony_ci     * In order for direct writes and direct appends to succeed, we therefore
5841cb0ef41Sopenharmony_ci     * exclude FILE_APPEND_DATA if FILE_WRITE_DATA is specified, and otherwise
5851cb0ef41Sopenharmony_ci     * fail if the user's sole permission is a direct append, since this
5861cb0ef41Sopenharmony_ci     * particular combination is invalid.
5871cb0ef41Sopenharmony_ci     */
5881cb0ef41Sopenharmony_ci    if (access & FILE_APPEND_DATA) {
5891cb0ef41Sopenharmony_ci      if (access & FILE_WRITE_DATA) {
5901cb0ef41Sopenharmony_ci        access &= ~FILE_APPEND_DATA;
5911cb0ef41Sopenharmony_ci      } else {
5921cb0ef41Sopenharmony_ci        goto einval;
5931cb0ef41Sopenharmony_ci      }
5941cb0ef41Sopenharmony_ci    }
5951cb0ef41Sopenharmony_ci    attributes |= FILE_FLAG_NO_BUFFERING;
5961cb0ef41Sopenharmony_ci  }
5971cb0ef41Sopenharmony_ci
5981cb0ef41Sopenharmony_ci  switch (flags & (UV_FS_O_DSYNC | UV_FS_O_SYNC)) {
5991cb0ef41Sopenharmony_ci  case 0:
6001cb0ef41Sopenharmony_ci    break;
6011cb0ef41Sopenharmony_ci  case UV_FS_O_DSYNC:
6021cb0ef41Sopenharmony_ci  case UV_FS_O_SYNC:
6031cb0ef41Sopenharmony_ci    attributes |= FILE_FLAG_WRITE_THROUGH;
6041cb0ef41Sopenharmony_ci    break;
6051cb0ef41Sopenharmony_ci  default:
6061cb0ef41Sopenharmony_ci    goto einval;
6071cb0ef41Sopenharmony_ci  }
6081cb0ef41Sopenharmony_ci
6091cb0ef41Sopenharmony_ci  /* Setting this flag makes it possible to open a directory. */
6101cb0ef41Sopenharmony_ci  attributes |= FILE_FLAG_BACKUP_SEMANTICS;
6111cb0ef41Sopenharmony_ci
6121cb0ef41Sopenharmony_ci  file = CreateFileW(req->file.pathw,
6131cb0ef41Sopenharmony_ci                     access,
6141cb0ef41Sopenharmony_ci                     share,
6151cb0ef41Sopenharmony_ci                     NULL,
6161cb0ef41Sopenharmony_ci                     disposition,
6171cb0ef41Sopenharmony_ci                     attributes,
6181cb0ef41Sopenharmony_ci                     NULL);
6191cb0ef41Sopenharmony_ci  if (file == INVALID_HANDLE_VALUE) {
6201cb0ef41Sopenharmony_ci    DWORD error = GetLastError();
6211cb0ef41Sopenharmony_ci    if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&
6221cb0ef41Sopenharmony_ci        !(flags & UV_FS_O_EXCL)) {
6231cb0ef41Sopenharmony_ci      /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was
6241cb0ef41Sopenharmony_ci       * specified, it means the path referred to a directory. */
6251cb0ef41Sopenharmony_ci      SET_REQ_UV_ERROR(req, UV_EISDIR, error);
6261cb0ef41Sopenharmony_ci    } else {
6271cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, GetLastError());
6281cb0ef41Sopenharmony_ci    }
6291cb0ef41Sopenharmony_ci    return;
6301cb0ef41Sopenharmony_ci  }
6311cb0ef41Sopenharmony_ci
6321cb0ef41Sopenharmony_ci  fd = _open_osfhandle((intptr_t) file, flags);
6331cb0ef41Sopenharmony_ci  if (fd < 0) {
6341cb0ef41Sopenharmony_ci    /* The only known failure mode for _open_osfhandle() is EMFILE, in which
6351cb0ef41Sopenharmony_ci     * case GetLastError() will return zero. However we'll try to handle other
6361cb0ef41Sopenharmony_ci     * errors as well, should they ever occur.
6371cb0ef41Sopenharmony_ci     */
6381cb0ef41Sopenharmony_ci    if (errno == EMFILE)
6391cb0ef41Sopenharmony_ci      SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES);
6401cb0ef41Sopenharmony_ci    else if (GetLastError() != ERROR_SUCCESS)
6411cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, GetLastError());
6421cb0ef41Sopenharmony_ci    else
6431cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, (DWORD) UV_UNKNOWN);
6441cb0ef41Sopenharmony_ci    CloseHandle(file);
6451cb0ef41Sopenharmony_ci    return;
6461cb0ef41Sopenharmony_ci  }
6471cb0ef41Sopenharmony_ci
6481cb0ef41Sopenharmony_ci  if (flags & UV_FS_O_FILEMAP) {
6491cb0ef41Sopenharmony_ci    FILE_STANDARD_INFO file_info;
6501cb0ef41Sopenharmony_ci    if (!GetFileInformationByHandleEx(file,
6511cb0ef41Sopenharmony_ci                                      FileStandardInfo,
6521cb0ef41Sopenharmony_ci                                      &file_info,
6531cb0ef41Sopenharmony_ci                                      sizeof file_info)) {
6541cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, GetLastError());
6551cb0ef41Sopenharmony_ci      CloseHandle(file);
6561cb0ef41Sopenharmony_ci      return;
6571cb0ef41Sopenharmony_ci    }
6581cb0ef41Sopenharmony_ci    fd_info.is_directory = file_info.Directory;
6591cb0ef41Sopenharmony_ci
6601cb0ef41Sopenharmony_ci    if (fd_info.is_directory) {
6611cb0ef41Sopenharmony_ci      fd_info.size.QuadPart = 0;
6621cb0ef41Sopenharmony_ci      fd_info.mapping = INVALID_HANDLE_VALUE;
6631cb0ef41Sopenharmony_ci    } else {
6641cb0ef41Sopenharmony_ci      if (!GetFileSizeEx(file, &fd_info.size)) {
6651cb0ef41Sopenharmony_ci        SET_REQ_WIN32_ERROR(req, GetLastError());
6661cb0ef41Sopenharmony_ci        CloseHandle(file);
6671cb0ef41Sopenharmony_ci        return;
6681cb0ef41Sopenharmony_ci      }
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci      if (fd_info.size.QuadPart == 0) {
6711cb0ef41Sopenharmony_ci        fd_info.mapping = INVALID_HANDLE_VALUE;
6721cb0ef41Sopenharmony_ci      } else {
6731cb0ef41Sopenharmony_ci        DWORD flProtect = (fd_info.flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY |
6741cb0ef41Sopenharmony_ci          UV_FS_O_RDWR)) == UV_FS_O_RDONLY ? PAGE_READONLY : PAGE_READWRITE;
6751cb0ef41Sopenharmony_ci        fd_info.mapping = CreateFileMapping(file,
6761cb0ef41Sopenharmony_ci                                            NULL,
6771cb0ef41Sopenharmony_ci                                            flProtect,
6781cb0ef41Sopenharmony_ci                                            fd_info.size.HighPart,
6791cb0ef41Sopenharmony_ci                                            fd_info.size.LowPart,
6801cb0ef41Sopenharmony_ci                                            NULL);
6811cb0ef41Sopenharmony_ci        if (fd_info.mapping == NULL) {
6821cb0ef41Sopenharmony_ci          SET_REQ_WIN32_ERROR(req, GetLastError());
6831cb0ef41Sopenharmony_ci          CloseHandle(file);
6841cb0ef41Sopenharmony_ci          return;
6851cb0ef41Sopenharmony_ci        }
6861cb0ef41Sopenharmony_ci      }
6871cb0ef41Sopenharmony_ci    }
6881cb0ef41Sopenharmony_ci
6891cb0ef41Sopenharmony_ci    uv__fd_hash_add(fd, &fd_info);
6901cb0ef41Sopenharmony_ci  }
6911cb0ef41Sopenharmony_ci
6921cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, fd);
6931cb0ef41Sopenharmony_ci  return;
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ci einval:
6961cb0ef41Sopenharmony_ci  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
6971cb0ef41Sopenharmony_ci}
6981cb0ef41Sopenharmony_ci
6991cb0ef41Sopenharmony_civoid fs__close(uv_fs_t* req) {
7001cb0ef41Sopenharmony_ci  int fd = req->file.fd;
7011cb0ef41Sopenharmony_ci  int result;
7021cb0ef41Sopenharmony_ci  struct uv__fd_info_s fd_info;
7031cb0ef41Sopenharmony_ci
7041cb0ef41Sopenharmony_ci  VERIFY_FD(fd, req);
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_ci  if (uv__fd_hash_remove(fd, &fd_info)) {
7071cb0ef41Sopenharmony_ci    if (fd_info.mapping != INVALID_HANDLE_VALUE) {
7081cb0ef41Sopenharmony_ci      CloseHandle(fd_info.mapping);
7091cb0ef41Sopenharmony_ci    }
7101cb0ef41Sopenharmony_ci  }
7111cb0ef41Sopenharmony_ci
7121cb0ef41Sopenharmony_ci  if (fd > 2)
7131cb0ef41Sopenharmony_ci    result = _close(fd);
7141cb0ef41Sopenharmony_ci  else
7151cb0ef41Sopenharmony_ci    result = 0;
7161cb0ef41Sopenharmony_ci
7171cb0ef41Sopenharmony_ci  /* _close doesn't set _doserrno on failure, but it does always set errno
7181cb0ef41Sopenharmony_ci   * to EBADF on failure.
7191cb0ef41Sopenharmony_ci   */
7201cb0ef41Sopenharmony_ci  if (result == -1) {
7211cb0ef41Sopenharmony_ci    assert(errno == EBADF);
7221cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE);
7231cb0ef41Sopenharmony_ci  } else {
7241cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
7251cb0ef41Sopenharmony_ci  }
7261cb0ef41Sopenharmony_ci}
7271cb0ef41Sopenharmony_ci
7281cb0ef41Sopenharmony_ci
7291cb0ef41Sopenharmony_ciLONG fs__filemap_ex_filter(LONG excode, PEXCEPTION_POINTERS pep,
7301cb0ef41Sopenharmony_ci                           int* perror) {
7311cb0ef41Sopenharmony_ci  if (excode != (LONG)EXCEPTION_IN_PAGE_ERROR) {
7321cb0ef41Sopenharmony_ci    return EXCEPTION_CONTINUE_SEARCH;
7331cb0ef41Sopenharmony_ci  }
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ci  assert(perror != NULL);
7361cb0ef41Sopenharmony_ci  if (pep != NULL && pep->ExceptionRecord != NULL &&
7371cb0ef41Sopenharmony_ci      pep->ExceptionRecord->NumberParameters >= 3) {
7381cb0ef41Sopenharmony_ci    NTSTATUS status = (NTSTATUS)pep->ExceptionRecord->ExceptionInformation[3];
7391cb0ef41Sopenharmony_ci    *perror = pRtlNtStatusToDosError(status);
7401cb0ef41Sopenharmony_ci    if (*perror != ERROR_SUCCESS) {
7411cb0ef41Sopenharmony_ci      return EXCEPTION_EXECUTE_HANDLER;
7421cb0ef41Sopenharmony_ci    }
7431cb0ef41Sopenharmony_ci  }
7441cb0ef41Sopenharmony_ci  *perror = UV_UNKNOWN;
7451cb0ef41Sopenharmony_ci  return EXCEPTION_EXECUTE_HANDLER;
7461cb0ef41Sopenharmony_ci}
7471cb0ef41Sopenharmony_ci
7481cb0ef41Sopenharmony_ci
7491cb0ef41Sopenharmony_civoid fs__read_filemap(uv_fs_t* req, struct uv__fd_info_s* fd_info) {
7501cb0ef41Sopenharmony_ci  int fd = req->file.fd; /* VERIFY_FD done in fs__read */
7511cb0ef41Sopenharmony_ci  int rw_flags = fd_info->flags &
7521cb0ef41Sopenharmony_ci    (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
7531cb0ef41Sopenharmony_ci  size_t read_size, done_read;
7541cb0ef41Sopenharmony_ci  unsigned int index;
7551cb0ef41Sopenharmony_ci  LARGE_INTEGER pos, end_pos;
7561cb0ef41Sopenharmony_ci  size_t view_offset;
7571cb0ef41Sopenharmony_ci  LARGE_INTEGER view_base;
7581cb0ef41Sopenharmony_ci  void* view;
7591cb0ef41Sopenharmony_ci
7601cb0ef41Sopenharmony_ci  if (rw_flags == UV_FS_O_WRONLY) {
7611cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FLAGS);
7621cb0ef41Sopenharmony_ci    return;
7631cb0ef41Sopenharmony_ci  }
7641cb0ef41Sopenharmony_ci  if (fd_info->is_directory) {
7651cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FUNCTION);
7661cb0ef41Sopenharmony_ci    return;
7671cb0ef41Sopenharmony_ci  }
7681cb0ef41Sopenharmony_ci
7691cb0ef41Sopenharmony_ci  if (req->fs.info.offset == -1) {
7701cb0ef41Sopenharmony_ci    pos = fd_info->current_pos;
7711cb0ef41Sopenharmony_ci  } else {
7721cb0ef41Sopenharmony_ci    pos.QuadPart = req->fs.info.offset;
7731cb0ef41Sopenharmony_ci  }
7741cb0ef41Sopenharmony_ci
7751cb0ef41Sopenharmony_ci  /* Make sure we wont read past EOF. */
7761cb0ef41Sopenharmony_ci  if (pos.QuadPart >= fd_info->size.QuadPart) {
7771cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
7781cb0ef41Sopenharmony_ci    return;
7791cb0ef41Sopenharmony_ci  }
7801cb0ef41Sopenharmony_ci
7811cb0ef41Sopenharmony_ci  read_size = 0;
7821cb0ef41Sopenharmony_ci  for (index = 0; index < req->fs.info.nbufs; ++index) {
7831cb0ef41Sopenharmony_ci    read_size += req->fs.info.bufs[index].len;
7841cb0ef41Sopenharmony_ci  }
7851cb0ef41Sopenharmony_ci  read_size = (size_t) MIN((LONGLONG) read_size,
7861cb0ef41Sopenharmony_ci                           fd_info->size.QuadPart - pos.QuadPart);
7871cb0ef41Sopenharmony_ci  if (read_size == 0) {
7881cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
7891cb0ef41Sopenharmony_ci    return;
7901cb0ef41Sopenharmony_ci  }
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_ci  end_pos.QuadPart = pos.QuadPart + read_size;
7931cb0ef41Sopenharmony_ci
7941cb0ef41Sopenharmony_ci  view_offset = pos.QuadPart % uv__allocation_granularity;
7951cb0ef41Sopenharmony_ci  view_base.QuadPart = pos.QuadPart - view_offset;
7961cb0ef41Sopenharmony_ci  view = MapViewOfFile(fd_info->mapping,
7971cb0ef41Sopenharmony_ci                       FILE_MAP_READ,
7981cb0ef41Sopenharmony_ci                       view_base.HighPart,
7991cb0ef41Sopenharmony_ci                       view_base.LowPart,
8001cb0ef41Sopenharmony_ci                       view_offset + read_size);
8011cb0ef41Sopenharmony_ci  if (view == NULL) {
8021cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
8031cb0ef41Sopenharmony_ci    return;
8041cb0ef41Sopenharmony_ci  }
8051cb0ef41Sopenharmony_ci
8061cb0ef41Sopenharmony_ci  done_read = 0;
8071cb0ef41Sopenharmony_ci  for (index = 0;
8081cb0ef41Sopenharmony_ci       index < req->fs.info.nbufs && done_read < read_size;
8091cb0ef41Sopenharmony_ci       ++index) {
8101cb0ef41Sopenharmony_ci    size_t this_read_size = MIN(req->fs.info.bufs[index].len,
8111cb0ef41Sopenharmony_ci                                read_size - done_read);
8121cb0ef41Sopenharmony_ci#ifdef _MSC_VER
8131cb0ef41Sopenharmony_ci    int err = 0;
8141cb0ef41Sopenharmony_ci    __try {
8151cb0ef41Sopenharmony_ci#endif
8161cb0ef41Sopenharmony_ci      memcpy(req->fs.info.bufs[index].base,
8171cb0ef41Sopenharmony_ci             (char*)view + view_offset + done_read,
8181cb0ef41Sopenharmony_ci             this_read_size);
8191cb0ef41Sopenharmony_ci#ifdef _MSC_VER
8201cb0ef41Sopenharmony_ci    }
8211cb0ef41Sopenharmony_ci    __except (fs__filemap_ex_filter(GetExceptionCode(),
8221cb0ef41Sopenharmony_ci                                    GetExceptionInformation(), &err)) {
8231cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, err);
8241cb0ef41Sopenharmony_ci      UnmapViewOfFile(view);
8251cb0ef41Sopenharmony_ci      return;
8261cb0ef41Sopenharmony_ci    }
8271cb0ef41Sopenharmony_ci#endif
8281cb0ef41Sopenharmony_ci    done_read += this_read_size;
8291cb0ef41Sopenharmony_ci  }
8301cb0ef41Sopenharmony_ci  assert(done_read == read_size);
8311cb0ef41Sopenharmony_ci
8321cb0ef41Sopenharmony_ci  if (!UnmapViewOfFile(view)) {
8331cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
8341cb0ef41Sopenharmony_ci    return;
8351cb0ef41Sopenharmony_ci  }
8361cb0ef41Sopenharmony_ci
8371cb0ef41Sopenharmony_ci  if (req->fs.info.offset == -1) {
8381cb0ef41Sopenharmony_ci    fd_info->current_pos = end_pos;
8391cb0ef41Sopenharmony_ci    uv__fd_hash_add(fd, fd_info);
8401cb0ef41Sopenharmony_ci  }
8411cb0ef41Sopenharmony_ci
8421cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, read_size);
8431cb0ef41Sopenharmony_ci  return;
8441cb0ef41Sopenharmony_ci}
8451cb0ef41Sopenharmony_ci
8461cb0ef41Sopenharmony_civoid fs__read(uv_fs_t* req) {
8471cb0ef41Sopenharmony_ci  int fd = req->file.fd;
8481cb0ef41Sopenharmony_ci  int64_t offset = req->fs.info.offset;
8491cb0ef41Sopenharmony_ci  HANDLE handle;
8501cb0ef41Sopenharmony_ci  OVERLAPPED overlapped, *overlapped_ptr;
8511cb0ef41Sopenharmony_ci  LARGE_INTEGER offset_;
8521cb0ef41Sopenharmony_ci  DWORD bytes;
8531cb0ef41Sopenharmony_ci  DWORD error;
8541cb0ef41Sopenharmony_ci  int result;
8551cb0ef41Sopenharmony_ci  unsigned int index;
8561cb0ef41Sopenharmony_ci  LARGE_INTEGER original_position;
8571cb0ef41Sopenharmony_ci  LARGE_INTEGER zero_offset;
8581cb0ef41Sopenharmony_ci  int restore_position;
8591cb0ef41Sopenharmony_ci  struct uv__fd_info_s fd_info;
8601cb0ef41Sopenharmony_ci
8611cb0ef41Sopenharmony_ci  VERIFY_FD(fd, req);
8621cb0ef41Sopenharmony_ci
8631cb0ef41Sopenharmony_ci  if (uv__fd_hash_get(fd, &fd_info)) {
8641cb0ef41Sopenharmony_ci    fs__read_filemap(req, &fd_info);
8651cb0ef41Sopenharmony_ci    return;
8661cb0ef41Sopenharmony_ci  }
8671cb0ef41Sopenharmony_ci
8681cb0ef41Sopenharmony_ci  zero_offset.QuadPart = 0;
8691cb0ef41Sopenharmony_ci  restore_position = 0;
8701cb0ef41Sopenharmony_ci  handle = uv__get_osfhandle(fd);
8711cb0ef41Sopenharmony_ci
8721cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE) {
8731cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
8741cb0ef41Sopenharmony_ci    return;
8751cb0ef41Sopenharmony_ci  }
8761cb0ef41Sopenharmony_ci
8771cb0ef41Sopenharmony_ci  if (offset != -1) {
8781cb0ef41Sopenharmony_ci    memset(&overlapped, 0, sizeof overlapped);
8791cb0ef41Sopenharmony_ci    overlapped_ptr = &overlapped;
8801cb0ef41Sopenharmony_ci    if (SetFilePointerEx(handle, zero_offset, &original_position,
8811cb0ef41Sopenharmony_ci                         FILE_CURRENT)) {
8821cb0ef41Sopenharmony_ci      restore_position = 1;
8831cb0ef41Sopenharmony_ci    }
8841cb0ef41Sopenharmony_ci  } else {
8851cb0ef41Sopenharmony_ci    overlapped_ptr = NULL;
8861cb0ef41Sopenharmony_ci  }
8871cb0ef41Sopenharmony_ci
8881cb0ef41Sopenharmony_ci  index = 0;
8891cb0ef41Sopenharmony_ci  bytes = 0;
8901cb0ef41Sopenharmony_ci  do {
8911cb0ef41Sopenharmony_ci    DWORD incremental_bytes;
8921cb0ef41Sopenharmony_ci
8931cb0ef41Sopenharmony_ci    if (offset != -1) {
8941cb0ef41Sopenharmony_ci      offset_.QuadPart = offset + bytes;
8951cb0ef41Sopenharmony_ci      overlapped.Offset = offset_.LowPart;
8961cb0ef41Sopenharmony_ci      overlapped.OffsetHigh = offset_.HighPart;
8971cb0ef41Sopenharmony_ci    }
8981cb0ef41Sopenharmony_ci
8991cb0ef41Sopenharmony_ci    result = ReadFile(handle,
9001cb0ef41Sopenharmony_ci                      req->fs.info.bufs[index].base,
9011cb0ef41Sopenharmony_ci                      req->fs.info.bufs[index].len,
9021cb0ef41Sopenharmony_ci                      &incremental_bytes,
9031cb0ef41Sopenharmony_ci                      overlapped_ptr);
9041cb0ef41Sopenharmony_ci    bytes += incremental_bytes;
9051cb0ef41Sopenharmony_ci    ++index;
9061cb0ef41Sopenharmony_ci  } while (result && index < req->fs.info.nbufs);
9071cb0ef41Sopenharmony_ci
9081cb0ef41Sopenharmony_ci  if (restore_position)
9091cb0ef41Sopenharmony_ci    SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
9101cb0ef41Sopenharmony_ci
9111cb0ef41Sopenharmony_ci  if (result || bytes > 0) {
9121cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, bytes);
9131cb0ef41Sopenharmony_ci  } else {
9141cb0ef41Sopenharmony_ci    error = GetLastError();
9151cb0ef41Sopenharmony_ci    if (error == ERROR_ACCESS_DENIED) {
9161cb0ef41Sopenharmony_ci      error = ERROR_INVALID_FLAGS;
9171cb0ef41Sopenharmony_ci    }
9181cb0ef41Sopenharmony_ci
9191cb0ef41Sopenharmony_ci    if (error == ERROR_HANDLE_EOF || error == ERROR_BROKEN_PIPE) {
9201cb0ef41Sopenharmony_ci      SET_REQ_RESULT(req, bytes);
9211cb0ef41Sopenharmony_ci    } else {
9221cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, error);
9231cb0ef41Sopenharmony_ci    }
9241cb0ef41Sopenharmony_ci  }
9251cb0ef41Sopenharmony_ci}
9261cb0ef41Sopenharmony_ci
9271cb0ef41Sopenharmony_ci
9281cb0ef41Sopenharmony_civoid fs__write_filemap(uv_fs_t* req, HANDLE file,
9291cb0ef41Sopenharmony_ci                       struct uv__fd_info_s* fd_info) {
9301cb0ef41Sopenharmony_ci  int fd = req->file.fd; /* VERIFY_FD done in fs__write */
9311cb0ef41Sopenharmony_ci  int force_append = fd_info->flags & UV_FS_O_APPEND;
9321cb0ef41Sopenharmony_ci  int rw_flags = fd_info->flags &
9331cb0ef41Sopenharmony_ci    (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
9341cb0ef41Sopenharmony_ci  size_t write_size, done_write;
9351cb0ef41Sopenharmony_ci  unsigned int index;
9361cb0ef41Sopenharmony_ci  LARGE_INTEGER pos, end_pos;
9371cb0ef41Sopenharmony_ci  size_t view_offset;
9381cb0ef41Sopenharmony_ci  LARGE_INTEGER view_base;
9391cb0ef41Sopenharmony_ci  void* view;
9401cb0ef41Sopenharmony_ci  FILETIME ft;
9411cb0ef41Sopenharmony_ci
9421cb0ef41Sopenharmony_ci  if (rw_flags == UV_FS_O_RDONLY) {
9431cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FLAGS);
9441cb0ef41Sopenharmony_ci    return;
9451cb0ef41Sopenharmony_ci  }
9461cb0ef41Sopenharmony_ci  if (fd_info->is_directory) {
9471cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FUNCTION);
9481cb0ef41Sopenharmony_ci    return;
9491cb0ef41Sopenharmony_ci  }
9501cb0ef41Sopenharmony_ci
9511cb0ef41Sopenharmony_ci  write_size = 0;
9521cb0ef41Sopenharmony_ci  for (index = 0; index < req->fs.info.nbufs; ++index) {
9531cb0ef41Sopenharmony_ci    write_size += req->fs.info.bufs[index].len;
9541cb0ef41Sopenharmony_ci  }
9551cb0ef41Sopenharmony_ci
9561cb0ef41Sopenharmony_ci  if (write_size == 0) {
9571cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
9581cb0ef41Sopenharmony_ci    return;
9591cb0ef41Sopenharmony_ci  }
9601cb0ef41Sopenharmony_ci
9611cb0ef41Sopenharmony_ci  if (force_append) {
9621cb0ef41Sopenharmony_ci    pos = fd_info->size;
9631cb0ef41Sopenharmony_ci  } else if (req->fs.info.offset == -1) {
9641cb0ef41Sopenharmony_ci    pos = fd_info->current_pos;
9651cb0ef41Sopenharmony_ci  } else {
9661cb0ef41Sopenharmony_ci    pos.QuadPart = req->fs.info.offset;
9671cb0ef41Sopenharmony_ci  }
9681cb0ef41Sopenharmony_ci
9691cb0ef41Sopenharmony_ci  end_pos.QuadPart = pos.QuadPart + write_size;
9701cb0ef41Sopenharmony_ci
9711cb0ef41Sopenharmony_ci  /* Recreate the mapping to enlarge the file if needed */
9721cb0ef41Sopenharmony_ci  if (end_pos.QuadPart > fd_info->size.QuadPart) {
9731cb0ef41Sopenharmony_ci    if (fd_info->mapping != INVALID_HANDLE_VALUE) {
9741cb0ef41Sopenharmony_ci      CloseHandle(fd_info->mapping);
9751cb0ef41Sopenharmony_ci    }
9761cb0ef41Sopenharmony_ci
9771cb0ef41Sopenharmony_ci    fd_info->mapping = CreateFileMapping(file,
9781cb0ef41Sopenharmony_ci                                         NULL,
9791cb0ef41Sopenharmony_ci                                         PAGE_READWRITE,
9801cb0ef41Sopenharmony_ci                                         end_pos.HighPart,
9811cb0ef41Sopenharmony_ci                                         end_pos.LowPart,
9821cb0ef41Sopenharmony_ci                                         NULL);
9831cb0ef41Sopenharmony_ci    if (fd_info->mapping == NULL) {
9841cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, GetLastError());
9851cb0ef41Sopenharmony_ci      CloseHandle(file);
9861cb0ef41Sopenharmony_ci      fd_info->mapping = INVALID_HANDLE_VALUE;
9871cb0ef41Sopenharmony_ci      fd_info->size.QuadPart = 0;
9881cb0ef41Sopenharmony_ci      fd_info->current_pos.QuadPart = 0;
9891cb0ef41Sopenharmony_ci      uv__fd_hash_add(fd, fd_info);
9901cb0ef41Sopenharmony_ci      return;
9911cb0ef41Sopenharmony_ci    }
9921cb0ef41Sopenharmony_ci
9931cb0ef41Sopenharmony_ci    fd_info->size = end_pos;
9941cb0ef41Sopenharmony_ci    uv__fd_hash_add(fd, fd_info);
9951cb0ef41Sopenharmony_ci  }
9961cb0ef41Sopenharmony_ci
9971cb0ef41Sopenharmony_ci  view_offset = pos.QuadPart % uv__allocation_granularity;
9981cb0ef41Sopenharmony_ci  view_base.QuadPart = pos.QuadPart - view_offset;
9991cb0ef41Sopenharmony_ci  view = MapViewOfFile(fd_info->mapping,
10001cb0ef41Sopenharmony_ci                       FILE_MAP_WRITE,
10011cb0ef41Sopenharmony_ci                       view_base.HighPart,
10021cb0ef41Sopenharmony_ci                       view_base.LowPart,
10031cb0ef41Sopenharmony_ci                       view_offset + write_size);
10041cb0ef41Sopenharmony_ci  if (view == NULL) {
10051cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
10061cb0ef41Sopenharmony_ci    return;
10071cb0ef41Sopenharmony_ci  }
10081cb0ef41Sopenharmony_ci
10091cb0ef41Sopenharmony_ci  done_write = 0;
10101cb0ef41Sopenharmony_ci  for (index = 0; index < req->fs.info.nbufs; ++index) {
10111cb0ef41Sopenharmony_ci#ifdef _MSC_VER
10121cb0ef41Sopenharmony_ci    int err = 0;
10131cb0ef41Sopenharmony_ci    __try {
10141cb0ef41Sopenharmony_ci#endif
10151cb0ef41Sopenharmony_ci      memcpy((char*)view + view_offset + done_write,
10161cb0ef41Sopenharmony_ci             req->fs.info.bufs[index].base,
10171cb0ef41Sopenharmony_ci             req->fs.info.bufs[index].len);
10181cb0ef41Sopenharmony_ci#ifdef _MSC_VER
10191cb0ef41Sopenharmony_ci    }
10201cb0ef41Sopenharmony_ci    __except (fs__filemap_ex_filter(GetExceptionCode(),
10211cb0ef41Sopenharmony_ci                                    GetExceptionInformation(), &err)) {
10221cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, err);
10231cb0ef41Sopenharmony_ci      UnmapViewOfFile(view);
10241cb0ef41Sopenharmony_ci      return;
10251cb0ef41Sopenharmony_ci    }
10261cb0ef41Sopenharmony_ci#endif
10271cb0ef41Sopenharmony_ci    done_write += req->fs.info.bufs[index].len;
10281cb0ef41Sopenharmony_ci  }
10291cb0ef41Sopenharmony_ci  assert(done_write == write_size);
10301cb0ef41Sopenharmony_ci
10311cb0ef41Sopenharmony_ci  if (!FlushViewOfFile(view, 0)) {
10321cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
10331cb0ef41Sopenharmony_ci    UnmapViewOfFile(view);
10341cb0ef41Sopenharmony_ci    return;
10351cb0ef41Sopenharmony_ci  }
10361cb0ef41Sopenharmony_ci  if (!UnmapViewOfFile(view)) {
10371cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
10381cb0ef41Sopenharmony_ci    return;
10391cb0ef41Sopenharmony_ci  }
10401cb0ef41Sopenharmony_ci
10411cb0ef41Sopenharmony_ci  if (req->fs.info.offset == -1) {
10421cb0ef41Sopenharmony_ci    fd_info->current_pos = end_pos;
10431cb0ef41Sopenharmony_ci    uv__fd_hash_add(fd, fd_info);
10441cb0ef41Sopenharmony_ci  }
10451cb0ef41Sopenharmony_ci
10461cb0ef41Sopenharmony_ci  GetSystemTimeAsFileTime(&ft);
10471cb0ef41Sopenharmony_ci  SetFileTime(file, NULL, NULL, &ft);
10481cb0ef41Sopenharmony_ci
10491cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, done_write);
10501cb0ef41Sopenharmony_ci}
10511cb0ef41Sopenharmony_ci
10521cb0ef41Sopenharmony_civoid fs__write(uv_fs_t* req) {
10531cb0ef41Sopenharmony_ci  int fd = req->file.fd;
10541cb0ef41Sopenharmony_ci  int64_t offset = req->fs.info.offset;
10551cb0ef41Sopenharmony_ci  HANDLE handle;
10561cb0ef41Sopenharmony_ci  OVERLAPPED overlapped, *overlapped_ptr;
10571cb0ef41Sopenharmony_ci  LARGE_INTEGER offset_;
10581cb0ef41Sopenharmony_ci  DWORD bytes;
10591cb0ef41Sopenharmony_ci  DWORD error;
10601cb0ef41Sopenharmony_ci  int result;
10611cb0ef41Sopenharmony_ci  unsigned int index;
10621cb0ef41Sopenharmony_ci  LARGE_INTEGER original_position;
10631cb0ef41Sopenharmony_ci  LARGE_INTEGER zero_offset;
10641cb0ef41Sopenharmony_ci  int restore_position;
10651cb0ef41Sopenharmony_ci  struct uv__fd_info_s fd_info;
10661cb0ef41Sopenharmony_ci
10671cb0ef41Sopenharmony_ci  VERIFY_FD(fd, req);
10681cb0ef41Sopenharmony_ci
10691cb0ef41Sopenharmony_ci  zero_offset.QuadPart = 0;
10701cb0ef41Sopenharmony_ci  restore_position = 0;
10711cb0ef41Sopenharmony_ci  handle = uv__get_osfhandle(fd);
10721cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE) {
10731cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
10741cb0ef41Sopenharmony_ci    return;
10751cb0ef41Sopenharmony_ci  }
10761cb0ef41Sopenharmony_ci
10771cb0ef41Sopenharmony_ci  if (uv__fd_hash_get(fd, &fd_info)) {
10781cb0ef41Sopenharmony_ci    fs__write_filemap(req, handle, &fd_info);
10791cb0ef41Sopenharmony_ci    return;
10801cb0ef41Sopenharmony_ci  }
10811cb0ef41Sopenharmony_ci
10821cb0ef41Sopenharmony_ci  if (offset != -1) {
10831cb0ef41Sopenharmony_ci    memset(&overlapped, 0, sizeof overlapped);
10841cb0ef41Sopenharmony_ci    overlapped_ptr = &overlapped;
10851cb0ef41Sopenharmony_ci    if (SetFilePointerEx(handle, zero_offset, &original_position,
10861cb0ef41Sopenharmony_ci                         FILE_CURRENT)) {
10871cb0ef41Sopenharmony_ci      restore_position = 1;
10881cb0ef41Sopenharmony_ci    }
10891cb0ef41Sopenharmony_ci  } else {
10901cb0ef41Sopenharmony_ci    overlapped_ptr = NULL;
10911cb0ef41Sopenharmony_ci  }
10921cb0ef41Sopenharmony_ci
10931cb0ef41Sopenharmony_ci  index = 0;
10941cb0ef41Sopenharmony_ci  bytes = 0;
10951cb0ef41Sopenharmony_ci  do {
10961cb0ef41Sopenharmony_ci    DWORD incremental_bytes;
10971cb0ef41Sopenharmony_ci
10981cb0ef41Sopenharmony_ci    if (offset != -1) {
10991cb0ef41Sopenharmony_ci      offset_.QuadPart = offset + bytes;
11001cb0ef41Sopenharmony_ci      overlapped.Offset = offset_.LowPart;
11011cb0ef41Sopenharmony_ci      overlapped.OffsetHigh = offset_.HighPart;
11021cb0ef41Sopenharmony_ci    }
11031cb0ef41Sopenharmony_ci
11041cb0ef41Sopenharmony_ci    result = WriteFile(handle,
11051cb0ef41Sopenharmony_ci                       req->fs.info.bufs[index].base,
11061cb0ef41Sopenharmony_ci                       req->fs.info.bufs[index].len,
11071cb0ef41Sopenharmony_ci                       &incremental_bytes,
11081cb0ef41Sopenharmony_ci                       overlapped_ptr);
11091cb0ef41Sopenharmony_ci    bytes += incremental_bytes;
11101cb0ef41Sopenharmony_ci    ++index;
11111cb0ef41Sopenharmony_ci  } while (result && index < req->fs.info.nbufs);
11121cb0ef41Sopenharmony_ci
11131cb0ef41Sopenharmony_ci  if (restore_position)
11141cb0ef41Sopenharmony_ci    SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
11151cb0ef41Sopenharmony_ci
11161cb0ef41Sopenharmony_ci  if (result || bytes > 0) {
11171cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, bytes);
11181cb0ef41Sopenharmony_ci  } else {
11191cb0ef41Sopenharmony_ci    error = GetLastError();
11201cb0ef41Sopenharmony_ci
11211cb0ef41Sopenharmony_ci    if (error == ERROR_ACCESS_DENIED) {
11221cb0ef41Sopenharmony_ci      error = ERROR_INVALID_FLAGS;
11231cb0ef41Sopenharmony_ci    }
11241cb0ef41Sopenharmony_ci
11251cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, error);
11261cb0ef41Sopenharmony_ci  }
11271cb0ef41Sopenharmony_ci}
11281cb0ef41Sopenharmony_ci
11291cb0ef41Sopenharmony_ci
11301cb0ef41Sopenharmony_civoid fs__rmdir(uv_fs_t* req) {
11311cb0ef41Sopenharmony_ci  int result = _wrmdir(req->file.pathw);
11321cb0ef41Sopenharmony_ci  if (result == -1)
11331cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, _doserrno);
11341cb0ef41Sopenharmony_ci  else
11351cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
11361cb0ef41Sopenharmony_ci}
11371cb0ef41Sopenharmony_ci
11381cb0ef41Sopenharmony_ci
11391cb0ef41Sopenharmony_civoid fs__unlink(uv_fs_t* req) {
11401cb0ef41Sopenharmony_ci  const WCHAR* pathw = req->file.pathw;
11411cb0ef41Sopenharmony_ci  HANDLE handle;
11421cb0ef41Sopenharmony_ci  BY_HANDLE_FILE_INFORMATION info;
11431cb0ef41Sopenharmony_ci  FILE_DISPOSITION_INFORMATION disposition;
11441cb0ef41Sopenharmony_ci  IO_STATUS_BLOCK iosb;
11451cb0ef41Sopenharmony_ci  NTSTATUS status;
11461cb0ef41Sopenharmony_ci
11471cb0ef41Sopenharmony_ci  handle = CreateFileW(pathw,
11481cb0ef41Sopenharmony_ci                       FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE,
11491cb0ef41Sopenharmony_ci                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
11501cb0ef41Sopenharmony_ci                       NULL,
11511cb0ef41Sopenharmony_ci                       OPEN_EXISTING,
11521cb0ef41Sopenharmony_ci                       FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
11531cb0ef41Sopenharmony_ci                       NULL);
11541cb0ef41Sopenharmony_ci
11551cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE) {
11561cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
11571cb0ef41Sopenharmony_ci    return;
11581cb0ef41Sopenharmony_ci  }
11591cb0ef41Sopenharmony_ci
11601cb0ef41Sopenharmony_ci  if (!GetFileInformationByHandle(handle, &info)) {
11611cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
11621cb0ef41Sopenharmony_ci    CloseHandle(handle);
11631cb0ef41Sopenharmony_ci    return;
11641cb0ef41Sopenharmony_ci  }
11651cb0ef41Sopenharmony_ci
11661cb0ef41Sopenharmony_ci  if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
11671cb0ef41Sopenharmony_ci    /* Do not allow deletion of directories, unless it is a symlink. When the
11681cb0ef41Sopenharmony_ci     * path refers to a non-symlink directory, report EPERM as mandated by
11691cb0ef41Sopenharmony_ci     * POSIX.1. */
11701cb0ef41Sopenharmony_ci
11711cb0ef41Sopenharmony_ci    /* Check if it is a reparse point. If it's not, it's a normal directory. */
11721cb0ef41Sopenharmony_ci    if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
11731cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
11741cb0ef41Sopenharmony_ci      CloseHandle(handle);
11751cb0ef41Sopenharmony_ci      return;
11761cb0ef41Sopenharmony_ci    }
11771cb0ef41Sopenharmony_ci
11781cb0ef41Sopenharmony_ci    /* Read the reparse point and check if it is a valid symlink. If not, don't
11791cb0ef41Sopenharmony_ci     * unlink. */
11801cb0ef41Sopenharmony_ci    if (fs__readlink_handle(handle, NULL, NULL) < 0) {
11811cb0ef41Sopenharmony_ci      DWORD error = GetLastError();
11821cb0ef41Sopenharmony_ci      if (error == ERROR_SYMLINK_NOT_SUPPORTED)
11831cb0ef41Sopenharmony_ci        error = ERROR_ACCESS_DENIED;
11841cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, error);
11851cb0ef41Sopenharmony_ci      CloseHandle(handle);
11861cb0ef41Sopenharmony_ci      return;
11871cb0ef41Sopenharmony_ci    }
11881cb0ef41Sopenharmony_ci  }
11891cb0ef41Sopenharmony_ci
11901cb0ef41Sopenharmony_ci  if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
11911cb0ef41Sopenharmony_ci    /* Remove read-only attribute */
11921cb0ef41Sopenharmony_ci    FILE_BASIC_INFORMATION basic = { 0 };
11931cb0ef41Sopenharmony_ci
11941cb0ef41Sopenharmony_ci    basic.FileAttributes = (info.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY) |
11951cb0ef41Sopenharmony_ci                           FILE_ATTRIBUTE_ARCHIVE;
11961cb0ef41Sopenharmony_ci
11971cb0ef41Sopenharmony_ci    status = pNtSetInformationFile(handle,
11981cb0ef41Sopenharmony_ci                                   &iosb,
11991cb0ef41Sopenharmony_ci                                   &basic,
12001cb0ef41Sopenharmony_ci                                   sizeof basic,
12011cb0ef41Sopenharmony_ci                                   FileBasicInformation);
12021cb0ef41Sopenharmony_ci    if (!NT_SUCCESS(status)) {
12031cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
12041cb0ef41Sopenharmony_ci      CloseHandle(handle);
12051cb0ef41Sopenharmony_ci      return;
12061cb0ef41Sopenharmony_ci    }
12071cb0ef41Sopenharmony_ci  }
12081cb0ef41Sopenharmony_ci
12091cb0ef41Sopenharmony_ci  /* Try to set the delete flag. */
12101cb0ef41Sopenharmony_ci  disposition.DeleteFile = TRUE;
12111cb0ef41Sopenharmony_ci  status = pNtSetInformationFile(handle,
12121cb0ef41Sopenharmony_ci                                 &iosb,
12131cb0ef41Sopenharmony_ci                                 &disposition,
12141cb0ef41Sopenharmony_ci                                 sizeof disposition,
12151cb0ef41Sopenharmony_ci                                 FileDispositionInformation);
12161cb0ef41Sopenharmony_ci  if (NT_SUCCESS(status)) {
12171cb0ef41Sopenharmony_ci    SET_REQ_SUCCESS(req);
12181cb0ef41Sopenharmony_ci  } else {
12191cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
12201cb0ef41Sopenharmony_ci  }
12211cb0ef41Sopenharmony_ci
12221cb0ef41Sopenharmony_ci  CloseHandle(handle);
12231cb0ef41Sopenharmony_ci}
12241cb0ef41Sopenharmony_ci
12251cb0ef41Sopenharmony_ci
12261cb0ef41Sopenharmony_civoid fs__mkdir(uv_fs_t* req) {
12271cb0ef41Sopenharmony_ci  /* TODO: use req->mode. */
12281cb0ef41Sopenharmony_ci  if (CreateDirectoryW(req->file.pathw, NULL)) {
12291cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
12301cb0ef41Sopenharmony_ci  } else {
12311cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
12321cb0ef41Sopenharmony_ci    if (req->sys_errno_ == ERROR_INVALID_NAME ||
12331cb0ef41Sopenharmony_ci        req->sys_errno_ == ERROR_DIRECTORY)
12341cb0ef41Sopenharmony_ci      req->result = UV_EINVAL;
12351cb0ef41Sopenharmony_ci  }
12361cb0ef41Sopenharmony_ci}
12371cb0ef41Sopenharmony_ci
12381cb0ef41Sopenharmony_citypedef int (*uv__fs_mktemp_func)(uv_fs_t* req);
12391cb0ef41Sopenharmony_ci
12401cb0ef41Sopenharmony_ci/* OpenBSD original: lib/libc/stdio/mktemp.c */
12411cb0ef41Sopenharmony_civoid fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) {
12421cb0ef41Sopenharmony_ci  static const WCHAR *tempchars =
12431cb0ef41Sopenharmony_ci    L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
12441cb0ef41Sopenharmony_ci  static const size_t num_chars = 62;
12451cb0ef41Sopenharmony_ci  static const size_t num_x = 6;
12461cb0ef41Sopenharmony_ci  WCHAR *cp, *ep;
12471cb0ef41Sopenharmony_ci  unsigned int tries, i;
12481cb0ef41Sopenharmony_ci  size_t len;
12491cb0ef41Sopenharmony_ci  uint64_t v;
12501cb0ef41Sopenharmony_ci  char* path;
12511cb0ef41Sopenharmony_ci
12521cb0ef41Sopenharmony_ci  path = (char*)req->path;
12531cb0ef41Sopenharmony_ci  len = wcslen(req->file.pathw);
12541cb0ef41Sopenharmony_ci  ep = req->file.pathw + len;
12551cb0ef41Sopenharmony_ci  if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) {
12561cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
12571cb0ef41Sopenharmony_ci    goto clobber;
12581cb0ef41Sopenharmony_ci  }
12591cb0ef41Sopenharmony_ci
12601cb0ef41Sopenharmony_ci  tries = TMP_MAX;
12611cb0ef41Sopenharmony_ci  do {
12621cb0ef41Sopenharmony_ci    if (uv__random_rtlgenrandom((void *)&v, sizeof(v)) < 0) {
12631cb0ef41Sopenharmony_ci      SET_REQ_UV_ERROR(req, UV_EIO, ERROR_IO_DEVICE);
12641cb0ef41Sopenharmony_ci      goto clobber;
12651cb0ef41Sopenharmony_ci    }
12661cb0ef41Sopenharmony_ci
12671cb0ef41Sopenharmony_ci    cp = ep - num_x;
12681cb0ef41Sopenharmony_ci    for (i = 0; i < num_x; i++) {
12691cb0ef41Sopenharmony_ci      *cp++ = tempchars[v % num_chars];
12701cb0ef41Sopenharmony_ci      v /= num_chars;
12711cb0ef41Sopenharmony_ci    }
12721cb0ef41Sopenharmony_ci
12731cb0ef41Sopenharmony_ci    if (func(req)) {
12741cb0ef41Sopenharmony_ci      if (req->result >= 0) {
12751cb0ef41Sopenharmony_ci        len = strlen(path);
12761cb0ef41Sopenharmony_ci        wcstombs(path + len - num_x, ep - num_x, num_x);
12771cb0ef41Sopenharmony_ci      }
12781cb0ef41Sopenharmony_ci      return;
12791cb0ef41Sopenharmony_ci    }
12801cb0ef41Sopenharmony_ci  } while (--tries);
12811cb0ef41Sopenharmony_ci
12821cb0ef41Sopenharmony_ci  SET_REQ_WIN32_ERROR(req, GetLastError());
12831cb0ef41Sopenharmony_ci
12841cb0ef41Sopenharmony_ciclobber:
12851cb0ef41Sopenharmony_ci  path[0] = '\0';
12861cb0ef41Sopenharmony_ci}
12871cb0ef41Sopenharmony_ci
12881cb0ef41Sopenharmony_ci
12891cb0ef41Sopenharmony_cistatic int fs__mkdtemp_func(uv_fs_t* req) {
12901cb0ef41Sopenharmony_ci  DWORD error;
12911cb0ef41Sopenharmony_ci  if (CreateDirectoryW(req->file.pathw, NULL)) {
12921cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
12931cb0ef41Sopenharmony_ci    return 1;
12941cb0ef41Sopenharmony_ci  }
12951cb0ef41Sopenharmony_ci  error = GetLastError();
12961cb0ef41Sopenharmony_ci  if (error != ERROR_ALREADY_EXISTS) {
12971cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, error);
12981cb0ef41Sopenharmony_ci    return 1;
12991cb0ef41Sopenharmony_ci  }
13001cb0ef41Sopenharmony_ci
13011cb0ef41Sopenharmony_ci  return 0;
13021cb0ef41Sopenharmony_ci}
13031cb0ef41Sopenharmony_ci
13041cb0ef41Sopenharmony_ci
13051cb0ef41Sopenharmony_civoid fs__mkdtemp(uv_fs_t* req) {
13061cb0ef41Sopenharmony_ci  fs__mktemp(req, fs__mkdtemp_func);
13071cb0ef41Sopenharmony_ci}
13081cb0ef41Sopenharmony_ci
13091cb0ef41Sopenharmony_ci
13101cb0ef41Sopenharmony_cistatic int fs__mkstemp_func(uv_fs_t* req) {
13111cb0ef41Sopenharmony_ci  HANDLE file;
13121cb0ef41Sopenharmony_ci  int fd;
13131cb0ef41Sopenharmony_ci
13141cb0ef41Sopenharmony_ci  file = CreateFileW(req->file.pathw,
13151cb0ef41Sopenharmony_ci                     GENERIC_READ | GENERIC_WRITE,
13161cb0ef41Sopenharmony_ci                     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
13171cb0ef41Sopenharmony_ci                     NULL,
13181cb0ef41Sopenharmony_ci                     CREATE_NEW,
13191cb0ef41Sopenharmony_ci                     FILE_ATTRIBUTE_NORMAL,
13201cb0ef41Sopenharmony_ci                     NULL);
13211cb0ef41Sopenharmony_ci
13221cb0ef41Sopenharmony_ci  if (file == INVALID_HANDLE_VALUE) {
13231cb0ef41Sopenharmony_ci    DWORD error;
13241cb0ef41Sopenharmony_ci    error = GetLastError();
13251cb0ef41Sopenharmony_ci
13261cb0ef41Sopenharmony_ci    /* If the file exists, the main fs__mktemp() function
13271cb0ef41Sopenharmony_ci       will retry. If it's another error, we want to stop. */
13281cb0ef41Sopenharmony_ci    if (error != ERROR_FILE_EXISTS) {
13291cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, error);
13301cb0ef41Sopenharmony_ci      return 1;
13311cb0ef41Sopenharmony_ci    }
13321cb0ef41Sopenharmony_ci
13331cb0ef41Sopenharmony_ci    return 0;
13341cb0ef41Sopenharmony_ci  }
13351cb0ef41Sopenharmony_ci
13361cb0ef41Sopenharmony_ci  fd = _open_osfhandle((intptr_t) file, 0);
13371cb0ef41Sopenharmony_ci  if (fd < 0) {
13381cb0ef41Sopenharmony_ci    /* The only known failure mode for _open_osfhandle() is EMFILE, in which
13391cb0ef41Sopenharmony_ci     * case GetLastError() will return zero. However we'll try to handle other
13401cb0ef41Sopenharmony_ci     * errors as well, should they ever occur.
13411cb0ef41Sopenharmony_ci     */
13421cb0ef41Sopenharmony_ci    if (errno == EMFILE)
13431cb0ef41Sopenharmony_ci      SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES);
13441cb0ef41Sopenharmony_ci    else if (GetLastError() != ERROR_SUCCESS)
13451cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, GetLastError());
13461cb0ef41Sopenharmony_ci    else
13471cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, UV_UNKNOWN);
13481cb0ef41Sopenharmony_ci    CloseHandle(file);
13491cb0ef41Sopenharmony_ci    return 1;
13501cb0ef41Sopenharmony_ci  }
13511cb0ef41Sopenharmony_ci
13521cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, fd);
13531cb0ef41Sopenharmony_ci
13541cb0ef41Sopenharmony_ci  return 1;
13551cb0ef41Sopenharmony_ci}
13561cb0ef41Sopenharmony_ci
13571cb0ef41Sopenharmony_ci
13581cb0ef41Sopenharmony_civoid fs__mkstemp(uv_fs_t* req) {
13591cb0ef41Sopenharmony_ci  fs__mktemp(req, fs__mkstemp_func);
13601cb0ef41Sopenharmony_ci}
13611cb0ef41Sopenharmony_ci
13621cb0ef41Sopenharmony_ci
13631cb0ef41Sopenharmony_civoid fs__scandir(uv_fs_t* req) {
13641cb0ef41Sopenharmony_ci  static const size_t dirents_initial_size = 32;
13651cb0ef41Sopenharmony_ci
13661cb0ef41Sopenharmony_ci  HANDLE dir_handle = INVALID_HANDLE_VALUE;
13671cb0ef41Sopenharmony_ci
13681cb0ef41Sopenharmony_ci  uv__dirent_t** dirents = NULL;
13691cb0ef41Sopenharmony_ci  size_t dirents_size = 0;
13701cb0ef41Sopenharmony_ci  size_t dirents_used = 0;
13711cb0ef41Sopenharmony_ci
13721cb0ef41Sopenharmony_ci  IO_STATUS_BLOCK iosb;
13731cb0ef41Sopenharmony_ci  NTSTATUS status;
13741cb0ef41Sopenharmony_ci
13751cb0ef41Sopenharmony_ci  /* Buffer to hold directory entries returned by NtQueryDirectoryFile.
13761cb0ef41Sopenharmony_ci   * It's important that this buffer can hold at least one entry, regardless
13771cb0ef41Sopenharmony_ci   * of the length of the file names present in the enumerated directory.
13781cb0ef41Sopenharmony_ci   * A file name is at most 256 WCHARs long.
13791cb0ef41Sopenharmony_ci   * According to MSDN, the buffer must be aligned at an 8-byte boundary.
13801cb0ef41Sopenharmony_ci   */
13811cb0ef41Sopenharmony_ci#if _MSC_VER
13821cb0ef41Sopenharmony_ci  __declspec(align(8)) char buffer[8192];
13831cb0ef41Sopenharmony_ci#else
13841cb0ef41Sopenharmony_ci  __attribute__ ((aligned (8))) char buffer[8192];
13851cb0ef41Sopenharmony_ci#endif
13861cb0ef41Sopenharmony_ci
13871cb0ef41Sopenharmony_ci  STATIC_ASSERT(sizeof buffer >=
13881cb0ef41Sopenharmony_ci                sizeof(FILE_DIRECTORY_INFORMATION) + 256 * sizeof(WCHAR));
13891cb0ef41Sopenharmony_ci
13901cb0ef41Sopenharmony_ci  /* Open the directory. */
13911cb0ef41Sopenharmony_ci  dir_handle =
13921cb0ef41Sopenharmony_ci      CreateFileW(req->file.pathw,
13931cb0ef41Sopenharmony_ci                  FILE_LIST_DIRECTORY | SYNCHRONIZE,
13941cb0ef41Sopenharmony_ci                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
13951cb0ef41Sopenharmony_ci                  NULL,
13961cb0ef41Sopenharmony_ci                  OPEN_EXISTING,
13971cb0ef41Sopenharmony_ci                  FILE_FLAG_BACKUP_SEMANTICS,
13981cb0ef41Sopenharmony_ci                  NULL);
13991cb0ef41Sopenharmony_ci  if (dir_handle == INVALID_HANDLE_VALUE)
14001cb0ef41Sopenharmony_ci    goto win32_error;
14011cb0ef41Sopenharmony_ci
14021cb0ef41Sopenharmony_ci  /* Read the first chunk. */
14031cb0ef41Sopenharmony_ci  status = pNtQueryDirectoryFile(dir_handle,
14041cb0ef41Sopenharmony_ci                                 NULL,
14051cb0ef41Sopenharmony_ci                                 NULL,
14061cb0ef41Sopenharmony_ci                                 NULL,
14071cb0ef41Sopenharmony_ci                                 &iosb,
14081cb0ef41Sopenharmony_ci                                 &buffer,
14091cb0ef41Sopenharmony_ci                                 sizeof buffer,
14101cb0ef41Sopenharmony_ci                                 FileDirectoryInformation,
14111cb0ef41Sopenharmony_ci                                 FALSE,
14121cb0ef41Sopenharmony_ci                                 NULL,
14131cb0ef41Sopenharmony_ci                                 TRUE);
14141cb0ef41Sopenharmony_ci
14151cb0ef41Sopenharmony_ci  /* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER.
14161cb0ef41Sopenharmony_ci   * This should be reported back as UV_ENOTDIR.
14171cb0ef41Sopenharmony_ci   */
14181cb0ef41Sopenharmony_ci  if (status == (NTSTATUS)STATUS_INVALID_PARAMETER)
14191cb0ef41Sopenharmony_ci    goto not_a_directory_error;
14201cb0ef41Sopenharmony_ci
14211cb0ef41Sopenharmony_ci  while (NT_SUCCESS(status)) {
14221cb0ef41Sopenharmony_ci    char* position = buffer;
14231cb0ef41Sopenharmony_ci    size_t next_entry_offset = 0;
14241cb0ef41Sopenharmony_ci
14251cb0ef41Sopenharmony_ci    do {
14261cb0ef41Sopenharmony_ci      FILE_DIRECTORY_INFORMATION* info;
14271cb0ef41Sopenharmony_ci      uv__dirent_t* dirent;
14281cb0ef41Sopenharmony_ci
14291cb0ef41Sopenharmony_ci      size_t wchar_len;
14301cb0ef41Sopenharmony_ci      size_t utf8_len;
14311cb0ef41Sopenharmony_ci
14321cb0ef41Sopenharmony_ci      /* Obtain a pointer to the current directory entry. */
14331cb0ef41Sopenharmony_ci      position += next_entry_offset;
14341cb0ef41Sopenharmony_ci      info = (FILE_DIRECTORY_INFORMATION*) position;
14351cb0ef41Sopenharmony_ci
14361cb0ef41Sopenharmony_ci      /* Fetch the offset to the next directory entry. */
14371cb0ef41Sopenharmony_ci      next_entry_offset = info->NextEntryOffset;
14381cb0ef41Sopenharmony_ci
14391cb0ef41Sopenharmony_ci      /* Compute the length of the filename in WCHARs. */
14401cb0ef41Sopenharmony_ci      wchar_len = info->FileNameLength / sizeof info->FileName[0];
14411cb0ef41Sopenharmony_ci
14421cb0ef41Sopenharmony_ci      /* Skip over '.' and '..' entries.  It has been reported that
14431cb0ef41Sopenharmony_ci       * the SharePoint driver includes the terminating zero byte in
14441cb0ef41Sopenharmony_ci       * the filename length.  Strip those first.
14451cb0ef41Sopenharmony_ci       */
14461cb0ef41Sopenharmony_ci      while (wchar_len > 0 && info->FileName[wchar_len - 1] == L'\0')
14471cb0ef41Sopenharmony_ci        wchar_len -= 1;
14481cb0ef41Sopenharmony_ci
14491cb0ef41Sopenharmony_ci      if (wchar_len == 0)
14501cb0ef41Sopenharmony_ci        continue;
14511cb0ef41Sopenharmony_ci      if (wchar_len == 1 && info->FileName[0] == L'.')
14521cb0ef41Sopenharmony_ci        continue;
14531cb0ef41Sopenharmony_ci      if (wchar_len == 2 && info->FileName[0] == L'.' &&
14541cb0ef41Sopenharmony_ci          info->FileName[1] == L'.')
14551cb0ef41Sopenharmony_ci        continue;
14561cb0ef41Sopenharmony_ci
14571cb0ef41Sopenharmony_ci      /* Compute the space required to store the filename as UTF-8. */
14581cb0ef41Sopenharmony_ci      utf8_len = WideCharToMultiByte(
14591cb0ef41Sopenharmony_ci          CP_UTF8, 0, &info->FileName[0], wchar_len, NULL, 0, NULL, NULL);
14601cb0ef41Sopenharmony_ci      if (utf8_len == 0)
14611cb0ef41Sopenharmony_ci        goto win32_error;
14621cb0ef41Sopenharmony_ci
14631cb0ef41Sopenharmony_ci      /* Resize the dirent array if needed. */
14641cb0ef41Sopenharmony_ci      if (dirents_used >= dirents_size) {
14651cb0ef41Sopenharmony_ci        size_t new_dirents_size =
14661cb0ef41Sopenharmony_ci            dirents_size == 0 ? dirents_initial_size : dirents_size << 1;
14671cb0ef41Sopenharmony_ci        uv__dirent_t** new_dirents =
14681cb0ef41Sopenharmony_ci            uv__realloc(dirents, new_dirents_size * sizeof *dirents);
14691cb0ef41Sopenharmony_ci
14701cb0ef41Sopenharmony_ci        if (new_dirents == NULL)
14711cb0ef41Sopenharmony_ci          goto out_of_memory_error;
14721cb0ef41Sopenharmony_ci
14731cb0ef41Sopenharmony_ci        dirents_size = new_dirents_size;
14741cb0ef41Sopenharmony_ci        dirents = new_dirents;
14751cb0ef41Sopenharmony_ci      }
14761cb0ef41Sopenharmony_ci
14771cb0ef41Sopenharmony_ci      /* Allocate space for the uv dirent structure. The dirent structure
14781cb0ef41Sopenharmony_ci       * includes room for the first character of the filename, but `utf8_len`
14791cb0ef41Sopenharmony_ci       * doesn't count the NULL terminator at this point.
14801cb0ef41Sopenharmony_ci       */
14811cb0ef41Sopenharmony_ci      dirent = uv__malloc(sizeof *dirent + utf8_len);
14821cb0ef41Sopenharmony_ci      if (dirent == NULL)
14831cb0ef41Sopenharmony_ci        goto out_of_memory_error;
14841cb0ef41Sopenharmony_ci
14851cb0ef41Sopenharmony_ci      dirents[dirents_used++] = dirent;
14861cb0ef41Sopenharmony_ci
14871cb0ef41Sopenharmony_ci      /* Convert file name to UTF-8. */
14881cb0ef41Sopenharmony_ci      if (WideCharToMultiByte(CP_UTF8,
14891cb0ef41Sopenharmony_ci                              0,
14901cb0ef41Sopenharmony_ci                              &info->FileName[0],
14911cb0ef41Sopenharmony_ci                              wchar_len,
14921cb0ef41Sopenharmony_ci                              &dirent->d_name[0],
14931cb0ef41Sopenharmony_ci                              utf8_len,
14941cb0ef41Sopenharmony_ci                              NULL,
14951cb0ef41Sopenharmony_ci                              NULL) == 0)
14961cb0ef41Sopenharmony_ci        goto win32_error;
14971cb0ef41Sopenharmony_ci
14981cb0ef41Sopenharmony_ci      /* Add a null terminator to the filename. */
14991cb0ef41Sopenharmony_ci      dirent->d_name[utf8_len] = '\0';
15001cb0ef41Sopenharmony_ci
15011cb0ef41Sopenharmony_ci      /* Fill out the type field. */
15021cb0ef41Sopenharmony_ci      if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE)
15031cb0ef41Sopenharmony_ci        dirent->d_type = UV__DT_CHAR;
15041cb0ef41Sopenharmony_ci      else if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
15051cb0ef41Sopenharmony_ci        dirent->d_type = UV__DT_LINK;
15061cb0ef41Sopenharmony_ci      else if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
15071cb0ef41Sopenharmony_ci        dirent->d_type = UV__DT_DIR;
15081cb0ef41Sopenharmony_ci      else
15091cb0ef41Sopenharmony_ci        dirent->d_type = UV__DT_FILE;
15101cb0ef41Sopenharmony_ci    } while (next_entry_offset != 0);
15111cb0ef41Sopenharmony_ci
15121cb0ef41Sopenharmony_ci    /* Read the next chunk. */
15131cb0ef41Sopenharmony_ci    status = pNtQueryDirectoryFile(dir_handle,
15141cb0ef41Sopenharmony_ci                                   NULL,
15151cb0ef41Sopenharmony_ci                                   NULL,
15161cb0ef41Sopenharmony_ci                                   NULL,
15171cb0ef41Sopenharmony_ci                                   &iosb,
15181cb0ef41Sopenharmony_ci                                   &buffer,
15191cb0ef41Sopenharmony_ci                                   sizeof buffer,
15201cb0ef41Sopenharmony_ci                                   FileDirectoryInformation,
15211cb0ef41Sopenharmony_ci                                   FALSE,
15221cb0ef41Sopenharmony_ci                                   NULL,
15231cb0ef41Sopenharmony_ci                                   FALSE);
15241cb0ef41Sopenharmony_ci
15251cb0ef41Sopenharmony_ci    /* After the first pNtQueryDirectoryFile call, the function may return
15261cb0ef41Sopenharmony_ci     * STATUS_SUCCESS even if the buffer was too small to hold at least one
15271cb0ef41Sopenharmony_ci     * directory entry.
15281cb0ef41Sopenharmony_ci     */
15291cb0ef41Sopenharmony_ci    if (status == STATUS_SUCCESS && iosb.Information == 0)
15301cb0ef41Sopenharmony_ci      status = STATUS_BUFFER_OVERFLOW;
15311cb0ef41Sopenharmony_ci  }
15321cb0ef41Sopenharmony_ci
15331cb0ef41Sopenharmony_ci  if (status != STATUS_NO_MORE_FILES)
15341cb0ef41Sopenharmony_ci    goto nt_error;
15351cb0ef41Sopenharmony_ci
15361cb0ef41Sopenharmony_ci  CloseHandle(dir_handle);
15371cb0ef41Sopenharmony_ci
15381cb0ef41Sopenharmony_ci  /* Store the result in the request object. */
15391cb0ef41Sopenharmony_ci  req->ptr = dirents;
15401cb0ef41Sopenharmony_ci  if (dirents != NULL)
15411cb0ef41Sopenharmony_ci    req->flags |= UV_FS_FREE_PTR;
15421cb0ef41Sopenharmony_ci
15431cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, dirents_used);
15441cb0ef41Sopenharmony_ci
15451cb0ef41Sopenharmony_ci  /* `nbufs` will be used as index by uv_fs_scandir_next. */
15461cb0ef41Sopenharmony_ci  req->fs.info.nbufs = 0;
15471cb0ef41Sopenharmony_ci
15481cb0ef41Sopenharmony_ci  return;
15491cb0ef41Sopenharmony_ci
15501cb0ef41Sopenharmony_cint_error:
15511cb0ef41Sopenharmony_ci  SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
15521cb0ef41Sopenharmony_ci  goto cleanup;
15531cb0ef41Sopenharmony_ci
15541cb0ef41Sopenharmony_ciwin32_error:
15551cb0ef41Sopenharmony_ci  SET_REQ_WIN32_ERROR(req, GetLastError());
15561cb0ef41Sopenharmony_ci  goto cleanup;
15571cb0ef41Sopenharmony_ci
15581cb0ef41Sopenharmony_cinot_a_directory_error:
15591cb0ef41Sopenharmony_ci  SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
15601cb0ef41Sopenharmony_ci  goto cleanup;
15611cb0ef41Sopenharmony_ci
15621cb0ef41Sopenharmony_ciout_of_memory_error:
15631cb0ef41Sopenharmony_ci  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
15641cb0ef41Sopenharmony_ci  goto cleanup;
15651cb0ef41Sopenharmony_ci
15661cb0ef41Sopenharmony_cicleanup:
15671cb0ef41Sopenharmony_ci  if (dir_handle != INVALID_HANDLE_VALUE)
15681cb0ef41Sopenharmony_ci    CloseHandle(dir_handle);
15691cb0ef41Sopenharmony_ci  while (dirents_used > 0)
15701cb0ef41Sopenharmony_ci    uv__free(dirents[--dirents_used]);
15711cb0ef41Sopenharmony_ci  if (dirents != NULL)
15721cb0ef41Sopenharmony_ci    uv__free(dirents);
15731cb0ef41Sopenharmony_ci}
15741cb0ef41Sopenharmony_ci
15751cb0ef41Sopenharmony_civoid fs__opendir(uv_fs_t* req) {
15761cb0ef41Sopenharmony_ci  WCHAR* pathw;
15771cb0ef41Sopenharmony_ci  size_t len;
15781cb0ef41Sopenharmony_ci  const WCHAR* fmt;
15791cb0ef41Sopenharmony_ci  WCHAR* find_path;
15801cb0ef41Sopenharmony_ci  uv_dir_t* dir;
15811cb0ef41Sopenharmony_ci
15821cb0ef41Sopenharmony_ci  pathw = req->file.pathw;
15831cb0ef41Sopenharmony_ci  dir = NULL;
15841cb0ef41Sopenharmony_ci  find_path = NULL;
15851cb0ef41Sopenharmony_ci
15861cb0ef41Sopenharmony_ci  /* Figure out whether path is a file or a directory. */
15871cb0ef41Sopenharmony_ci  if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) {
15881cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
15891cb0ef41Sopenharmony_ci    goto error;
15901cb0ef41Sopenharmony_ci  }
15911cb0ef41Sopenharmony_ci
15921cb0ef41Sopenharmony_ci  dir = uv__malloc(sizeof(*dir));
15931cb0ef41Sopenharmony_ci  if (dir == NULL) {
15941cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
15951cb0ef41Sopenharmony_ci    goto error;
15961cb0ef41Sopenharmony_ci  }
15971cb0ef41Sopenharmony_ci
15981cb0ef41Sopenharmony_ci  len = wcslen(pathw);
15991cb0ef41Sopenharmony_ci
16001cb0ef41Sopenharmony_ci  if (len == 0)
16011cb0ef41Sopenharmony_ci    fmt = L"./*";
16021cb0ef41Sopenharmony_ci  else if (IS_SLASH(pathw[len - 1]))
16031cb0ef41Sopenharmony_ci    fmt = L"%s*";
16041cb0ef41Sopenharmony_ci  else
16051cb0ef41Sopenharmony_ci    fmt = L"%s\\*";
16061cb0ef41Sopenharmony_ci
16071cb0ef41Sopenharmony_ci  find_path = uv__malloc(sizeof(WCHAR) * (len + 4));
16081cb0ef41Sopenharmony_ci  if (find_path == NULL) {
16091cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
16101cb0ef41Sopenharmony_ci    goto error;
16111cb0ef41Sopenharmony_ci  }
16121cb0ef41Sopenharmony_ci
16131cb0ef41Sopenharmony_ci  _snwprintf(find_path, len + 3, fmt, pathw);
16141cb0ef41Sopenharmony_ci  dir->dir_handle = FindFirstFileW(find_path, &dir->find_data);
16151cb0ef41Sopenharmony_ci  uv__free(find_path);
16161cb0ef41Sopenharmony_ci  find_path = NULL;
16171cb0ef41Sopenharmony_ci  if (dir->dir_handle == INVALID_HANDLE_VALUE &&
16181cb0ef41Sopenharmony_ci      GetLastError() != ERROR_FILE_NOT_FOUND) {
16191cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
16201cb0ef41Sopenharmony_ci    goto error;
16211cb0ef41Sopenharmony_ci  }
16221cb0ef41Sopenharmony_ci
16231cb0ef41Sopenharmony_ci  dir->need_find_call = FALSE;
16241cb0ef41Sopenharmony_ci  req->ptr = dir;
16251cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
16261cb0ef41Sopenharmony_ci  return;
16271cb0ef41Sopenharmony_ci
16281cb0ef41Sopenharmony_cierror:
16291cb0ef41Sopenharmony_ci  uv__free(dir);
16301cb0ef41Sopenharmony_ci  uv__free(find_path);
16311cb0ef41Sopenharmony_ci  req->ptr = NULL;
16321cb0ef41Sopenharmony_ci}
16331cb0ef41Sopenharmony_ci
16341cb0ef41Sopenharmony_civoid fs__readdir(uv_fs_t* req) {
16351cb0ef41Sopenharmony_ci  uv_dir_t* dir;
16361cb0ef41Sopenharmony_ci  uv_dirent_t* dirents;
16371cb0ef41Sopenharmony_ci  uv__dirent_t dent;
16381cb0ef41Sopenharmony_ci  unsigned int dirent_idx;
16391cb0ef41Sopenharmony_ci  PWIN32_FIND_DATAW find_data;
16401cb0ef41Sopenharmony_ci  unsigned int i;
16411cb0ef41Sopenharmony_ci  int r;
16421cb0ef41Sopenharmony_ci
16431cb0ef41Sopenharmony_ci  req->flags |= UV_FS_FREE_PTR;
16441cb0ef41Sopenharmony_ci  dir = req->ptr;
16451cb0ef41Sopenharmony_ci  dirents = dir->dirents;
16461cb0ef41Sopenharmony_ci  memset(dirents, 0, dir->nentries * sizeof(*dir->dirents));
16471cb0ef41Sopenharmony_ci  find_data = &dir->find_data;
16481cb0ef41Sopenharmony_ci  dirent_idx = 0;
16491cb0ef41Sopenharmony_ci
16501cb0ef41Sopenharmony_ci  while (dirent_idx < dir->nentries) {
16511cb0ef41Sopenharmony_ci    if (dir->need_find_call && FindNextFileW(dir->dir_handle, find_data) == 0) {
16521cb0ef41Sopenharmony_ci      if (GetLastError() == ERROR_NO_MORE_FILES)
16531cb0ef41Sopenharmony_ci        break;
16541cb0ef41Sopenharmony_ci      goto error;
16551cb0ef41Sopenharmony_ci    }
16561cb0ef41Sopenharmony_ci
16571cb0ef41Sopenharmony_ci    /* Skip "." and ".." entries. */
16581cb0ef41Sopenharmony_ci    if (find_data->cFileName[0] == L'.' &&
16591cb0ef41Sopenharmony_ci        (find_data->cFileName[1] == L'\0' ||
16601cb0ef41Sopenharmony_ci        (find_data->cFileName[1] == L'.' &&
16611cb0ef41Sopenharmony_ci        find_data->cFileName[2] == L'\0'))) {
16621cb0ef41Sopenharmony_ci      dir->need_find_call = TRUE;
16631cb0ef41Sopenharmony_ci      continue;
16641cb0ef41Sopenharmony_ci    }
16651cb0ef41Sopenharmony_ci
16661cb0ef41Sopenharmony_ci    r = uv__convert_utf16_to_utf8((const WCHAR*) &find_data->cFileName,
16671cb0ef41Sopenharmony_ci                                  -1,
16681cb0ef41Sopenharmony_ci                                  (char**) &dirents[dirent_idx].name);
16691cb0ef41Sopenharmony_ci    if (r != 0)
16701cb0ef41Sopenharmony_ci      goto error;
16711cb0ef41Sopenharmony_ci
16721cb0ef41Sopenharmony_ci    /* Copy file type. */
16731cb0ef41Sopenharmony_ci    if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
16741cb0ef41Sopenharmony_ci      dent.d_type = UV__DT_DIR;
16751cb0ef41Sopenharmony_ci    else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
16761cb0ef41Sopenharmony_ci      dent.d_type = UV__DT_LINK;
16771cb0ef41Sopenharmony_ci    else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0)
16781cb0ef41Sopenharmony_ci      dent.d_type = UV__DT_CHAR;
16791cb0ef41Sopenharmony_ci    else
16801cb0ef41Sopenharmony_ci      dent.d_type = UV__DT_FILE;
16811cb0ef41Sopenharmony_ci
16821cb0ef41Sopenharmony_ci    dirents[dirent_idx].type = uv__fs_get_dirent_type(&dent);
16831cb0ef41Sopenharmony_ci    dir->need_find_call = TRUE;
16841cb0ef41Sopenharmony_ci    ++dirent_idx;
16851cb0ef41Sopenharmony_ci  }
16861cb0ef41Sopenharmony_ci
16871cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, dirent_idx);
16881cb0ef41Sopenharmony_ci  return;
16891cb0ef41Sopenharmony_ci
16901cb0ef41Sopenharmony_cierror:
16911cb0ef41Sopenharmony_ci  SET_REQ_WIN32_ERROR(req, GetLastError());
16921cb0ef41Sopenharmony_ci  for (i = 0; i < dirent_idx; ++i) {
16931cb0ef41Sopenharmony_ci    uv__free((char*) dirents[i].name);
16941cb0ef41Sopenharmony_ci    dirents[i].name = NULL;
16951cb0ef41Sopenharmony_ci  }
16961cb0ef41Sopenharmony_ci}
16971cb0ef41Sopenharmony_ci
16981cb0ef41Sopenharmony_civoid fs__closedir(uv_fs_t* req) {
16991cb0ef41Sopenharmony_ci  uv_dir_t* dir;
17001cb0ef41Sopenharmony_ci
17011cb0ef41Sopenharmony_ci  dir = req->ptr;
17021cb0ef41Sopenharmony_ci  FindClose(dir->dir_handle);
17031cb0ef41Sopenharmony_ci  uv__free(req->ptr);
17041cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
17051cb0ef41Sopenharmony_ci}
17061cb0ef41Sopenharmony_ci
17071cb0ef41Sopenharmony_ciINLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
17081cb0ef41Sopenharmony_ci    int do_lstat) {
17091cb0ef41Sopenharmony_ci  FILE_ALL_INFORMATION file_info;
17101cb0ef41Sopenharmony_ci  FILE_FS_VOLUME_INFORMATION volume_info;
17111cb0ef41Sopenharmony_ci  NTSTATUS nt_status;
17121cb0ef41Sopenharmony_ci  IO_STATUS_BLOCK io_status;
17131cb0ef41Sopenharmony_ci
17141cb0ef41Sopenharmony_ci  nt_status = pNtQueryInformationFile(handle,
17151cb0ef41Sopenharmony_ci                                      &io_status,
17161cb0ef41Sopenharmony_ci                                      &file_info,
17171cb0ef41Sopenharmony_ci                                      sizeof file_info,
17181cb0ef41Sopenharmony_ci                                      FileAllInformation);
17191cb0ef41Sopenharmony_ci
17201cb0ef41Sopenharmony_ci  /* Buffer overflow (a warning status code) is expected here. */
17211cb0ef41Sopenharmony_ci  if (NT_ERROR(nt_status)) {
17221cb0ef41Sopenharmony_ci    SetLastError(pRtlNtStatusToDosError(nt_status));
17231cb0ef41Sopenharmony_ci    return -1;
17241cb0ef41Sopenharmony_ci  }
17251cb0ef41Sopenharmony_ci
17261cb0ef41Sopenharmony_ci  nt_status = pNtQueryVolumeInformationFile(handle,
17271cb0ef41Sopenharmony_ci                                            &io_status,
17281cb0ef41Sopenharmony_ci                                            &volume_info,
17291cb0ef41Sopenharmony_ci                                            sizeof volume_info,
17301cb0ef41Sopenharmony_ci                                            FileFsVolumeInformation);
17311cb0ef41Sopenharmony_ci
17321cb0ef41Sopenharmony_ci  /* Buffer overflow (a warning status code) is expected here. */
17331cb0ef41Sopenharmony_ci  if (io_status.Status == STATUS_NOT_IMPLEMENTED) {
17341cb0ef41Sopenharmony_ci    statbuf->st_dev = 0;
17351cb0ef41Sopenharmony_ci  } else if (NT_ERROR(nt_status)) {
17361cb0ef41Sopenharmony_ci    SetLastError(pRtlNtStatusToDosError(nt_status));
17371cb0ef41Sopenharmony_ci    return -1;
17381cb0ef41Sopenharmony_ci  } else {
17391cb0ef41Sopenharmony_ci    statbuf->st_dev = volume_info.VolumeSerialNumber;
17401cb0ef41Sopenharmony_ci  }
17411cb0ef41Sopenharmony_ci
17421cb0ef41Sopenharmony_ci  /* Todo: st_mode should probably always be 0666 for everyone. We might also
17431cb0ef41Sopenharmony_ci   * want to report 0777 if the file is a .exe or a directory.
17441cb0ef41Sopenharmony_ci   *
17451cb0ef41Sopenharmony_ci   * Currently it's based on whether the 'readonly' attribute is set, which
17461cb0ef41Sopenharmony_ci   * makes little sense because the semantics are so different: the 'read-only'
17471cb0ef41Sopenharmony_ci   * flag is just a way for a user to protect against accidental deletion, and
17481cb0ef41Sopenharmony_ci   * serves no security purpose. Windows uses ACLs for that.
17491cb0ef41Sopenharmony_ci   *
17501cb0ef41Sopenharmony_ci   * Also people now use uv_fs_chmod() to take away the writable bit for good
17511cb0ef41Sopenharmony_ci   * reasons. Windows however just makes the file read-only, which makes it
17521cb0ef41Sopenharmony_ci   * impossible to delete the file afterwards, since read-only files can't be
17531cb0ef41Sopenharmony_ci   * deleted.
17541cb0ef41Sopenharmony_ci   *
17551cb0ef41Sopenharmony_ci   * IOW it's all just a clusterfuck and we should think of something that
17561cb0ef41Sopenharmony_ci   * makes slightly more sense.
17571cb0ef41Sopenharmony_ci   *
17581cb0ef41Sopenharmony_ci   * And uv_fs_chmod should probably just fail on windows or be a total no-op.
17591cb0ef41Sopenharmony_ci   * There's nothing sensible it can do anyway.
17601cb0ef41Sopenharmony_ci   */
17611cb0ef41Sopenharmony_ci  statbuf->st_mode = 0;
17621cb0ef41Sopenharmony_ci
17631cb0ef41Sopenharmony_ci  /*
17641cb0ef41Sopenharmony_ci  * On Windows, FILE_ATTRIBUTE_REPARSE_POINT is a general purpose mechanism
17651cb0ef41Sopenharmony_ci  * by which filesystem drivers can intercept and alter file system requests.
17661cb0ef41Sopenharmony_ci  *
17671cb0ef41Sopenharmony_ci  * The only reparse points we care about are symlinks and mount points, both
17681cb0ef41Sopenharmony_ci  * of which are treated as POSIX symlinks. Further, we only care when
17691cb0ef41Sopenharmony_ci  * invoked via lstat, which seeks information about the link instead of its
17701cb0ef41Sopenharmony_ci  * target. Otherwise, reparse points must be treated as regular files.
17711cb0ef41Sopenharmony_ci  */
17721cb0ef41Sopenharmony_ci  if (do_lstat &&
17731cb0ef41Sopenharmony_ci      (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
17741cb0ef41Sopenharmony_ci    /*
17751cb0ef41Sopenharmony_ci     * If reading the link fails, the reparse point is not a symlink and needs
17761cb0ef41Sopenharmony_ci     * to be treated as a regular file. The higher level lstat function will
17771cb0ef41Sopenharmony_ci     * detect this failure and retry without do_lstat if appropriate.
17781cb0ef41Sopenharmony_ci     */
17791cb0ef41Sopenharmony_ci    if (fs__readlink_handle(handle, NULL, &statbuf->st_size) != 0)
17801cb0ef41Sopenharmony_ci      return -1;
17811cb0ef41Sopenharmony_ci    statbuf->st_mode |= S_IFLNK;
17821cb0ef41Sopenharmony_ci  }
17831cb0ef41Sopenharmony_ci
17841cb0ef41Sopenharmony_ci  if (statbuf->st_mode == 0) {
17851cb0ef41Sopenharmony_ci    if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
17861cb0ef41Sopenharmony_ci      statbuf->st_mode |= _S_IFDIR;
17871cb0ef41Sopenharmony_ci      statbuf->st_size = 0;
17881cb0ef41Sopenharmony_ci    } else {
17891cb0ef41Sopenharmony_ci      statbuf->st_mode |= _S_IFREG;
17901cb0ef41Sopenharmony_ci      statbuf->st_size = file_info.StandardInformation.EndOfFile.QuadPart;
17911cb0ef41Sopenharmony_ci    }
17921cb0ef41Sopenharmony_ci  }
17931cb0ef41Sopenharmony_ci
17941cb0ef41Sopenharmony_ci  if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY)
17951cb0ef41Sopenharmony_ci    statbuf->st_mode |= _S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6);
17961cb0ef41Sopenharmony_ci  else
17971cb0ef41Sopenharmony_ci    statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) |
17981cb0ef41Sopenharmony_ci                        ((_S_IREAD | _S_IWRITE) >> 6);
17991cb0ef41Sopenharmony_ci
18001cb0ef41Sopenharmony_ci  uv__filetime_to_timespec(&statbuf->st_atim,
18011cb0ef41Sopenharmony_ci                           file_info.BasicInformation.LastAccessTime.QuadPart);
18021cb0ef41Sopenharmony_ci  uv__filetime_to_timespec(&statbuf->st_ctim,
18031cb0ef41Sopenharmony_ci                           file_info.BasicInformation.ChangeTime.QuadPart);
18041cb0ef41Sopenharmony_ci  uv__filetime_to_timespec(&statbuf->st_mtim,
18051cb0ef41Sopenharmony_ci                           file_info.BasicInformation.LastWriteTime.QuadPart);
18061cb0ef41Sopenharmony_ci  uv__filetime_to_timespec(&statbuf->st_birthtim,
18071cb0ef41Sopenharmony_ci                           file_info.BasicInformation.CreationTime.QuadPart);
18081cb0ef41Sopenharmony_ci
18091cb0ef41Sopenharmony_ci  statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart;
18101cb0ef41Sopenharmony_ci
18111cb0ef41Sopenharmony_ci  /* st_blocks contains the on-disk allocation size in 512-byte units. */
18121cb0ef41Sopenharmony_ci  statbuf->st_blocks =
18131cb0ef41Sopenharmony_ci      (uint64_t) file_info.StandardInformation.AllocationSize.QuadPart >> 9;
18141cb0ef41Sopenharmony_ci
18151cb0ef41Sopenharmony_ci  statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks;
18161cb0ef41Sopenharmony_ci
18171cb0ef41Sopenharmony_ci  /* The st_blksize is supposed to be the 'optimal' number of bytes for reading
18181cb0ef41Sopenharmony_ci   * and writing to the disk. That is, for any definition of 'optimal' - it's
18191cb0ef41Sopenharmony_ci   * supposed to at least avoid read-update-write behavior when writing to the
18201cb0ef41Sopenharmony_ci   * disk.
18211cb0ef41Sopenharmony_ci   *
18221cb0ef41Sopenharmony_ci   * However nobody knows this and even fewer people actually use this value,
18231cb0ef41Sopenharmony_ci   * and in order to fill it out we'd have to make another syscall to query the
18241cb0ef41Sopenharmony_ci   * volume for FILE_FS_SECTOR_SIZE_INFORMATION.
18251cb0ef41Sopenharmony_ci   *
18261cb0ef41Sopenharmony_ci   * Therefore we'll just report a sensible value that's quite commonly okay
18271cb0ef41Sopenharmony_ci   * on modern hardware.
18281cb0ef41Sopenharmony_ci   *
18291cb0ef41Sopenharmony_ci   * 4096 is the minimum required to be compatible with newer Advanced Format
18301cb0ef41Sopenharmony_ci   * drives (which have 4096 bytes per physical sector), and to be backwards
18311cb0ef41Sopenharmony_ci   * compatible with older drives (which have 512 bytes per physical sector).
18321cb0ef41Sopenharmony_ci   */
18331cb0ef41Sopenharmony_ci  statbuf->st_blksize = 4096;
18341cb0ef41Sopenharmony_ci
18351cb0ef41Sopenharmony_ci  /* Todo: set st_flags to something meaningful. Also provide a wrapper for
18361cb0ef41Sopenharmony_ci   * chattr(2).
18371cb0ef41Sopenharmony_ci   */
18381cb0ef41Sopenharmony_ci  statbuf->st_flags = 0;
18391cb0ef41Sopenharmony_ci
18401cb0ef41Sopenharmony_ci  /* Windows has nothing sensible to say about these values, so they'll just
18411cb0ef41Sopenharmony_ci   * remain empty.
18421cb0ef41Sopenharmony_ci   */
18431cb0ef41Sopenharmony_ci  statbuf->st_gid = 0;
18441cb0ef41Sopenharmony_ci  statbuf->st_uid = 0;
18451cb0ef41Sopenharmony_ci  statbuf->st_rdev = 0;
18461cb0ef41Sopenharmony_ci  statbuf->st_gen = 0;
18471cb0ef41Sopenharmony_ci
18481cb0ef41Sopenharmony_ci  return 0;
18491cb0ef41Sopenharmony_ci}
18501cb0ef41Sopenharmony_ci
18511cb0ef41Sopenharmony_ci
18521cb0ef41Sopenharmony_ciINLINE static void fs__stat_prepare_path(WCHAR* pathw) {
18531cb0ef41Sopenharmony_ci  size_t len = wcslen(pathw);
18541cb0ef41Sopenharmony_ci
18551cb0ef41Sopenharmony_ci  /* TODO: ignore namespaced paths. */
18561cb0ef41Sopenharmony_ci  if (len > 1 && pathw[len - 2] != L':' &&
18571cb0ef41Sopenharmony_ci      (pathw[len - 1] == L'\\' || pathw[len - 1] == L'/')) {
18581cb0ef41Sopenharmony_ci    pathw[len - 1] = '\0';
18591cb0ef41Sopenharmony_ci  }
18601cb0ef41Sopenharmony_ci}
18611cb0ef41Sopenharmony_ci
18621cb0ef41Sopenharmony_ci
18631cb0ef41Sopenharmony_ciINLINE static DWORD fs__stat_impl_from_path(WCHAR* path,
18641cb0ef41Sopenharmony_ci                                            int do_lstat,
18651cb0ef41Sopenharmony_ci                                            uv_stat_t* statbuf) {
18661cb0ef41Sopenharmony_ci  HANDLE handle;
18671cb0ef41Sopenharmony_ci  DWORD flags;
18681cb0ef41Sopenharmony_ci  DWORD ret;
18691cb0ef41Sopenharmony_ci
18701cb0ef41Sopenharmony_ci  flags = FILE_FLAG_BACKUP_SEMANTICS;
18711cb0ef41Sopenharmony_ci  if (do_lstat)
18721cb0ef41Sopenharmony_ci    flags |= FILE_FLAG_OPEN_REPARSE_POINT;
18731cb0ef41Sopenharmony_ci
18741cb0ef41Sopenharmony_ci  handle = CreateFileW(path,
18751cb0ef41Sopenharmony_ci                       FILE_READ_ATTRIBUTES,
18761cb0ef41Sopenharmony_ci                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
18771cb0ef41Sopenharmony_ci                       NULL,
18781cb0ef41Sopenharmony_ci                       OPEN_EXISTING,
18791cb0ef41Sopenharmony_ci                       flags,
18801cb0ef41Sopenharmony_ci                       NULL);
18811cb0ef41Sopenharmony_ci
18821cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE)
18831cb0ef41Sopenharmony_ci    return GetLastError();
18841cb0ef41Sopenharmony_ci
18851cb0ef41Sopenharmony_ci  if (fs__stat_handle(handle, statbuf, do_lstat) != 0)
18861cb0ef41Sopenharmony_ci    ret = GetLastError();
18871cb0ef41Sopenharmony_ci  else
18881cb0ef41Sopenharmony_ci    ret = 0;
18891cb0ef41Sopenharmony_ci
18901cb0ef41Sopenharmony_ci  CloseHandle(handle);
18911cb0ef41Sopenharmony_ci  return ret;
18921cb0ef41Sopenharmony_ci}
18931cb0ef41Sopenharmony_ci
18941cb0ef41Sopenharmony_ci
18951cb0ef41Sopenharmony_ciINLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {
18961cb0ef41Sopenharmony_ci  DWORD error;
18971cb0ef41Sopenharmony_ci
18981cb0ef41Sopenharmony_ci  error = fs__stat_impl_from_path(req->file.pathw, do_lstat, &req->statbuf);
18991cb0ef41Sopenharmony_ci  if (error != 0) {
19001cb0ef41Sopenharmony_ci    if (do_lstat &&
19011cb0ef41Sopenharmony_ci        (error == ERROR_SYMLINK_NOT_SUPPORTED ||
19021cb0ef41Sopenharmony_ci         error == ERROR_NOT_A_REPARSE_POINT)) {
19031cb0ef41Sopenharmony_ci      /* We opened a reparse point but it was not a symlink. Try again. */
19041cb0ef41Sopenharmony_ci      fs__stat_impl(req, 0);
19051cb0ef41Sopenharmony_ci    } else {
19061cb0ef41Sopenharmony_ci      /* Stat failed. */
19071cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, error);
19081cb0ef41Sopenharmony_ci    }
19091cb0ef41Sopenharmony_ci
19101cb0ef41Sopenharmony_ci    return;
19111cb0ef41Sopenharmony_ci  }
19121cb0ef41Sopenharmony_ci
19131cb0ef41Sopenharmony_ci  req->ptr = &req->statbuf;
19141cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
19151cb0ef41Sopenharmony_ci}
19161cb0ef41Sopenharmony_ci
19171cb0ef41Sopenharmony_ci
19181cb0ef41Sopenharmony_cistatic void fs__stat(uv_fs_t* req) {
19191cb0ef41Sopenharmony_ci  fs__stat_prepare_path(req->file.pathw);
19201cb0ef41Sopenharmony_ci  fs__stat_impl(req, 0);
19211cb0ef41Sopenharmony_ci}
19221cb0ef41Sopenharmony_ci
19231cb0ef41Sopenharmony_ci
19241cb0ef41Sopenharmony_cistatic void fs__lstat(uv_fs_t* req) {
19251cb0ef41Sopenharmony_ci  fs__stat_prepare_path(req->file.pathw);
19261cb0ef41Sopenharmony_ci  fs__stat_impl(req, 1);
19271cb0ef41Sopenharmony_ci}
19281cb0ef41Sopenharmony_ci
19291cb0ef41Sopenharmony_ci
19301cb0ef41Sopenharmony_cistatic void fs__fstat(uv_fs_t* req) {
19311cb0ef41Sopenharmony_ci  int fd = req->file.fd;
19321cb0ef41Sopenharmony_ci  HANDLE handle;
19331cb0ef41Sopenharmony_ci
19341cb0ef41Sopenharmony_ci  VERIFY_FD(fd, req);
19351cb0ef41Sopenharmony_ci
19361cb0ef41Sopenharmony_ci  handle = uv__get_osfhandle(fd);
19371cb0ef41Sopenharmony_ci
19381cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE) {
19391cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
19401cb0ef41Sopenharmony_ci    return;
19411cb0ef41Sopenharmony_ci  }
19421cb0ef41Sopenharmony_ci
19431cb0ef41Sopenharmony_ci  if (fs__stat_handle(handle, &req->statbuf, 0) != 0) {
19441cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
19451cb0ef41Sopenharmony_ci    return;
19461cb0ef41Sopenharmony_ci  }
19471cb0ef41Sopenharmony_ci
19481cb0ef41Sopenharmony_ci  req->ptr = &req->statbuf;
19491cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
19501cb0ef41Sopenharmony_ci}
19511cb0ef41Sopenharmony_ci
19521cb0ef41Sopenharmony_ci
19531cb0ef41Sopenharmony_cistatic void fs__rename(uv_fs_t* req) {
19541cb0ef41Sopenharmony_ci  if (!MoveFileExW(req->file.pathw, req->fs.info.new_pathw, MOVEFILE_REPLACE_EXISTING)) {
19551cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
19561cb0ef41Sopenharmony_ci    return;
19571cb0ef41Sopenharmony_ci  }
19581cb0ef41Sopenharmony_ci
19591cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
19601cb0ef41Sopenharmony_ci}
19611cb0ef41Sopenharmony_ci
19621cb0ef41Sopenharmony_ci
19631cb0ef41Sopenharmony_ciINLINE static void fs__sync_impl(uv_fs_t* req) {
19641cb0ef41Sopenharmony_ci  int fd = req->file.fd;
19651cb0ef41Sopenharmony_ci  int result;
19661cb0ef41Sopenharmony_ci
19671cb0ef41Sopenharmony_ci  VERIFY_FD(fd, req);
19681cb0ef41Sopenharmony_ci
19691cb0ef41Sopenharmony_ci  result = FlushFileBuffers(uv__get_osfhandle(fd)) ? 0 : -1;
19701cb0ef41Sopenharmony_ci  if (result == -1) {
19711cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
19721cb0ef41Sopenharmony_ci  } else {
19731cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, result);
19741cb0ef41Sopenharmony_ci  }
19751cb0ef41Sopenharmony_ci}
19761cb0ef41Sopenharmony_ci
19771cb0ef41Sopenharmony_ci
19781cb0ef41Sopenharmony_cistatic void fs__fsync(uv_fs_t* req) {
19791cb0ef41Sopenharmony_ci  fs__sync_impl(req);
19801cb0ef41Sopenharmony_ci}
19811cb0ef41Sopenharmony_ci
19821cb0ef41Sopenharmony_ci
19831cb0ef41Sopenharmony_cistatic void fs__fdatasync(uv_fs_t* req) {
19841cb0ef41Sopenharmony_ci  fs__sync_impl(req);
19851cb0ef41Sopenharmony_ci}
19861cb0ef41Sopenharmony_ci
19871cb0ef41Sopenharmony_ci
19881cb0ef41Sopenharmony_cistatic void fs__ftruncate(uv_fs_t* req) {
19891cb0ef41Sopenharmony_ci  int fd = req->file.fd;
19901cb0ef41Sopenharmony_ci  HANDLE handle;
19911cb0ef41Sopenharmony_ci  struct uv__fd_info_s fd_info = { 0 };
19921cb0ef41Sopenharmony_ci  NTSTATUS status;
19931cb0ef41Sopenharmony_ci  IO_STATUS_BLOCK io_status;
19941cb0ef41Sopenharmony_ci  FILE_END_OF_FILE_INFORMATION eof_info;
19951cb0ef41Sopenharmony_ci
19961cb0ef41Sopenharmony_ci  VERIFY_FD(fd, req);
19971cb0ef41Sopenharmony_ci
19981cb0ef41Sopenharmony_ci  handle = uv__get_osfhandle(fd);
19991cb0ef41Sopenharmony_ci
20001cb0ef41Sopenharmony_ci  if (uv__fd_hash_get(fd, &fd_info)) {
20011cb0ef41Sopenharmony_ci    if (fd_info.is_directory) {
20021cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
20031cb0ef41Sopenharmony_ci      return;
20041cb0ef41Sopenharmony_ci    }
20051cb0ef41Sopenharmony_ci
20061cb0ef41Sopenharmony_ci    if (fd_info.mapping != INVALID_HANDLE_VALUE) {
20071cb0ef41Sopenharmony_ci      CloseHandle(fd_info.mapping);
20081cb0ef41Sopenharmony_ci    }
20091cb0ef41Sopenharmony_ci  }
20101cb0ef41Sopenharmony_ci
20111cb0ef41Sopenharmony_ci  eof_info.EndOfFile.QuadPart = req->fs.info.offset;
20121cb0ef41Sopenharmony_ci
20131cb0ef41Sopenharmony_ci  status = pNtSetInformationFile(handle,
20141cb0ef41Sopenharmony_ci                                 &io_status,
20151cb0ef41Sopenharmony_ci                                 &eof_info,
20161cb0ef41Sopenharmony_ci                                 sizeof eof_info,
20171cb0ef41Sopenharmony_ci                                 FileEndOfFileInformation);
20181cb0ef41Sopenharmony_ci
20191cb0ef41Sopenharmony_ci  if (NT_SUCCESS(status)) {
20201cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
20211cb0ef41Sopenharmony_ci  } else {
20221cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
20231cb0ef41Sopenharmony_ci
20241cb0ef41Sopenharmony_ci    if (fd_info.flags) {
20251cb0ef41Sopenharmony_ci      CloseHandle(handle);
20261cb0ef41Sopenharmony_ci      fd_info.mapping = INVALID_HANDLE_VALUE;
20271cb0ef41Sopenharmony_ci      fd_info.size.QuadPart = 0;
20281cb0ef41Sopenharmony_ci      fd_info.current_pos.QuadPart = 0;
20291cb0ef41Sopenharmony_ci      uv__fd_hash_add(fd, &fd_info);
20301cb0ef41Sopenharmony_ci      return;
20311cb0ef41Sopenharmony_ci    }
20321cb0ef41Sopenharmony_ci  }
20331cb0ef41Sopenharmony_ci
20341cb0ef41Sopenharmony_ci  if (fd_info.flags) {
20351cb0ef41Sopenharmony_ci    fd_info.size = eof_info.EndOfFile;
20361cb0ef41Sopenharmony_ci
20371cb0ef41Sopenharmony_ci    if (fd_info.size.QuadPart == 0) {
20381cb0ef41Sopenharmony_ci      fd_info.mapping = INVALID_HANDLE_VALUE;
20391cb0ef41Sopenharmony_ci    } else {
20401cb0ef41Sopenharmony_ci      DWORD flProtect = (fd_info.flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY |
20411cb0ef41Sopenharmony_ci        UV_FS_O_RDWR)) == UV_FS_O_RDONLY ? PAGE_READONLY : PAGE_READWRITE;
20421cb0ef41Sopenharmony_ci      fd_info.mapping = CreateFileMapping(handle,
20431cb0ef41Sopenharmony_ci                                          NULL,
20441cb0ef41Sopenharmony_ci                                          flProtect,
20451cb0ef41Sopenharmony_ci                                          fd_info.size.HighPart,
20461cb0ef41Sopenharmony_ci                                          fd_info.size.LowPart,
20471cb0ef41Sopenharmony_ci                                          NULL);
20481cb0ef41Sopenharmony_ci      if (fd_info.mapping == NULL) {
20491cb0ef41Sopenharmony_ci        SET_REQ_WIN32_ERROR(req, GetLastError());
20501cb0ef41Sopenharmony_ci        CloseHandle(handle);
20511cb0ef41Sopenharmony_ci        fd_info.mapping = INVALID_HANDLE_VALUE;
20521cb0ef41Sopenharmony_ci        fd_info.size.QuadPart = 0;
20531cb0ef41Sopenharmony_ci        fd_info.current_pos.QuadPart = 0;
20541cb0ef41Sopenharmony_ci        uv__fd_hash_add(fd, &fd_info);
20551cb0ef41Sopenharmony_ci        return;
20561cb0ef41Sopenharmony_ci      }
20571cb0ef41Sopenharmony_ci    }
20581cb0ef41Sopenharmony_ci
20591cb0ef41Sopenharmony_ci    uv__fd_hash_add(fd, &fd_info);
20601cb0ef41Sopenharmony_ci  }
20611cb0ef41Sopenharmony_ci}
20621cb0ef41Sopenharmony_ci
20631cb0ef41Sopenharmony_ci
20641cb0ef41Sopenharmony_cistatic void fs__copyfile(uv_fs_t* req) {
20651cb0ef41Sopenharmony_ci  int flags;
20661cb0ef41Sopenharmony_ci  int overwrite;
20671cb0ef41Sopenharmony_ci  uv_stat_t statbuf;
20681cb0ef41Sopenharmony_ci  uv_stat_t new_statbuf;
20691cb0ef41Sopenharmony_ci
20701cb0ef41Sopenharmony_ci  flags = req->fs.info.file_flags;
20711cb0ef41Sopenharmony_ci
20721cb0ef41Sopenharmony_ci  if (flags & UV_FS_COPYFILE_FICLONE_FORCE) {
20731cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
20741cb0ef41Sopenharmony_ci    return;
20751cb0ef41Sopenharmony_ci  }
20761cb0ef41Sopenharmony_ci
20771cb0ef41Sopenharmony_ci  overwrite = flags & UV_FS_COPYFILE_EXCL;
20781cb0ef41Sopenharmony_ci
20791cb0ef41Sopenharmony_ci  if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) != 0) {
20801cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
20811cb0ef41Sopenharmony_ci    return;
20821cb0ef41Sopenharmony_ci  }
20831cb0ef41Sopenharmony_ci
20841cb0ef41Sopenharmony_ci  SET_REQ_WIN32_ERROR(req, GetLastError());
20851cb0ef41Sopenharmony_ci  if (req->result != UV_EBUSY)
20861cb0ef41Sopenharmony_ci    return;
20871cb0ef41Sopenharmony_ci
20881cb0ef41Sopenharmony_ci  /* if error UV_EBUSY check if src and dst file are the same */
20891cb0ef41Sopenharmony_ci  if (fs__stat_impl_from_path(req->file.pathw, 0, &statbuf) != 0 ||
20901cb0ef41Sopenharmony_ci      fs__stat_impl_from_path(req->fs.info.new_pathw, 0, &new_statbuf) != 0) {
20911cb0ef41Sopenharmony_ci    return;
20921cb0ef41Sopenharmony_ci  }
20931cb0ef41Sopenharmony_ci
20941cb0ef41Sopenharmony_ci  if (statbuf.st_dev == new_statbuf.st_dev &&
20951cb0ef41Sopenharmony_ci      statbuf.st_ino == new_statbuf.st_ino) {
20961cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
20971cb0ef41Sopenharmony_ci  }
20981cb0ef41Sopenharmony_ci}
20991cb0ef41Sopenharmony_ci
21001cb0ef41Sopenharmony_ci
21011cb0ef41Sopenharmony_cistatic void fs__sendfile(uv_fs_t* req) {
21021cb0ef41Sopenharmony_ci  int fd_in = req->file.fd, fd_out = req->fs.info.fd_out;
21031cb0ef41Sopenharmony_ci  size_t length = req->fs.info.bufsml[0].len;
21041cb0ef41Sopenharmony_ci  int64_t offset = req->fs.info.offset;
21051cb0ef41Sopenharmony_ci  const size_t max_buf_size = 65536;
21061cb0ef41Sopenharmony_ci  size_t buf_size = length < max_buf_size ? length : max_buf_size;
21071cb0ef41Sopenharmony_ci  int n, result = 0;
21081cb0ef41Sopenharmony_ci  int64_t result_offset = 0;
21091cb0ef41Sopenharmony_ci  char* buf = (char*) uv__malloc(buf_size);
21101cb0ef41Sopenharmony_ci  if (!buf) {
21111cb0ef41Sopenharmony_ci    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
21121cb0ef41Sopenharmony_ci  }
21131cb0ef41Sopenharmony_ci
21141cb0ef41Sopenharmony_ci  if (offset != -1) {
21151cb0ef41Sopenharmony_ci    result_offset = _lseeki64(fd_in, offset, SEEK_SET);
21161cb0ef41Sopenharmony_ci  }
21171cb0ef41Sopenharmony_ci
21181cb0ef41Sopenharmony_ci  if (result_offset == -1) {
21191cb0ef41Sopenharmony_ci    result = -1;
21201cb0ef41Sopenharmony_ci  } else {
21211cb0ef41Sopenharmony_ci    while (length > 0) {
21221cb0ef41Sopenharmony_ci      n = _read(fd_in, buf, length < buf_size ? length : buf_size);
21231cb0ef41Sopenharmony_ci      if (n == 0) {
21241cb0ef41Sopenharmony_ci        break;
21251cb0ef41Sopenharmony_ci      } else if (n == -1) {
21261cb0ef41Sopenharmony_ci        result = -1;
21271cb0ef41Sopenharmony_ci        break;
21281cb0ef41Sopenharmony_ci      }
21291cb0ef41Sopenharmony_ci
21301cb0ef41Sopenharmony_ci      length -= n;
21311cb0ef41Sopenharmony_ci
21321cb0ef41Sopenharmony_ci      n = _write(fd_out, buf, n);
21331cb0ef41Sopenharmony_ci      if (n == -1) {
21341cb0ef41Sopenharmony_ci        result = -1;
21351cb0ef41Sopenharmony_ci        break;
21361cb0ef41Sopenharmony_ci      }
21371cb0ef41Sopenharmony_ci
21381cb0ef41Sopenharmony_ci      result += n;
21391cb0ef41Sopenharmony_ci    }
21401cb0ef41Sopenharmony_ci  }
21411cb0ef41Sopenharmony_ci
21421cb0ef41Sopenharmony_ci  uv__free(buf);
21431cb0ef41Sopenharmony_ci
21441cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, result);
21451cb0ef41Sopenharmony_ci}
21461cb0ef41Sopenharmony_ci
21471cb0ef41Sopenharmony_ci
21481cb0ef41Sopenharmony_cistatic void fs__access(uv_fs_t* req) {
21491cb0ef41Sopenharmony_ci  DWORD attr = GetFileAttributesW(req->file.pathw);
21501cb0ef41Sopenharmony_ci
21511cb0ef41Sopenharmony_ci  if (attr == INVALID_FILE_ATTRIBUTES) {
21521cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
21531cb0ef41Sopenharmony_ci    return;
21541cb0ef41Sopenharmony_ci  }
21551cb0ef41Sopenharmony_ci
21561cb0ef41Sopenharmony_ci  /*
21571cb0ef41Sopenharmony_ci   * Access is possible if
21581cb0ef41Sopenharmony_ci   * - write access wasn't requested,
21591cb0ef41Sopenharmony_ci   * - or the file isn't read-only,
21601cb0ef41Sopenharmony_ci   * - or it's a directory.
21611cb0ef41Sopenharmony_ci   * (Directories cannot be read-only on Windows.)
21621cb0ef41Sopenharmony_ci   */
21631cb0ef41Sopenharmony_ci  if (!(req->fs.info.mode & W_OK) ||
21641cb0ef41Sopenharmony_ci      !(attr & FILE_ATTRIBUTE_READONLY) ||
21651cb0ef41Sopenharmony_ci      (attr & FILE_ATTRIBUTE_DIRECTORY)) {
21661cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
21671cb0ef41Sopenharmony_ci  } else {
21681cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, UV_EPERM);
21691cb0ef41Sopenharmony_ci  }
21701cb0ef41Sopenharmony_ci
21711cb0ef41Sopenharmony_ci}
21721cb0ef41Sopenharmony_ci
21731cb0ef41Sopenharmony_ci
21741cb0ef41Sopenharmony_cistatic void fs__chmod(uv_fs_t* req) {
21751cb0ef41Sopenharmony_ci  int result = _wchmod(req->file.pathw, req->fs.info.mode);
21761cb0ef41Sopenharmony_ci  if (result == -1)
21771cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, _doserrno);
21781cb0ef41Sopenharmony_ci  else
21791cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
21801cb0ef41Sopenharmony_ci}
21811cb0ef41Sopenharmony_ci
21821cb0ef41Sopenharmony_ci
21831cb0ef41Sopenharmony_cistatic void fs__fchmod(uv_fs_t* req) {
21841cb0ef41Sopenharmony_ci  int fd = req->file.fd;
21851cb0ef41Sopenharmony_ci  int clear_archive_flag;
21861cb0ef41Sopenharmony_ci  HANDLE handle;
21871cb0ef41Sopenharmony_ci  NTSTATUS nt_status;
21881cb0ef41Sopenharmony_ci  IO_STATUS_BLOCK io_status;
21891cb0ef41Sopenharmony_ci  FILE_BASIC_INFORMATION file_info;
21901cb0ef41Sopenharmony_ci
21911cb0ef41Sopenharmony_ci  VERIFY_FD(fd, req);
21921cb0ef41Sopenharmony_ci
21931cb0ef41Sopenharmony_ci  handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0);
21941cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE) {
21951cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
21961cb0ef41Sopenharmony_ci    return;
21971cb0ef41Sopenharmony_ci  }
21981cb0ef41Sopenharmony_ci
21991cb0ef41Sopenharmony_ci  nt_status = pNtQueryInformationFile(handle,
22001cb0ef41Sopenharmony_ci                                      &io_status,
22011cb0ef41Sopenharmony_ci                                      &file_info,
22021cb0ef41Sopenharmony_ci                                      sizeof file_info,
22031cb0ef41Sopenharmony_ci                                      FileBasicInformation);
22041cb0ef41Sopenharmony_ci
22051cb0ef41Sopenharmony_ci  if (!NT_SUCCESS(nt_status)) {
22061cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
22071cb0ef41Sopenharmony_ci    goto fchmod_cleanup;
22081cb0ef41Sopenharmony_ci  }
22091cb0ef41Sopenharmony_ci
22101cb0ef41Sopenharmony_ci  /* Test if the Archive attribute is cleared */
22111cb0ef41Sopenharmony_ci  if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) {
22121cb0ef41Sopenharmony_ci      /* Set Archive flag, otherwise setting or clearing the read-only
22131cb0ef41Sopenharmony_ci         flag will not work */
22141cb0ef41Sopenharmony_ci      file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
22151cb0ef41Sopenharmony_ci      nt_status = pNtSetInformationFile(handle,
22161cb0ef41Sopenharmony_ci                                        &io_status,
22171cb0ef41Sopenharmony_ci                                        &file_info,
22181cb0ef41Sopenharmony_ci                                        sizeof file_info,
22191cb0ef41Sopenharmony_ci                                        FileBasicInformation);
22201cb0ef41Sopenharmony_ci      if (!NT_SUCCESS(nt_status)) {
22211cb0ef41Sopenharmony_ci        SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
22221cb0ef41Sopenharmony_ci        goto fchmod_cleanup;
22231cb0ef41Sopenharmony_ci      }
22241cb0ef41Sopenharmony_ci      /* Remeber to clear the flag later on */
22251cb0ef41Sopenharmony_ci      clear_archive_flag = 1;
22261cb0ef41Sopenharmony_ci  } else {
22271cb0ef41Sopenharmony_ci      clear_archive_flag = 0;
22281cb0ef41Sopenharmony_ci  }
22291cb0ef41Sopenharmony_ci
22301cb0ef41Sopenharmony_ci  if (req->fs.info.mode & _S_IWRITE) {
22311cb0ef41Sopenharmony_ci    file_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
22321cb0ef41Sopenharmony_ci  } else {
22331cb0ef41Sopenharmony_ci    file_info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
22341cb0ef41Sopenharmony_ci  }
22351cb0ef41Sopenharmony_ci
22361cb0ef41Sopenharmony_ci  nt_status = pNtSetInformationFile(handle,
22371cb0ef41Sopenharmony_ci                                    &io_status,
22381cb0ef41Sopenharmony_ci                                    &file_info,
22391cb0ef41Sopenharmony_ci                                    sizeof file_info,
22401cb0ef41Sopenharmony_ci                                    FileBasicInformation);
22411cb0ef41Sopenharmony_ci
22421cb0ef41Sopenharmony_ci  if (!NT_SUCCESS(nt_status)) {
22431cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
22441cb0ef41Sopenharmony_ci    goto fchmod_cleanup;
22451cb0ef41Sopenharmony_ci  }
22461cb0ef41Sopenharmony_ci
22471cb0ef41Sopenharmony_ci  if (clear_archive_flag) {
22481cb0ef41Sopenharmony_ci      file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
22491cb0ef41Sopenharmony_ci      if (file_info.FileAttributes == 0) {
22501cb0ef41Sopenharmony_ci          file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
22511cb0ef41Sopenharmony_ci      }
22521cb0ef41Sopenharmony_ci      nt_status = pNtSetInformationFile(handle,
22531cb0ef41Sopenharmony_ci                                        &io_status,
22541cb0ef41Sopenharmony_ci                                        &file_info,
22551cb0ef41Sopenharmony_ci                                        sizeof file_info,
22561cb0ef41Sopenharmony_ci                                        FileBasicInformation);
22571cb0ef41Sopenharmony_ci      if (!NT_SUCCESS(nt_status)) {
22581cb0ef41Sopenharmony_ci        SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
22591cb0ef41Sopenharmony_ci        goto fchmod_cleanup;
22601cb0ef41Sopenharmony_ci      }
22611cb0ef41Sopenharmony_ci  }
22621cb0ef41Sopenharmony_ci
22631cb0ef41Sopenharmony_ci  SET_REQ_SUCCESS(req);
22641cb0ef41Sopenharmony_cifchmod_cleanup:
22651cb0ef41Sopenharmony_ci  CloseHandle(handle);
22661cb0ef41Sopenharmony_ci}
22671cb0ef41Sopenharmony_ci
22681cb0ef41Sopenharmony_ci
22691cb0ef41Sopenharmony_ciINLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
22701cb0ef41Sopenharmony_ci  FILETIME filetime_a, filetime_m;
22711cb0ef41Sopenharmony_ci
22721cb0ef41Sopenharmony_ci  TIME_T_TO_FILETIME(atime, &filetime_a);
22731cb0ef41Sopenharmony_ci  TIME_T_TO_FILETIME(mtime, &filetime_m);
22741cb0ef41Sopenharmony_ci
22751cb0ef41Sopenharmony_ci  if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) {
22761cb0ef41Sopenharmony_ci    return -1;
22771cb0ef41Sopenharmony_ci  }
22781cb0ef41Sopenharmony_ci
22791cb0ef41Sopenharmony_ci  return 0;
22801cb0ef41Sopenharmony_ci}
22811cb0ef41Sopenharmony_ci
22821cb0ef41Sopenharmony_ciINLINE static DWORD fs__utime_impl_from_path(WCHAR* path,
22831cb0ef41Sopenharmony_ci                                             double atime,
22841cb0ef41Sopenharmony_ci                                             double mtime,
22851cb0ef41Sopenharmony_ci                                             int do_lutime) {
22861cb0ef41Sopenharmony_ci  HANDLE handle;
22871cb0ef41Sopenharmony_ci  DWORD flags;
22881cb0ef41Sopenharmony_ci  DWORD ret;
22891cb0ef41Sopenharmony_ci
22901cb0ef41Sopenharmony_ci  flags = FILE_FLAG_BACKUP_SEMANTICS;
22911cb0ef41Sopenharmony_ci  if (do_lutime) {
22921cb0ef41Sopenharmony_ci    flags |= FILE_FLAG_OPEN_REPARSE_POINT;
22931cb0ef41Sopenharmony_ci  }
22941cb0ef41Sopenharmony_ci
22951cb0ef41Sopenharmony_ci  handle = CreateFileW(path,
22961cb0ef41Sopenharmony_ci                       FILE_WRITE_ATTRIBUTES,
22971cb0ef41Sopenharmony_ci                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
22981cb0ef41Sopenharmony_ci                       NULL,
22991cb0ef41Sopenharmony_ci                       OPEN_EXISTING,
23001cb0ef41Sopenharmony_ci                       flags,
23011cb0ef41Sopenharmony_ci                       NULL);
23021cb0ef41Sopenharmony_ci
23031cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE)
23041cb0ef41Sopenharmony_ci    return GetLastError();
23051cb0ef41Sopenharmony_ci
23061cb0ef41Sopenharmony_ci  if (fs__utime_handle(handle, atime, mtime) != 0)
23071cb0ef41Sopenharmony_ci    ret = GetLastError();
23081cb0ef41Sopenharmony_ci  else
23091cb0ef41Sopenharmony_ci    ret = 0;
23101cb0ef41Sopenharmony_ci
23111cb0ef41Sopenharmony_ci  CloseHandle(handle);
23121cb0ef41Sopenharmony_ci  return ret;
23131cb0ef41Sopenharmony_ci}
23141cb0ef41Sopenharmony_ci
23151cb0ef41Sopenharmony_ciINLINE static void fs__utime_impl(uv_fs_t* req, int do_lutime) {
23161cb0ef41Sopenharmony_ci  DWORD error;
23171cb0ef41Sopenharmony_ci
23181cb0ef41Sopenharmony_ci  error = fs__utime_impl_from_path(req->file.pathw,
23191cb0ef41Sopenharmony_ci                                   req->fs.time.atime,
23201cb0ef41Sopenharmony_ci                                   req->fs.time.mtime,
23211cb0ef41Sopenharmony_ci                                   do_lutime);
23221cb0ef41Sopenharmony_ci
23231cb0ef41Sopenharmony_ci  if (error != 0) {
23241cb0ef41Sopenharmony_ci    if (do_lutime &&
23251cb0ef41Sopenharmony_ci        (error == ERROR_SYMLINK_NOT_SUPPORTED ||
23261cb0ef41Sopenharmony_ci         error == ERROR_NOT_A_REPARSE_POINT)) {
23271cb0ef41Sopenharmony_ci      /* Opened file is a reparse point but not a symlink. Try again. */
23281cb0ef41Sopenharmony_ci      fs__utime_impl(req, 0);
23291cb0ef41Sopenharmony_ci    } else {
23301cb0ef41Sopenharmony_ci      /* utime failed. */
23311cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, error);
23321cb0ef41Sopenharmony_ci    }
23331cb0ef41Sopenharmony_ci
23341cb0ef41Sopenharmony_ci    return;
23351cb0ef41Sopenharmony_ci  }
23361cb0ef41Sopenharmony_ci
23371cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
23381cb0ef41Sopenharmony_ci}
23391cb0ef41Sopenharmony_ci
23401cb0ef41Sopenharmony_cistatic void fs__utime(uv_fs_t* req) {
23411cb0ef41Sopenharmony_ci  fs__utime_impl(req, /* do_lutime */ 0);
23421cb0ef41Sopenharmony_ci}
23431cb0ef41Sopenharmony_ci
23441cb0ef41Sopenharmony_ci
23451cb0ef41Sopenharmony_cistatic void fs__futime(uv_fs_t* req) {
23461cb0ef41Sopenharmony_ci  int fd = req->file.fd;
23471cb0ef41Sopenharmony_ci  HANDLE handle;
23481cb0ef41Sopenharmony_ci  VERIFY_FD(fd, req);
23491cb0ef41Sopenharmony_ci
23501cb0ef41Sopenharmony_ci  handle = uv__get_osfhandle(fd);
23511cb0ef41Sopenharmony_ci
23521cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE) {
23531cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
23541cb0ef41Sopenharmony_ci    return;
23551cb0ef41Sopenharmony_ci  }
23561cb0ef41Sopenharmony_ci
23571cb0ef41Sopenharmony_ci  if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {
23581cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
23591cb0ef41Sopenharmony_ci    return;
23601cb0ef41Sopenharmony_ci  }
23611cb0ef41Sopenharmony_ci
23621cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
23631cb0ef41Sopenharmony_ci}
23641cb0ef41Sopenharmony_ci
23651cb0ef41Sopenharmony_cistatic void fs__lutime(uv_fs_t* req) {
23661cb0ef41Sopenharmony_ci  fs__utime_impl(req, /* do_lutime */ 1);
23671cb0ef41Sopenharmony_ci}
23681cb0ef41Sopenharmony_ci
23691cb0ef41Sopenharmony_ci
23701cb0ef41Sopenharmony_cistatic void fs__link(uv_fs_t* req) {
23711cb0ef41Sopenharmony_ci  DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL);
23721cb0ef41Sopenharmony_ci  if (r == 0)
23731cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
23741cb0ef41Sopenharmony_ci  else
23751cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
23761cb0ef41Sopenharmony_ci}
23771cb0ef41Sopenharmony_ci
23781cb0ef41Sopenharmony_ci
23791cb0ef41Sopenharmony_cistatic void fs__create_junction(uv_fs_t* req, const WCHAR* path,
23801cb0ef41Sopenharmony_ci    const WCHAR* new_path) {
23811cb0ef41Sopenharmony_ci  HANDLE handle = INVALID_HANDLE_VALUE;
23821cb0ef41Sopenharmony_ci  REPARSE_DATA_BUFFER *buffer = NULL;
23831cb0ef41Sopenharmony_ci  int created = 0;
23841cb0ef41Sopenharmony_ci  int target_len;
23851cb0ef41Sopenharmony_ci  int is_absolute, is_long_path;
23861cb0ef41Sopenharmony_ci  int needed_buf_size, used_buf_size, used_data_size, path_buf_len;
23871cb0ef41Sopenharmony_ci  int start, len, i;
23881cb0ef41Sopenharmony_ci  int add_slash;
23891cb0ef41Sopenharmony_ci  DWORD bytes;
23901cb0ef41Sopenharmony_ci  WCHAR* path_buf;
23911cb0ef41Sopenharmony_ci
23921cb0ef41Sopenharmony_ci  target_len = wcslen(path);
23931cb0ef41Sopenharmony_ci  is_long_path = wcsncmp(path, LONG_PATH_PREFIX, LONG_PATH_PREFIX_LEN) == 0;
23941cb0ef41Sopenharmony_ci
23951cb0ef41Sopenharmony_ci  if (is_long_path) {
23961cb0ef41Sopenharmony_ci    is_absolute = 1;
23971cb0ef41Sopenharmony_ci  } else {
23981cb0ef41Sopenharmony_ci    is_absolute = target_len >= 3 && IS_LETTER(path[0]) &&
23991cb0ef41Sopenharmony_ci      path[1] == L':' && IS_SLASH(path[2]);
24001cb0ef41Sopenharmony_ci  }
24011cb0ef41Sopenharmony_ci
24021cb0ef41Sopenharmony_ci  if (!is_absolute) {
24031cb0ef41Sopenharmony_ci    /* Not supporting relative paths */
24041cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_NOT_SUPPORTED);
24051cb0ef41Sopenharmony_ci    return;
24061cb0ef41Sopenharmony_ci  }
24071cb0ef41Sopenharmony_ci
24081cb0ef41Sopenharmony_ci  /* Do a pessimistic calculation of the required buffer size */
24091cb0ef41Sopenharmony_ci  needed_buf_size =
24101cb0ef41Sopenharmony_ci      FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
24111cb0ef41Sopenharmony_ci      JUNCTION_PREFIX_LEN * sizeof(WCHAR) +
24121cb0ef41Sopenharmony_ci      2 * (target_len + 2) * sizeof(WCHAR);
24131cb0ef41Sopenharmony_ci
24141cb0ef41Sopenharmony_ci  /* Allocate the buffer */
24151cb0ef41Sopenharmony_ci  buffer = (REPARSE_DATA_BUFFER*)uv__malloc(needed_buf_size);
24161cb0ef41Sopenharmony_ci  if (!buffer) {
24171cb0ef41Sopenharmony_ci    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
24181cb0ef41Sopenharmony_ci  }
24191cb0ef41Sopenharmony_ci
24201cb0ef41Sopenharmony_ci  /* Grab a pointer to the part of the buffer where filenames go */
24211cb0ef41Sopenharmony_ci  path_buf = (WCHAR*)&(buffer->MountPointReparseBuffer.PathBuffer);
24221cb0ef41Sopenharmony_ci  path_buf_len = 0;
24231cb0ef41Sopenharmony_ci
24241cb0ef41Sopenharmony_ci  /* Copy the substitute (internal) target path */
24251cb0ef41Sopenharmony_ci  start = path_buf_len;
24261cb0ef41Sopenharmony_ci
24271cb0ef41Sopenharmony_ci  wcsncpy((WCHAR*)&path_buf[path_buf_len], JUNCTION_PREFIX,
24281cb0ef41Sopenharmony_ci    JUNCTION_PREFIX_LEN);
24291cb0ef41Sopenharmony_ci  path_buf_len += JUNCTION_PREFIX_LEN;
24301cb0ef41Sopenharmony_ci
24311cb0ef41Sopenharmony_ci  add_slash = 0;
24321cb0ef41Sopenharmony_ci  for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
24331cb0ef41Sopenharmony_ci    if (IS_SLASH(path[i])) {
24341cb0ef41Sopenharmony_ci      add_slash = 1;
24351cb0ef41Sopenharmony_ci      continue;
24361cb0ef41Sopenharmony_ci    }
24371cb0ef41Sopenharmony_ci
24381cb0ef41Sopenharmony_ci    if (add_slash) {
24391cb0ef41Sopenharmony_ci      path_buf[path_buf_len++] = L'\\';
24401cb0ef41Sopenharmony_ci      add_slash = 0;
24411cb0ef41Sopenharmony_ci    }
24421cb0ef41Sopenharmony_ci
24431cb0ef41Sopenharmony_ci    path_buf[path_buf_len++] = path[i];
24441cb0ef41Sopenharmony_ci  }
24451cb0ef41Sopenharmony_ci  path_buf[path_buf_len++] = L'\\';
24461cb0ef41Sopenharmony_ci  len = path_buf_len - start;
24471cb0ef41Sopenharmony_ci
24481cb0ef41Sopenharmony_ci  /* Set the info about the substitute name */
24491cb0ef41Sopenharmony_ci  buffer->MountPointReparseBuffer.SubstituteNameOffset = start * sizeof(WCHAR);
24501cb0ef41Sopenharmony_ci  buffer->MountPointReparseBuffer.SubstituteNameLength = len * sizeof(WCHAR);
24511cb0ef41Sopenharmony_ci
24521cb0ef41Sopenharmony_ci  /* Insert null terminator */
24531cb0ef41Sopenharmony_ci  path_buf[path_buf_len++] = L'\0';
24541cb0ef41Sopenharmony_ci
24551cb0ef41Sopenharmony_ci  /* Copy the print name of the target path */
24561cb0ef41Sopenharmony_ci  start = path_buf_len;
24571cb0ef41Sopenharmony_ci  add_slash = 0;
24581cb0ef41Sopenharmony_ci  for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
24591cb0ef41Sopenharmony_ci    if (IS_SLASH(path[i])) {
24601cb0ef41Sopenharmony_ci      add_slash = 1;
24611cb0ef41Sopenharmony_ci      continue;
24621cb0ef41Sopenharmony_ci    }
24631cb0ef41Sopenharmony_ci
24641cb0ef41Sopenharmony_ci    if (add_slash) {
24651cb0ef41Sopenharmony_ci      path_buf[path_buf_len++] = L'\\';
24661cb0ef41Sopenharmony_ci      add_slash = 0;
24671cb0ef41Sopenharmony_ci    }
24681cb0ef41Sopenharmony_ci
24691cb0ef41Sopenharmony_ci    path_buf[path_buf_len++] = path[i];
24701cb0ef41Sopenharmony_ci  }
24711cb0ef41Sopenharmony_ci  len = path_buf_len - start;
24721cb0ef41Sopenharmony_ci  if (len == 2) {
24731cb0ef41Sopenharmony_ci    path_buf[path_buf_len++] = L'\\';
24741cb0ef41Sopenharmony_ci    len++;
24751cb0ef41Sopenharmony_ci  }
24761cb0ef41Sopenharmony_ci
24771cb0ef41Sopenharmony_ci  /* Set the info about the print name */
24781cb0ef41Sopenharmony_ci  buffer->MountPointReparseBuffer.PrintNameOffset = start * sizeof(WCHAR);
24791cb0ef41Sopenharmony_ci  buffer->MountPointReparseBuffer.PrintNameLength = len * sizeof(WCHAR);
24801cb0ef41Sopenharmony_ci
24811cb0ef41Sopenharmony_ci  /* Insert another null terminator */
24821cb0ef41Sopenharmony_ci  path_buf[path_buf_len++] = L'\0';
24831cb0ef41Sopenharmony_ci
24841cb0ef41Sopenharmony_ci  /* Calculate how much buffer space was actually used */
24851cb0ef41Sopenharmony_ci  used_buf_size = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
24861cb0ef41Sopenharmony_ci    path_buf_len * sizeof(WCHAR);
24871cb0ef41Sopenharmony_ci  used_data_size = used_buf_size -
24881cb0ef41Sopenharmony_ci    FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer);
24891cb0ef41Sopenharmony_ci
24901cb0ef41Sopenharmony_ci  /* Put general info in the data buffer */
24911cb0ef41Sopenharmony_ci  buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
24921cb0ef41Sopenharmony_ci  buffer->ReparseDataLength = used_data_size;
24931cb0ef41Sopenharmony_ci  buffer->Reserved = 0;
24941cb0ef41Sopenharmony_ci
24951cb0ef41Sopenharmony_ci  /* Create a new directory */
24961cb0ef41Sopenharmony_ci  if (!CreateDirectoryW(new_path, NULL)) {
24971cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
24981cb0ef41Sopenharmony_ci    goto error;
24991cb0ef41Sopenharmony_ci  }
25001cb0ef41Sopenharmony_ci  created = 1;
25011cb0ef41Sopenharmony_ci
25021cb0ef41Sopenharmony_ci  /* Open the directory */
25031cb0ef41Sopenharmony_ci  handle = CreateFileW(new_path,
25041cb0ef41Sopenharmony_ci                       GENERIC_WRITE,
25051cb0ef41Sopenharmony_ci                       0,
25061cb0ef41Sopenharmony_ci                       NULL,
25071cb0ef41Sopenharmony_ci                       OPEN_EXISTING,
25081cb0ef41Sopenharmony_ci                       FILE_FLAG_BACKUP_SEMANTICS |
25091cb0ef41Sopenharmony_ci                         FILE_FLAG_OPEN_REPARSE_POINT,
25101cb0ef41Sopenharmony_ci                       NULL);
25111cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE) {
25121cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
25131cb0ef41Sopenharmony_ci    goto error;
25141cb0ef41Sopenharmony_ci  }
25151cb0ef41Sopenharmony_ci
25161cb0ef41Sopenharmony_ci  /* Create the actual reparse point */
25171cb0ef41Sopenharmony_ci  if (!DeviceIoControl(handle,
25181cb0ef41Sopenharmony_ci                       FSCTL_SET_REPARSE_POINT,
25191cb0ef41Sopenharmony_ci                       buffer,
25201cb0ef41Sopenharmony_ci                       used_buf_size,
25211cb0ef41Sopenharmony_ci                       NULL,
25221cb0ef41Sopenharmony_ci                       0,
25231cb0ef41Sopenharmony_ci                       &bytes,
25241cb0ef41Sopenharmony_ci                       NULL)) {
25251cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
25261cb0ef41Sopenharmony_ci    goto error;
25271cb0ef41Sopenharmony_ci  }
25281cb0ef41Sopenharmony_ci
25291cb0ef41Sopenharmony_ci  /* Clean up */
25301cb0ef41Sopenharmony_ci  CloseHandle(handle);
25311cb0ef41Sopenharmony_ci  uv__free(buffer);
25321cb0ef41Sopenharmony_ci
25331cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
25341cb0ef41Sopenharmony_ci  return;
25351cb0ef41Sopenharmony_ci
25361cb0ef41Sopenharmony_cierror:
25371cb0ef41Sopenharmony_ci  uv__free(buffer);
25381cb0ef41Sopenharmony_ci
25391cb0ef41Sopenharmony_ci  if (handle != INVALID_HANDLE_VALUE) {
25401cb0ef41Sopenharmony_ci    CloseHandle(handle);
25411cb0ef41Sopenharmony_ci  }
25421cb0ef41Sopenharmony_ci
25431cb0ef41Sopenharmony_ci  if (created) {
25441cb0ef41Sopenharmony_ci    RemoveDirectoryW(new_path);
25451cb0ef41Sopenharmony_ci  }
25461cb0ef41Sopenharmony_ci}
25471cb0ef41Sopenharmony_ci
25481cb0ef41Sopenharmony_ci
25491cb0ef41Sopenharmony_cistatic void fs__symlink(uv_fs_t* req) {
25501cb0ef41Sopenharmony_ci  WCHAR* pathw;
25511cb0ef41Sopenharmony_ci  WCHAR* new_pathw;
25521cb0ef41Sopenharmony_ci  int flags;
25531cb0ef41Sopenharmony_ci  int err;
25541cb0ef41Sopenharmony_ci
25551cb0ef41Sopenharmony_ci  pathw = req->file.pathw;
25561cb0ef41Sopenharmony_ci  new_pathw = req->fs.info.new_pathw;
25571cb0ef41Sopenharmony_ci
25581cb0ef41Sopenharmony_ci  if (req->fs.info.file_flags & UV_FS_SYMLINK_JUNCTION) {
25591cb0ef41Sopenharmony_ci    fs__create_junction(req, pathw, new_pathw);
25601cb0ef41Sopenharmony_ci    return;
25611cb0ef41Sopenharmony_ci  }
25621cb0ef41Sopenharmony_ci
25631cb0ef41Sopenharmony_ci  if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
25641cb0ef41Sopenharmony_ci    flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag;
25651cb0ef41Sopenharmony_ci  else
25661cb0ef41Sopenharmony_ci    flags = uv__file_symlink_usermode_flag;
25671cb0ef41Sopenharmony_ci
25681cb0ef41Sopenharmony_ci  if (CreateSymbolicLinkW(new_pathw, pathw, flags)) {
25691cb0ef41Sopenharmony_ci    SET_REQ_RESULT(req, 0);
25701cb0ef41Sopenharmony_ci    return;
25711cb0ef41Sopenharmony_ci  }
25721cb0ef41Sopenharmony_ci
25731cb0ef41Sopenharmony_ci  /* Something went wrong. We will test if it is because of user-mode
25741cb0ef41Sopenharmony_ci   * symlinks.
25751cb0ef41Sopenharmony_ci   */
25761cb0ef41Sopenharmony_ci  err = GetLastError();
25771cb0ef41Sopenharmony_ci  if (err == ERROR_INVALID_PARAMETER &&
25781cb0ef41Sopenharmony_ci      flags & SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) {
25791cb0ef41Sopenharmony_ci    /* This system does not support user-mode symlinks. We will clear the
25801cb0ef41Sopenharmony_ci     * unsupported flag and retry.
25811cb0ef41Sopenharmony_ci     */
25821cb0ef41Sopenharmony_ci    uv__file_symlink_usermode_flag = 0;
25831cb0ef41Sopenharmony_ci    fs__symlink(req);
25841cb0ef41Sopenharmony_ci  } else {
25851cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
25861cb0ef41Sopenharmony_ci  }
25871cb0ef41Sopenharmony_ci}
25881cb0ef41Sopenharmony_ci
25891cb0ef41Sopenharmony_ci
25901cb0ef41Sopenharmony_cistatic void fs__readlink(uv_fs_t* req) {
25911cb0ef41Sopenharmony_ci  HANDLE handle;
25921cb0ef41Sopenharmony_ci
25931cb0ef41Sopenharmony_ci  handle = CreateFileW(req->file.pathw,
25941cb0ef41Sopenharmony_ci                       0,
25951cb0ef41Sopenharmony_ci                       0,
25961cb0ef41Sopenharmony_ci                       NULL,
25971cb0ef41Sopenharmony_ci                       OPEN_EXISTING,
25981cb0ef41Sopenharmony_ci                       FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
25991cb0ef41Sopenharmony_ci                       NULL);
26001cb0ef41Sopenharmony_ci
26011cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE) {
26021cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
26031cb0ef41Sopenharmony_ci    return;
26041cb0ef41Sopenharmony_ci  }
26051cb0ef41Sopenharmony_ci
26061cb0ef41Sopenharmony_ci  if (fs__readlink_handle(handle, (char**) &req->ptr, NULL) != 0) {
26071cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
26081cb0ef41Sopenharmony_ci    CloseHandle(handle);
26091cb0ef41Sopenharmony_ci    return;
26101cb0ef41Sopenharmony_ci  }
26111cb0ef41Sopenharmony_ci
26121cb0ef41Sopenharmony_ci  req->flags |= UV_FS_FREE_PTR;
26131cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
26141cb0ef41Sopenharmony_ci
26151cb0ef41Sopenharmony_ci  CloseHandle(handle);
26161cb0ef41Sopenharmony_ci}
26171cb0ef41Sopenharmony_ci
26181cb0ef41Sopenharmony_ci
26191cb0ef41Sopenharmony_cistatic ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
26201cb0ef41Sopenharmony_ci  int r;
26211cb0ef41Sopenharmony_ci  DWORD w_realpath_len;
26221cb0ef41Sopenharmony_ci  WCHAR* w_realpath_ptr = NULL;
26231cb0ef41Sopenharmony_ci  WCHAR* w_realpath_buf;
26241cb0ef41Sopenharmony_ci
26251cb0ef41Sopenharmony_ci  w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
26261cb0ef41Sopenharmony_ci  if (w_realpath_len == 0) {
26271cb0ef41Sopenharmony_ci    return -1;
26281cb0ef41Sopenharmony_ci  }
26291cb0ef41Sopenharmony_ci
26301cb0ef41Sopenharmony_ci  w_realpath_buf = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR));
26311cb0ef41Sopenharmony_ci  if (w_realpath_buf == NULL) {
26321cb0ef41Sopenharmony_ci    SetLastError(ERROR_OUTOFMEMORY);
26331cb0ef41Sopenharmony_ci    return -1;
26341cb0ef41Sopenharmony_ci  }
26351cb0ef41Sopenharmony_ci  w_realpath_ptr = w_realpath_buf;
26361cb0ef41Sopenharmony_ci
26371cb0ef41Sopenharmony_ci  if (GetFinalPathNameByHandleW(
26381cb0ef41Sopenharmony_ci          handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) {
26391cb0ef41Sopenharmony_ci    uv__free(w_realpath_buf);
26401cb0ef41Sopenharmony_ci    SetLastError(ERROR_INVALID_HANDLE);
26411cb0ef41Sopenharmony_ci    return -1;
26421cb0ef41Sopenharmony_ci  }
26431cb0ef41Sopenharmony_ci
26441cb0ef41Sopenharmony_ci  /* convert UNC path to long path */
26451cb0ef41Sopenharmony_ci  if (wcsncmp(w_realpath_ptr,
26461cb0ef41Sopenharmony_ci              UNC_PATH_PREFIX,
26471cb0ef41Sopenharmony_ci              UNC_PATH_PREFIX_LEN) == 0) {
26481cb0ef41Sopenharmony_ci    w_realpath_ptr += 6;
26491cb0ef41Sopenharmony_ci    *w_realpath_ptr = L'\\';
26501cb0ef41Sopenharmony_ci    w_realpath_len -= 6;
26511cb0ef41Sopenharmony_ci  } else if (wcsncmp(w_realpath_ptr,
26521cb0ef41Sopenharmony_ci                      LONG_PATH_PREFIX,
26531cb0ef41Sopenharmony_ci                      LONG_PATH_PREFIX_LEN) == 0) {
26541cb0ef41Sopenharmony_ci    w_realpath_ptr += 4;
26551cb0ef41Sopenharmony_ci    w_realpath_len -= 4;
26561cb0ef41Sopenharmony_ci  } else {
26571cb0ef41Sopenharmony_ci    uv__free(w_realpath_buf);
26581cb0ef41Sopenharmony_ci    SetLastError(ERROR_INVALID_HANDLE);
26591cb0ef41Sopenharmony_ci    return -1;
26601cb0ef41Sopenharmony_ci  }
26611cb0ef41Sopenharmony_ci
26621cb0ef41Sopenharmony_ci  r = fs__wide_to_utf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL);
26631cb0ef41Sopenharmony_ci  uv__free(w_realpath_buf);
26641cb0ef41Sopenharmony_ci  return r;
26651cb0ef41Sopenharmony_ci}
26661cb0ef41Sopenharmony_ci
26671cb0ef41Sopenharmony_cistatic void fs__realpath(uv_fs_t* req) {
26681cb0ef41Sopenharmony_ci  HANDLE handle;
26691cb0ef41Sopenharmony_ci
26701cb0ef41Sopenharmony_ci  handle = CreateFileW(req->file.pathw,
26711cb0ef41Sopenharmony_ci                       0,
26721cb0ef41Sopenharmony_ci                       0,
26731cb0ef41Sopenharmony_ci                       NULL,
26741cb0ef41Sopenharmony_ci                       OPEN_EXISTING,
26751cb0ef41Sopenharmony_ci                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
26761cb0ef41Sopenharmony_ci                       NULL);
26771cb0ef41Sopenharmony_ci  if (handle == INVALID_HANDLE_VALUE) {
26781cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
26791cb0ef41Sopenharmony_ci    return;
26801cb0ef41Sopenharmony_ci  }
26811cb0ef41Sopenharmony_ci
26821cb0ef41Sopenharmony_ci  if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) {
26831cb0ef41Sopenharmony_ci    CloseHandle(handle);
26841cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, GetLastError());
26851cb0ef41Sopenharmony_ci    return;
26861cb0ef41Sopenharmony_ci  }
26871cb0ef41Sopenharmony_ci
26881cb0ef41Sopenharmony_ci  CloseHandle(handle);
26891cb0ef41Sopenharmony_ci  req->flags |= UV_FS_FREE_PTR;
26901cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
26911cb0ef41Sopenharmony_ci}
26921cb0ef41Sopenharmony_ci
26931cb0ef41Sopenharmony_ci
26941cb0ef41Sopenharmony_cistatic void fs__chown(uv_fs_t* req) {
26951cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
26961cb0ef41Sopenharmony_ci}
26971cb0ef41Sopenharmony_ci
26981cb0ef41Sopenharmony_ci
26991cb0ef41Sopenharmony_cistatic void fs__fchown(uv_fs_t* req) {
27001cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
27011cb0ef41Sopenharmony_ci}
27021cb0ef41Sopenharmony_ci
27031cb0ef41Sopenharmony_ci
27041cb0ef41Sopenharmony_cistatic void fs__lchown(uv_fs_t* req) {
27051cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
27061cb0ef41Sopenharmony_ci}
27071cb0ef41Sopenharmony_ci
27081cb0ef41Sopenharmony_ci
27091cb0ef41Sopenharmony_cistatic void fs__statfs(uv_fs_t* req) {
27101cb0ef41Sopenharmony_ci  uv_statfs_t* stat_fs;
27111cb0ef41Sopenharmony_ci  DWORD sectors_per_cluster;
27121cb0ef41Sopenharmony_ci  DWORD bytes_per_sector;
27131cb0ef41Sopenharmony_ci  DWORD free_clusters;
27141cb0ef41Sopenharmony_ci  DWORD total_clusters;
27151cb0ef41Sopenharmony_ci  WCHAR* pathw;
27161cb0ef41Sopenharmony_ci
27171cb0ef41Sopenharmony_ci  pathw = req->file.pathw;
27181cb0ef41Sopenharmony_ciretry_get_disk_free_space:
27191cb0ef41Sopenharmony_ci  if (0 == GetDiskFreeSpaceW(pathw,
27201cb0ef41Sopenharmony_ci                             &sectors_per_cluster,
27211cb0ef41Sopenharmony_ci                             &bytes_per_sector,
27221cb0ef41Sopenharmony_ci                             &free_clusters,
27231cb0ef41Sopenharmony_ci                             &total_clusters)) {
27241cb0ef41Sopenharmony_ci    DWORD err;
27251cb0ef41Sopenharmony_ci    WCHAR* fpart;
27261cb0ef41Sopenharmony_ci    size_t len;
27271cb0ef41Sopenharmony_ci    DWORD ret;
27281cb0ef41Sopenharmony_ci    BOOL is_second;
27291cb0ef41Sopenharmony_ci
27301cb0ef41Sopenharmony_ci    err = GetLastError();
27311cb0ef41Sopenharmony_ci    is_second = pathw != req->file.pathw;
27321cb0ef41Sopenharmony_ci    if (err != ERROR_DIRECTORY || is_second) {
27331cb0ef41Sopenharmony_ci      if (is_second)
27341cb0ef41Sopenharmony_ci        uv__free(pathw);
27351cb0ef41Sopenharmony_ci
27361cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, err);
27371cb0ef41Sopenharmony_ci      return;
27381cb0ef41Sopenharmony_ci    }
27391cb0ef41Sopenharmony_ci
27401cb0ef41Sopenharmony_ci    len = MAX_PATH + 1;
27411cb0ef41Sopenharmony_ci    pathw = uv__malloc(len * sizeof(*pathw));
27421cb0ef41Sopenharmony_ci    if (pathw == NULL) {
27431cb0ef41Sopenharmony_ci      SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
27441cb0ef41Sopenharmony_ci      return;
27451cb0ef41Sopenharmony_ci    }
27461cb0ef41Sopenharmony_ciretry_get_full_path_name:
27471cb0ef41Sopenharmony_ci    ret = GetFullPathNameW(req->file.pathw,
27481cb0ef41Sopenharmony_ci                           len,
27491cb0ef41Sopenharmony_ci                           pathw,
27501cb0ef41Sopenharmony_ci                           &fpart);
27511cb0ef41Sopenharmony_ci    if (ret == 0) {
27521cb0ef41Sopenharmony_ci      uv__free(pathw);
27531cb0ef41Sopenharmony_ci      SET_REQ_WIN32_ERROR(req, err);
27541cb0ef41Sopenharmony_ci      return;
27551cb0ef41Sopenharmony_ci    } else if (ret > len) {
27561cb0ef41Sopenharmony_ci      len = ret;
27571cb0ef41Sopenharmony_ci      pathw = uv__reallocf(pathw, len * sizeof(*pathw));
27581cb0ef41Sopenharmony_ci      if (pathw == NULL) {
27591cb0ef41Sopenharmony_ci        SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
27601cb0ef41Sopenharmony_ci        return;
27611cb0ef41Sopenharmony_ci      }
27621cb0ef41Sopenharmony_ci      goto retry_get_full_path_name;
27631cb0ef41Sopenharmony_ci    }
27641cb0ef41Sopenharmony_ci    if (fpart != 0)
27651cb0ef41Sopenharmony_ci      *fpart = L'\0';
27661cb0ef41Sopenharmony_ci
27671cb0ef41Sopenharmony_ci    goto retry_get_disk_free_space;
27681cb0ef41Sopenharmony_ci  }
27691cb0ef41Sopenharmony_ci  if (pathw != req->file.pathw) {
27701cb0ef41Sopenharmony_ci    uv__free(pathw);
27711cb0ef41Sopenharmony_ci  }
27721cb0ef41Sopenharmony_ci
27731cb0ef41Sopenharmony_ci  stat_fs = uv__malloc(sizeof(*stat_fs));
27741cb0ef41Sopenharmony_ci  if (stat_fs == NULL) {
27751cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
27761cb0ef41Sopenharmony_ci    return;
27771cb0ef41Sopenharmony_ci  }
27781cb0ef41Sopenharmony_ci
27791cb0ef41Sopenharmony_ci  stat_fs->f_type = 0;
27801cb0ef41Sopenharmony_ci  stat_fs->f_bsize = bytes_per_sector * sectors_per_cluster;
27811cb0ef41Sopenharmony_ci  stat_fs->f_blocks = total_clusters;
27821cb0ef41Sopenharmony_ci  stat_fs->f_bfree = free_clusters;
27831cb0ef41Sopenharmony_ci  stat_fs->f_bavail = free_clusters;
27841cb0ef41Sopenharmony_ci  stat_fs->f_files = 0;
27851cb0ef41Sopenharmony_ci  stat_fs->f_ffree = 0;
27861cb0ef41Sopenharmony_ci  req->ptr = stat_fs;
27871cb0ef41Sopenharmony_ci  req->flags |= UV_FS_FREE_PTR;
27881cb0ef41Sopenharmony_ci  SET_REQ_RESULT(req, 0);
27891cb0ef41Sopenharmony_ci}
27901cb0ef41Sopenharmony_ci
27911cb0ef41Sopenharmony_ci
27921cb0ef41Sopenharmony_cistatic void uv__fs_work(struct uv__work* w) {
27931cb0ef41Sopenharmony_ci  uv_fs_t* req;
27941cb0ef41Sopenharmony_ci
27951cb0ef41Sopenharmony_ci  req = container_of(w, uv_fs_t, work_req);
27961cb0ef41Sopenharmony_ci  assert(req->type == UV_FS);
27971cb0ef41Sopenharmony_ci
27981cb0ef41Sopenharmony_ci#define XX(uc, lc)  case UV_FS_##uc: fs__##lc(req); break;
27991cb0ef41Sopenharmony_ci  switch (req->fs_type) {
28001cb0ef41Sopenharmony_ci    XX(OPEN, open)
28011cb0ef41Sopenharmony_ci    XX(CLOSE, close)
28021cb0ef41Sopenharmony_ci    XX(READ, read)
28031cb0ef41Sopenharmony_ci    XX(WRITE, write)
28041cb0ef41Sopenharmony_ci    XX(COPYFILE, copyfile)
28051cb0ef41Sopenharmony_ci    XX(SENDFILE, sendfile)
28061cb0ef41Sopenharmony_ci    XX(STAT, stat)
28071cb0ef41Sopenharmony_ci    XX(LSTAT, lstat)
28081cb0ef41Sopenharmony_ci    XX(FSTAT, fstat)
28091cb0ef41Sopenharmony_ci    XX(FTRUNCATE, ftruncate)
28101cb0ef41Sopenharmony_ci    XX(UTIME, utime)
28111cb0ef41Sopenharmony_ci    XX(FUTIME, futime)
28121cb0ef41Sopenharmony_ci    XX(LUTIME, lutime)
28131cb0ef41Sopenharmony_ci    XX(ACCESS, access)
28141cb0ef41Sopenharmony_ci    XX(CHMOD, chmod)
28151cb0ef41Sopenharmony_ci    XX(FCHMOD, fchmod)
28161cb0ef41Sopenharmony_ci    XX(FSYNC, fsync)
28171cb0ef41Sopenharmony_ci    XX(FDATASYNC, fdatasync)
28181cb0ef41Sopenharmony_ci    XX(UNLINK, unlink)
28191cb0ef41Sopenharmony_ci    XX(RMDIR, rmdir)
28201cb0ef41Sopenharmony_ci    XX(MKDIR, mkdir)
28211cb0ef41Sopenharmony_ci    XX(MKDTEMP, mkdtemp)
28221cb0ef41Sopenharmony_ci    XX(MKSTEMP, mkstemp)
28231cb0ef41Sopenharmony_ci    XX(RENAME, rename)
28241cb0ef41Sopenharmony_ci    XX(SCANDIR, scandir)
28251cb0ef41Sopenharmony_ci    XX(READDIR, readdir)
28261cb0ef41Sopenharmony_ci    XX(OPENDIR, opendir)
28271cb0ef41Sopenharmony_ci    XX(CLOSEDIR, closedir)
28281cb0ef41Sopenharmony_ci    XX(LINK, link)
28291cb0ef41Sopenharmony_ci    XX(SYMLINK, symlink)
28301cb0ef41Sopenharmony_ci    XX(READLINK, readlink)
28311cb0ef41Sopenharmony_ci    XX(REALPATH, realpath)
28321cb0ef41Sopenharmony_ci    XX(CHOWN, chown)
28331cb0ef41Sopenharmony_ci    XX(FCHOWN, fchown)
28341cb0ef41Sopenharmony_ci    XX(LCHOWN, lchown)
28351cb0ef41Sopenharmony_ci    XX(STATFS, statfs)
28361cb0ef41Sopenharmony_ci    default:
28371cb0ef41Sopenharmony_ci      assert(!"bad uv_fs_type");
28381cb0ef41Sopenharmony_ci  }
28391cb0ef41Sopenharmony_ci}
28401cb0ef41Sopenharmony_ci
28411cb0ef41Sopenharmony_ci
28421cb0ef41Sopenharmony_cistatic void uv__fs_done(struct uv__work* w, int status) {
28431cb0ef41Sopenharmony_ci  uv_fs_t* req;
28441cb0ef41Sopenharmony_ci
28451cb0ef41Sopenharmony_ci  req = container_of(w, uv_fs_t, work_req);
28461cb0ef41Sopenharmony_ci  uv__req_unregister(req->loop, req);
28471cb0ef41Sopenharmony_ci
28481cb0ef41Sopenharmony_ci  if (status == UV_ECANCELED) {
28491cb0ef41Sopenharmony_ci    assert(req->result == 0);
28501cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_ECANCELED, 0);
28511cb0ef41Sopenharmony_ci  }
28521cb0ef41Sopenharmony_ci
28531cb0ef41Sopenharmony_ci  req->cb(req);
28541cb0ef41Sopenharmony_ci}
28551cb0ef41Sopenharmony_ci
28561cb0ef41Sopenharmony_ci
28571cb0ef41Sopenharmony_civoid uv_fs_req_cleanup(uv_fs_t* req) {
28581cb0ef41Sopenharmony_ci  if (req == NULL)
28591cb0ef41Sopenharmony_ci    return;
28601cb0ef41Sopenharmony_ci
28611cb0ef41Sopenharmony_ci  if (req->flags & UV_FS_CLEANEDUP)
28621cb0ef41Sopenharmony_ci    return;
28631cb0ef41Sopenharmony_ci
28641cb0ef41Sopenharmony_ci  if (req->flags & UV_FS_FREE_PATHS)
28651cb0ef41Sopenharmony_ci    uv__free(req->file.pathw);
28661cb0ef41Sopenharmony_ci
28671cb0ef41Sopenharmony_ci  if (req->flags & UV_FS_FREE_PTR) {
28681cb0ef41Sopenharmony_ci    if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
28691cb0ef41Sopenharmony_ci      uv__fs_scandir_cleanup(req);
28701cb0ef41Sopenharmony_ci    else if (req->fs_type == UV_FS_READDIR)
28711cb0ef41Sopenharmony_ci      uv__fs_readdir_cleanup(req);
28721cb0ef41Sopenharmony_ci    else
28731cb0ef41Sopenharmony_ci      uv__free(req->ptr);
28741cb0ef41Sopenharmony_ci  }
28751cb0ef41Sopenharmony_ci
28761cb0ef41Sopenharmony_ci  if (req->fs.info.bufs != req->fs.info.bufsml)
28771cb0ef41Sopenharmony_ci    uv__free(req->fs.info.bufs);
28781cb0ef41Sopenharmony_ci
28791cb0ef41Sopenharmony_ci  req->path = NULL;
28801cb0ef41Sopenharmony_ci  req->file.pathw = NULL;
28811cb0ef41Sopenharmony_ci  req->fs.info.new_pathw = NULL;
28821cb0ef41Sopenharmony_ci  req->fs.info.bufs = NULL;
28831cb0ef41Sopenharmony_ci  req->ptr = NULL;
28841cb0ef41Sopenharmony_ci
28851cb0ef41Sopenharmony_ci  req->flags |= UV_FS_CLEANEDUP;
28861cb0ef41Sopenharmony_ci}
28871cb0ef41Sopenharmony_ci
28881cb0ef41Sopenharmony_ci
28891cb0ef41Sopenharmony_ciint uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
28901cb0ef41Sopenharmony_ci    int mode, uv_fs_cb cb) {
28911cb0ef41Sopenharmony_ci  int err;
28921cb0ef41Sopenharmony_ci
28931cb0ef41Sopenharmony_ci  INIT(UV_FS_OPEN);
28941cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
28951cb0ef41Sopenharmony_ci  if (err) {
28961cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
28971cb0ef41Sopenharmony_ci    return req->result;
28981cb0ef41Sopenharmony_ci  }
28991cb0ef41Sopenharmony_ci
29001cb0ef41Sopenharmony_ci  req->fs.info.file_flags = flags;
29011cb0ef41Sopenharmony_ci  req->fs.info.mode = mode;
29021cb0ef41Sopenharmony_ci  POST;
29031cb0ef41Sopenharmony_ci}
29041cb0ef41Sopenharmony_ci
29051cb0ef41Sopenharmony_ci
29061cb0ef41Sopenharmony_ciint uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
29071cb0ef41Sopenharmony_ci  INIT(UV_FS_CLOSE);
29081cb0ef41Sopenharmony_ci  req->file.fd = fd;
29091cb0ef41Sopenharmony_ci  POST;
29101cb0ef41Sopenharmony_ci}
29111cb0ef41Sopenharmony_ci
29121cb0ef41Sopenharmony_ci
29131cb0ef41Sopenharmony_ciint uv_fs_read(uv_loop_t* loop,
29141cb0ef41Sopenharmony_ci               uv_fs_t* req,
29151cb0ef41Sopenharmony_ci               uv_file fd,
29161cb0ef41Sopenharmony_ci               const uv_buf_t bufs[],
29171cb0ef41Sopenharmony_ci               unsigned int nbufs,
29181cb0ef41Sopenharmony_ci               int64_t offset,
29191cb0ef41Sopenharmony_ci               uv_fs_cb cb) {
29201cb0ef41Sopenharmony_ci  INIT(UV_FS_READ);
29211cb0ef41Sopenharmony_ci
29221cb0ef41Sopenharmony_ci  if (bufs == NULL || nbufs == 0) {
29231cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
29241cb0ef41Sopenharmony_ci    return UV_EINVAL;
29251cb0ef41Sopenharmony_ci  }
29261cb0ef41Sopenharmony_ci
29271cb0ef41Sopenharmony_ci  req->file.fd = fd;
29281cb0ef41Sopenharmony_ci
29291cb0ef41Sopenharmony_ci  req->fs.info.nbufs = nbufs;
29301cb0ef41Sopenharmony_ci  req->fs.info.bufs = req->fs.info.bufsml;
29311cb0ef41Sopenharmony_ci  if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
29321cb0ef41Sopenharmony_ci    req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
29331cb0ef41Sopenharmony_ci
29341cb0ef41Sopenharmony_ci  if (req->fs.info.bufs == NULL) {
29351cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
29361cb0ef41Sopenharmony_ci    return UV_ENOMEM;
29371cb0ef41Sopenharmony_ci  }
29381cb0ef41Sopenharmony_ci
29391cb0ef41Sopenharmony_ci  memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
29401cb0ef41Sopenharmony_ci
29411cb0ef41Sopenharmony_ci  req->fs.info.offset = offset;
29421cb0ef41Sopenharmony_ci  POST;
29431cb0ef41Sopenharmony_ci}
29441cb0ef41Sopenharmony_ci
29451cb0ef41Sopenharmony_ci
29461cb0ef41Sopenharmony_ciint uv_fs_write(uv_loop_t* loop,
29471cb0ef41Sopenharmony_ci                uv_fs_t* req,
29481cb0ef41Sopenharmony_ci                uv_file fd,
29491cb0ef41Sopenharmony_ci                const uv_buf_t bufs[],
29501cb0ef41Sopenharmony_ci                unsigned int nbufs,
29511cb0ef41Sopenharmony_ci                int64_t offset,
29521cb0ef41Sopenharmony_ci                uv_fs_cb cb) {
29531cb0ef41Sopenharmony_ci  INIT(UV_FS_WRITE);
29541cb0ef41Sopenharmony_ci
29551cb0ef41Sopenharmony_ci  if (bufs == NULL || nbufs == 0) {
29561cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
29571cb0ef41Sopenharmony_ci    return UV_EINVAL;
29581cb0ef41Sopenharmony_ci  }
29591cb0ef41Sopenharmony_ci
29601cb0ef41Sopenharmony_ci  req->file.fd = fd;
29611cb0ef41Sopenharmony_ci
29621cb0ef41Sopenharmony_ci  req->fs.info.nbufs = nbufs;
29631cb0ef41Sopenharmony_ci  req->fs.info.bufs = req->fs.info.bufsml;
29641cb0ef41Sopenharmony_ci  if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
29651cb0ef41Sopenharmony_ci    req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
29661cb0ef41Sopenharmony_ci
29671cb0ef41Sopenharmony_ci  if (req->fs.info.bufs == NULL) {
29681cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
29691cb0ef41Sopenharmony_ci    return UV_ENOMEM;
29701cb0ef41Sopenharmony_ci  }
29711cb0ef41Sopenharmony_ci
29721cb0ef41Sopenharmony_ci  memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
29731cb0ef41Sopenharmony_ci
29741cb0ef41Sopenharmony_ci  req->fs.info.offset = offset;
29751cb0ef41Sopenharmony_ci  POST;
29761cb0ef41Sopenharmony_ci}
29771cb0ef41Sopenharmony_ci
29781cb0ef41Sopenharmony_ci
29791cb0ef41Sopenharmony_ciint uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
29801cb0ef41Sopenharmony_ci    uv_fs_cb cb) {
29811cb0ef41Sopenharmony_ci  int err;
29821cb0ef41Sopenharmony_ci
29831cb0ef41Sopenharmony_ci  INIT(UV_FS_UNLINK);
29841cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
29851cb0ef41Sopenharmony_ci  if (err) {
29861cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
29871cb0ef41Sopenharmony_ci    return req->result;
29881cb0ef41Sopenharmony_ci  }
29891cb0ef41Sopenharmony_ci
29901cb0ef41Sopenharmony_ci  POST;
29911cb0ef41Sopenharmony_ci}
29921cb0ef41Sopenharmony_ci
29931cb0ef41Sopenharmony_ci
29941cb0ef41Sopenharmony_ciint uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
29951cb0ef41Sopenharmony_ci    uv_fs_cb cb) {
29961cb0ef41Sopenharmony_ci  int err;
29971cb0ef41Sopenharmony_ci
29981cb0ef41Sopenharmony_ci  INIT(UV_FS_MKDIR);
29991cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
30001cb0ef41Sopenharmony_ci  if (err) {
30011cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
30021cb0ef41Sopenharmony_ci    return req->result;
30031cb0ef41Sopenharmony_ci  }
30041cb0ef41Sopenharmony_ci
30051cb0ef41Sopenharmony_ci  req->fs.info.mode = mode;
30061cb0ef41Sopenharmony_ci  POST;
30071cb0ef41Sopenharmony_ci}
30081cb0ef41Sopenharmony_ci
30091cb0ef41Sopenharmony_ci
30101cb0ef41Sopenharmony_ciint uv_fs_mkdtemp(uv_loop_t* loop,
30111cb0ef41Sopenharmony_ci                  uv_fs_t* req,
30121cb0ef41Sopenharmony_ci                  const char* tpl,
30131cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
30141cb0ef41Sopenharmony_ci  int err;
30151cb0ef41Sopenharmony_ci
30161cb0ef41Sopenharmony_ci  INIT(UV_FS_MKDTEMP);
30171cb0ef41Sopenharmony_ci  err = fs__capture_path(req, tpl, NULL, TRUE);
30181cb0ef41Sopenharmony_ci  if (err) {
30191cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
30201cb0ef41Sopenharmony_ci    return req->result;
30211cb0ef41Sopenharmony_ci  }
30221cb0ef41Sopenharmony_ci
30231cb0ef41Sopenharmony_ci  POST;
30241cb0ef41Sopenharmony_ci}
30251cb0ef41Sopenharmony_ci
30261cb0ef41Sopenharmony_ci
30271cb0ef41Sopenharmony_ciint uv_fs_mkstemp(uv_loop_t* loop,
30281cb0ef41Sopenharmony_ci                  uv_fs_t* req,
30291cb0ef41Sopenharmony_ci                  const char* tpl,
30301cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
30311cb0ef41Sopenharmony_ci  int err;
30321cb0ef41Sopenharmony_ci
30331cb0ef41Sopenharmony_ci  INIT(UV_FS_MKSTEMP);
30341cb0ef41Sopenharmony_ci  err = fs__capture_path(req, tpl, NULL, TRUE);
30351cb0ef41Sopenharmony_ci  if (err) {
30361cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
30371cb0ef41Sopenharmony_ci    return req->result;
30381cb0ef41Sopenharmony_ci  }
30391cb0ef41Sopenharmony_ci
30401cb0ef41Sopenharmony_ci  POST;
30411cb0ef41Sopenharmony_ci}
30421cb0ef41Sopenharmony_ci
30431cb0ef41Sopenharmony_ci
30441cb0ef41Sopenharmony_ciint uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
30451cb0ef41Sopenharmony_ci  int err;
30461cb0ef41Sopenharmony_ci
30471cb0ef41Sopenharmony_ci  INIT(UV_FS_RMDIR);
30481cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
30491cb0ef41Sopenharmony_ci  if (err) {
30501cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
30511cb0ef41Sopenharmony_ci    return req->result;
30521cb0ef41Sopenharmony_ci  }
30531cb0ef41Sopenharmony_ci
30541cb0ef41Sopenharmony_ci  POST;
30551cb0ef41Sopenharmony_ci}
30561cb0ef41Sopenharmony_ci
30571cb0ef41Sopenharmony_ci
30581cb0ef41Sopenharmony_ciint uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
30591cb0ef41Sopenharmony_ci    uv_fs_cb cb) {
30601cb0ef41Sopenharmony_ci  int err;
30611cb0ef41Sopenharmony_ci
30621cb0ef41Sopenharmony_ci  INIT(UV_FS_SCANDIR);
30631cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
30641cb0ef41Sopenharmony_ci  if (err) {
30651cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
30661cb0ef41Sopenharmony_ci    return req->result;
30671cb0ef41Sopenharmony_ci  }
30681cb0ef41Sopenharmony_ci
30691cb0ef41Sopenharmony_ci  req->fs.info.file_flags = flags;
30701cb0ef41Sopenharmony_ci  POST;
30711cb0ef41Sopenharmony_ci}
30721cb0ef41Sopenharmony_ci
30731cb0ef41Sopenharmony_ciint uv_fs_opendir(uv_loop_t* loop,
30741cb0ef41Sopenharmony_ci                  uv_fs_t* req,
30751cb0ef41Sopenharmony_ci                  const char* path,
30761cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
30771cb0ef41Sopenharmony_ci  int err;
30781cb0ef41Sopenharmony_ci
30791cb0ef41Sopenharmony_ci  INIT(UV_FS_OPENDIR);
30801cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
30811cb0ef41Sopenharmony_ci  if (err) {
30821cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
30831cb0ef41Sopenharmony_ci    return req->result;
30841cb0ef41Sopenharmony_ci  }
30851cb0ef41Sopenharmony_ci  POST;
30861cb0ef41Sopenharmony_ci}
30871cb0ef41Sopenharmony_ci
30881cb0ef41Sopenharmony_ciint uv_fs_readdir(uv_loop_t* loop,
30891cb0ef41Sopenharmony_ci                  uv_fs_t* req,
30901cb0ef41Sopenharmony_ci                  uv_dir_t* dir,
30911cb0ef41Sopenharmony_ci                  uv_fs_cb cb) {
30921cb0ef41Sopenharmony_ci  INIT(UV_FS_READDIR);
30931cb0ef41Sopenharmony_ci
30941cb0ef41Sopenharmony_ci  if (dir == NULL ||
30951cb0ef41Sopenharmony_ci      dir->dirents == NULL ||
30961cb0ef41Sopenharmony_ci      dir->dir_handle == INVALID_HANDLE_VALUE) {
30971cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
30981cb0ef41Sopenharmony_ci    return UV_EINVAL;
30991cb0ef41Sopenharmony_ci  }
31001cb0ef41Sopenharmony_ci
31011cb0ef41Sopenharmony_ci  req->ptr = dir;
31021cb0ef41Sopenharmony_ci  POST;
31031cb0ef41Sopenharmony_ci}
31041cb0ef41Sopenharmony_ci
31051cb0ef41Sopenharmony_ciint uv_fs_closedir(uv_loop_t* loop,
31061cb0ef41Sopenharmony_ci                   uv_fs_t* req,
31071cb0ef41Sopenharmony_ci                   uv_dir_t* dir,
31081cb0ef41Sopenharmony_ci                   uv_fs_cb cb) {
31091cb0ef41Sopenharmony_ci  INIT(UV_FS_CLOSEDIR);
31101cb0ef41Sopenharmony_ci  if (dir == NULL) {
31111cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
31121cb0ef41Sopenharmony_ci    return UV_EINVAL;
31131cb0ef41Sopenharmony_ci  }
31141cb0ef41Sopenharmony_ci  req->ptr = dir;
31151cb0ef41Sopenharmony_ci  POST;
31161cb0ef41Sopenharmony_ci}
31171cb0ef41Sopenharmony_ci
31181cb0ef41Sopenharmony_ciint uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
31191cb0ef41Sopenharmony_ci    const char* new_path, uv_fs_cb cb) {
31201cb0ef41Sopenharmony_ci  int err;
31211cb0ef41Sopenharmony_ci
31221cb0ef41Sopenharmony_ci  INIT(UV_FS_LINK);
31231cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, new_path, cb != NULL);
31241cb0ef41Sopenharmony_ci  if (err) {
31251cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
31261cb0ef41Sopenharmony_ci    return req->result;
31271cb0ef41Sopenharmony_ci  }
31281cb0ef41Sopenharmony_ci
31291cb0ef41Sopenharmony_ci  POST;
31301cb0ef41Sopenharmony_ci}
31311cb0ef41Sopenharmony_ci
31321cb0ef41Sopenharmony_ci
31331cb0ef41Sopenharmony_ciint uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
31341cb0ef41Sopenharmony_ci    const char* new_path, int flags, uv_fs_cb cb) {
31351cb0ef41Sopenharmony_ci  int err;
31361cb0ef41Sopenharmony_ci
31371cb0ef41Sopenharmony_ci  INIT(UV_FS_SYMLINK);
31381cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, new_path, cb != NULL);
31391cb0ef41Sopenharmony_ci  if (err) {
31401cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
31411cb0ef41Sopenharmony_ci    return req->result;
31421cb0ef41Sopenharmony_ci  }
31431cb0ef41Sopenharmony_ci
31441cb0ef41Sopenharmony_ci  req->fs.info.file_flags = flags;
31451cb0ef41Sopenharmony_ci  POST;
31461cb0ef41Sopenharmony_ci}
31471cb0ef41Sopenharmony_ci
31481cb0ef41Sopenharmony_ci
31491cb0ef41Sopenharmony_ciint uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
31501cb0ef41Sopenharmony_ci    uv_fs_cb cb) {
31511cb0ef41Sopenharmony_ci  int err;
31521cb0ef41Sopenharmony_ci
31531cb0ef41Sopenharmony_ci  INIT(UV_FS_READLINK);
31541cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
31551cb0ef41Sopenharmony_ci  if (err) {
31561cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
31571cb0ef41Sopenharmony_ci    return req->result;
31581cb0ef41Sopenharmony_ci  }
31591cb0ef41Sopenharmony_ci
31601cb0ef41Sopenharmony_ci  POST;
31611cb0ef41Sopenharmony_ci}
31621cb0ef41Sopenharmony_ci
31631cb0ef41Sopenharmony_ci
31641cb0ef41Sopenharmony_ciint uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,
31651cb0ef41Sopenharmony_ci    uv_fs_cb cb) {
31661cb0ef41Sopenharmony_ci  int err;
31671cb0ef41Sopenharmony_ci
31681cb0ef41Sopenharmony_ci  INIT(UV_FS_REALPATH);
31691cb0ef41Sopenharmony_ci
31701cb0ef41Sopenharmony_ci  if (!path) {
31711cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
31721cb0ef41Sopenharmony_ci    return UV_EINVAL;
31731cb0ef41Sopenharmony_ci  }
31741cb0ef41Sopenharmony_ci
31751cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
31761cb0ef41Sopenharmony_ci  if (err) {
31771cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
31781cb0ef41Sopenharmony_ci    return req->result;
31791cb0ef41Sopenharmony_ci  }
31801cb0ef41Sopenharmony_ci
31811cb0ef41Sopenharmony_ci  POST;
31821cb0ef41Sopenharmony_ci}
31831cb0ef41Sopenharmony_ci
31841cb0ef41Sopenharmony_ci
31851cb0ef41Sopenharmony_ciint uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
31861cb0ef41Sopenharmony_ci    uv_gid_t gid, uv_fs_cb cb) {
31871cb0ef41Sopenharmony_ci  int err;
31881cb0ef41Sopenharmony_ci
31891cb0ef41Sopenharmony_ci  INIT(UV_FS_CHOWN);
31901cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
31911cb0ef41Sopenharmony_ci  if (err) {
31921cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
31931cb0ef41Sopenharmony_ci    return req->result;
31941cb0ef41Sopenharmony_ci  }
31951cb0ef41Sopenharmony_ci
31961cb0ef41Sopenharmony_ci  POST;
31971cb0ef41Sopenharmony_ci}
31981cb0ef41Sopenharmony_ci
31991cb0ef41Sopenharmony_ci
32001cb0ef41Sopenharmony_ciint uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid,
32011cb0ef41Sopenharmony_ci    uv_gid_t gid, uv_fs_cb cb) {
32021cb0ef41Sopenharmony_ci  INIT(UV_FS_FCHOWN);
32031cb0ef41Sopenharmony_ci  POST;
32041cb0ef41Sopenharmony_ci}
32051cb0ef41Sopenharmony_ci
32061cb0ef41Sopenharmony_ci
32071cb0ef41Sopenharmony_ciint uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
32081cb0ef41Sopenharmony_ci    uv_gid_t gid, uv_fs_cb cb) {
32091cb0ef41Sopenharmony_ci  int err;
32101cb0ef41Sopenharmony_ci
32111cb0ef41Sopenharmony_ci  INIT(UV_FS_LCHOWN);
32121cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
32131cb0ef41Sopenharmony_ci  if (err) {
32141cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
32151cb0ef41Sopenharmony_ci    return req->result;
32161cb0ef41Sopenharmony_ci  }
32171cb0ef41Sopenharmony_ci
32181cb0ef41Sopenharmony_ci  POST;
32191cb0ef41Sopenharmony_ci}
32201cb0ef41Sopenharmony_ci
32211cb0ef41Sopenharmony_ci
32221cb0ef41Sopenharmony_ciint uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
32231cb0ef41Sopenharmony_ci  int err;
32241cb0ef41Sopenharmony_ci
32251cb0ef41Sopenharmony_ci  INIT(UV_FS_STAT);
32261cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
32271cb0ef41Sopenharmony_ci  if (err) {
32281cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
32291cb0ef41Sopenharmony_ci    return req->result;
32301cb0ef41Sopenharmony_ci  }
32311cb0ef41Sopenharmony_ci
32321cb0ef41Sopenharmony_ci  POST;
32331cb0ef41Sopenharmony_ci}
32341cb0ef41Sopenharmony_ci
32351cb0ef41Sopenharmony_ci
32361cb0ef41Sopenharmony_ciint uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
32371cb0ef41Sopenharmony_ci  int err;
32381cb0ef41Sopenharmony_ci
32391cb0ef41Sopenharmony_ci  INIT(UV_FS_LSTAT);
32401cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
32411cb0ef41Sopenharmony_ci  if (err) {
32421cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
32431cb0ef41Sopenharmony_ci    return req->result;
32441cb0ef41Sopenharmony_ci  }
32451cb0ef41Sopenharmony_ci
32461cb0ef41Sopenharmony_ci  POST;
32471cb0ef41Sopenharmony_ci}
32481cb0ef41Sopenharmony_ci
32491cb0ef41Sopenharmony_ci
32501cb0ef41Sopenharmony_ciint uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
32511cb0ef41Sopenharmony_ci  INIT(UV_FS_FSTAT);
32521cb0ef41Sopenharmony_ci  req->file.fd = fd;
32531cb0ef41Sopenharmony_ci  POST;
32541cb0ef41Sopenharmony_ci}
32551cb0ef41Sopenharmony_ci
32561cb0ef41Sopenharmony_ci
32571cb0ef41Sopenharmony_ciint uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
32581cb0ef41Sopenharmony_ci    const char* new_path, uv_fs_cb cb) {
32591cb0ef41Sopenharmony_ci  int err;
32601cb0ef41Sopenharmony_ci
32611cb0ef41Sopenharmony_ci  INIT(UV_FS_RENAME);
32621cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, new_path, cb != NULL);
32631cb0ef41Sopenharmony_ci  if (err) {
32641cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
32651cb0ef41Sopenharmony_ci    return req->result;
32661cb0ef41Sopenharmony_ci  }
32671cb0ef41Sopenharmony_ci
32681cb0ef41Sopenharmony_ci  POST;
32691cb0ef41Sopenharmony_ci}
32701cb0ef41Sopenharmony_ci
32711cb0ef41Sopenharmony_ci
32721cb0ef41Sopenharmony_ciint uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
32731cb0ef41Sopenharmony_ci  INIT(UV_FS_FSYNC);
32741cb0ef41Sopenharmony_ci  req->file.fd = fd;
32751cb0ef41Sopenharmony_ci  POST;
32761cb0ef41Sopenharmony_ci}
32771cb0ef41Sopenharmony_ci
32781cb0ef41Sopenharmony_ci
32791cb0ef41Sopenharmony_ciint uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
32801cb0ef41Sopenharmony_ci  INIT(UV_FS_FDATASYNC);
32811cb0ef41Sopenharmony_ci  req->file.fd = fd;
32821cb0ef41Sopenharmony_ci  POST;
32831cb0ef41Sopenharmony_ci}
32841cb0ef41Sopenharmony_ci
32851cb0ef41Sopenharmony_ci
32861cb0ef41Sopenharmony_ciint uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file fd,
32871cb0ef41Sopenharmony_ci    int64_t offset, uv_fs_cb cb) {
32881cb0ef41Sopenharmony_ci  INIT(UV_FS_FTRUNCATE);
32891cb0ef41Sopenharmony_ci  req->file.fd = fd;
32901cb0ef41Sopenharmony_ci  req->fs.info.offset = offset;
32911cb0ef41Sopenharmony_ci  POST;
32921cb0ef41Sopenharmony_ci}
32931cb0ef41Sopenharmony_ci
32941cb0ef41Sopenharmony_ci
32951cb0ef41Sopenharmony_ciint uv_fs_copyfile(uv_loop_t* loop,
32961cb0ef41Sopenharmony_ci                   uv_fs_t* req,
32971cb0ef41Sopenharmony_ci                   const char* path,
32981cb0ef41Sopenharmony_ci                   const char* new_path,
32991cb0ef41Sopenharmony_ci                   int flags,
33001cb0ef41Sopenharmony_ci                   uv_fs_cb cb) {
33011cb0ef41Sopenharmony_ci  int err;
33021cb0ef41Sopenharmony_ci
33031cb0ef41Sopenharmony_ci  INIT(UV_FS_COPYFILE);
33041cb0ef41Sopenharmony_ci
33051cb0ef41Sopenharmony_ci  if (flags & ~(UV_FS_COPYFILE_EXCL |
33061cb0ef41Sopenharmony_ci                UV_FS_COPYFILE_FICLONE |
33071cb0ef41Sopenharmony_ci                UV_FS_COPYFILE_FICLONE_FORCE)) {
33081cb0ef41Sopenharmony_ci    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
33091cb0ef41Sopenharmony_ci    return UV_EINVAL;
33101cb0ef41Sopenharmony_ci  }
33111cb0ef41Sopenharmony_ci
33121cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, new_path, cb != NULL);
33131cb0ef41Sopenharmony_ci  if (err) {
33141cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
33151cb0ef41Sopenharmony_ci    return req->result;
33161cb0ef41Sopenharmony_ci  }
33171cb0ef41Sopenharmony_ci
33181cb0ef41Sopenharmony_ci  req->fs.info.file_flags = flags;
33191cb0ef41Sopenharmony_ci  POST;
33201cb0ef41Sopenharmony_ci}
33211cb0ef41Sopenharmony_ci
33221cb0ef41Sopenharmony_ci
33231cb0ef41Sopenharmony_ciint uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out,
33241cb0ef41Sopenharmony_ci    uv_file fd_in, int64_t in_offset, size_t length, uv_fs_cb cb) {
33251cb0ef41Sopenharmony_ci  INIT(UV_FS_SENDFILE);
33261cb0ef41Sopenharmony_ci  req->file.fd = fd_in;
33271cb0ef41Sopenharmony_ci  req->fs.info.fd_out = fd_out;
33281cb0ef41Sopenharmony_ci  req->fs.info.offset = in_offset;
33291cb0ef41Sopenharmony_ci  req->fs.info.bufsml[0].len = length;
33301cb0ef41Sopenharmony_ci  POST;
33311cb0ef41Sopenharmony_ci}
33321cb0ef41Sopenharmony_ci
33331cb0ef41Sopenharmony_ci
33341cb0ef41Sopenharmony_ciint uv_fs_access(uv_loop_t* loop,
33351cb0ef41Sopenharmony_ci                 uv_fs_t* req,
33361cb0ef41Sopenharmony_ci                 const char* path,
33371cb0ef41Sopenharmony_ci                 int flags,
33381cb0ef41Sopenharmony_ci                 uv_fs_cb cb) {
33391cb0ef41Sopenharmony_ci  int err;
33401cb0ef41Sopenharmony_ci
33411cb0ef41Sopenharmony_ci  INIT(UV_FS_ACCESS);
33421cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
33431cb0ef41Sopenharmony_ci  if (err) {
33441cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
33451cb0ef41Sopenharmony_ci    return req->result;
33461cb0ef41Sopenharmony_ci  }
33471cb0ef41Sopenharmony_ci
33481cb0ef41Sopenharmony_ci  req->fs.info.mode = flags;
33491cb0ef41Sopenharmony_ci  POST;
33501cb0ef41Sopenharmony_ci}
33511cb0ef41Sopenharmony_ci
33521cb0ef41Sopenharmony_ci
33531cb0ef41Sopenharmony_ciint uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
33541cb0ef41Sopenharmony_ci    uv_fs_cb cb) {
33551cb0ef41Sopenharmony_ci  int err;
33561cb0ef41Sopenharmony_ci
33571cb0ef41Sopenharmony_ci  INIT(UV_FS_CHMOD);
33581cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
33591cb0ef41Sopenharmony_ci  if (err) {
33601cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
33611cb0ef41Sopenharmony_ci    return req->result;
33621cb0ef41Sopenharmony_ci  }
33631cb0ef41Sopenharmony_ci
33641cb0ef41Sopenharmony_ci  req->fs.info.mode = mode;
33651cb0ef41Sopenharmony_ci  POST;
33661cb0ef41Sopenharmony_ci}
33671cb0ef41Sopenharmony_ci
33681cb0ef41Sopenharmony_ci
33691cb0ef41Sopenharmony_ciint uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int mode,
33701cb0ef41Sopenharmony_ci    uv_fs_cb cb) {
33711cb0ef41Sopenharmony_ci  INIT(UV_FS_FCHMOD);
33721cb0ef41Sopenharmony_ci  req->file.fd = fd;
33731cb0ef41Sopenharmony_ci  req->fs.info.mode = mode;
33741cb0ef41Sopenharmony_ci  POST;
33751cb0ef41Sopenharmony_ci}
33761cb0ef41Sopenharmony_ci
33771cb0ef41Sopenharmony_ci
33781cb0ef41Sopenharmony_ciint uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
33791cb0ef41Sopenharmony_ci    double mtime, uv_fs_cb cb) {
33801cb0ef41Sopenharmony_ci  int err;
33811cb0ef41Sopenharmony_ci
33821cb0ef41Sopenharmony_ci  INIT(UV_FS_UTIME);
33831cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
33841cb0ef41Sopenharmony_ci  if (err) {
33851cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
33861cb0ef41Sopenharmony_ci    return req->result;
33871cb0ef41Sopenharmony_ci  }
33881cb0ef41Sopenharmony_ci
33891cb0ef41Sopenharmony_ci  req->fs.time.atime = atime;
33901cb0ef41Sopenharmony_ci  req->fs.time.mtime = mtime;
33911cb0ef41Sopenharmony_ci  POST;
33921cb0ef41Sopenharmony_ci}
33931cb0ef41Sopenharmony_ci
33941cb0ef41Sopenharmony_ci
33951cb0ef41Sopenharmony_ciint uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime,
33961cb0ef41Sopenharmony_ci    double mtime, uv_fs_cb cb) {
33971cb0ef41Sopenharmony_ci  INIT(UV_FS_FUTIME);
33981cb0ef41Sopenharmony_ci  req->file.fd = fd;
33991cb0ef41Sopenharmony_ci  req->fs.time.atime = atime;
34001cb0ef41Sopenharmony_ci  req->fs.time.mtime = mtime;
34011cb0ef41Sopenharmony_ci  POST;
34021cb0ef41Sopenharmony_ci}
34031cb0ef41Sopenharmony_ci
34041cb0ef41Sopenharmony_ciint uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
34051cb0ef41Sopenharmony_ci    double mtime, uv_fs_cb cb) {
34061cb0ef41Sopenharmony_ci  int err;
34071cb0ef41Sopenharmony_ci
34081cb0ef41Sopenharmony_ci  INIT(UV_FS_LUTIME);
34091cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
34101cb0ef41Sopenharmony_ci  if (err) {
34111cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
34121cb0ef41Sopenharmony_ci    return req->result;
34131cb0ef41Sopenharmony_ci  }
34141cb0ef41Sopenharmony_ci
34151cb0ef41Sopenharmony_ci  req->fs.time.atime = atime;
34161cb0ef41Sopenharmony_ci  req->fs.time.mtime = mtime;
34171cb0ef41Sopenharmony_ci  POST;
34181cb0ef41Sopenharmony_ci}
34191cb0ef41Sopenharmony_ci
34201cb0ef41Sopenharmony_ci
34211cb0ef41Sopenharmony_ciint uv_fs_statfs(uv_loop_t* loop,
34221cb0ef41Sopenharmony_ci                 uv_fs_t* req,
34231cb0ef41Sopenharmony_ci                 const char* path,
34241cb0ef41Sopenharmony_ci                 uv_fs_cb cb) {
34251cb0ef41Sopenharmony_ci  int err;
34261cb0ef41Sopenharmony_ci
34271cb0ef41Sopenharmony_ci  INIT(UV_FS_STATFS);
34281cb0ef41Sopenharmony_ci  err = fs__capture_path(req, path, NULL, cb != NULL);
34291cb0ef41Sopenharmony_ci  if (err) {
34301cb0ef41Sopenharmony_ci    SET_REQ_WIN32_ERROR(req, err);
34311cb0ef41Sopenharmony_ci    return req->result;
34321cb0ef41Sopenharmony_ci  }
34331cb0ef41Sopenharmony_ci
34341cb0ef41Sopenharmony_ci  POST;
34351cb0ef41Sopenharmony_ci}
34361cb0ef41Sopenharmony_ci
34371cb0ef41Sopenharmony_ciint uv_fs_get_system_error(const uv_fs_t* req) {
34381cb0ef41Sopenharmony_ci  return req->sys_errno_;
34391cb0ef41Sopenharmony_ci}
3440