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