Blame src/win/fs.c

Packit Service 7c31a4
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit Service 7c31a4
 * of this software and associated documentation files (the "Software"), to
Packit Service 7c31a4
 * deal in the Software without restriction, including without limitation the
Packit Service 7c31a4
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit Service 7c31a4
 * sell copies of the Software, and to permit persons to whom the Software is
Packit Service 7c31a4
 * furnished to do so, subject to the following conditions:
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * The above copyright notice and this permission notice shall be included in
Packit Service 7c31a4
 * all copies or substantial portions of the Software.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service 7c31a4
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service 7c31a4
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Packit Service 7c31a4
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit Service 7c31a4
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit Service 7c31a4
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Packit Service 7c31a4
 * IN THE SOFTWARE.
Packit Service 7c31a4
 */
Packit Service 7c31a4
Packit Service 7c31a4
#include <assert.h>
Packit Service 7c31a4
#include <stdlib.h>
Packit Service 7c31a4
#include <direct.h>
Packit Service 7c31a4
#include <errno.h>
Packit Service 7c31a4
#include <fcntl.h>
Packit Service 7c31a4
#include <io.h>
Packit Service 7c31a4
#include <limits.h>
Packit Service 7c31a4
#include <sys/stat.h>
Packit Service 7c31a4
#include <sys/utime.h>
Packit Service 7c31a4
#include <stdio.h>
Packit Service 7c31a4
Packit Service 7c31a4
#include "uv.h"
Packit Service 7c31a4
#include "internal.h"
Packit Service 7c31a4
#include "req-inl.h"
Packit Service 7c31a4
#include "handle-inl.h"
Packit Service 7c31a4
#include "fs-fd-hash-inl.h"
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#define UV_FS_FREE_PATHS         0x0002
Packit Service 7c31a4
#define UV_FS_FREE_PTR           0x0008
Packit Service 7c31a4
#define UV_FS_CLEANEDUP          0x0010
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#define INIT(subtype)                                                         \
Packit Service 7c31a4
  do {                                                                        \
Packit Service 7c31a4
    if (req == NULL)                                                          \
Packit Service 7c31a4
      return UV_EINVAL;                                                       \
Packit Service 7c31a4
    uv_fs_req_init(loop, req, subtype, cb);                                   \
Packit Service 7c31a4
  }                                                                           \
Packit Service 7c31a4
  while (0)
Packit Service 7c31a4
Packit Service 7c31a4
#define POST                                                                  \
Packit Service 7c31a4
  do {                                                                        \
Packit Service 7c31a4
    if (cb != NULL) {                                                         \
Packit Service 7c31a4
      uv__req_register(loop, req);                                            \
Packit Service 7c31a4
      uv__work_submit(loop,                                                   \
Packit Service 7c31a4
                      &req->work_req,                                         \
Packit Service 7c31a4
                      UV__WORK_FAST_IO,                                       \
Packit Service 7c31a4
                      uv__fs_work,                                            \
Packit Service 7c31a4
                      uv__fs_done);                                           \
Packit Service 7c31a4
      return 0;                                                               \
Packit Service 7c31a4
    } else {                                                                  \
Packit Service 7c31a4
      uv__fs_work(&req->work_req);                                            \
Packit Service 7c31a4
      return req->result;                                                     \
Packit Service 7c31a4
    }                                                                         \
Packit Service 7c31a4
  }                                                                           \
Packit Service 7c31a4
  while (0)
Packit Service 7c31a4
Packit Service 7c31a4
#define SET_REQ_RESULT(req, result_value)                                   \
Packit Service 7c31a4
  do {                                                                      \
Packit Service 7c31a4
    req->result = (result_value);                                           \
Packit Service e2ebee
    assert(req->result != -1);                                              \
Packit Service 7c31a4
  } while (0)
Packit Service 7c31a4
Packit Service 7c31a4
#define SET_REQ_WIN32_ERROR(req, sys_errno)                                 \
Packit Service 7c31a4
  do {                                                                      \
Packit Service 7c31a4
    req->sys_errno_ = (sys_errno);                                          \
Packit Service 7c31a4
    req->result = uv_translate_sys_error(req->sys_errno_);                  \
Packit Service 7c31a4
  } while (0)
Packit Service 7c31a4
Packit Service 7c31a4
#define SET_REQ_UV_ERROR(req, uv_errno, sys_errno)                          \
Packit Service 7c31a4
  do {                                                                      \
Packit Service 7c31a4
    req->result = (uv_errno);                                               \
Packit Service 7c31a4
    req->sys_errno_ = (sys_errno);                                          \
Packit Service 7c31a4
  } while (0)
Packit Service 7c31a4
Packit Service 7c31a4
#define VERIFY_FD(fd, req)                                                  \
Packit Service 7c31a4
  if (fd == -1) {                                                           \
Packit Service 7c31a4
    req->result = UV_EBADF;                                                 \
Packit Service 7c31a4
    req->sys_errno_ = ERROR_INVALID_HANDLE;                                 \
Packit Service 7c31a4
    return;                                                                 \
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
#define MILLIONu (1000U * 1000U)
Packit Service 7c31a4
#define BILLIONu (1000U * 1000U * 1000U)
Packit Service 7c31a4
Packit Service 7c31a4
#define FILETIME_TO_UINT(filetime)                                          \
Packit Service 7c31a4
   (*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu)
Packit Service 7c31a4
Packit Service 7c31a4
#define FILETIME_TO_TIME_T(filetime)                                        \
Packit Service 7c31a4
   (FILETIME_TO_UINT(filetime) / (10u * MILLIONu))
Packit Service 7c31a4
Packit Service 7c31a4
#define FILETIME_TO_TIME_NS(filetime, secs)                                 \
Packit Service 7c31a4
   ((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U)
Packit Service 7c31a4
Packit Service 7c31a4
#define FILETIME_TO_TIMESPEC(ts, filetime)                                  \
Packit Service 7c31a4
   do {                                                                     \
Packit Service 7c31a4
     (ts).tv_sec = (long) FILETIME_TO_TIME_T(filetime);                     \
Packit Service 7c31a4
     (ts).tv_nsec = (long) FILETIME_TO_TIME_NS(filetime, (ts).tv_sec);      \
Packit Service 7c31a4
   } while(0)
Packit Service 7c31a4
Packit Service 7c31a4
#define TIME_T_TO_FILETIME(time, filetime_ptr)                              \
Packit Service 7c31a4
  do {                                                                      \
Packit Service 7c31a4
    uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) +   \
Packit Service 7c31a4
                       (uint64_t) 116444736 * BILLIONu;                     \
Packit Service 7c31a4
    (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF;                   \
Packit Service 7c31a4
    (filetime_ptr)->dwHighDateTime = bigtime >> 32;                         \
Packit Service 7c31a4
  } while(0)
Packit Service 7c31a4
Packit Service 7c31a4
#define IS_SLASH(c) ((c) == L'\\' || (c) == L'/')
Packit Service 7c31a4
#define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \
Packit Service 7c31a4
  ((c) >= L'A' && (c) <= L'Z'))
Packit Service 7c31a4
Packit Service 7c31a4
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
Packit Service 7c31a4
Packit Service 7c31a4
const WCHAR JUNCTION_PREFIX[] = L"\\??\\";
Packit Service 7c31a4
const WCHAR JUNCTION_PREFIX_LEN = 4;
Packit Service 7c31a4
Packit Service 7c31a4
const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\";
Packit Service 7c31a4
const WCHAR LONG_PATH_PREFIX_LEN = 4;
Packit Service 7c31a4
Packit Service 7c31a4
const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
Packit Service 7c31a4
const WCHAR UNC_PATH_PREFIX_LEN = 8;
Packit Service 7c31a4
Packit Service 7c31a4
static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
Packit Service 7c31a4
Packit Service 7c31a4
static DWORD uv__allocation_granularity;
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv_fs_init(void) {
Packit Service 7c31a4
  SYSTEM_INFO system_info;
Packit Service 7c31a4
Packit Service 7c31a4
  GetSystemInfo(&system_info);
Packit Service 7c31a4
  uv__allocation_granularity = system_info.dwAllocationGranularity;
Packit Service 7c31a4
Packit Service 7c31a4
  uv__fd_hash_init();
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
Packit Service 7c31a4
    const char* new_path, const int copy_path) {
Packit Service 7c31a4
  char* buf;
Packit Service 7c31a4
  char* pos;
Packit Service 7c31a4
  ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  /* new_path can only be set if path is also set. */
Packit Service 7c31a4
  assert(new_path == NULL || path != NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (path != NULL) {
Packit Service 7c31a4
    pathw_len = MultiByteToWideChar(CP_UTF8,
Packit Service 7c31a4
                                    0,
Packit Service 7c31a4
                                    path,
Packit Service 7c31a4
                                    -1,
Packit Service 7c31a4
                                    NULL,
Packit Service 7c31a4
                                    0);
Packit Service 7c31a4
    if (pathw_len == 0) {
Packit Service 7c31a4
      return GetLastError();
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    buf_sz += pathw_len * sizeof(WCHAR);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (path != NULL && copy_path) {
Packit Service 7c31a4
    path_len = 1 + strlen(path);
Packit Service 7c31a4
    buf_sz += path_len;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (new_path != NULL) {
Packit Service 7c31a4
    new_pathw_len = MultiByteToWideChar(CP_UTF8,
Packit Service 7c31a4
                                        0,
Packit Service 7c31a4
                                        new_path,
Packit Service 7c31a4
                                        -1,
Packit Service 7c31a4
                                        NULL,
Packit Service 7c31a4
                                        0);
Packit Service 7c31a4
    if (new_pathw_len == 0) {
Packit Service 7c31a4
      return GetLastError();
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    buf_sz += new_pathw_len * sizeof(WCHAR);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
  if (buf_sz == 0) {
Packit Service 7c31a4
    req->file.pathw = NULL;
Packit Service 7c31a4
    req->fs.info.new_pathw = NULL;
Packit Service 7c31a4
    req->path = NULL;
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  buf = (char*) uv__malloc(buf_sz);
Packit Service 7c31a4
  if (buf == NULL) {
Packit Service 7c31a4
    return ERROR_OUTOFMEMORY;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  pos = buf;
Packit Service 7c31a4
Packit Service 7c31a4
  if (path != NULL) {
Packit Service 7c31a4
    DWORD r = MultiByteToWideChar(CP_UTF8,
Packit Service 7c31a4
                                  0,
Packit Service 7c31a4
                                  path,
Packit Service 7c31a4
                                  -1,
Packit Service 7c31a4
                                  (WCHAR*) pos,
Packit Service 7c31a4
                                  pathw_len);
Packit Service 7c31a4
    assert(r == (DWORD) pathw_len);
Packit Service 7c31a4
    req->file.pathw = (WCHAR*) pos;
Packit Service 7c31a4
    pos += r * sizeof(WCHAR);
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    req->file.pathw = NULL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (new_path != NULL) {
Packit Service 7c31a4
    DWORD r = MultiByteToWideChar(CP_UTF8,
Packit Service 7c31a4
                                  0,
Packit Service 7c31a4
                                  new_path,
Packit Service 7c31a4
                                  -1,
Packit Service 7c31a4
                                  (WCHAR*) pos,
Packit Service 7c31a4
                                  new_pathw_len);
Packit Service 7c31a4
    assert(r == (DWORD) new_pathw_len);
Packit Service 7c31a4
    req->fs.info.new_pathw = (WCHAR*) pos;
Packit Service 7c31a4
    pos += r * sizeof(WCHAR);
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    req->fs.info.new_pathw = NULL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->path = path;
Packit Service 7c31a4
  if (path != NULL && copy_path) {
Packit Service 7c31a4
    memcpy(pos, path, path_len);
Packit Service 7c31a4
    assert(path_len == buf_sz - (pos - buf));
Packit Service 7c31a4
    req->path = pos;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->flags |= UV_FS_FREE_PATHS;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
Packit Service 7c31a4
    uv_fs_type fs_type, const uv_fs_cb cb) {
Packit Service 7c31a4
  uv__once_init();
Packit Service 7c31a4
  UV_REQ_INIT(req, UV_FS);
Packit Service 7c31a4
  req->loop = loop;
Packit Service 7c31a4
  req->flags = 0;
Packit Service 7c31a4
  req->fs_type = fs_type;
Packit Service 7c31a4
  req->sys_errno_ = 0;
Packit Service 7c31a4
  req->result = 0;
Packit Service 7c31a4
  req->ptr = NULL;
Packit Service 7c31a4
  req->path = NULL;
Packit Service 7c31a4
  req->cb = cb;
Packit Service 7c31a4
  memset(&req->fs, 0, sizeof(req->fs));
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static int fs__wide_to_utf8(WCHAR* w_source_ptr,
Packit Service 7c31a4
                               DWORD w_source_len,
Packit Service 7c31a4
                               char** target_ptr,
Packit Service 7c31a4
                               uint64_t* target_len_ptr) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  int target_len;
Packit Service 7c31a4
  char* target;
Packit Service 7c31a4
  target_len = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                                   0,
Packit Service 7c31a4
                                   w_source_ptr,
Packit Service 7c31a4
                                   w_source_len,
Packit Service 7c31a4
                                   NULL,
Packit Service 7c31a4
                                   0,
Packit Service 7c31a4
                                   NULL,
Packit Service 7c31a4
                                   NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (target_len == 0) {
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (target_len_ptr != NULL) {
Packit Service 7c31a4
    *target_len_ptr = target_len;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (target_ptr == NULL) {
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  target = uv__malloc(target_len + 1);
Packit Service 7c31a4
  if (target == NULL) {
Packit Service 7c31a4
    SetLastError(ERROR_OUTOFMEMORY);
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  r = WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                          0,
Packit Service 7c31a4
                          w_source_ptr,
Packit Service 7c31a4
                          w_source_len,
Packit Service 7c31a4
                          target,
Packit Service 7c31a4
                          target_len,
Packit Service 7c31a4
                          NULL,
Packit Service 7c31a4
                          NULL);
Packit Service 7c31a4
  assert(r == target_len);
Packit Service 7c31a4
  target[target_len] = '\0';
Packit Service 7c31a4
  *target_ptr = target;
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
Packit Service 7c31a4
    uint64_t* target_len_ptr) {
Packit Service 7c31a4
  char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
Packit Service 7c31a4
  REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer;
Packit Service 7c31a4
  WCHAR* w_target;
Packit Service 7c31a4
  DWORD w_target_len;
Packit Service 7c31a4
  DWORD bytes;
Packit Service 7c31a4
  size_t i;
Packit Service 7c31a4
  size_t len;
Packit Service 7c31a4
Packit Service 7c31a4
  if (!DeviceIoControl(handle,
Packit Service 7c31a4
                       FSCTL_GET_REPARSE_POINT,
Packit Service 7c31a4
                       NULL,
Packit Service 7c31a4
                       0,
Packit Service 7c31a4
                       buffer,
Packit Service 7c31a4
                       sizeof buffer,
Packit Service 7c31a4
                       &bytes,
Packit Service 7c31a4
                       NULL)) {
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
Packit Service 7c31a4
    /* Real symlink */
Packit Service 7c31a4
    w_target = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
Packit Service 7c31a4
        (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset /
Packit Service 7c31a4
        sizeof(WCHAR));
Packit Service 7c31a4
    w_target_len =
Packit Service 7c31a4
        reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
Packit Service 7c31a4
        sizeof(WCHAR);
Packit Service 7c31a4
Packit Service 7c31a4
    /* Real symlinks can contain pretty much everything, but the only thing we
Packit Service 7c31a4
     * really care about is undoing the implicit conversion to an NT namespaced
Packit Service 7c31a4
     * path that CreateSymbolicLink will perform on absolute paths. If the path
Packit Service 7c31a4
     * is win32-namespaced then the user must have explicitly made it so, and
Packit Service 7c31a4
     * we better just return the unmodified reparse data. */
Packit Service 7c31a4
    if (w_target_len >= 4 &&
Packit Service 7c31a4
        w_target[0] == L'\\' &&
Packit Service 7c31a4
        w_target[1] == L'?' &&
Packit Service 7c31a4
        w_target[2] == L'?' &&
Packit Service 7c31a4
        w_target[3] == L'\\') {
Packit Service 7c31a4
      /* Starts with \??\ */
Packit Service 7c31a4
      if (w_target_len >= 6 &&
Packit Service 7c31a4
          ((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
Packit Service 7c31a4
           (w_target[4] >= L'a' && w_target[4] <= L'z')) &&
Packit Service 7c31a4
          w_target[5] == L':' &&
Packit Service 7c31a4
          (w_target_len == 6 || w_target[6] == L'\\')) {
Packit Service 7c31a4
        /* \??\<drive>:\ */
Packit Service 7c31a4
        w_target += 4;
Packit Service 7c31a4
        w_target_len -= 4;
Packit Service 7c31a4
Packit Service 7c31a4
      } else if (w_target_len >= 8 &&
Packit Service 7c31a4
                 (w_target[4] == L'U' || w_target[4] == L'u') &&
Packit Service 7c31a4
                 (w_target[5] == L'N' || w_target[5] == L'n') &&
Packit Service 7c31a4
                 (w_target[6] == L'C' || w_target[6] == L'c') &&
Packit Service 7c31a4
                 w_target[7] == L'\\') {
Packit Service 7c31a4
        /* \??\UNC\<server>\<share>\ - make sure the final path looks like
Packit Service 7c31a4
         * \\<server>\<share>\ */
Packit Service 7c31a4
        w_target += 6;
Packit Service 7c31a4
        w_target[0] = L'\\';
Packit Service 7c31a4
        w_target_len -= 6;
Packit Service 7c31a4
      }
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
  } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
Packit Service 7c31a4
    /* Junction. */
Packit Service 7c31a4
    w_target = reparse_data->MountPointReparseBuffer.PathBuffer +
Packit Service 7c31a4
        (reparse_data->MountPointReparseBuffer.SubstituteNameOffset /
Packit Service 7c31a4
        sizeof(WCHAR));
Packit Service 7c31a4
    w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
Packit Service 7c31a4
        sizeof(WCHAR);
Packit Service 7c31a4
Packit Service 7c31a4
    /* Only treat junctions that look like \??\<drive>:\ as symlink. Junctions
Packit Service 7c31a4
     * can also be used as mount points, like \??\Volume{<guid>}, but that's
Packit Service 7c31a4
     * confusing for programs since they wouldn't be able to actually
Packit Service 7c31a4
     * understand such a path when returned by uv_readlink(). UNC paths are
Packit Service 7c31a4
     * never valid for junctions so we don't care about them. */
Packit Service 7c31a4
    if (!(w_target_len >= 6 &&
Packit Service 7c31a4
          w_target[0] == L'\\' &&
Packit Service 7c31a4
          w_target[1] == L'?' &&
Packit Service 7c31a4
          w_target[2] == L'?' &&
Packit Service 7c31a4
          w_target[3] == L'\\' &&
Packit Service 7c31a4
          ((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
Packit Service 7c31a4
           (w_target[4] >= L'a' && w_target[4] <= L'z')) &&
Packit Service 7c31a4
          w_target[5] == L':' &&
Packit Service 7c31a4
          (w_target_len == 6 || w_target[6] == L'\\'))) {
Packit Service 7c31a4
      SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
Packit Service 7c31a4
      return -1;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    /* Remove leading \??\ */
Packit Service 7c31a4
    w_target += 4;
Packit Service 7c31a4
    w_target_len -= 4;
Packit Service 7c31a4
Packit Service 7c31a4
  } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) {
Packit Service 7c31a4
    /* String #3 in the list has the target filename. */
Packit Service 7c31a4
    if (reparse_data->AppExecLinkReparseBuffer.StringCount < 3) {
Packit Service 7c31a4
      SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
Packit Service 7c31a4
      return -1;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    w_target = reparse_data->AppExecLinkReparseBuffer.StringList;
Packit Service 7c31a4
    /* The StringList buffer contains a list of strings separated by "\0",   */
Packit Service 7c31a4
    /* with "\0\0" terminating the list. Move to the 3rd string in the list: */
Packit Service 7c31a4
    for (i = 0; i < 2; ++i) {
Packit Service 7c31a4
      len = wcslen(w_target);
Packit Service 7c31a4
      if (len == 0) {
Packit Service 7c31a4
        SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
Packit Service 7c31a4
        return -1;
Packit Service 7c31a4
      }
Packit Service 7c31a4
      w_target += len + 1;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    w_target_len = wcslen(w_target);
Packit Service 7c31a4
    if (w_target_len == 0) {
Packit Service 7c31a4
      SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
Packit Service 7c31a4
      return -1;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    /* Make sure it is an absolute path. */
Packit Service 7c31a4
    if (!(w_target_len >= 3 &&
Packit Service 7c31a4
         ((w_target[0] >= L'a' && w_target[0] <= L'z') ||
Packit Service 7c31a4
          (w_target[0] >= L'A' && w_target[0] <= L'Z')) &&
Packit Service 7c31a4
         w_target[1] == L':' &&
Packit Service 7c31a4
         w_target[2] == L'\\')) {
Packit Service 7c31a4
      SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
Packit Service 7c31a4
      return -1;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    /* Reparse tag does not indicate a symlink. */
Packit Service 7c31a4
    SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void fs__open(uv_fs_t* req) {
Packit Service 7c31a4
  DWORD access;
Packit Service 7c31a4
  DWORD share;
Packit Service 7c31a4
  DWORD disposition;
Packit Service 7c31a4
  DWORD attributes = 0;
Packit Service 7c31a4
  HANDLE file;
Packit Service 7c31a4
  int fd, current_umask;
Packit Service 7c31a4
  int flags = req->fs.info.file_flags;
Packit Service 7c31a4
  struct uv__fd_info_s fd_info;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Adjust flags to be compatible with the memory file mapping. Save the
Packit Service 7c31a4
   * original flags to emulate the correct behavior. */
Packit Service 7c31a4
  if (flags & UV_FS_O_FILEMAP) {
Packit Service 7c31a4
    fd_info.flags = flags;
Packit Service 7c31a4
    fd_info.current_pos.QuadPart = 0;
Packit Service 7c31a4
Packit Service 7c31a4
    if ((flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) ==
Packit Service 7c31a4
        UV_FS_O_WRONLY) {
Packit Service 7c31a4
      /* CreateFileMapping always needs read access */
Packit Service 7c31a4
      flags = (flags & ~UV_FS_O_WRONLY) | UV_FS_O_RDWR;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    if (flags & UV_FS_O_APPEND) {
Packit Service 7c31a4
      /* Clear the append flag and ensure RDRW mode */
Packit Service 7c31a4
      flags &= ~UV_FS_O_APPEND;
Packit Service 7c31a4
      flags &= ~(UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
Packit Service 7c31a4
      flags |= UV_FS_O_RDWR;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Obtain the active umask. umask() never fails and returns the previous
Packit Service 7c31a4
   * umask. */
Packit Service 7c31a4
  current_umask = umask(0);
Packit Service 7c31a4
  umask(current_umask);
Packit Service 7c31a4
Packit Service 7c31a4
  /* convert flags and mode to CreateFile parameters */
Packit Service 7c31a4
  switch (flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) {
Packit Service 7c31a4
  case UV_FS_O_RDONLY:
Packit Service 7c31a4
    access = FILE_GENERIC_READ;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  case UV_FS_O_WRONLY:
Packit Service 7c31a4
    access = FILE_GENERIC_WRITE;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  case UV_FS_O_RDWR:
Packit Service 7c31a4
    access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  default:
Packit Service 7c31a4
    goto einval;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (flags & UV_FS_O_APPEND) {
Packit Service 7c31a4
    access &= ~FILE_WRITE_DATA;
Packit Service 7c31a4
    access |= FILE_APPEND_DATA;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /*
Packit Service 7c31a4
   * Here is where we deviate significantly from what CRT's _open()
Packit Service 7c31a4
   * does. We indiscriminately use all the sharing modes, to match
Packit Service 7c31a4
   * UNIX semantics. In particular, this ensures that the file can
Packit Service 7c31a4
   * be deleted even whilst it's open, fixing issue
Packit Service 7c31a4
   * https://github.com/nodejs/node-v0.x-archive/issues/1449.
Packit Service 7c31a4
   * We still support exclusive sharing mode, since it is necessary
Packit Service 7c31a4
   * for opening raw block devices, otherwise Windows will prevent
Packit Service 7c31a4
   * any attempt to write past the master boot record.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  if (flags & UV_FS_O_EXLOCK) {
Packit Service 7c31a4
    share = 0;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  switch (flags & (UV_FS_O_CREAT | UV_FS_O_EXCL | UV_FS_O_TRUNC)) {
Packit Service 7c31a4
  case 0:
Packit Service 7c31a4
  case UV_FS_O_EXCL:
Packit Service 7c31a4
    disposition = OPEN_EXISTING;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  case UV_FS_O_CREAT:
Packit Service 7c31a4
    disposition = OPEN_ALWAYS;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  case UV_FS_O_CREAT | UV_FS_O_EXCL:
Packit Service 7c31a4
  case UV_FS_O_CREAT | UV_FS_O_TRUNC | UV_FS_O_EXCL:
Packit Service 7c31a4
    disposition = CREATE_NEW;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  case UV_FS_O_TRUNC:
Packit Service 7c31a4
  case UV_FS_O_TRUNC | UV_FS_O_EXCL:
Packit Service 7c31a4
    disposition = TRUNCATE_EXISTING;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  case UV_FS_O_CREAT | UV_FS_O_TRUNC:
Packit Service 7c31a4
    disposition = CREATE_ALWAYS;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  default:
Packit Service 7c31a4
    goto einval;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  attributes |= FILE_ATTRIBUTE_NORMAL;
Packit Service 7c31a4
  if (flags & UV_FS_O_CREAT) {
Packit Service 7c31a4
    if (!((req->fs.info.mode & ~current_umask) & _S_IWRITE)) {
Packit Service 7c31a4
      attributes |= FILE_ATTRIBUTE_READONLY;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (flags & UV_FS_O_TEMPORARY ) {
Packit Service 7c31a4
    attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
Packit Service 7c31a4
    access |= DELETE;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (flags & UV_FS_O_SHORT_LIVED) {
Packit Service 7c31a4
    attributes |= FILE_ATTRIBUTE_TEMPORARY;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  switch (flags & (UV_FS_O_SEQUENTIAL | UV_FS_O_RANDOM)) {
Packit Service 7c31a4
  case 0:
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  case UV_FS_O_SEQUENTIAL:
Packit Service 7c31a4
    attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  case UV_FS_O_RANDOM:
Packit Service 7c31a4
    attributes |= FILE_FLAG_RANDOM_ACCESS;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  default:
Packit Service 7c31a4
    goto einval;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (flags & UV_FS_O_DIRECT) {
Packit Service 7c31a4
    /*
Packit Service 7c31a4
     * FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually exclusive.
Packit Service 7c31a4
     * Windows returns 87, ERROR_INVALID_PARAMETER if these are combined.
Packit Service 7c31a4
     *
Packit Service 7c31a4
     * FILE_APPEND_DATA is included in FILE_GENERIC_WRITE:
Packit Service 7c31a4
     *
Packit Service 7c31a4
     * FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE |
Packit Service 7c31a4
     *                      FILE_WRITE_DATA |
Packit Service 7c31a4
     *                      FILE_WRITE_ATTRIBUTES |
Packit Service 7c31a4
     *                      FILE_WRITE_EA |
Packit Service 7c31a4
     *                      FILE_APPEND_DATA |
Packit Service 7c31a4
     *                      SYNCHRONIZE
Packit Service 7c31a4
     *
Packit Service 7c31a4
     * Note: Appends are also permitted by FILE_WRITE_DATA.
Packit Service 7c31a4
     *
Packit Service 7c31a4
     * In order for direct writes and direct appends to succeed, we therefore
Packit Service 7c31a4
     * exclude FILE_APPEND_DATA if FILE_WRITE_DATA is specified, and otherwise
Packit Service 7c31a4
     * fail if the user's sole permission is a direct append, since this
Packit Service 7c31a4
     * particular combination is invalid.
Packit Service 7c31a4
     */
Packit Service 7c31a4
    if (access & FILE_APPEND_DATA) {
Packit Service 7c31a4
      if (access & FILE_WRITE_DATA) {
Packit Service 7c31a4
        access &= ~FILE_APPEND_DATA;
Packit Service 7c31a4
      } else {
Packit Service 7c31a4
        goto einval;
Packit Service 7c31a4
      }
Packit Service 7c31a4
    }
Packit Service 7c31a4
    attributes |= FILE_FLAG_NO_BUFFERING;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  switch (flags & (UV_FS_O_DSYNC | UV_FS_O_SYNC)) {
Packit Service 7c31a4
  case 0:
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  case UV_FS_O_DSYNC:
Packit Service 7c31a4
  case UV_FS_O_SYNC:
Packit Service 7c31a4
    attributes |= FILE_FLAG_WRITE_THROUGH;
Packit Service 7c31a4
    break;
Packit Service 7c31a4
  default:
Packit Service 7c31a4
    goto einval;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Setting this flag makes it possible to open a directory. */
Packit Service 7c31a4
  attributes |= FILE_FLAG_BACKUP_SEMANTICS;
Packit Service 7c31a4
Packit Service 7c31a4
  file = CreateFileW(req->file.pathw,
Packit Service 7c31a4
                     access,
Packit Service 7c31a4
                     share,
Packit Service 7c31a4
                     NULL,
Packit Service 7c31a4
                     disposition,
Packit Service 7c31a4
                     attributes,
Packit Service 7c31a4
                     NULL);
Packit Service 7c31a4
  if (file == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    DWORD error = GetLastError();
Packit Service 7c31a4
    if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&
Packit Service 7c31a4
        !(flags & UV_FS_O_EXCL)) {
Packit Service 7c31a4
      /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was
Packit Service 7c31a4
       * specified, it means the path referred to a directory. */
Packit Service 7c31a4
      SET_REQ_UV_ERROR(req, UV_EISDIR, error);
Packit Service 7c31a4
    } else {
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    }
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  fd = _open_osfhandle((intptr_t) file, flags);
Packit Service 7c31a4
  if (fd < 0) {
Packit Service 7c31a4
    /* The only known failure mode for _open_osfhandle() is EMFILE, in which
Packit Service 7c31a4
     * case GetLastError() will return zero. However we'll try to handle other
Packit Service 7c31a4
     * errors as well, should they ever occur.
Packit Service 7c31a4
     */
Packit Service 7c31a4
    if (errno == EMFILE)
Packit Service 7c31a4
      SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES);
Packit Service 7c31a4
    else if (GetLastError() != ERROR_SUCCESS)
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    else
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, (DWORD) UV_UNKNOWN);
Packit Service 7c31a4
    CloseHandle(file);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (flags & UV_FS_O_FILEMAP) {
Packit Service 7c31a4
    FILE_STANDARD_INFO file_info;
Packit Service 7c31a4
    if (!GetFileInformationByHandleEx(file,
Packit Service 7c31a4
                                      FileStandardInfo,
Packit Service 7c31a4
                                      &file_info,
Packit Service 7c31a4
                                      sizeof file_info)) {
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
      CloseHandle(file);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    fd_info.is_directory = file_info.Directory;
Packit Service 7c31a4
Packit Service 7c31a4
    if (fd_info.is_directory) {
Packit Service 7c31a4
      fd_info.size.QuadPart = 0;
Packit Service 7c31a4
      fd_info.mapping = INVALID_HANDLE_VALUE;
Packit Service 7c31a4
    } else {
Packit Service 7c31a4
      if (!GetFileSizeEx(file, &fd_info.size)) {
Packit Service 7c31a4
        SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
        CloseHandle(file);
Packit Service 7c31a4
        return;
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      if (fd_info.size.QuadPart == 0) {
Packit Service 7c31a4
        fd_info.mapping = INVALID_HANDLE_VALUE;
Packit Service 7c31a4
      } else {
Packit Service 7c31a4
        DWORD flProtect = (fd_info.flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY |
Packit Service 7c31a4
          UV_FS_O_RDWR)) == UV_FS_O_RDONLY ? PAGE_READONLY : PAGE_READWRITE;
Packit Service 7c31a4
        fd_info.mapping = CreateFileMapping(file,
Packit Service 7c31a4
                                            NULL,
Packit Service 7c31a4
                                            flProtect,
Packit Service 7c31a4
                                            fd_info.size.HighPart,
Packit Service 7c31a4
                                            fd_info.size.LowPart,
Packit Service 7c31a4
                                            NULL);
Packit Service 7c31a4
        if (fd_info.mapping == NULL) {
Packit Service 7c31a4
          SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
          CloseHandle(file);
Packit Service 7c31a4
          return;
Packit Service 7c31a4
        }
Packit Service 7c31a4
      }
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    uv__fd_hash_add(fd, &fd_info);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_RESULT(req, fd);
Packit Service 7c31a4
  return;
Packit Service 7c31a4
Packit Service 7c31a4
 einval:
Packit Service 7c31a4
  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
void fs__close(uv_fs_t* req) {
Packit Service 7c31a4
  int fd = req->file.fd;
Packit Service 7c31a4
  int result;
Packit Service 7c31a4
  struct uv__fd_info_s fd_info;
Packit Service 7c31a4
Packit Service 7c31a4
  VERIFY_FD(fd, req);
Packit Service 7c31a4
Packit Service 7c31a4
  if (uv__fd_hash_remove(fd, &fd_info)) {
Packit Service 7c31a4
    if (fd_info.mapping != INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
      CloseHandle(fd_info.mapping);
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (fd > 2)
Packit Service 7c31a4
    result = _close(fd);
Packit Service 7c31a4
  else
Packit Service 7c31a4
    result = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  /* _close doesn't set _doserrno on failure, but it does always set errno
Packit Service 7c31a4
   * to EBADF on failure.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  if (result == -1) {
Packit Service 7c31a4
    assert(errno == EBADF);
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE);
Packit Service 7c31a4
  } else {
Packit Service e2ebee
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
LONG fs__filemap_ex_filter(LONG excode, PEXCEPTION_POINTERS pep,
Packit Service 7c31a4
                           int* perror) {
Packit Service e2ebee
  if (excode != (LONG)EXCEPTION_IN_PAGE_ERROR) {
Packit Service 7c31a4
    return EXCEPTION_CONTINUE_SEARCH;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  assert(perror != NULL);
Packit Service 7c31a4
  if (pep != NULL && pep->ExceptionRecord != NULL &&
Packit Service 7c31a4
      pep->ExceptionRecord->NumberParameters >= 3) {
Packit Service 7c31a4
    NTSTATUS status = (NTSTATUS)pep->ExceptionRecord->ExceptionInformation[3];
Packit Service 7c31a4
    *perror = pRtlNtStatusToDosError(status);
Packit Service 7c31a4
    if (*perror != ERROR_SUCCESS) {
Packit Service 7c31a4
      return EXCEPTION_EXECUTE_HANDLER;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
  *perror = UV_UNKNOWN;
Packit Service 7c31a4
  return EXCEPTION_EXECUTE_HANDLER;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void fs__read_filemap(uv_fs_t* req, struct uv__fd_info_s* fd_info) {
Packit Service 7c31a4
  int fd = req->file.fd; /* VERIFY_FD done in fs__read */
Packit Service 7c31a4
  int rw_flags = fd_info->flags &
Packit Service 7c31a4
    (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
Packit Service 7c31a4
  size_t read_size, done_read;
Packit Service 7c31a4
  unsigned int index;
Packit Service 7c31a4
  LARGE_INTEGER pos, end_pos;
Packit Service 7c31a4
  size_t view_offset;
Packit Service 7c31a4
  LARGE_INTEGER view_base;
Packit Service 7c31a4
  void* view;
Packit Service 7c31a4
Packit Service 7c31a4
  if (rw_flags == UV_FS_O_WRONLY) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  if (fd_info->is_directory) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FUNCTION);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->fs.info.offset == -1) {
Packit Service 7c31a4
    pos = fd_info->current_pos;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    pos.QuadPart = req->fs.info.offset;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Make sure we wont read past EOF. */
Packit Service 7c31a4
  if (pos.QuadPart >= fd_info->size.QuadPart) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  read_size = 0;
Packit Service 7c31a4
  for (index = 0; index < req->fs.info.nbufs; ++index) {
Packit Service 7c31a4
    read_size += req->fs.info.bufs[index].len;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  read_size = (size_t) MIN((LONGLONG) read_size,
Packit Service 7c31a4
                           fd_info->size.QuadPart - pos.QuadPart);
Packit Service 7c31a4
  if (read_size == 0) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  end_pos.QuadPart = pos.QuadPart + read_size;
Packit Service 7c31a4
Packit Service 7c31a4
  view_offset = pos.QuadPart % uv__allocation_granularity;
Packit Service 7c31a4
  view_base.QuadPart = pos.QuadPart - view_offset;
Packit Service 7c31a4
  view = MapViewOfFile(fd_info->mapping,
Packit Service 7c31a4
                       FILE_MAP_READ,
Packit Service 7c31a4
                       view_base.HighPart,
Packit Service 7c31a4
                       view_base.LowPart,
Packit Service 7c31a4
                       view_offset + read_size);
Packit Service 7c31a4
  if (view == NULL) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  done_read = 0;
Packit Service 7c31a4
  for (index = 0;
Packit Service 7c31a4
       index < req->fs.info.nbufs && done_read < read_size;
Packit Service 7c31a4
       ++index) {
Packit Service 7c31a4
    size_t this_read_size = MIN(req->fs.info.bufs[index].len,
Packit Service 7c31a4
                                read_size - done_read);
Packit Service 7c31a4
#ifdef _MSC_VER
Packit Service e2ebee
    int err = 0;
Packit Service 7c31a4
    __try {
Packit Service 7c31a4
#endif
Packit Service 7c31a4
      memcpy(req->fs.info.bufs[index].base,
Packit Service 7c31a4
             (char*)view + view_offset + done_read,
Packit Service 7c31a4
             this_read_size);
Packit Service 7c31a4
#ifdef _MSC_VER
Packit Service 7c31a4
    }
Packit Service 7c31a4
    __except (fs__filemap_ex_filter(GetExceptionCode(),
Packit Service 7c31a4
                                    GetExceptionInformation(), &err)) {
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
      UnmapViewOfFile(view);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
#endif
Packit Service 7c31a4
    done_read += this_read_size;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  assert(done_read == read_size);
Packit Service 7c31a4
Packit Service 7c31a4
  if (!UnmapViewOfFile(view)) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->fs.info.offset == -1) {
Packit Service 7c31a4
    fd_info->current_pos = end_pos;
Packit Service 7c31a4
    uv__fd_hash_add(fd, fd_info);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_RESULT(req, read_size);
Packit Service 7c31a4
  return;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
void fs__read(uv_fs_t* req) {
Packit Service 7c31a4
  int fd = req->file.fd;
Packit Service 7c31a4
  int64_t offset = req->fs.info.offset;
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  OVERLAPPED overlapped, *overlapped_ptr;
Packit Service 7c31a4
  LARGE_INTEGER offset_;
Packit Service 7c31a4
  DWORD bytes;
Packit Service 7c31a4
  DWORD error;
Packit Service 7c31a4
  int result;
Packit Service 7c31a4
  unsigned int index;
Packit Service 7c31a4
  LARGE_INTEGER original_position;
Packit Service 7c31a4
  LARGE_INTEGER zero_offset;
Packit Service 7c31a4
  int restore_position;
Packit Service 7c31a4
  struct uv__fd_info_s fd_info;
Packit Service 7c31a4
Packit Service 7c31a4
  VERIFY_FD(fd, req);
Packit Service 7c31a4
Packit Service 7c31a4
  if (uv__fd_hash_get(fd, &fd_info)) {
Packit Service 7c31a4
    fs__read_filemap(req, &fd_info);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  zero_offset.QuadPart = 0;
Packit Service 7c31a4
  restore_position = 0;
Packit Service 7c31a4
  handle = uv__get_osfhandle(fd);
Packit Service 7c31a4
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (offset != -1) {
Packit Service 7c31a4
    memset(&overlapped, 0, sizeof overlapped);
Packit Service 7c31a4
    overlapped_ptr = &overlapped;
Packit Service 7c31a4
    if (SetFilePointerEx(handle, zero_offset, &original_position,
Packit Service 7c31a4
                         FILE_CURRENT)) {
Packit Service 7c31a4
      restore_position = 1;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    overlapped_ptr = NULL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  index = 0;
Packit Service 7c31a4
  bytes = 0;
Packit Service 7c31a4
  do {
Packit Service 7c31a4
    DWORD incremental_bytes;
Packit Service 7c31a4
Packit Service 7c31a4
    if (offset != -1) {
Packit Service 7c31a4
      offset_.QuadPart = offset + bytes;
Packit Service 7c31a4
      overlapped.Offset = offset_.LowPart;
Packit Service 7c31a4
      overlapped.OffsetHigh = offset_.HighPart;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    result = ReadFile(handle,
Packit Service 7c31a4
                      req->fs.info.bufs[index].base,
Packit Service 7c31a4
                      req->fs.info.bufs[index].len,
Packit Service 7c31a4
                      &incremental_bytes,
Packit Service 7c31a4
                      overlapped_ptr);
Packit Service 7c31a4
    bytes += incremental_bytes;
Packit Service 7c31a4
    ++index;
Packit Service 7c31a4
  } while (result && index < req->fs.info.nbufs);
Packit Service 7c31a4
Packit Service 7c31a4
  if (restore_position)
Packit Service 7c31a4
    SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
Packit Service 7c31a4
Packit Service 7c31a4
  if (result || bytes > 0) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, bytes);
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    error = GetLastError();
Packit Service 7c31a4
    if (error == ERROR_HANDLE_EOF) {
Packit Service 7c31a4
      SET_REQ_RESULT(req, bytes);
Packit Service 7c31a4
    } else {
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, error);
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void fs__write_filemap(uv_fs_t* req, HANDLE file,
Packit Service 7c31a4
                       struct uv__fd_info_s* fd_info) {
Packit Service 7c31a4
  int fd = req->file.fd; /* VERIFY_FD done in fs__write */
Packit Service 7c31a4
  int force_append = fd_info->flags & UV_FS_O_APPEND;
Packit Service 7c31a4
  int rw_flags = fd_info->flags &
Packit Service 7c31a4
    (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
Packit Service 7c31a4
  size_t write_size, done_write;
Packit Service 7c31a4
  unsigned int index;
Packit Service e2ebee
  LARGE_INTEGER pos, end_pos;
Packit Service 7c31a4
  size_t view_offset;
Packit Service 7c31a4
  LARGE_INTEGER view_base;
Packit Service 7c31a4
  void* view;
Packit Service 7c31a4
  FILETIME ft;
Packit Service 7c31a4
Packit Service 7c31a4
  if (rw_flags == UV_FS_O_RDONLY) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  if (fd_info->is_directory) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FUNCTION);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  write_size = 0;
Packit Service 7c31a4
  for (index = 0; index < req->fs.info.nbufs; ++index) {
Packit Service 7c31a4
    write_size += req->fs.info.bufs[index].len;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (write_size == 0) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (force_append) {
Packit Service 7c31a4
    pos = fd_info->size;
Packit Service 7c31a4
  } else if (req->fs.info.offset == -1) {
Packit Service 7c31a4
    pos = fd_info->current_pos;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    pos.QuadPart = req->fs.info.offset;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  end_pos.QuadPart = pos.QuadPart + write_size;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Recreate the mapping to enlarge the file if needed */
Packit Service 7c31a4
  if (end_pos.QuadPart > fd_info->size.QuadPart) {
Packit Service 7c31a4
    if (fd_info->mapping != INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
      CloseHandle(fd_info->mapping);
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    fd_info->mapping = CreateFileMapping(file,
Packit Service 7c31a4
                                         NULL,
Packit Service 7c31a4
                                         PAGE_READWRITE,
Packit Service 7c31a4
                                         end_pos.HighPart,
Packit Service 7c31a4
                                         end_pos.LowPart,
Packit Service 7c31a4
                                         NULL);
Packit Service 7c31a4
    if (fd_info->mapping == NULL) {
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
      CloseHandle(file);
Packit Service 7c31a4
      fd_info->mapping = INVALID_HANDLE_VALUE;
Packit Service 7c31a4
      fd_info->size.QuadPart = 0;
Packit Service 7c31a4
      fd_info->current_pos.QuadPart = 0;
Packit Service 7c31a4
      uv__fd_hash_add(fd, fd_info);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    fd_info->size = end_pos;
Packit Service 7c31a4
    uv__fd_hash_add(fd, fd_info);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  view_offset = pos.QuadPart % uv__allocation_granularity;
Packit Service 7c31a4
  view_base.QuadPart = pos.QuadPart - view_offset;
Packit Service 7c31a4
  view = MapViewOfFile(fd_info->mapping,
Packit Service 7c31a4
                       FILE_MAP_WRITE,
Packit Service 7c31a4
                       view_base.HighPart,
Packit Service 7c31a4
                       view_base.LowPart,
Packit Service 7c31a4
                       view_offset + write_size);
Packit Service 7c31a4
  if (view == NULL) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  done_write = 0;
Packit Service 7c31a4
  for (index = 0; index < req->fs.info.nbufs; ++index) {
Packit Service 7c31a4
#ifdef _MSC_VER
Packit Service e2ebee
    int err = 0;
Packit Service 7c31a4
    __try {
Packit Service 7c31a4
#endif
Packit Service 7c31a4
      memcpy((char*)view + view_offset + done_write,
Packit Service 7c31a4
             req->fs.info.bufs[index].base,
Packit Service 7c31a4
             req->fs.info.bufs[index].len);
Packit Service 7c31a4
#ifdef _MSC_VER
Packit Service 7c31a4
    }
Packit Service 7c31a4
    __except (fs__filemap_ex_filter(GetExceptionCode(),
Packit Service 7c31a4
                                    GetExceptionInformation(), &err)) {
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
      UnmapViewOfFile(view);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
#endif
Packit Service 7c31a4
    done_write += req->fs.info.bufs[index].len;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  assert(done_write == write_size);
Packit Service 7c31a4
Packit Service 7c31a4
  if (!FlushViewOfFile(view, 0)) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    UnmapViewOfFile(view);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  if (!UnmapViewOfFile(view)) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->fs.info.offset == -1) {
Packit Service 7c31a4
    fd_info->current_pos = end_pos;
Packit Service 7c31a4
    uv__fd_hash_add(fd, fd_info);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  GetSystemTimeAsFileTime(&ft;;
Packit Service 7c31a4
  SetFileTime(file, NULL, NULL, &ft;;
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_RESULT(req, done_write);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
void fs__write(uv_fs_t* req) {
Packit Service 7c31a4
  int fd = req->file.fd;
Packit Service 7c31a4
  int64_t offset = req->fs.info.offset;
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  OVERLAPPED overlapped, *overlapped_ptr;
Packit Service 7c31a4
  LARGE_INTEGER offset_;
Packit Service 7c31a4
  DWORD bytes;
Packit Service 7c31a4
  int result;
Packit Service 7c31a4
  unsigned int index;
Packit Service 7c31a4
  LARGE_INTEGER original_position;
Packit Service 7c31a4
  LARGE_INTEGER zero_offset;
Packit Service 7c31a4
  int restore_position;
Packit Service 7c31a4
  struct uv__fd_info_s fd_info;
Packit Service 7c31a4
Packit Service 7c31a4
  VERIFY_FD(fd, req);
Packit Service 7c31a4
Packit Service 7c31a4
  zero_offset.QuadPart = 0;
Packit Service 7c31a4
  restore_position = 0;
Packit Service 7c31a4
  handle = uv__get_osfhandle(fd);
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (uv__fd_hash_get(fd, &fd_info)) {
Packit Service 7c31a4
    fs__write_filemap(req, handle, &fd_info);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (offset != -1) {
Packit Service 7c31a4
    memset(&overlapped, 0, sizeof overlapped);
Packit Service 7c31a4
    overlapped_ptr = &overlapped;
Packit Service 7c31a4
    if (SetFilePointerEx(handle, zero_offset, &original_position,
Packit Service 7c31a4
                         FILE_CURRENT)) {
Packit Service 7c31a4
      restore_position = 1;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    overlapped_ptr = NULL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  index = 0;
Packit Service 7c31a4
  bytes = 0;
Packit Service 7c31a4
  do {
Packit Service 7c31a4
    DWORD incremental_bytes;
Packit Service 7c31a4
Packit Service 7c31a4
    if (offset != -1) {
Packit Service 7c31a4
      offset_.QuadPart = offset + bytes;
Packit Service 7c31a4
      overlapped.Offset = offset_.LowPart;
Packit Service 7c31a4
      overlapped.OffsetHigh = offset_.HighPart;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    result = WriteFile(handle,
Packit Service 7c31a4
                       req->fs.info.bufs[index].base,
Packit Service 7c31a4
                       req->fs.info.bufs[index].len,
Packit Service 7c31a4
                       &incremental_bytes,
Packit Service 7c31a4
                       overlapped_ptr);
Packit Service 7c31a4
    bytes += incremental_bytes;
Packit Service 7c31a4
    ++index;
Packit Service 7c31a4
  } while (result && index < req->fs.info.nbufs);
Packit Service 7c31a4
Packit Service 7c31a4
  if (restore_position)
Packit Service 7c31a4
    SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
Packit Service 7c31a4
Packit Service 7c31a4
  if (result || bytes > 0) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, bytes);
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void fs__rmdir(uv_fs_t* req) {
Packit Service 7c31a4
  int result = _wrmdir(req->file.pathw);
Packit Service e2ebee
  if (result == -1)
Packit Service e2ebee
    SET_REQ_WIN32_ERROR(req, _doserrno);
Packit Service e2ebee
  else
Packit Service e2ebee
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void fs__unlink(uv_fs_t* req) {
Packit Service 7c31a4
  const WCHAR* pathw = req->file.pathw;
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  BY_HANDLE_FILE_INFORMATION info;
Packit Service 7c31a4
  FILE_DISPOSITION_INFORMATION disposition;
Packit Service 7c31a4
  IO_STATUS_BLOCK iosb;
Packit Service 7c31a4
  NTSTATUS status;
Packit Service 7c31a4
Packit Service 7c31a4
  handle = CreateFileW(pathw,
Packit Service 7c31a4
                       FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE,
Packit Service 7c31a4
                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
Packit Service 7c31a4
                       NULL,
Packit Service 7c31a4
                       OPEN_EXISTING,
Packit Service 7c31a4
                       FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
Packit Service 7c31a4
                       NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (!GetFileInformationByHandle(handle, &info)) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    CloseHandle(handle);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
Packit Service 7c31a4
    /* Do not allow deletion of directories, unless it is a symlink. When the
Packit Service 7c31a4
     * path refers to a non-symlink directory, report EPERM as mandated by
Packit Service 7c31a4
     * POSIX.1. */
Packit Service 7c31a4
Packit Service 7c31a4
    /* Check if it is a reparse point. If it's not, it's a normal directory. */
Packit Service 7c31a4
    if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
Packit Service 7c31a4
      CloseHandle(handle);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    /* Read the reparse point and check if it is a valid symlink. If not, don't
Packit Service 7c31a4
     * unlink. */
Packit Service 7c31a4
    if (fs__readlink_handle(handle, NULL, NULL) < 0) {
Packit Service 7c31a4
      DWORD error = GetLastError();
Packit Service 7c31a4
      if (error == ERROR_SYMLINK_NOT_SUPPORTED)
Packit Service 7c31a4
        error = ERROR_ACCESS_DENIED;
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, error);
Packit Service 7c31a4
      CloseHandle(handle);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
Packit Service 7c31a4
    /* Remove read-only attribute */
Packit Service 7c31a4
    FILE_BASIC_INFORMATION basic = { 0 };
Packit Service 7c31a4
Packit Service 7c31a4
    basic.FileAttributes = (info.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY) |
Packit Service 7c31a4
                           FILE_ATTRIBUTE_ARCHIVE;
Packit Service 7c31a4
Packit Service 7c31a4
    status = pNtSetInformationFile(handle,
Packit Service 7c31a4
                                   &iosb,
Packit Service 7c31a4
                                   &basic,
Packit Service 7c31a4
                                   sizeof basic,
Packit Service 7c31a4
                                   FileBasicInformation);
Packit Service 7c31a4
    if (!NT_SUCCESS(status)) {
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
Packit Service 7c31a4
      CloseHandle(handle);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Try to set the delete flag. */
Packit Service 7c31a4
  disposition.DeleteFile = TRUE;
Packit Service 7c31a4
  status = pNtSetInformationFile(handle,
Packit Service 7c31a4
                                 &iosb,
Packit Service 7c31a4
                                 &disposition,
Packit Service 7c31a4
                                 sizeof disposition,
Packit Service 7c31a4
                                 FileDispositionInformation);
Packit Service 7c31a4
  if (NT_SUCCESS(status)) {
Packit Service 7c31a4
    SET_REQ_SUCCESS(req);
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  CloseHandle(handle);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void fs__mkdir(uv_fs_t* req) {
Packit Service 7c31a4
  /* TODO: use req->mode. */
Packit Service e2ebee
  if (CreateDirectoryW(req->file.pathw, NULL)) {
Packit Service e2ebee
    SET_REQ_RESULT(req, 0);
Packit Service e2ebee
  } else {
Packit Service e2ebee
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service e2ebee
    if (req->sys_errno_ == ERROR_INVALID_NAME)
Packit Service e2ebee
      req->result = UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
typedef int (*uv__fs_mktemp_func)(uv_fs_t* req);
Packit Service 7c31a4
Packit Service 7c31a4
/* OpenBSD original: lib/libc/stdio/mktemp.c */
Packit Service 7c31a4
void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) {
Packit Service 7c31a4
  static const WCHAR *tempchars =
Packit Service 7c31a4
    L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Packit Service 7c31a4
  static const size_t num_chars = 62;
Packit Service 7c31a4
  static const size_t num_x = 6;
Packit Service 7c31a4
  WCHAR *cp, *ep;
Packit Service 7c31a4
  unsigned int tries, i;
Packit Service 7c31a4
  size_t len;
Packit Service 7c31a4
  uint64_t v;
Packit Service e2ebee
  char* path;
Packit Service e2ebee
  
Packit Service e2ebee
  path = req->path;
Packit Service 7c31a4
  len = wcslen(req->file.pathw);
Packit Service 7c31a4
  ep = req->file.pathw + len;
Packit Service 7c31a4
  if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
Packit Service e2ebee
    goto clobber;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  tries = TMP_MAX;
Packit Service 7c31a4
  do {
Packit Service 7c31a4
    if (uv__random_rtlgenrandom((void *)&v, sizeof(v)) < 0) {
Packit Service 7c31a4
      SET_REQ_UV_ERROR(req, UV_EIO, ERROR_IO_DEVICE);
Packit Service e2ebee
      goto clobber;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    cp = ep - num_x;
Packit Service 7c31a4
    for (i = 0; i < num_x; i++) {
Packit Service 7c31a4
      *cp++ = tempchars[v % num_chars];
Packit Service 7c31a4
      v /= num_chars;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    if (func(req)) {
Packit Service 7c31a4
      if (req->result >= 0) {
Packit Service e2ebee
        len = strlen(path);
Packit Service e2ebee
        wcstombs(path + len - num_x, ep - num_x, num_x);
Packit Service 7c31a4
      }
Packit Service e2ebee
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  } while (--tries);
Packit Service 7c31a4
Packit Service e2ebee
  SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service e2ebee
Packit Service e2ebee
clobber:
Packit Service e2ebee
  path[0] = '\0';
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static int fs__mkdtemp_func(uv_fs_t* req) {
Packit Service e2ebee
  DWORD error;
Packit Service e2ebee
  if (CreateDirectoryW(req->file.pathw, NULL)) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
    return 1;
Packit Service e2ebee
  }
Packit Service e2ebee
  error = GetLastError();
Packit Service e2ebee
  if (error != ERROR_ALREADY_EXISTS) {
Packit Service e2ebee
    SET_REQ_WIN32_ERROR(req, error);
Packit Service 7c31a4
    return 1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void fs__mkdtemp(uv_fs_t* req) {
Packit Service 7c31a4
  fs__mktemp(req, fs__mkdtemp_func);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static int fs__mkstemp_func(uv_fs_t* req) {
Packit Service 7c31a4
  HANDLE file;
Packit Service 7c31a4
  int fd;
Packit Service 7c31a4
Packit Service 7c31a4
  file = CreateFileW(req->file.pathw,
Packit Service 7c31a4
                     GENERIC_READ | GENERIC_WRITE,
Packit Service 7c31a4
                     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
Packit Service 7c31a4
                     NULL,
Packit Service 7c31a4
                     CREATE_NEW,
Packit Service 7c31a4
                     FILE_ATTRIBUTE_NORMAL,
Packit Service 7c31a4
                     NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (file == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    DWORD error;
Packit Service 7c31a4
    error = GetLastError();
Packit Service 7c31a4
Packit Service 7c31a4
    /* If the file exists, the main fs__mktemp() function
Packit Service 7c31a4
       will retry. If it's another error, we want to stop. */
Packit Service 7c31a4
    if (error != ERROR_FILE_EXISTS) {
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, error);
Packit Service 7c31a4
      return 1;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  fd = _open_osfhandle((intptr_t) file, 0);
Packit Service 7c31a4
  if (fd < 0) {
Packit Service 7c31a4
    /* The only known failure mode for _open_osfhandle() is EMFILE, in which
Packit Service 7c31a4
     * case GetLastError() will return zero. However we'll try to handle other
Packit Service 7c31a4
     * errors as well, should they ever occur.
Packit Service 7c31a4
     */
Packit Service 7c31a4
    if (errno == EMFILE)
Packit Service 7c31a4
      SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES);
Packit Service 7c31a4
    else if (GetLastError() != ERROR_SUCCESS)
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    else
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, UV_UNKNOWN);
Packit Service 7c31a4
    CloseHandle(file);
Packit Service 7c31a4
    return 1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_RESULT(req, fd);
Packit Service 7c31a4
Packit Service 7c31a4
  return 1;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void fs__mkstemp(uv_fs_t* req) {
Packit Service 7c31a4
  fs__mktemp(req, fs__mkstemp_func);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void fs__scandir(uv_fs_t* req) {
Packit Service 7c31a4
  static const size_t dirents_initial_size = 32;
Packit Service 7c31a4
Packit Service 7c31a4
  HANDLE dir_handle = INVALID_HANDLE_VALUE;
Packit Service 7c31a4
Packit Service 7c31a4
  uv__dirent_t** dirents = NULL;
Packit Service 7c31a4
  size_t dirents_size = 0;
Packit Service 7c31a4
  size_t dirents_used = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  IO_STATUS_BLOCK iosb;
Packit Service 7c31a4
  NTSTATUS status;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Buffer to hold directory entries returned by NtQueryDirectoryFile.
Packit Service 7c31a4
   * It's important that this buffer can hold at least one entry, regardless
Packit Service 7c31a4
   * of the length of the file names present in the enumerated directory.
Packit Service 7c31a4
   * A file name is at most 256 WCHARs long.
Packit Service 7c31a4
   * According to MSDN, the buffer must be aligned at an 8-byte boundary.
Packit Service 7c31a4
   */
Packit Service 7c31a4
#if _MSC_VER
Packit Service 7c31a4
  __declspec(align(8)) char buffer[8192];
Packit Service 7c31a4
#else
Packit Service 7c31a4
  __attribute__ ((aligned (8))) char buffer[8192];
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
  STATIC_ASSERT(sizeof buffer >=
Packit Service 7c31a4
                sizeof(FILE_DIRECTORY_INFORMATION) + 256 * sizeof(WCHAR));
Packit Service 7c31a4
Packit Service 7c31a4
  /* Open the directory. */
Packit Service 7c31a4
  dir_handle =
Packit Service 7c31a4
      CreateFileW(req->file.pathw,
Packit Service 7c31a4
                  FILE_LIST_DIRECTORY | SYNCHRONIZE,
Packit Service 7c31a4
                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
Packit Service 7c31a4
                  NULL,
Packit Service 7c31a4
                  OPEN_EXISTING,
Packit Service 7c31a4
                  FILE_FLAG_BACKUP_SEMANTICS,
Packit Service 7c31a4
                  NULL);
Packit Service 7c31a4
  if (dir_handle == INVALID_HANDLE_VALUE)
Packit Service 7c31a4
    goto win32_error;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Read the first chunk. */
Packit Service 7c31a4
  status = pNtQueryDirectoryFile(dir_handle,
Packit Service 7c31a4
                                 NULL,
Packit Service 7c31a4
                                 NULL,
Packit Service 7c31a4
                                 NULL,
Packit Service 7c31a4
                                 &iosb,
Packit Service 7c31a4
                                 &buffer,
Packit Service 7c31a4
                                 sizeof buffer,
Packit Service 7c31a4
                                 FileDirectoryInformation,
Packit Service 7c31a4
                                 FALSE,
Packit Service 7c31a4
                                 NULL,
Packit Service 7c31a4
                                 TRUE);
Packit Service 7c31a4
Packit Service 7c31a4
  /* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER.
Packit Service 7c31a4
   * This should be reported back as UV_ENOTDIR.
Packit Service 7c31a4
   */
Packit Service e2ebee
  if (status == (NTSTATUS)STATUS_INVALID_PARAMETER)
Packit Service 7c31a4
    goto not_a_directory_error;
Packit Service 7c31a4
Packit Service 7c31a4
  while (NT_SUCCESS(status)) {
Packit Service 7c31a4
    char* position = buffer;
Packit Service 7c31a4
    size_t next_entry_offset = 0;
Packit Service 7c31a4
Packit Service 7c31a4
    do {
Packit Service 7c31a4
      FILE_DIRECTORY_INFORMATION* info;
Packit Service 7c31a4
      uv__dirent_t* dirent;
Packit Service 7c31a4
Packit Service 7c31a4
      size_t wchar_len;
Packit Service 7c31a4
      size_t utf8_len;
Packit Service 7c31a4
Packit Service 7c31a4
      /* Obtain a pointer to the current directory entry. */
Packit Service 7c31a4
      position += next_entry_offset;
Packit Service 7c31a4
      info = (FILE_DIRECTORY_INFORMATION*) position;
Packit Service 7c31a4
Packit Service 7c31a4
      /* Fetch the offset to the next directory entry. */
Packit Service 7c31a4
      next_entry_offset = info->NextEntryOffset;
Packit Service 7c31a4
Packit Service 7c31a4
      /* Compute the length of the filename in WCHARs. */
Packit Service 7c31a4
      wchar_len = info->FileNameLength / sizeof info->FileName[0];
Packit Service 7c31a4
Packit Service 7c31a4
      /* Skip over '.' and '..' entries.  It has been reported that
Packit Service 7c31a4
       * the SharePoint driver includes the terminating zero byte in
Packit Service 7c31a4
       * the filename length.  Strip those first.
Packit Service 7c31a4
       */
Packit Service 7c31a4
      while (wchar_len > 0 && info->FileName[wchar_len - 1] == L'\0')
Packit Service 7c31a4
        wchar_len -= 1;
Packit Service 7c31a4
Packit Service 7c31a4
      if (wchar_len == 0)
Packit Service 7c31a4
        continue;
Packit Service 7c31a4
      if (wchar_len == 1 && info->FileName[0] == L'.')
Packit Service 7c31a4
        continue;
Packit Service 7c31a4
      if (wchar_len == 2 && info->FileName[0] == L'.' &&
Packit Service 7c31a4
          info->FileName[1] == L'.')
Packit Service 7c31a4
        continue;
Packit Service 7c31a4
Packit Service 7c31a4
      /* Compute the space required to store the filename as UTF-8. */
Packit Service 7c31a4
      utf8_len = WideCharToMultiByte(
Packit Service 7c31a4
          CP_UTF8, 0, &info->FileName[0], wchar_len, NULL, 0, NULL, NULL);
Packit Service 7c31a4
      if (utf8_len == 0)
Packit Service 7c31a4
        goto win32_error;
Packit Service 7c31a4
Packit Service 7c31a4
      /* Resize the dirent array if needed. */
Packit Service 7c31a4
      if (dirents_used >= dirents_size) {
Packit Service 7c31a4
        size_t new_dirents_size =
Packit Service 7c31a4
            dirents_size == 0 ? dirents_initial_size : dirents_size << 1;
Packit Service 7c31a4
        uv__dirent_t** new_dirents =
Packit Service 7c31a4
            uv__realloc(dirents, new_dirents_size * sizeof *dirents);
Packit Service 7c31a4
Packit Service 7c31a4
        if (new_dirents == NULL)
Packit Service 7c31a4
          goto out_of_memory_error;
Packit Service 7c31a4
Packit Service 7c31a4
        dirents_size = new_dirents_size;
Packit Service 7c31a4
        dirents = new_dirents;
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      /* Allocate space for the uv dirent structure. The dirent structure
Packit Service 7c31a4
       * includes room for the first character of the filename, but `utf8_len`
Packit Service 7c31a4
       * doesn't count the NULL terminator at this point.
Packit Service 7c31a4
       */
Packit Service 7c31a4
      dirent = uv__malloc(sizeof *dirent + utf8_len);
Packit Service 7c31a4
      if (dirent == NULL)
Packit Service 7c31a4
        goto out_of_memory_error;
Packit Service 7c31a4
Packit Service 7c31a4
      dirents[dirents_used++] = dirent;
Packit Service 7c31a4
Packit Service 7c31a4
      /* Convert file name to UTF-8. */
Packit Service 7c31a4
      if (WideCharToMultiByte(CP_UTF8,
Packit Service 7c31a4
                              0,
Packit Service 7c31a4
                              &info->FileName[0],
Packit Service 7c31a4
                              wchar_len,
Packit Service 7c31a4
                              &dirent->d_name[0],
Packit Service 7c31a4
                              utf8_len,
Packit Service 7c31a4
                              NULL,
Packit Service 7c31a4
                              NULL) == 0)
Packit Service 7c31a4
        goto win32_error;
Packit Service 7c31a4
Packit Service 7c31a4
      /* Add a null terminator to the filename. */
Packit Service 7c31a4
      dirent->d_name[utf8_len] = '\0';
Packit Service 7c31a4
Packit Service 7c31a4
      /* Fill out the type field. */
Packit Service 7c31a4
      if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE)
Packit Service 7c31a4
        dirent->d_type = UV__DT_CHAR;
Packit Service 7c31a4
      else if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
Packit Service 7c31a4
        dirent->d_type = UV__DT_LINK;
Packit Service 7c31a4
      else if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
Packit Service 7c31a4
        dirent->d_type = UV__DT_DIR;
Packit Service 7c31a4
      else
Packit Service 7c31a4
        dirent->d_type = UV__DT_FILE;
Packit Service 7c31a4
    } while (next_entry_offset != 0);
Packit Service 7c31a4
Packit Service 7c31a4
    /* Read the next chunk. */
Packit Service 7c31a4
    status = pNtQueryDirectoryFile(dir_handle,
Packit Service 7c31a4
                                   NULL,
Packit Service 7c31a4
                                   NULL,
Packit Service 7c31a4
                                   NULL,
Packit Service 7c31a4
                                   &iosb,
Packit Service 7c31a4
                                   &buffer,
Packit Service 7c31a4
                                   sizeof buffer,
Packit Service 7c31a4
                                   FileDirectoryInformation,
Packit Service 7c31a4
                                   FALSE,
Packit Service 7c31a4
                                   NULL,
Packit Service 7c31a4
                                   FALSE);
Packit Service 7c31a4
Packit Service 7c31a4
    /* After the first pNtQueryDirectoryFile call, the function may return
Packit Service 7c31a4
     * STATUS_SUCCESS even if the buffer was too small to hold at least one
Packit Service 7c31a4
     * directory entry.
Packit Service 7c31a4
     */
Packit Service 7c31a4
    if (status == STATUS_SUCCESS && iosb.Information == 0)
Packit Service 7c31a4
      status = STATUS_BUFFER_OVERFLOW;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (status != STATUS_NO_MORE_FILES)
Packit Service 7c31a4
    goto nt_error;
Packit Service 7c31a4
Packit Service 7c31a4
  CloseHandle(dir_handle);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Store the result in the request object. */
Packit Service 7c31a4
  req->ptr = dirents;
Packit Service 7c31a4
  if (dirents != NULL)
Packit Service 7c31a4
    req->flags |= UV_FS_FREE_PTR;
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_RESULT(req, dirents_used);
Packit Service 7c31a4
Packit Service 7c31a4
  /* `nbufs` will be used as index by uv_fs_scandir_next. */
Packit Service 7c31a4
  req->fs.info.nbufs = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  return;
Packit Service 7c31a4
Packit Service 7c31a4
nt_error:
Packit Service 7c31a4
  SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
Packit Service 7c31a4
  goto cleanup;
Packit Service 7c31a4
Packit Service 7c31a4
win32_error:
Packit Service 7c31a4
  SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
  goto cleanup;
Packit Service 7c31a4
Packit Service 7c31a4
not_a_directory_error:
Packit Service 7c31a4
  SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
Packit Service 7c31a4
  goto cleanup;
Packit Service 7c31a4
Packit Service 7c31a4
out_of_memory_error:
Packit Service 7c31a4
  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
Packit Service 7c31a4
  goto cleanup;
Packit Service 7c31a4
Packit Service 7c31a4
cleanup:
Packit Service 7c31a4
  if (dir_handle != INVALID_HANDLE_VALUE)
Packit Service 7c31a4
    CloseHandle(dir_handle);
Packit Service 7c31a4
  while (dirents_used > 0)
Packit Service 7c31a4
    uv__free(dirents[--dirents_used]);
Packit Service 7c31a4
  if (dirents != NULL)
Packit Service 7c31a4
    uv__free(dirents);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
void fs__opendir(uv_fs_t* req) {
Packit Service 7c31a4
  WCHAR* pathw;
Packit Service 7c31a4
  size_t len;
Packit Service 7c31a4
  const WCHAR* fmt;
Packit Service 7c31a4
  WCHAR* find_path;
Packit Service 7c31a4
  uv_dir_t* dir;
Packit Service 7c31a4
Packit Service 7c31a4
  pathw = req->file.pathw;
Packit Service 7c31a4
  dir = NULL;
Packit Service 7c31a4
  find_path = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Figure out whether path is a file or a directory. */
Packit Service 7c31a4
  if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  dir = uv__malloc(sizeof(*dir));
Packit Service 7c31a4
  if (dir == NULL) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  len = wcslen(pathw);
Packit Service 7c31a4
Packit Service 7c31a4
  if (len == 0)
Packit Service 7c31a4
    fmt = L"./*";
Packit Service 7c31a4
  else if (IS_SLASH(pathw[len - 1]))
Packit Service 7c31a4
    fmt = L"%s*";
Packit Service 7c31a4
  else
Packit Service 7c31a4
    fmt = L"%s\\*";
Packit Service 7c31a4
Packit Service 7c31a4
  find_path = uv__malloc(sizeof(WCHAR) * (len + 4));
Packit Service 7c31a4
  if (find_path == NULL) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  _snwprintf(find_path, len + 3, fmt, pathw);
Packit Service 7c31a4
  dir->dir_handle = FindFirstFileW(find_path, &dir->find_data);
Packit Service 7c31a4
  uv__free(find_path);
Packit Service 7c31a4
  find_path = NULL;
Packit Service 7c31a4
  if (dir->dir_handle == INVALID_HANDLE_VALUE &&
Packit Service 7c31a4
      GetLastError() != ERROR_FILE_NOT_FOUND) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  dir->need_find_call = FALSE;
Packit Service 7c31a4
  req->ptr = dir;
Packit Service 7c31a4
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
  return;
Packit Service 7c31a4
Packit Service 7c31a4
error:
Packit Service 7c31a4
  uv__free(dir);
Packit Service 7c31a4
  uv__free(find_path);
Packit Service 7c31a4
  req->ptr = NULL;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
void fs__readdir(uv_fs_t* req) {
Packit Service 7c31a4
  uv_dir_t* dir;
Packit Service 7c31a4
  uv_dirent_t* dirents;
Packit Service 7c31a4
  uv__dirent_t dent;
Packit Service 7c31a4
  unsigned int dirent_idx;
Packit Service 7c31a4
  PWIN32_FIND_DATAW find_data;
Packit Service 7c31a4
  unsigned int i;
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
Packit Service 7c31a4
  req->flags |= UV_FS_FREE_PTR;
Packit Service 7c31a4
  dir = req->ptr;
Packit Service 7c31a4
  dirents = dir->dirents;
Packit Service 7c31a4
  memset(dirents, 0, dir->nentries * sizeof(*dir->dirents));
Packit Service 7c31a4
  find_data = &dir->find_data;
Packit Service 7c31a4
  dirent_idx = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  while (dirent_idx < dir->nentries) {
Packit Service 7c31a4
    if (dir->need_find_call && FindNextFileW(dir->dir_handle, find_data) == 0) {
Packit Service 7c31a4
      if (GetLastError() == ERROR_NO_MORE_FILES)
Packit Service 7c31a4
        break;
Packit Service 7c31a4
      goto error;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    /* Skip "." and ".." entries. */
Packit Service 7c31a4
    if (find_data->cFileName[0] == L'.' &&
Packit Service 7c31a4
        (find_data->cFileName[1] == L'\0' ||
Packit Service 7c31a4
        (find_data->cFileName[1] == L'.' &&
Packit Service 7c31a4
        find_data->cFileName[2] == L'\0'))) {
Packit Service 7c31a4
      dir->need_find_call = TRUE;
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    r = uv__convert_utf16_to_utf8((const WCHAR*) &find_data->cFileName,
Packit Service 7c31a4
                                  -1,
Packit Service 7c31a4
                                  (char**) &dirents[dirent_idx].name);
Packit Service 7c31a4
    if (r != 0)
Packit Service 7c31a4
      goto error;
Packit Service 7c31a4
Packit Service 7c31a4
    /* Copy file type. */
Packit Service 7c31a4
    if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
Packit Service 7c31a4
      dent.d_type = UV__DT_DIR;
Packit Service 7c31a4
    else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
Packit Service 7c31a4
      dent.d_type = UV__DT_LINK;
Packit Service 7c31a4
    else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0)
Packit Service 7c31a4
      dent.d_type = UV__DT_CHAR;
Packit Service 7c31a4
    else
Packit Service 7c31a4
      dent.d_type = UV__DT_FILE;
Packit Service 7c31a4
Packit Service 7c31a4
    dirents[dirent_idx].type = uv__fs_get_dirent_type(&dent);
Packit Service 7c31a4
    dir->need_find_call = TRUE;
Packit Service 7c31a4
    ++dirent_idx;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_RESULT(req, dirent_idx);
Packit Service 7c31a4
  return;
Packit Service 7c31a4
Packit Service 7c31a4
error:
Packit Service 7c31a4
  SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
  for (i = 0; i < dirent_idx; ++i) {
Packit Service 7c31a4
    uv__free((char*) dirents[i].name);
Packit Service 7c31a4
    dirents[i].name = NULL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
void fs__closedir(uv_fs_t* req) {
Packit Service 7c31a4
  uv_dir_t* dir;
Packit Service 7c31a4
Packit Service 7c31a4
  dir = req->ptr;
Packit Service 7c31a4
  FindClose(dir->dir_handle);
Packit Service 7c31a4
  uv__free(req->ptr);
Packit Service 7c31a4
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
Packit Service 7c31a4
    int do_lstat) {
Packit Service 7c31a4
  FILE_ALL_INFORMATION file_info;
Packit Service 7c31a4
  FILE_FS_VOLUME_INFORMATION volume_info;
Packit Service 7c31a4
  NTSTATUS nt_status;
Packit Service 7c31a4
  IO_STATUS_BLOCK io_status;
Packit Service 7c31a4
Packit Service 7c31a4
  nt_status = pNtQueryInformationFile(handle,
Packit Service 7c31a4
                                      &io_status,
Packit Service 7c31a4
                                      &file_info,
Packit Service 7c31a4
                                      sizeof file_info,
Packit Service 7c31a4
                                      FileAllInformation);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Buffer overflow (a warning status code) is expected here. */
Packit Service 7c31a4
  if (NT_ERROR(nt_status)) {
Packit Service 7c31a4
    SetLastError(pRtlNtStatusToDosError(nt_status));
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  nt_status = pNtQueryVolumeInformationFile(handle,
Packit Service 7c31a4
                                            &io_status,
Packit Service 7c31a4
                                            &volume_info,
Packit Service 7c31a4
                                            sizeof volume_info,
Packit Service 7c31a4
                                            FileFsVolumeInformation);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Buffer overflow (a warning status code) is expected here. */
Packit Service 7c31a4
  if (io_status.Status == STATUS_NOT_IMPLEMENTED) {
Packit Service 7c31a4
    statbuf->st_dev = 0;
Packit Service 7c31a4
  } else if (NT_ERROR(nt_status)) {
Packit Service 7c31a4
    SetLastError(pRtlNtStatusToDosError(nt_status));
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    statbuf->st_dev = volume_info.VolumeSerialNumber;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Todo: st_mode should probably always be 0666 for everyone. We might also
Packit Service 7c31a4
   * want to report 0777 if the file is a .exe or a directory.
Packit Service 7c31a4
   *
Packit Service 7c31a4
   * Currently it's based on whether the 'readonly' attribute is set, which
Packit Service 7c31a4
   * makes little sense because the semantics are so different: the 'read-only'
Packit Service 7c31a4
   * flag is just a way for a user to protect against accidental deletion, and
Packit Service 7c31a4
   * serves no security purpose. Windows uses ACLs for that.
Packit Service 7c31a4
   *
Packit Service 7c31a4
   * Also people now use uv_fs_chmod() to take away the writable bit for good
Packit Service 7c31a4
   * reasons. Windows however just makes the file read-only, which makes it
Packit Service 7c31a4
   * impossible to delete the file afterwards, since read-only files can't be
Packit Service 7c31a4
   * deleted.
Packit Service 7c31a4
   *
Packit Service 7c31a4
   * IOW it's all just a clusterfuck and we should think of something that
Packit Service 7c31a4
   * makes slightly more sense.
Packit Service 7c31a4
   *
Packit Service 7c31a4
   * And uv_fs_chmod should probably just fail on windows or be a total no-op.
Packit Service 7c31a4
   * There's nothing sensible it can do anyway.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  statbuf->st_mode = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  /*
Packit Service 7c31a4
  * On Windows, FILE_ATTRIBUTE_REPARSE_POINT is a general purpose mechanism
Packit Service 7c31a4
  * by which filesystem drivers can intercept and alter file system requests.
Packit Service 7c31a4
  *
Packit Service 7c31a4
  * The only reparse points we care about are symlinks and mount points, both
Packit Service 7c31a4
  * of which are treated as POSIX symlinks. Further, we only care when
Packit Service 7c31a4
  * invoked via lstat, which seeks information about the link instead of its
Packit Service 7c31a4
  * target. Otherwise, reparse points must be treated as regular files.
Packit Service 7c31a4
  */
Packit Service 7c31a4
  if (do_lstat &&
Packit Service 7c31a4
      (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
Packit Service 7c31a4
    /*
Packit Service 7c31a4
     * If reading the link fails, the reparse point is not a symlink and needs
Packit Service 7c31a4
     * to be treated as a regular file. The higher level lstat function will
Packit Service 7c31a4
     * detect this failure and retry without do_lstat if appropriate.
Packit Service 7c31a4
     */
Packit Service 7c31a4
    if (fs__readlink_handle(handle, NULL, &statbuf->st_size) != 0)
Packit Service 7c31a4
      return -1;
Packit Service 7c31a4
    statbuf->st_mode |= S_IFLNK;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (statbuf->st_mode == 0) {
Packit Service 7c31a4
    if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
Packit Service 7c31a4
      statbuf->st_mode |= _S_IFDIR;
Packit Service 7c31a4
      statbuf->st_size = 0;
Packit Service 7c31a4
    } else {
Packit Service 7c31a4
      statbuf->st_mode |= _S_IFREG;
Packit Service 7c31a4
      statbuf->st_size = file_info.StandardInformation.EndOfFile.QuadPart;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY)
Packit Service 7c31a4
    statbuf->st_mode |= _S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6);
Packit Service 7c31a4
  else
Packit Service 7c31a4
    statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) |
Packit Service 7c31a4
                        ((_S_IREAD | _S_IWRITE) >> 6);
Packit Service 7c31a4
Packit Service 7c31a4
  FILETIME_TO_TIMESPEC(statbuf->st_atim, file_info.BasicInformation.LastAccessTime);
Packit Service 7c31a4
  FILETIME_TO_TIMESPEC(statbuf->st_ctim, file_info.BasicInformation.ChangeTime);
Packit Service 7c31a4
  FILETIME_TO_TIMESPEC(statbuf->st_mtim, file_info.BasicInformation.LastWriteTime);
Packit Service 7c31a4
  FILETIME_TO_TIMESPEC(statbuf->st_birthtim, file_info.BasicInformation.CreationTime);
Packit Service 7c31a4
Packit Service 7c31a4
  statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart;
Packit Service 7c31a4
Packit Service 7c31a4
  /* st_blocks contains the on-disk allocation size in 512-byte units. */
Packit Service 7c31a4
  statbuf->st_blocks =
Packit Service 7c31a4
      (uint64_t) file_info.StandardInformation.AllocationSize.QuadPart >> 9;
Packit Service 7c31a4
Packit Service 7c31a4
  statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks;
Packit Service 7c31a4
Packit Service 7c31a4
  /* The st_blksize is supposed to be the 'optimal' number of bytes for reading
Packit Service 7c31a4
   * and writing to the disk. That is, for any definition of 'optimal' - it's
Packit Service 7c31a4
   * supposed to at least avoid read-update-write behavior when writing to the
Packit Service 7c31a4
   * disk.
Packit Service 7c31a4
   *
Packit Service 7c31a4
   * However nobody knows this and even fewer people actually use this value,
Packit Service 7c31a4
   * and in order to fill it out we'd have to make another syscall to query the
Packit Service 7c31a4
   * volume for FILE_FS_SECTOR_SIZE_INFORMATION.
Packit Service 7c31a4
   *
Packit Service 7c31a4
   * Therefore we'll just report a sensible value that's quite commonly okay
Packit Service 7c31a4
   * on modern hardware.
Packit Service 7c31a4
   *
Packit Service 7c31a4
   * 4096 is the minimum required to be compatible with newer Advanced Format
Packit Service 7c31a4
   * drives (which have 4096 bytes per physical sector), and to be backwards
Packit Service 7c31a4
   * compatible with older drives (which have 512 bytes per physical sector).
Packit Service 7c31a4
   */
Packit Service 7c31a4
  statbuf->st_blksize = 4096;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Todo: set st_flags to something meaningful. Also provide a wrapper for
Packit Service 7c31a4
   * chattr(2).
Packit Service 7c31a4
   */
Packit Service 7c31a4
  statbuf->st_flags = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Windows has nothing sensible to say about these values, so they'll just
Packit Service 7c31a4
   * remain empty.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  statbuf->st_gid = 0;
Packit Service 7c31a4
  statbuf->st_uid = 0;
Packit Service 7c31a4
  statbuf->st_rdev = 0;
Packit Service 7c31a4
  statbuf->st_gen = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static void fs__stat_prepare_path(WCHAR* pathw) {
Packit Service 7c31a4
  size_t len = wcslen(pathw);
Packit Service 7c31a4
Packit Service 7c31a4
  /* TODO: ignore namespaced paths. */
Packit Service 7c31a4
  if (len > 1 && pathw[len - 2] != L':' &&
Packit Service 7c31a4
      (pathw[len - 1] == L'\\' || pathw[len - 1] == L'/')) {
Packit Service 7c31a4
    pathw[len - 1] = '\0';
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static DWORD fs__stat_impl_from_path(WCHAR* path,
Packit Service 7c31a4
                                            int do_lstat,
Packit Service 7c31a4
                                            uv_stat_t* statbuf) {
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  DWORD flags;
Packit Service 7c31a4
  DWORD ret;
Packit Service 7c31a4
Packit Service 7c31a4
  flags = FILE_FLAG_BACKUP_SEMANTICS;
Packit Service 7c31a4
  if (do_lstat)
Packit Service 7c31a4
    flags |= FILE_FLAG_OPEN_REPARSE_POINT;
Packit Service 7c31a4
Packit Service 7c31a4
  handle = CreateFileW(path,
Packit Service 7c31a4
                       FILE_READ_ATTRIBUTES,
Packit Service 7c31a4
                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
Packit Service 7c31a4
                       NULL,
Packit Service 7c31a4
                       OPEN_EXISTING,
Packit Service 7c31a4
                       flags,
Packit Service 7c31a4
                       NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE)
Packit Service 7c31a4
    ret = GetLastError();
Packit Service 7c31a4
  else if (fs__stat_handle(handle, statbuf, do_lstat) != 0)
Packit Service 7c31a4
    ret = GetLastError();
Packit Service 7c31a4
  else
Packit Service 7c31a4
    ret = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  CloseHandle(handle);
Packit Service 7c31a4
  return ret;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {
Packit Service 7c31a4
  DWORD error;
Packit Service 7c31a4
Packit Service 7c31a4
  error = fs__stat_impl_from_path(req->file.pathw, do_lstat, &req->statbuf);
Packit Service 7c31a4
  if (error != 0) {
Packit Service 7c31a4
    if (do_lstat &&
Packit Service 7c31a4
        (error == ERROR_SYMLINK_NOT_SUPPORTED ||
Packit Service 7c31a4
         error == ERROR_NOT_A_REPARSE_POINT)) {
Packit Service 7c31a4
      /* We opened a reparse point but it was not a symlink. Try again. */
Packit Service 7c31a4
      fs__stat_impl(req, 0);
Packit Service 7c31a4
    } else {
Packit Service 7c31a4
      /* Stat failed. */
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, error);
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->ptr = &req->statbuf;
Packit Service e2ebee
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__stat(uv_fs_t* req) {
Packit Service 7c31a4
  fs__stat_prepare_path(req->file.pathw);
Packit Service 7c31a4
  fs__stat_impl(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__lstat(uv_fs_t* req) {
Packit Service 7c31a4
  fs__stat_prepare_path(req->file.pathw);
Packit Service 7c31a4
  fs__stat_impl(req, 1);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__fstat(uv_fs_t* req) {
Packit Service 7c31a4
  int fd = req->file.fd;
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
Packit Service 7c31a4
  VERIFY_FD(fd, req);
Packit Service 7c31a4
Packit Service 7c31a4
  handle = uv__get_osfhandle(fd);
Packit Service 7c31a4
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (fs__stat_handle(handle, &req->statbuf, 0) != 0) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->ptr = &req->statbuf;
Packit Service e2ebee
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__rename(uv_fs_t* req) {
Packit Service 7c31a4
  if (!MoveFileExW(req->file.pathw, req->fs.info.new_pathw, MOVEFILE_REPLACE_EXISTING)) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static void fs__sync_impl(uv_fs_t* req) {
Packit Service 7c31a4
  int fd = req->file.fd;
Packit Service 7c31a4
  int result;
Packit Service 7c31a4
Packit Service 7c31a4
  VERIFY_FD(fd, req);
Packit Service 7c31a4
Packit Service 7c31a4
  result = FlushFileBuffers(uv__get_osfhandle(fd)) ? 0 : -1;
Packit Service 7c31a4
  if (result == -1) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    SET_REQ_RESULT(req, result);
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__fsync(uv_fs_t* req) {
Packit Service 7c31a4
  fs__sync_impl(req);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__fdatasync(uv_fs_t* req) {
Packit Service 7c31a4
  fs__sync_impl(req);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__ftruncate(uv_fs_t* req) {
Packit Service 7c31a4
  int fd = req->file.fd;
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  struct uv__fd_info_s fd_info = { 0 };
Packit Service 7c31a4
  NTSTATUS status;
Packit Service 7c31a4
  IO_STATUS_BLOCK io_status;
Packit Service 7c31a4
  FILE_END_OF_FILE_INFORMATION eof_info;
Packit Service 7c31a4
Packit Service 7c31a4
  VERIFY_FD(fd, req);
Packit Service 7c31a4
Packit Service 7c31a4
  handle = uv__get_osfhandle(fd);
Packit Service 7c31a4
Packit Service 7c31a4
  if (uv__fd_hash_get(fd, &fd_info)) {
Packit Service 7c31a4
    if (fd_info.is_directory) {
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    if (fd_info.mapping != INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
      CloseHandle(fd_info.mapping);
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  eof_info.EndOfFile.QuadPart = req->fs.info.offset;
Packit Service 7c31a4
Packit Service 7c31a4
  status = pNtSetInformationFile(handle,
Packit Service 7c31a4
                                 &io_status,
Packit Service 7c31a4
                                 &eof_info,
Packit Service 7c31a4
                                 sizeof eof_info,
Packit Service 7c31a4
                                 FileEndOfFileInformation);
Packit Service 7c31a4
Packit Service 7c31a4
  if (NT_SUCCESS(status)) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
Packit Service 7c31a4
Packit Service 7c31a4
    if (fd_info.flags) {
Packit Service 7c31a4
      CloseHandle(handle);
Packit Service 7c31a4
      fd_info.mapping = INVALID_HANDLE_VALUE;
Packit Service 7c31a4
      fd_info.size.QuadPart = 0;
Packit Service 7c31a4
      fd_info.current_pos.QuadPart = 0;
Packit Service 7c31a4
      uv__fd_hash_add(fd, &fd_info);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (fd_info.flags) {
Packit Service 7c31a4
    fd_info.size = eof_info.EndOfFile;
Packit Service 7c31a4
Packit Service 7c31a4
    if (fd_info.size.QuadPart == 0) {
Packit Service 7c31a4
      fd_info.mapping = INVALID_HANDLE_VALUE;
Packit Service 7c31a4
    } else {
Packit Service 7c31a4
      DWORD flProtect = (fd_info.flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY |
Packit Service 7c31a4
        UV_FS_O_RDWR)) == UV_FS_O_RDONLY ? PAGE_READONLY : PAGE_READWRITE;
Packit Service 7c31a4
      fd_info.mapping = CreateFileMapping(handle,
Packit Service 7c31a4
                                          NULL,
Packit Service 7c31a4
                                          flProtect,
Packit Service 7c31a4
                                          fd_info.size.HighPart,
Packit Service 7c31a4
                                          fd_info.size.LowPart,
Packit Service 7c31a4
                                          NULL);
Packit Service 7c31a4
      if (fd_info.mapping == NULL) {
Packit Service 7c31a4
        SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
        CloseHandle(handle);
Packit Service 7c31a4
        fd_info.mapping = INVALID_HANDLE_VALUE;
Packit Service 7c31a4
        fd_info.size.QuadPart = 0;
Packit Service 7c31a4
        fd_info.current_pos.QuadPart = 0;
Packit Service 7c31a4
        uv__fd_hash_add(fd, &fd_info);
Packit Service 7c31a4
        return;
Packit Service 7c31a4
      }
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    uv__fd_hash_add(fd, &fd_info);
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__copyfile(uv_fs_t* req) {
Packit Service 7c31a4
  int flags;
Packit Service 7c31a4
  int overwrite;
Packit Service 7c31a4
  uv_stat_t statbuf;
Packit Service 7c31a4
  uv_stat_t new_statbuf;
Packit Service 7c31a4
Packit Service 7c31a4
  flags = req->fs.info.file_flags;
Packit Service 7c31a4
Packit Service 7c31a4
  if (flags & UV_FS_COPYFILE_FICLONE_FORCE) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  overwrite = flags & UV_FS_COPYFILE_EXCL;
Packit Service 7c31a4
Packit Service 7c31a4
  if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) != 0) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
  if (req->result != UV_EBUSY)
Packit Service 7c31a4
    return;
Packit Service 7c31a4
Packit Service 7c31a4
  /* if error UV_EBUSY check if src and dst file are the same */
Packit Service 7c31a4
  if (fs__stat_impl_from_path(req->file.pathw, 0, &statbuf) != 0 ||
Packit Service 7c31a4
      fs__stat_impl_from_path(req->fs.info.new_pathw, 0, &new_statbuf) != 0) {
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (statbuf.st_dev == new_statbuf.st_dev &&
Packit Service 7c31a4
      statbuf.st_ino == new_statbuf.st_ino) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__sendfile(uv_fs_t* req) {
Packit Service 7c31a4
  int fd_in = req->file.fd, fd_out = req->fs.info.fd_out;
Packit Service 7c31a4
  size_t length = req->fs.info.bufsml[0].len;
Packit Service 7c31a4
  int64_t offset = req->fs.info.offset;
Packit Service 7c31a4
  const size_t max_buf_size = 65536;
Packit Service 7c31a4
  size_t buf_size = length < max_buf_size ? length : max_buf_size;
Packit Service 7c31a4
  int n, result = 0;
Packit Service 7c31a4
  int64_t result_offset = 0;
Packit Service 7c31a4
  char* buf = (char*) uv__malloc(buf_size);
Packit Service 7c31a4
  if (!buf) {
Packit Service 7c31a4
    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (offset != -1) {
Packit Service 7c31a4
    result_offset = _lseeki64(fd_in, offset, SEEK_SET);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (result_offset == -1) {
Packit Service 7c31a4
    result = -1;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    while (length > 0) {
Packit Service 7c31a4
      n = _read(fd_in, buf, length < buf_size ? length : buf_size);
Packit Service 7c31a4
      if (n == 0) {
Packit Service 7c31a4
        break;
Packit Service 7c31a4
      } else if (n == -1) {
Packit Service 7c31a4
        result = -1;
Packit Service 7c31a4
        break;
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      length -= n;
Packit Service 7c31a4
Packit Service 7c31a4
      n = _write(fd_out, buf, n);
Packit Service 7c31a4
      if (n == -1) {
Packit Service 7c31a4
        result = -1;
Packit Service 7c31a4
        break;
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      result += n;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(buf);
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_RESULT(req, result);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__access(uv_fs_t* req) {
Packit Service 7c31a4
  DWORD attr = GetFileAttributesW(req->file.pathw);
Packit Service 7c31a4
Packit Service 7c31a4
  if (attr == INVALID_FILE_ATTRIBUTES) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /*
Packit Service 7c31a4
   * Access is possible if
Packit Service 7c31a4
   * - write access wasn't requested,
Packit Service 7c31a4
   * - or the file isn't read-only,
Packit Service 7c31a4
   * - or it's a directory.
Packit Service 7c31a4
   * (Directories cannot be read-only on Windows.)
Packit Service 7c31a4
   */
Packit Service 7c31a4
  if (!(req->fs.info.mode & W_OK) ||
Packit Service 7c31a4
      !(attr & FILE_ATTRIBUTE_READONLY) ||
Packit Service 7c31a4
      (attr & FILE_ATTRIBUTE_DIRECTORY)) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, UV_EPERM);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__chmod(uv_fs_t* req) {
Packit Service 7c31a4
  int result = _wchmod(req->file.pathw, req->fs.info.mode);
Packit Service e2ebee
  if (result == -1)
Packit Service e2ebee
    SET_REQ_WIN32_ERROR(req, _doserrno);
Packit Service e2ebee
  else
Packit Service e2ebee
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__fchmod(uv_fs_t* req) {
Packit Service 7c31a4
  int fd = req->file.fd;
Packit Service 7c31a4
  int clear_archive_flag;
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  NTSTATUS nt_status;
Packit Service 7c31a4
  IO_STATUS_BLOCK io_status;
Packit Service 7c31a4
  FILE_BASIC_INFORMATION file_info;
Packit Service 7c31a4
Packit Service 7c31a4
  VERIFY_FD(fd, req);
Packit Service 7c31a4
Packit Service 7c31a4
  handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0);
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  nt_status = pNtQueryInformationFile(handle,
Packit Service 7c31a4
                                      &io_status,
Packit Service 7c31a4
                                      &file_info,
Packit Service 7c31a4
                                      sizeof file_info,
Packit Service 7c31a4
                                      FileBasicInformation);
Packit Service 7c31a4
Packit Service 7c31a4
  if (!NT_SUCCESS(nt_status)) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
Packit Service 7c31a4
    goto fchmod_cleanup;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Test if the Archive attribute is cleared */
Packit Service 7c31a4
  if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) {
Packit Service 7c31a4
      /* Set Archive flag, otherwise setting or clearing the read-only
Packit Service 7c31a4
         flag will not work */
Packit Service 7c31a4
      file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
Packit Service 7c31a4
      nt_status = pNtSetInformationFile(handle,
Packit Service 7c31a4
                                        &io_status,
Packit Service 7c31a4
                                        &file_info,
Packit Service 7c31a4
                                        sizeof file_info,
Packit Service 7c31a4
                                        FileBasicInformation);
Packit Service 7c31a4
      if (!NT_SUCCESS(nt_status)) {
Packit Service 7c31a4
        SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
Packit Service 7c31a4
        goto fchmod_cleanup;
Packit Service 7c31a4
      }
Packit Service 7c31a4
      /* Remeber to clear the flag later on */
Packit Service 7c31a4
      clear_archive_flag = 1;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
      clear_archive_flag = 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->fs.info.mode & _S_IWRITE) {
Packit Service 7c31a4
    file_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    file_info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  nt_status = pNtSetInformationFile(handle,
Packit Service 7c31a4
                                    &io_status,
Packit Service 7c31a4
                                    &file_info,
Packit Service 7c31a4
                                    sizeof file_info,
Packit Service 7c31a4
                                    FileBasicInformation);
Packit Service 7c31a4
Packit Service 7c31a4
  if (!NT_SUCCESS(nt_status)) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
Packit Service 7c31a4
    goto fchmod_cleanup;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (clear_archive_flag) {
Packit Service 7c31a4
      file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
Packit Service 7c31a4
      if (file_info.FileAttributes == 0) {
Packit Service 7c31a4
          file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
Packit Service 7c31a4
      }
Packit Service 7c31a4
      nt_status = pNtSetInformationFile(handle,
Packit Service 7c31a4
                                        &io_status,
Packit Service 7c31a4
                                        &file_info,
Packit Service 7c31a4
                                        sizeof file_info,
Packit Service 7c31a4
                                        FileBasicInformation);
Packit Service 7c31a4
      if (!NT_SUCCESS(nt_status)) {
Packit Service 7c31a4
        SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
Packit Service 7c31a4
        goto fchmod_cleanup;
Packit Service 7c31a4
      }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_SUCCESS(req);
Packit Service 7c31a4
fchmod_cleanup:
Packit Service 7c31a4
  CloseHandle(handle);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
Packit Service 7c31a4
  FILETIME filetime_a, filetime_m;
Packit Service 7c31a4
Packit Service 7c31a4
  TIME_T_TO_FILETIME(atime, &filetime_a);
Packit Service 7c31a4
  TIME_T_TO_FILETIME(mtime, &filetime_m);
Packit Service 7c31a4
Packit Service 7c31a4
  if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) {
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static DWORD fs__utime_impl_from_path(WCHAR* path,
Packit Service 7c31a4
                                             double atime,
Packit Service 7c31a4
                                             double mtime,
Packit Service 7c31a4
                                             int do_lutime) {
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  DWORD flags;
Packit Service 7c31a4
  DWORD ret;
Packit Service 7c31a4
Packit Service 7c31a4
  flags = FILE_FLAG_BACKUP_SEMANTICS;
Packit Service 7c31a4
  if (do_lutime) {
Packit Service 7c31a4
    flags |= FILE_FLAG_OPEN_REPARSE_POINT;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  handle = CreateFileW(path,
Packit Service 7c31a4
                       FILE_WRITE_ATTRIBUTES,
Packit Service 7c31a4
                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
Packit Service 7c31a4
                       NULL,
Packit Service 7c31a4
                       OPEN_EXISTING,
Packit Service 7c31a4
                       flags,
Packit Service 7c31a4
                       NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    ret = GetLastError();
Packit Service 7c31a4
  } else if (fs__utime_handle(handle, atime, mtime) != 0) {
Packit Service 7c31a4
    ret = GetLastError();
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    ret = 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  CloseHandle(handle);
Packit Service 7c31a4
  return ret;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
INLINE static void fs__utime_impl(uv_fs_t* req, int do_lutime) {
Packit Service 7c31a4
  DWORD error;
Packit Service 7c31a4
Packit Service 7c31a4
  error = fs__utime_impl_from_path(req->file.pathw,
Packit Service 7c31a4
                                   req->fs.time.atime,
Packit Service 7c31a4
                                   req->fs.time.mtime,
Packit Service 7c31a4
                                   do_lutime);
Packit Service 7c31a4
Packit Service 7c31a4
  if (error != 0) {
Packit Service 7c31a4
    if (do_lutime &&
Packit Service 7c31a4
        (error == ERROR_SYMLINK_NOT_SUPPORTED ||
Packit Service 7c31a4
         error == ERROR_NOT_A_REPARSE_POINT)) {
Packit Service 7c31a4
      /* Opened file is a reparse point but not a symlink. Try again. */
Packit Service 7c31a4
      fs__utime_impl(req, 0);
Packit Service 7c31a4
    } else {
Packit Service 7c31a4
      /* utime failed. */
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, error);
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service e2ebee
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__utime(uv_fs_t* req) {
Packit Service 7c31a4
  fs__utime_impl(req, /* do_lutime */ 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__futime(uv_fs_t* req) {
Packit Service 7c31a4
  int fd = req->file.fd;
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
  VERIFY_FD(fd, req);
Packit Service 7c31a4
Packit Service 7c31a4
  handle = uv__get_osfhandle(fd);
Packit Service 7c31a4
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service e2ebee
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__lutime(uv_fs_t* req) {
Packit Service 7c31a4
  fs__utime_impl(req, /* do_lutime */ 1);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__link(uv_fs_t* req) {
Packit Service 7c31a4
  DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL);
Packit Service e2ebee
  if (r == 0)
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service e2ebee
  else
Packit Service e2ebee
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__create_junction(uv_fs_t* req, const WCHAR* path,
Packit Service 7c31a4
    const WCHAR* new_path) {
Packit Service 7c31a4
  HANDLE handle = INVALID_HANDLE_VALUE;
Packit Service 7c31a4
  REPARSE_DATA_BUFFER *buffer = NULL;
Packit Service 7c31a4
  int created = 0;
Packit Service 7c31a4
  int target_len;
Packit Service 7c31a4
  int is_absolute, is_long_path;
Packit Service 7c31a4
  int needed_buf_size, used_buf_size, used_data_size, path_buf_len;
Packit Service 7c31a4
  int start, len, i;
Packit Service 7c31a4
  int add_slash;
Packit Service 7c31a4
  DWORD bytes;
Packit Service 7c31a4
  WCHAR* path_buf;
Packit Service 7c31a4
Packit Service 7c31a4
  target_len = wcslen(path);
Packit Service 7c31a4
  is_long_path = wcsncmp(path, LONG_PATH_PREFIX, LONG_PATH_PREFIX_LEN) == 0;
Packit Service 7c31a4
Packit Service 7c31a4
  if (is_long_path) {
Packit Service 7c31a4
    is_absolute = 1;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    is_absolute = target_len >= 3 && IS_LETTER(path[0]) &&
Packit Service 7c31a4
      path[1] == L':' && IS_SLASH(path[2]);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (!is_absolute) {
Packit Service 7c31a4
    /* Not supporting relative paths */
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_NOT_SUPPORTED);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Do a pessimistic calculation of the required buffer size */
Packit Service 7c31a4
  needed_buf_size =
Packit Service 7c31a4
      FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
Packit Service 7c31a4
      JUNCTION_PREFIX_LEN * sizeof(WCHAR) +
Packit Service 7c31a4
      2 * (target_len + 2) * sizeof(WCHAR);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Allocate the buffer */
Packit Service 7c31a4
  buffer = (REPARSE_DATA_BUFFER*)uv__malloc(needed_buf_size);
Packit Service 7c31a4
  if (!buffer) {
Packit Service 7c31a4
    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Grab a pointer to the part of the buffer where filenames go */
Packit Service 7c31a4
  path_buf = (WCHAR*)&(buffer->MountPointReparseBuffer.PathBuffer);
Packit Service 7c31a4
  path_buf_len = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Copy the substitute (internal) target path */
Packit Service 7c31a4
  start = path_buf_len;
Packit Service 7c31a4
Packit Service 7c31a4
  wcsncpy((WCHAR*)&path_buf[path_buf_len], JUNCTION_PREFIX,
Packit Service 7c31a4
    JUNCTION_PREFIX_LEN);
Packit Service 7c31a4
  path_buf_len += JUNCTION_PREFIX_LEN;
Packit Service 7c31a4
Packit Service 7c31a4
  add_slash = 0;
Packit Service 7c31a4
  for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
Packit Service 7c31a4
    if (IS_SLASH(path[i])) {
Packit Service 7c31a4
      add_slash = 1;
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    if (add_slash) {
Packit Service 7c31a4
      path_buf[path_buf_len++] = L'\\';
Packit Service 7c31a4
      add_slash = 0;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    path_buf[path_buf_len++] = path[i];
Packit Service 7c31a4
  }
Packit Service 7c31a4
  path_buf[path_buf_len++] = L'\\';
Packit Service 7c31a4
  len = path_buf_len - start;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Set the info about the substitute name */
Packit Service 7c31a4
  buffer->MountPointReparseBuffer.SubstituteNameOffset = start * sizeof(WCHAR);
Packit Service 7c31a4
  buffer->MountPointReparseBuffer.SubstituteNameLength = len * sizeof(WCHAR);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Insert null terminator */
Packit Service 7c31a4
  path_buf[path_buf_len++] = L'\0';
Packit Service 7c31a4
Packit Service 7c31a4
  /* Copy the print name of the target path */
Packit Service 7c31a4
  start = path_buf_len;
Packit Service 7c31a4
  add_slash = 0;
Packit Service 7c31a4
  for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
Packit Service 7c31a4
    if (IS_SLASH(path[i])) {
Packit Service 7c31a4
      add_slash = 1;
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    if (add_slash) {
Packit Service 7c31a4
      path_buf[path_buf_len++] = L'\\';
Packit Service 7c31a4
      add_slash = 0;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    path_buf[path_buf_len++] = path[i];
Packit Service 7c31a4
  }
Packit Service 7c31a4
  len = path_buf_len - start;
Packit Service 7c31a4
  if (len == 2) {
Packit Service 7c31a4
    path_buf[path_buf_len++] = L'\\';
Packit Service 7c31a4
    len++;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Set the info about the print name */
Packit Service 7c31a4
  buffer->MountPointReparseBuffer.PrintNameOffset = start * sizeof(WCHAR);
Packit Service 7c31a4
  buffer->MountPointReparseBuffer.PrintNameLength = len * sizeof(WCHAR);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Insert another null terminator */
Packit Service 7c31a4
  path_buf[path_buf_len++] = L'\0';
Packit Service 7c31a4
Packit Service 7c31a4
  /* Calculate how much buffer space was actually used */
Packit Service 7c31a4
  used_buf_size = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
Packit Service 7c31a4
    path_buf_len * sizeof(WCHAR);
Packit Service 7c31a4
  used_data_size = used_buf_size -
Packit Service 7c31a4
    FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Put general info in the data buffer */
Packit Service 7c31a4
  buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
Packit Service 7c31a4
  buffer->ReparseDataLength = used_data_size;
Packit Service 7c31a4
  buffer->Reserved = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Create a new directory */
Packit Service 7c31a4
  if (!CreateDirectoryW(new_path, NULL)) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  created = 1;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Open the directory */
Packit Service 7c31a4
  handle = CreateFileW(new_path,
Packit Service 7c31a4
                       GENERIC_WRITE,
Packit Service 7c31a4
                       0,
Packit Service 7c31a4
                       NULL,
Packit Service 7c31a4
                       OPEN_EXISTING,
Packit Service 7c31a4
                       FILE_FLAG_BACKUP_SEMANTICS |
Packit Service 7c31a4
                         FILE_FLAG_OPEN_REPARSE_POINT,
Packit Service 7c31a4
                       NULL);
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Create the actual reparse point */
Packit Service 7c31a4
  if (!DeviceIoControl(handle,
Packit Service 7c31a4
                       FSCTL_SET_REPARSE_POINT,
Packit Service 7c31a4
                       buffer,
Packit Service 7c31a4
                       used_buf_size,
Packit Service 7c31a4
                       NULL,
Packit Service 7c31a4
                       0,
Packit Service 7c31a4
                       &bytes,
Packit Service 7c31a4
                       NULL)) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    goto error;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Clean up */
Packit Service 7c31a4
  CloseHandle(handle);
Packit Service 7c31a4
  uv__free(buffer);
Packit Service 7c31a4
Packit Service 7c31a4
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
  return;
Packit Service 7c31a4
Packit Service 7c31a4
error:
Packit Service 7c31a4
  uv__free(buffer);
Packit Service 7c31a4
Packit Service 7c31a4
  if (handle != INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    CloseHandle(handle);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (created) {
Packit Service 7c31a4
    RemoveDirectoryW(new_path);
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__symlink(uv_fs_t* req) {
Packit Service 7c31a4
  WCHAR* pathw;
Packit Service 7c31a4
  WCHAR* new_pathw;
Packit Service 7c31a4
  int flags;
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  pathw = req->file.pathw;
Packit Service 7c31a4
  new_pathw = req->fs.info.new_pathw;
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->fs.info.file_flags & UV_FS_SYMLINK_JUNCTION) {
Packit Service 7c31a4
    fs__create_junction(req, pathw, new_pathw);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
Packit Service 7c31a4
    flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag;
Packit Service 7c31a4
  else
Packit Service 7c31a4
    flags = uv__file_symlink_usermode_flag;
Packit Service 7c31a4
Packit Service 7c31a4
  if (CreateSymbolicLinkW(new_pathw, pathw, flags)) {
Packit Service 7c31a4
    SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Something went wrong. We will test if it is because of user-mode
Packit Service 7c31a4
   * symlinks.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  err = GetLastError();
Packit Service 7c31a4
  if (err == ERROR_INVALID_PARAMETER &&
Packit Service 7c31a4
      flags & SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) {
Packit Service 7c31a4
    /* This system does not support user-mode symlinks. We will clear the
Packit Service 7c31a4
     * unsupported flag and retry.
Packit Service 7c31a4
     */
Packit Service 7c31a4
    uv__file_symlink_usermode_flag = 0;
Packit Service 7c31a4
    fs__symlink(req);
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__readlink(uv_fs_t* req) {
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
Packit Service 7c31a4
  handle = CreateFileW(req->file.pathw,
Packit Service 7c31a4
                       0,
Packit Service 7c31a4
                       0,
Packit Service 7c31a4
                       NULL,
Packit Service 7c31a4
                       OPEN_EXISTING,
Packit Service 7c31a4
                       FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
Packit Service 7c31a4
                       NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (fs__readlink_handle(handle, (char**) &req->ptr, NULL) != 0) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    CloseHandle(handle);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->flags |= UV_FS_FREE_PTR;
Packit Service 7c31a4
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
Packit Service 7c31a4
  CloseHandle(handle);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
Packit Service 7c31a4
  int r;
Packit Service 7c31a4
  DWORD w_realpath_len;
Packit Service 7c31a4
  WCHAR* w_realpath_ptr = NULL;
Packit Service 7c31a4
  WCHAR* w_realpath_buf;
Packit Service 7c31a4
Packit Service 7c31a4
  w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
Packit Service 7c31a4
  if (w_realpath_len == 0) {
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  w_realpath_buf = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR));
Packit Service 7c31a4
  if (w_realpath_buf == NULL) {
Packit Service 7c31a4
    SetLastError(ERROR_OUTOFMEMORY);
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  w_realpath_ptr = w_realpath_buf;
Packit Service 7c31a4
Packit Service 7c31a4
  if (GetFinalPathNameByHandleW(
Packit Service 7c31a4
          handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) {
Packit Service 7c31a4
    uv__free(w_realpath_buf);
Packit Service 7c31a4
    SetLastError(ERROR_INVALID_HANDLE);
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* convert UNC path to long path */
Packit Service 7c31a4
  if (wcsncmp(w_realpath_ptr,
Packit Service 7c31a4
              UNC_PATH_PREFIX,
Packit Service 7c31a4
              UNC_PATH_PREFIX_LEN) == 0) {
Packit Service 7c31a4
    w_realpath_ptr += 6;
Packit Service 7c31a4
    *w_realpath_ptr = L'\\';
Packit Service 7c31a4
    w_realpath_len -= 6;
Packit Service 7c31a4
  } else if (wcsncmp(w_realpath_ptr,
Packit Service 7c31a4
                      LONG_PATH_PREFIX,
Packit Service 7c31a4
                      LONG_PATH_PREFIX_LEN) == 0) {
Packit Service 7c31a4
    w_realpath_ptr += 4;
Packit Service 7c31a4
    w_realpath_len -= 4;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    uv__free(w_realpath_buf);
Packit Service 7c31a4
    SetLastError(ERROR_INVALID_HANDLE);
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  r = fs__wide_to_utf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL);
Packit Service 7c31a4
  uv__free(w_realpath_buf);
Packit Service 7c31a4
  return r;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__realpath(uv_fs_t* req) {
Packit Service 7c31a4
  HANDLE handle;
Packit Service 7c31a4
Packit Service 7c31a4
  handle = CreateFileW(req->file.pathw,
Packit Service 7c31a4
                       0,
Packit Service 7c31a4
                       0,
Packit Service 7c31a4
                       NULL,
Packit Service 7c31a4
                       OPEN_EXISTING,
Packit Service 7c31a4
                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
Packit Service 7c31a4
                       NULL);
Packit Service 7c31a4
  if (handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) {
Packit Service 7c31a4
    CloseHandle(handle);
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, GetLastError());
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  CloseHandle(handle);
Packit Service 7c31a4
  req->flags |= UV_FS_FREE_PTR;
Packit Service 7c31a4
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__chown(uv_fs_t* req) {
Packit Service e2ebee
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__fchown(uv_fs_t* req) {
Packit Service e2ebee
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__lchown(uv_fs_t* req) {
Packit Service e2ebee
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void fs__statfs(uv_fs_t* req) {
Packit Service 7c31a4
  uv_statfs_t* stat_fs;
Packit Service 7c31a4
  DWORD sectors_per_cluster;
Packit Service 7c31a4
  DWORD bytes_per_sector;
Packit Service 7c31a4
  DWORD free_clusters;
Packit Service 7c31a4
  DWORD total_clusters;
Packit Service 7c31a4
  WCHAR* pathw;
Packit Service 7c31a4
Packit Service 7c31a4
  pathw = req->file.pathw;
Packit Service 7c31a4
retry_get_disk_free_space:
Packit Service 7c31a4
  if (0 == GetDiskFreeSpaceW(pathw,
Packit Service 7c31a4
                             &sectors_per_cluster,
Packit Service 7c31a4
                             &bytes_per_sector,
Packit Service 7c31a4
                             &free_clusters,
Packit Service 7c31a4
                             &total_clusters)) {
Packit Service 7c31a4
    DWORD err;
Packit Service 7c31a4
    WCHAR* fpart;
Packit Service 7c31a4
    size_t len;
Packit Service 7c31a4
    DWORD ret;
Packit Service 7c31a4
    BOOL is_second;
Packit Service 7c31a4
Packit Service 7c31a4
    err = GetLastError();
Packit Service 7c31a4
    is_second = pathw != req->file.pathw;
Packit Service 7c31a4
    if (err != ERROR_DIRECTORY || is_second) {
Packit Service 7c31a4
      if (is_second)
Packit Service 7c31a4
        uv__free(pathw);
Packit Service 7c31a4
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    len = MAX_PATH + 1;
Packit Service 7c31a4
    pathw = uv__malloc(len * sizeof(*pathw));
Packit Service 7c31a4
    if (pathw == NULL) {
Packit Service 7c31a4
      SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
retry_get_full_path_name:
Packit Service 7c31a4
    ret = GetFullPathNameW(req->file.pathw,
Packit Service 7c31a4
                           len,
Packit Service 7c31a4
                           pathw,
Packit Service 7c31a4
                           &fpart);
Packit Service 7c31a4
    if (ret == 0) {
Packit Service 7c31a4
      uv__free(pathw);
Packit Service 7c31a4
      SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    } else if (ret > len) {
Packit Service 7c31a4
      len = ret;
Packit Service 7c31a4
      pathw = uv__reallocf(pathw, len * sizeof(*pathw));
Packit Service 7c31a4
      if (pathw == NULL) {
Packit Service 7c31a4
        SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
Packit Service 7c31a4
        return;
Packit Service 7c31a4
      }
Packit Service 7c31a4
      goto retry_get_full_path_name;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    if (fpart != 0)
Packit Service 7c31a4
      *fpart = L'\0';
Packit Service 7c31a4
Packit Service 7c31a4
    goto retry_get_disk_free_space;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  if (pathw != req->file.pathw) {
Packit Service 7c31a4
    uv__free(pathw);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  stat_fs = uv__malloc(sizeof(*stat_fs));
Packit Service 7c31a4
  if (stat_fs == NULL) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  stat_fs->f_type = 0;
Packit Service 7c31a4
  stat_fs->f_bsize = bytes_per_sector * sectors_per_cluster;
Packit Service 7c31a4
  stat_fs->f_blocks = total_clusters;
Packit Service 7c31a4
  stat_fs->f_bfree = free_clusters;
Packit Service 7c31a4
  stat_fs->f_bavail = free_clusters;
Packit Service 7c31a4
  stat_fs->f_files = 0;
Packit Service 7c31a4
  stat_fs->f_ffree = 0;
Packit Service 7c31a4
  req->ptr = stat_fs;
Packit Service 7c31a4
  req->flags |= UV_FS_FREE_PTR;
Packit Service 7c31a4
  SET_REQ_RESULT(req, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void uv__fs_work(struct uv__work* w) {
Packit Service 7c31a4
  uv_fs_t* req;
Packit Service 7c31a4
Packit Service 7c31a4
  req = container_of(w, uv_fs_t, work_req);
Packit Service 7c31a4
  assert(req->type == UV_FS);
Packit Service 7c31a4
Packit Service 7c31a4
#define XX(uc, lc)  case UV_FS_##uc: fs__##lc(req); break;
Packit Service 7c31a4
  switch (req->fs_type) {
Packit Service 7c31a4
    XX(OPEN, open)
Packit Service 7c31a4
    XX(CLOSE, close)
Packit Service 7c31a4
    XX(READ, read)
Packit Service 7c31a4
    XX(WRITE, write)
Packit Service 7c31a4
    XX(COPYFILE, copyfile)
Packit Service 7c31a4
    XX(SENDFILE, sendfile)
Packit Service 7c31a4
    XX(STAT, stat)
Packit Service 7c31a4
    XX(LSTAT, lstat)
Packit Service 7c31a4
    XX(FSTAT, fstat)
Packit Service 7c31a4
    XX(FTRUNCATE, ftruncate)
Packit Service 7c31a4
    XX(UTIME, utime)
Packit Service 7c31a4
    XX(FUTIME, futime)
Packit Service 7c31a4
    XX(LUTIME, lutime)
Packit Service 7c31a4
    XX(ACCESS, access)
Packit Service 7c31a4
    XX(CHMOD, chmod)
Packit Service 7c31a4
    XX(FCHMOD, fchmod)
Packit Service 7c31a4
    XX(FSYNC, fsync)
Packit Service 7c31a4
    XX(FDATASYNC, fdatasync)
Packit Service 7c31a4
    XX(UNLINK, unlink)
Packit Service 7c31a4
    XX(RMDIR, rmdir)
Packit Service 7c31a4
    XX(MKDIR, mkdir)
Packit Service 7c31a4
    XX(MKDTEMP, mkdtemp)
Packit Service 7c31a4
    XX(MKSTEMP, mkstemp)
Packit Service 7c31a4
    XX(RENAME, rename)
Packit Service 7c31a4
    XX(SCANDIR, scandir)
Packit Service 7c31a4
    XX(READDIR, readdir)
Packit Service 7c31a4
    XX(OPENDIR, opendir)
Packit Service 7c31a4
    XX(CLOSEDIR, closedir)
Packit Service 7c31a4
    XX(LINK, link)
Packit Service 7c31a4
    XX(SYMLINK, symlink)
Packit Service 7c31a4
    XX(READLINK, readlink)
Packit Service 7c31a4
    XX(REALPATH, realpath)
Packit Service 7c31a4
    XX(CHOWN, chown)
Packit Service 7c31a4
    XX(FCHOWN, fchown)
Packit Service 7c31a4
    XX(LCHOWN, lchown)
Packit Service 7c31a4
    XX(STATFS, statfs)
Packit Service 7c31a4
    default:
Packit Service 7c31a4
      assert(!"bad uv_fs_type");
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void uv__fs_done(struct uv__work* w, int status) {
Packit Service 7c31a4
  uv_fs_t* req;
Packit Service 7c31a4
Packit Service 7c31a4
  req = container_of(w, uv_fs_t, work_req);
Packit Service 7c31a4
  uv__req_unregister(req->loop, req);
Packit Service 7c31a4
Packit Service 7c31a4
  if (status == UV_ECANCELED) {
Packit Service 7c31a4
    assert(req->result == 0);
Packit Service e2ebee
    SET_REQ_UV_ERROR(req, UV_ECANCELED, 0);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->cb(req);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv_fs_req_cleanup(uv_fs_t* req) {
Packit Service 7c31a4
  if (req == NULL)
Packit Service 7c31a4
    return;
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->flags & UV_FS_CLEANEDUP)
Packit Service 7c31a4
    return;
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->flags & UV_FS_FREE_PATHS)
Packit Service 7c31a4
    uv__free(req->file.pathw);
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->flags & UV_FS_FREE_PTR) {
Packit Service 7c31a4
    if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
Packit Service 7c31a4
      uv__fs_scandir_cleanup(req);
Packit Service 7c31a4
    else if (req->fs_type == UV_FS_READDIR)
Packit Service 7c31a4
      uv__fs_readdir_cleanup(req);
Packit Service 7c31a4
    else
Packit Service 7c31a4
      uv__free(req->ptr);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->fs.info.bufs != req->fs.info.bufsml)
Packit Service 7c31a4
    uv__free(req->fs.info.bufs);
Packit Service 7c31a4
Packit Service 7c31a4
  req->path = NULL;
Packit Service 7c31a4
  req->file.pathw = NULL;
Packit Service 7c31a4
  req->fs.info.new_pathw = NULL;
Packit Service 7c31a4
  req->fs.info.bufs = NULL;
Packit Service 7c31a4
  req->ptr = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  req->flags |= UV_FS_CLEANEDUP;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
Packit Service 7c31a4
    int mode, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_OPEN);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.file_flags = flags;
Packit Service 7c31a4
  req->fs.info.mode = mode;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_CLOSE);
Packit Service 7c31a4
  req->file.fd = fd;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_read(uv_loop_t* loop,
Packit Service 7c31a4
               uv_fs_t* req,
Packit Service 7c31a4
               uv_file fd,
Packit Service 7c31a4
               const uv_buf_t bufs[],
Packit Service 7c31a4
               unsigned int nbufs,
Packit Service 7c31a4
               int64_t offset,
Packit Service 7c31a4
               uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_READ);
Packit Service 7c31a4
Packit Service 7c31a4
  if (bufs == NULL || nbufs == 0) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->file.fd = fd;
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.nbufs = nbufs;
Packit Service 7c31a4
  req->fs.info.bufs = req->fs.info.bufsml;
Packit Service 7c31a4
  if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
Packit Service 7c31a4
    req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->fs.info.bufs == NULL) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.offset = offset;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_write(uv_loop_t* loop,
Packit Service 7c31a4
                uv_fs_t* req,
Packit Service 7c31a4
                uv_file fd,
Packit Service 7c31a4
                const uv_buf_t bufs[],
Packit Service 7c31a4
                unsigned int nbufs,
Packit Service 7c31a4
                int64_t offset,
Packit Service 7c31a4
                uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_WRITE);
Packit Service 7c31a4
Packit Service 7c31a4
  if (bufs == NULL || nbufs == 0) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->file.fd = fd;
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.nbufs = nbufs;
Packit Service 7c31a4
  req->fs.info.bufs = req->fs.info.bufsml;
Packit Service 7c31a4
  if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
Packit Service 7c31a4
    req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
Packit Service 7c31a4
Packit Service 7c31a4
  if (req->fs.info.bufs == NULL) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.offset = offset;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
Packit Service 7c31a4
    uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_UNLINK);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
Packit Service 7c31a4
    uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_MKDIR);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.mode = mode;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_mkdtemp(uv_loop_t* loop,
Packit Service 7c31a4
                  uv_fs_t* req,
Packit Service 7c31a4
                  const char* tpl,
Packit Service 7c31a4
                  uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_MKDTEMP);
Packit Service 7c31a4
  err = fs__capture_path(req, tpl, NULL, TRUE);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_mkstemp(uv_loop_t* loop,
Packit Service 7c31a4
                  uv_fs_t* req,
Packit Service 7c31a4
                  const char* tpl,
Packit Service 7c31a4
                  uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_MKSTEMP);
Packit Service 7c31a4
  err = fs__capture_path(req, tpl, NULL, TRUE);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_RMDIR);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
Packit Service 7c31a4
    uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_SCANDIR);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.file_flags = flags;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_opendir(uv_loop_t* loop,
Packit Service 7c31a4
                  uv_fs_t* req,
Packit Service 7c31a4
                  const char* path,
Packit Service 7c31a4
                  uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_OPENDIR);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_readdir(uv_loop_t* loop,
Packit Service 7c31a4
                  uv_fs_t* req,
Packit Service 7c31a4
                  uv_dir_t* dir,
Packit Service 7c31a4
                  uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_READDIR);
Packit Service 7c31a4
Packit Service 7c31a4
  if (dir == NULL ||
Packit Service 7c31a4
      dir->dirents == NULL ||
Packit Service 7c31a4
      dir->dir_handle == INVALID_HANDLE_VALUE) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->ptr = dir;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_closedir(uv_loop_t* loop,
Packit Service 7c31a4
                   uv_fs_t* req,
Packit Service 7c31a4
                   uv_dir_t* dir,
Packit Service 7c31a4
                   uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_CLOSEDIR);
Packit Service 7c31a4
  if (dir == NULL) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  req->ptr = dir;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
Packit Service 7c31a4
    const char* new_path, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_LINK);
Packit Service 7c31a4
  err = fs__capture_path(req, path, new_path, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
Packit Service 7c31a4
    const char* new_path, int flags, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_SYMLINK);
Packit Service 7c31a4
  err = fs__capture_path(req, path, new_path, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.file_flags = flags;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
Packit Service 7c31a4
    uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_READLINK);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,
Packit Service 7c31a4
    uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_REALPATH);
Packit Service 7c31a4
Packit Service 7c31a4
  if (!path) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
Packit Service 7c31a4
    uv_gid_t gid, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_CHOWN);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid,
Packit Service 7c31a4
    uv_gid_t gid, uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_FCHOWN);
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
Packit Service 7c31a4
    uv_gid_t gid, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_LCHOWN);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_STAT);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_LSTAT);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_FSTAT);
Packit Service 7c31a4
  req->file.fd = fd;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
Packit Service 7c31a4
    const char* new_path, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_RENAME);
Packit Service 7c31a4
  err = fs__capture_path(req, path, new_path, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_FSYNC);
Packit Service 7c31a4
  req->file.fd = fd;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_FDATASYNC);
Packit Service 7c31a4
  req->file.fd = fd;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file fd,
Packit Service 7c31a4
    int64_t offset, uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_FTRUNCATE);
Packit Service 7c31a4
  req->file.fd = fd;
Packit Service 7c31a4
  req->fs.info.offset = offset;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_copyfile(uv_loop_t* loop,
Packit Service 7c31a4
                   uv_fs_t* req,
Packit Service 7c31a4
                   const char* path,
Packit Service 7c31a4
                   const char* new_path,
Packit Service 7c31a4
                   int flags,
Packit Service 7c31a4
                   uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_COPYFILE);
Packit Service 7c31a4
Packit Service 7c31a4
  if (flags & ~(UV_FS_COPYFILE_EXCL |
Packit Service 7c31a4
                UV_FS_COPYFILE_FICLONE |
Packit Service 7c31a4
                UV_FS_COPYFILE_FICLONE_FORCE)) {
Packit Service 7c31a4
    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  err = fs__capture_path(req, path, new_path, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.file_flags = flags;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out,
Packit Service 7c31a4
    uv_file fd_in, int64_t in_offset, size_t length, uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_SENDFILE);
Packit Service 7c31a4
  req->file.fd = fd_in;
Packit Service 7c31a4
  req->fs.info.fd_out = fd_out;
Packit Service 7c31a4
  req->fs.info.offset = in_offset;
Packit Service 7c31a4
  req->fs.info.bufsml[0].len = length;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_access(uv_loop_t* loop,
Packit Service 7c31a4
                 uv_fs_t* req,
Packit Service 7c31a4
                 const char* path,
Packit Service 7c31a4
                 int flags,
Packit Service 7c31a4
                 uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_ACCESS);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.mode = flags;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
Packit Service 7c31a4
    uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_CHMOD);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.info.mode = mode;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int mode,
Packit Service 7c31a4
    uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_FCHMOD);
Packit Service 7c31a4
  req->file.fd = fd;
Packit Service 7c31a4
  req->fs.info.mode = mode;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
Packit Service 7c31a4
    double mtime, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_UTIME);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.time.atime = atime;
Packit Service 7c31a4
  req->fs.time.mtime = mtime;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime,
Packit Service 7c31a4
    double mtime, uv_fs_cb cb) {
Packit Service 7c31a4
  INIT(UV_FS_FUTIME);
Packit Service 7c31a4
  req->file.fd = fd;
Packit Service 7c31a4
  req->fs.time.atime = atime;
Packit Service 7c31a4
  req->fs.time.mtime = mtime;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
Packit Service 7c31a4
    double mtime, uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_LUTIME);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  req->fs.time.atime = atime;
Packit Service 7c31a4
  req->fs.time.mtime = mtime;
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_statfs(uv_loop_t* loop,
Packit Service 7c31a4
                 uv_fs_t* req,
Packit Service 7c31a4
                 const char* path,
Packit Service 7c31a4
                 uv_fs_cb cb) {
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  INIT(UV_FS_STATFS);
Packit Service 7c31a4
  err = fs__capture_path(req, path, NULL, cb != NULL);
Packit Service 7c31a4
  if (err) {
Packit Service 7c31a4
    SET_REQ_WIN32_ERROR(req, err);
Packit Service 7c31a4
    return req->result;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  POST;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_get_system_error(const uv_fs_t* req) {
Packit Service 7c31a4
  return req->sys_errno_;
Packit Service 7c31a4
}