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