11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci#include "node_file.h"  // NOLINT(build/include_inline)
221cb0ef41Sopenharmony_ci#include "node_file-inl.h"
231cb0ef41Sopenharmony_ci#include "aliased_buffer-inl.h"
241cb0ef41Sopenharmony_ci#include "memory_tracker-inl.h"
251cb0ef41Sopenharmony_ci#include "node_buffer.h"
261cb0ef41Sopenharmony_ci#include "node_external_reference.h"
271cb0ef41Sopenharmony_ci#include "node_process-inl.h"
281cb0ef41Sopenharmony_ci#include "node_stat_watcher.h"
291cb0ef41Sopenharmony_ci#include "util-inl.h"
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci#include "tracing/trace_event.h"
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci#include "req_wrap-inl.h"
341cb0ef41Sopenharmony_ci#include "stream_base-inl.h"
351cb0ef41Sopenharmony_ci#include "string_bytes.h"
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci#include <fcntl.h>
381cb0ef41Sopenharmony_ci#include <sys/types.h>
391cb0ef41Sopenharmony_ci#include <sys/stat.h>
401cb0ef41Sopenharmony_ci#include <cstring>
411cb0ef41Sopenharmony_ci#include <cerrno>
421cb0ef41Sopenharmony_ci#include <climits>
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci#if defined(__MINGW32__) || defined(_MSC_VER)
451cb0ef41Sopenharmony_ci# include <io.h>
461cb0ef41Sopenharmony_ci#endif
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci#include <memory>
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_cinamespace node {
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_cinamespace fs {
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ciusing v8::Array;
551cb0ef41Sopenharmony_ciusing v8::BigInt;
561cb0ef41Sopenharmony_ciusing v8::Boolean;
571cb0ef41Sopenharmony_ciusing v8::Context;
581cb0ef41Sopenharmony_ciusing v8::EscapableHandleScope;
591cb0ef41Sopenharmony_ciusing v8::Function;
601cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
611cb0ef41Sopenharmony_ciusing v8::FunctionTemplate;
621cb0ef41Sopenharmony_ciusing v8::HandleScope;
631cb0ef41Sopenharmony_ciusing v8::Int32;
641cb0ef41Sopenharmony_ciusing v8::Integer;
651cb0ef41Sopenharmony_ciusing v8::Isolate;
661cb0ef41Sopenharmony_ciusing v8::Local;
671cb0ef41Sopenharmony_ciusing v8::MaybeLocal;
681cb0ef41Sopenharmony_ciusing v8::Number;
691cb0ef41Sopenharmony_ciusing v8::Object;
701cb0ef41Sopenharmony_ciusing v8::ObjectTemplate;
711cb0ef41Sopenharmony_ciusing v8::Promise;
721cb0ef41Sopenharmony_ciusing v8::String;
731cb0ef41Sopenharmony_ciusing v8::Undefined;
741cb0ef41Sopenharmony_ciusing v8::Value;
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci#ifndef S_ISDIR
771cb0ef41Sopenharmony_ci# define S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
781cb0ef41Sopenharmony_ci#endif
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci#ifdef __POSIX__
811cb0ef41Sopenharmony_ciconstexpr char kPathSeparator = '/';
821cb0ef41Sopenharmony_ci#else
831cb0ef41Sopenharmony_ciconst char* const kPathSeparator = "\\/";
841cb0ef41Sopenharmony_ci#endif
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_cistd::string Basename(const std::string& str, const std::string& extension) {
871cb0ef41Sopenharmony_ci  // Remove everything leading up to and including the final path separator.
881cb0ef41Sopenharmony_ci  std::string::size_type pos = str.find_last_of(kPathSeparator);
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  // Starting index for the resulting string
911cb0ef41Sopenharmony_ci  std::size_t start_pos = 0;
921cb0ef41Sopenharmony_ci  // String size to return
931cb0ef41Sopenharmony_ci  std::size_t str_size = str.size();
941cb0ef41Sopenharmony_ci  if (pos != std::string::npos) {
951cb0ef41Sopenharmony_ci    start_pos = pos + 1;
961cb0ef41Sopenharmony_ci    str_size -= start_pos;
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  // Strip away the extension, if any.
1001cb0ef41Sopenharmony_ci  if (str_size >= extension.size() &&
1011cb0ef41Sopenharmony_ci      str.compare(str.size() - extension.size(),
1021cb0ef41Sopenharmony_ci        extension.size(), extension) == 0) {
1031cb0ef41Sopenharmony_ci    str_size -= extension.size();
1041cb0ef41Sopenharmony_ci  }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  return str.substr(start_pos, str_size);
1071cb0ef41Sopenharmony_ci}
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ciinline int64_t GetOffset(Local<Value> value) {
1101cb0ef41Sopenharmony_ci  return IsSafeJsInt(value) ? value.As<Integer>()->Value() : -1;
1111cb0ef41Sopenharmony_ci}
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_cistatic const char* get_fs_func_name_by_type(uv_fs_type req_type) {
1141cb0ef41Sopenharmony_ci  switch (req_type) {
1151cb0ef41Sopenharmony_ci#define FS_TYPE_TO_NAME(type, name)                                            \
1161cb0ef41Sopenharmony_ci  case UV_FS_##type:                                                           \
1171cb0ef41Sopenharmony_ci    return name;
1181cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(OPEN, "open")
1191cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(CLOSE, "close")
1201cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(READ, "read")
1211cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(WRITE, "write")
1221cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(SENDFILE, "sendfile")
1231cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(STAT, "stat")
1241cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(LSTAT, "lstat")
1251cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(FSTAT, "fstat")
1261cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(FTRUNCATE, "ftruncate")
1271cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(UTIME, "utime")
1281cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(FUTIME, "futime")
1291cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(ACCESS, "access")
1301cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(CHMOD, "chmod")
1311cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(FCHMOD, "fchmod")
1321cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(FSYNC, "fsync")
1331cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(FDATASYNC, "fdatasync")
1341cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(UNLINK, "unlink")
1351cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(RMDIR, "rmdir")
1361cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(MKDIR, "mkdir")
1371cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(MKDTEMP, "mkdtemp")
1381cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(RENAME, "rename")
1391cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(SCANDIR, "scandir")
1401cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(LINK, "link")
1411cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(SYMLINK, "symlink")
1421cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(READLINK, "readlink")
1431cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(CHOWN, "chown")
1441cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(FCHOWN, "fchown")
1451cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(REALPATH, "realpath")
1461cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(COPYFILE, "copyfile")
1471cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(LCHOWN, "lchown")
1481cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(STATFS, "statfs")
1491cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(MKSTEMP, "mkstemp")
1501cb0ef41Sopenharmony_ci    FS_TYPE_TO_NAME(LUTIME, "lutime")
1511cb0ef41Sopenharmony_ci#undef FS_TYPE_TO_NAME
1521cb0ef41Sopenharmony_ci    default:
1531cb0ef41Sopenharmony_ci      return "unknow";
1541cb0ef41Sopenharmony_ci  }
1551cb0ef41Sopenharmony_ci}
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci#define TRACE_NAME(name) "fs.sync." #name
1581cb0ef41Sopenharmony_ci#define GET_TRACE_ENABLED                                                      \
1591cb0ef41Sopenharmony_ci  (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(                                \
1601cb0ef41Sopenharmony_ci       TRACING_CATEGORY_NODE2(fs, sync)) != 0)
1611cb0ef41Sopenharmony_ci#define FS_SYNC_TRACE_BEGIN(syscall, ...)                                      \
1621cb0ef41Sopenharmony_ci  if (GET_TRACE_ENABLED)                                                       \
1631cb0ef41Sopenharmony_ci    TRACE_EVENT_BEGIN(                                                         \
1641cb0ef41Sopenharmony_ci        TRACING_CATEGORY_NODE2(fs, sync), TRACE_NAME(syscall), ##__VA_ARGS__);
1651cb0ef41Sopenharmony_ci#define FS_SYNC_TRACE_END(syscall, ...)                                        \
1661cb0ef41Sopenharmony_ci  if (GET_TRACE_ENABLED)                                                       \
1671cb0ef41Sopenharmony_ci    TRACE_EVENT_END(                                                           \
1681cb0ef41Sopenharmony_ci        TRACING_CATEGORY_NODE2(fs, sync), TRACE_NAME(syscall), ##__VA_ARGS__);
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci#define FS_ASYNC_TRACE_BEGIN0(fs_type, id)                                     \
1711cb0ef41Sopenharmony_ci  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(TRACING_CATEGORY_NODE2(fs, async),         \
1721cb0ef41Sopenharmony_ci                                    get_fs_func_name_by_type(fs_type),         \
1731cb0ef41Sopenharmony_ci                                    id);
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci#define FS_ASYNC_TRACE_END0(fs_type, id)                                       \
1761cb0ef41Sopenharmony_ci  TRACE_EVENT_NESTABLE_ASYNC_END0(TRACING_CATEGORY_NODE2(fs, async),           \
1771cb0ef41Sopenharmony_ci                                  get_fs_func_name_by_type(fs_type),           \
1781cb0ef41Sopenharmony_ci                                  id);
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci#define FS_ASYNC_TRACE_BEGIN1(fs_type, id, name, value)                        \
1811cb0ef41Sopenharmony_ci  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(TRACING_CATEGORY_NODE2(fs, async),         \
1821cb0ef41Sopenharmony_ci                                    get_fs_func_name_by_type(fs_type),         \
1831cb0ef41Sopenharmony_ci                                    id,                                        \
1841cb0ef41Sopenharmony_ci                                    name,                                      \
1851cb0ef41Sopenharmony_ci                                    value);
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci#define FS_ASYNC_TRACE_END1(fs_type, id, name, value)                          \
1881cb0ef41Sopenharmony_ci  TRACE_EVENT_NESTABLE_ASYNC_END1(TRACING_CATEGORY_NODE2(fs, async),           \
1891cb0ef41Sopenharmony_ci                                  get_fs_func_name_by_type(fs_type),           \
1901cb0ef41Sopenharmony_ci                                  id,                                          \
1911cb0ef41Sopenharmony_ci                                  name,                                        \
1921cb0ef41Sopenharmony_ci                                  value);
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci#define FS_ASYNC_TRACE_BEGIN2(fs_type, id, name1, value1, name2, value2)       \
1951cb0ef41Sopenharmony_ci  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(TRACING_CATEGORY_NODE2(fs, async),         \
1961cb0ef41Sopenharmony_ci                                    get_fs_func_name_by_type(fs_type),         \
1971cb0ef41Sopenharmony_ci                                    id,                                        \
1981cb0ef41Sopenharmony_ci                                    name1,                                     \
1991cb0ef41Sopenharmony_ci                                    value1,                                    \
2001cb0ef41Sopenharmony_ci                                    name2,                                     \
2011cb0ef41Sopenharmony_ci                                    value2);
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci#define FS_ASYNC_TRACE_END2(fs_type, id, name1, value1, name2, value2)         \
2041cb0ef41Sopenharmony_ci  TRACE_EVENT_NESTABLE_ASYNC_END2(TRACING_CATEGORY_NODE2(fs, async),           \
2051cb0ef41Sopenharmony_ci                                  get_fs_func_name_by_type(fs_type),           \
2061cb0ef41Sopenharmony_ci                                  id,                                          \
2071cb0ef41Sopenharmony_ci                                  name1,                                       \
2081cb0ef41Sopenharmony_ci                                  value1,                                      \
2091cb0ef41Sopenharmony_ci                                  name2,                                       \
2101cb0ef41Sopenharmony_ci                                  value2);
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci// We sometimes need to convert a C++ lambda function to a raw C-style function.
2131cb0ef41Sopenharmony_ci// This is helpful, because ReqWrap::Dispatch() does not recognize lambda
2141cb0ef41Sopenharmony_ci// functions, and thus does not wrap them properly.
2151cb0ef41Sopenharmony_citypedef void(*uv_fs_callback_t)(uv_fs_t*);
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_civoid FSContinuationData::MemoryInfo(MemoryTracker* tracker) const {
2191cb0ef41Sopenharmony_ci  tracker->TrackField("paths", paths_);
2201cb0ef41Sopenharmony_ci}
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ciFileHandleReadWrap::~FileHandleReadWrap() = default;
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ciFSReqBase::~FSReqBase() = default;
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_civoid FSReqBase::MemoryInfo(MemoryTracker* tracker) const {
2271cb0ef41Sopenharmony_ci  tracker->TrackField("continuation_data", continuation_data_);
2281cb0ef41Sopenharmony_ci}
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci// The FileHandle object wraps a file descriptor and will close it on garbage
2311cb0ef41Sopenharmony_ci// collection if necessary. If that happens, a process warning will be
2321cb0ef41Sopenharmony_ci// emitted (or a fatal exception will occur if the fd cannot be closed.)
2331cb0ef41Sopenharmony_ciFileHandle::FileHandle(BindingData* binding_data,
2341cb0ef41Sopenharmony_ci                       Local<Object> obj, int fd)
2351cb0ef41Sopenharmony_ci    : AsyncWrap(binding_data->env(), obj, AsyncWrap::PROVIDER_FILEHANDLE),
2361cb0ef41Sopenharmony_ci      StreamBase(env()),
2371cb0ef41Sopenharmony_ci      fd_(fd),
2381cb0ef41Sopenharmony_ci      binding_data_(binding_data) {
2391cb0ef41Sopenharmony_ci  MakeWeak();
2401cb0ef41Sopenharmony_ci  StreamBase::AttachToObject(GetObject());
2411cb0ef41Sopenharmony_ci}
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ciFileHandle* FileHandle::New(BindingData* binding_data,
2441cb0ef41Sopenharmony_ci                            int fd, Local<Object> obj) {
2451cb0ef41Sopenharmony_ci  Environment* env = binding_data->env();
2461cb0ef41Sopenharmony_ci  if (obj.IsEmpty() && !env->fd_constructor_template()
2471cb0ef41Sopenharmony_ci                            ->NewInstance(env->context())
2481cb0ef41Sopenharmony_ci                            .ToLocal(&obj)) {
2491cb0ef41Sopenharmony_ci    return nullptr;
2501cb0ef41Sopenharmony_ci  }
2511cb0ef41Sopenharmony_ci  return new FileHandle(binding_data, obj, fd);
2521cb0ef41Sopenharmony_ci}
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_civoid FileHandle::New(const FunctionCallbackInfo<Value>& args) {
2551cb0ef41Sopenharmony_ci  BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
2561cb0ef41Sopenharmony_ci  Environment* env = binding_data->env();
2571cb0ef41Sopenharmony_ci  CHECK(args.IsConstructCall());
2581cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci  FileHandle* handle =
2611cb0ef41Sopenharmony_ci      FileHandle::New(binding_data, args[0].As<Int32>()->Value(), args.This());
2621cb0ef41Sopenharmony_ci  if (handle == nullptr) return;
2631cb0ef41Sopenharmony_ci  if (args[1]->IsNumber())
2641cb0ef41Sopenharmony_ci    handle->read_offset_ = args[1]->IntegerValue(env->context()).FromJust();
2651cb0ef41Sopenharmony_ci  if (args[2]->IsNumber())
2661cb0ef41Sopenharmony_ci    handle->read_length_ = args[2]->IntegerValue(env->context()).FromJust();
2671cb0ef41Sopenharmony_ci}
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ciFileHandle::~FileHandle() {
2701cb0ef41Sopenharmony_ci  CHECK(!closing_);  // We should not be deleting while explicitly closing!
2711cb0ef41Sopenharmony_ci  Close();           // Close synchronously and emit warning
2721cb0ef41Sopenharmony_ci  CHECK(closed_);    // We have to be closed at the point
2731cb0ef41Sopenharmony_ci}
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ciint FileHandle::DoWrite(WriteWrap* w,
2761cb0ef41Sopenharmony_ci                        uv_buf_t* bufs,
2771cb0ef41Sopenharmony_ci                        size_t count,
2781cb0ef41Sopenharmony_ci                        uv_stream_t* send_handle) {
2791cb0ef41Sopenharmony_ci  return UV_ENOSYS;  // Not implemented (yet).
2801cb0ef41Sopenharmony_ci}
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_civoid FileHandle::MemoryInfo(MemoryTracker* tracker) const {
2831cb0ef41Sopenharmony_ci  tracker->TrackField("current_read", current_read_);
2841cb0ef41Sopenharmony_ci}
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ciFileHandle::TransferMode FileHandle::GetTransferMode() const {
2871cb0ef41Sopenharmony_ci  return reading_ || closing_ || closed_ ?
2881cb0ef41Sopenharmony_ci      TransferMode::kUntransferable : TransferMode::kTransferable;
2891cb0ef41Sopenharmony_ci}
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_cistd::unique_ptr<worker::TransferData> FileHandle::TransferForMessaging() {
2921cb0ef41Sopenharmony_ci  CHECK_NE(GetTransferMode(), TransferMode::kUntransferable);
2931cb0ef41Sopenharmony_ci  auto ret = std::make_unique<TransferData>(fd_);
2941cb0ef41Sopenharmony_ci  closed_ = true;
2951cb0ef41Sopenharmony_ci  return ret;
2961cb0ef41Sopenharmony_ci}
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ciFileHandle::TransferData::TransferData(int fd) : fd_(fd) {}
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ciFileHandle::TransferData::~TransferData() {
3011cb0ef41Sopenharmony_ci  if (fd_ > 0) {
3021cb0ef41Sopenharmony_ci    uv_fs_t close_req;
3031cb0ef41Sopenharmony_ci    CHECK_NE(fd_, -1);
3041cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(close);
3051cb0ef41Sopenharmony_ci    CHECK_EQ(0, uv_fs_close(nullptr, &close_req, fd_, nullptr));
3061cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(close);
3071cb0ef41Sopenharmony_ci    uv_fs_req_cleanup(&close_req);
3081cb0ef41Sopenharmony_ci  }
3091cb0ef41Sopenharmony_ci}
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ciBaseObjectPtr<BaseObject> FileHandle::TransferData::Deserialize(
3121cb0ef41Sopenharmony_ci    Environment* env,
3131cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context,
3141cb0ef41Sopenharmony_ci    std::unique_ptr<worker::TransferData> self) {
3151cb0ef41Sopenharmony_ci  BindingData* bd = Realm::GetBindingData<BindingData>(context);
3161cb0ef41Sopenharmony_ci  if (bd == nullptr) return {};
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci  int fd = fd_;
3191cb0ef41Sopenharmony_ci  fd_ = -1;
3201cb0ef41Sopenharmony_ci  return BaseObjectPtr<BaseObject> { FileHandle::New(bd, fd) };
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci// Close the file descriptor if it hasn't already been closed. A process
3241cb0ef41Sopenharmony_ci// warning will be emitted using a SetImmediate to avoid calling back to
3251cb0ef41Sopenharmony_ci// JS during GC. If closing the fd fails at this point, a fatal exception
3261cb0ef41Sopenharmony_ci// will crash the process immediately.
3271cb0ef41Sopenharmony_ciinline void FileHandle::Close() {
3281cb0ef41Sopenharmony_ci  if (closed_ || closing_) return;
3291cb0ef41Sopenharmony_ci  uv_fs_t req;
3301cb0ef41Sopenharmony_ci  CHECK_NE(fd_, -1);
3311cb0ef41Sopenharmony_ci  FS_SYNC_TRACE_BEGIN(close);
3321cb0ef41Sopenharmony_ci  int ret = uv_fs_close(env()->event_loop(), &req, fd_, nullptr);
3331cb0ef41Sopenharmony_ci  FS_SYNC_TRACE_END(close);
3341cb0ef41Sopenharmony_ci  uv_fs_req_cleanup(&req);
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_ci  struct err_detail { int ret; int fd; };
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ci  err_detail detail { ret, fd_ };
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci  AfterClose();
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci  if (ret < 0) {
3431cb0ef41Sopenharmony_ci    // Do not unref this
3441cb0ef41Sopenharmony_ci    env()->SetImmediate([detail](Environment* env) {
3451cb0ef41Sopenharmony_ci      char msg[70];
3461cb0ef41Sopenharmony_ci      snprintf(msg, arraysize(msg),
3471cb0ef41Sopenharmony_ci              "Closing file descriptor %d on garbage collection failed",
3481cb0ef41Sopenharmony_ci              detail.fd);
3491cb0ef41Sopenharmony_ci      // This exception will end up being fatal for the process because
3501cb0ef41Sopenharmony_ci      // it is being thrown from within the SetImmediate handler and
3511cb0ef41Sopenharmony_ci      // there is no JS stack to bubble it to. In other words, tearing
3521cb0ef41Sopenharmony_ci      // down the process is the only reasonable thing we can do here.
3531cb0ef41Sopenharmony_ci      HandleScope handle_scope(env->isolate());
3541cb0ef41Sopenharmony_ci      env->ThrowUVException(detail.ret, "close", msg);
3551cb0ef41Sopenharmony_ci    });
3561cb0ef41Sopenharmony_ci    return;
3571cb0ef41Sopenharmony_ci  }
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci  // If the close was successful, we still want to emit a process warning
3601cb0ef41Sopenharmony_ci  // to notify that the file descriptor was gc'd. We want to be noisy about
3611cb0ef41Sopenharmony_ci  // this because not explicitly closing the FileHandle is a bug.
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci  env()->SetImmediate([detail](Environment* env) {
3641cb0ef41Sopenharmony_ci    ProcessEmitWarning(env,
3651cb0ef41Sopenharmony_ci                       "Closing file descriptor %d on garbage collection",
3661cb0ef41Sopenharmony_ci                       detail.fd);
3671cb0ef41Sopenharmony_ci    if (env->filehandle_close_warning()) {
3681cb0ef41Sopenharmony_ci      env->set_filehandle_close_warning(false);
3691cb0ef41Sopenharmony_ci      USE(ProcessEmitDeprecationWarning(
3701cb0ef41Sopenharmony_ci          env,
3711cb0ef41Sopenharmony_ci          "Closing a FileHandle object on garbage collection is deprecated. "
3721cb0ef41Sopenharmony_ci          "Please close FileHandle objects explicitly using "
3731cb0ef41Sopenharmony_ci          "FileHandle.prototype.close(). In the future, an error will be "
3741cb0ef41Sopenharmony_ci          "thrown if a file descriptor is closed during garbage collection.",
3751cb0ef41Sopenharmony_ci          "DEP0137"));
3761cb0ef41Sopenharmony_ci    }
3771cb0ef41Sopenharmony_ci  }, CallbackFlags::kUnrefed);
3781cb0ef41Sopenharmony_ci}
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_civoid FileHandle::CloseReq::Resolve() {
3811cb0ef41Sopenharmony_ci  Isolate* isolate = env()->isolate();
3821cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
3831cb0ef41Sopenharmony_ci  Context::Scope context_scope(env()->context());
3841cb0ef41Sopenharmony_ci  InternalCallbackScope callback_scope(this);
3851cb0ef41Sopenharmony_ci  Local<Promise> promise = promise_.Get(isolate);
3861cb0ef41Sopenharmony_ci  Local<Promise::Resolver> resolver = promise.As<Promise::Resolver>();
3871cb0ef41Sopenharmony_ci  resolver->Resolve(env()->context(), Undefined(isolate)).Check();
3881cb0ef41Sopenharmony_ci}
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_civoid FileHandle::CloseReq::Reject(Local<Value> reason) {
3911cb0ef41Sopenharmony_ci  Isolate* isolate = env()->isolate();
3921cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
3931cb0ef41Sopenharmony_ci  Context::Scope context_scope(env()->context());
3941cb0ef41Sopenharmony_ci  InternalCallbackScope callback_scope(this);
3951cb0ef41Sopenharmony_ci  Local<Promise> promise = promise_.Get(isolate);
3961cb0ef41Sopenharmony_ci  Local<Promise::Resolver> resolver = promise.As<Promise::Resolver>();
3971cb0ef41Sopenharmony_ci  resolver->Reject(env()->context(), reason).Check();
3981cb0ef41Sopenharmony_ci}
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ciFileHandle* FileHandle::CloseReq::file_handle() {
4011cb0ef41Sopenharmony_ci  Isolate* isolate = env()->isolate();
4021cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
4031cb0ef41Sopenharmony_ci  Local<Value> val = ref_.Get(isolate);
4041cb0ef41Sopenharmony_ci  Local<Object> obj = val.As<Object>();
4051cb0ef41Sopenharmony_ci  return Unwrap<FileHandle>(obj);
4061cb0ef41Sopenharmony_ci}
4071cb0ef41Sopenharmony_ci
4081cb0ef41Sopenharmony_ciFileHandle::CloseReq::CloseReq(Environment* env,
4091cb0ef41Sopenharmony_ci                               Local<Object> obj,
4101cb0ef41Sopenharmony_ci                               Local<Promise> promise,
4111cb0ef41Sopenharmony_ci                               Local<Value> ref)
4121cb0ef41Sopenharmony_ci  : ReqWrap(env, obj, AsyncWrap::PROVIDER_FILEHANDLECLOSEREQ) {
4131cb0ef41Sopenharmony_ci  promise_.Reset(env->isolate(), promise);
4141cb0ef41Sopenharmony_ci  ref_.Reset(env->isolate(), ref);
4151cb0ef41Sopenharmony_ci}
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_ciFileHandle::CloseReq::~CloseReq() {
4181cb0ef41Sopenharmony_ci  uv_fs_req_cleanup(req());
4191cb0ef41Sopenharmony_ci  promise_.Reset();
4201cb0ef41Sopenharmony_ci  ref_.Reset();
4211cb0ef41Sopenharmony_ci}
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_civoid FileHandle::CloseReq::MemoryInfo(MemoryTracker* tracker) const {
4241cb0ef41Sopenharmony_ci  tracker->TrackField("promise", promise_);
4251cb0ef41Sopenharmony_ci  tracker->TrackField("ref", ref_);
4261cb0ef41Sopenharmony_ci}
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci// Closes this FileHandle asynchronously and returns a Promise that will be
4311cb0ef41Sopenharmony_ci// resolved when the callback is invoked, or rejects with a UVException if
4321cb0ef41Sopenharmony_ci// there was a problem closing the fd. This is the preferred mechanism for
4331cb0ef41Sopenharmony_ci// closing the FD object even tho the object will attempt to close
4341cb0ef41Sopenharmony_ci// automatically on gc.
4351cb0ef41Sopenharmony_ciMaybeLocal<Promise> FileHandle::ClosePromise() {
4361cb0ef41Sopenharmony_ci  Isolate* isolate = env()->isolate();
4371cb0ef41Sopenharmony_ci  EscapableHandleScope scope(isolate);
4381cb0ef41Sopenharmony_ci  Local<Context> context = env()->context();
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ci  Local<Value> close_resolver =
4411cb0ef41Sopenharmony_ci      object()->GetInternalField(FileHandle::kClosingPromiseSlot).As<Value>();
4421cb0ef41Sopenharmony_ci  if (!close_resolver.IsEmpty() && !close_resolver->IsUndefined()) {
4431cb0ef41Sopenharmony_ci    CHECK(close_resolver->IsPromise());
4441cb0ef41Sopenharmony_ci    return close_resolver.As<Promise>();
4451cb0ef41Sopenharmony_ci  }
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_ci  CHECK(!closed_);
4481cb0ef41Sopenharmony_ci  CHECK(!closing_);
4491cb0ef41Sopenharmony_ci  CHECK(!reading_);
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_ci  auto maybe_resolver = Promise::Resolver::New(context);
4521cb0ef41Sopenharmony_ci  CHECK(!maybe_resolver.IsEmpty());
4531cb0ef41Sopenharmony_ci  Local<Promise::Resolver> resolver = maybe_resolver.ToLocalChecked();
4541cb0ef41Sopenharmony_ci  Local<Promise> promise = resolver.As<Promise>();
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  Local<Object> close_req_obj;
4571cb0ef41Sopenharmony_ci  if (!env()->fdclose_constructor_template()
4581cb0ef41Sopenharmony_ci          ->NewInstance(env()->context()).ToLocal(&close_req_obj)) {
4591cb0ef41Sopenharmony_ci    return MaybeLocal<Promise>();
4601cb0ef41Sopenharmony_ci  }
4611cb0ef41Sopenharmony_ci  closing_ = true;
4621cb0ef41Sopenharmony_ci  object()->SetInternalField(FileHandle::kClosingPromiseSlot, promise);
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ci  CloseReq* req = new CloseReq(env(), close_req_obj, promise, object());
4651cb0ef41Sopenharmony_ci  auto AfterClose = uv_fs_callback_t{[](uv_fs_t* req) {
4661cb0ef41Sopenharmony_ci    CloseReq* req_wrap = CloseReq::from_req(req);
4671cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_END1(
4681cb0ef41Sopenharmony_ci        req->fs_type, req_wrap, "result", static_cast<int>(req->result))
4691cb0ef41Sopenharmony_ci    BaseObjectPtr<CloseReq> close(req_wrap);
4701cb0ef41Sopenharmony_ci    CHECK(close);
4711cb0ef41Sopenharmony_ci    close->file_handle()->AfterClose();
4721cb0ef41Sopenharmony_ci    if (!close->env()->can_call_into_js()) return;
4731cb0ef41Sopenharmony_ci    Isolate* isolate = close->env()->isolate();
4741cb0ef41Sopenharmony_ci    if (req->result < 0) {
4751cb0ef41Sopenharmony_ci      HandleScope handle_scope(isolate);
4761cb0ef41Sopenharmony_ci      close->Reject(
4771cb0ef41Sopenharmony_ci          UVException(isolate, static_cast<int>(req->result), "close"));
4781cb0ef41Sopenharmony_ci    } else {
4791cb0ef41Sopenharmony_ci      close->Resolve();
4801cb0ef41Sopenharmony_ci    }
4811cb0ef41Sopenharmony_ci  }};
4821cb0ef41Sopenharmony_ci  CHECK_NE(fd_, -1);
4831cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_BEGIN0(UV_FS_CLOSE, req)
4841cb0ef41Sopenharmony_ci  int ret = req->Dispatch(uv_fs_close, fd_, AfterClose);
4851cb0ef41Sopenharmony_ci  if (ret < 0) {
4861cb0ef41Sopenharmony_ci    req->Reject(UVException(isolate, ret, "close"));
4871cb0ef41Sopenharmony_ci    delete req;
4881cb0ef41Sopenharmony_ci  }
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_ci  return scope.Escape(promise);
4911cb0ef41Sopenharmony_ci}
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_civoid FileHandle::Close(const FunctionCallbackInfo<Value>& args) {
4941cb0ef41Sopenharmony_ci  FileHandle* fd;
4951cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&fd, args.Holder());
4961cb0ef41Sopenharmony_ci  Local<Promise> ret;
4971cb0ef41Sopenharmony_ci  if (!fd->ClosePromise().ToLocal(&ret)) return;
4981cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(ret);
4991cb0ef41Sopenharmony_ci}
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_civoid FileHandle::ReleaseFD(const FunctionCallbackInfo<Value>& args) {
5031cb0ef41Sopenharmony_ci  FileHandle* fd;
5041cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&fd, args.Holder());
5051cb0ef41Sopenharmony_ci  // Just act as if this FileHandle has been closed.
5061cb0ef41Sopenharmony_ci  fd->AfterClose();
5071cb0ef41Sopenharmony_ci}
5081cb0ef41Sopenharmony_ci
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_civoid FileHandle::AfterClose() {
5111cb0ef41Sopenharmony_ci  closing_ = false;
5121cb0ef41Sopenharmony_ci  closed_ = true;
5131cb0ef41Sopenharmony_ci  fd_ = -1;
5141cb0ef41Sopenharmony_ci  if (reading_ && !persistent().IsEmpty())
5151cb0ef41Sopenharmony_ci    EmitRead(UV_EOF);
5161cb0ef41Sopenharmony_ci}
5171cb0ef41Sopenharmony_ci
5181cb0ef41Sopenharmony_civoid FileHandleReadWrap::MemoryInfo(MemoryTracker* tracker) const {
5191cb0ef41Sopenharmony_ci  tracker->TrackField("buffer", buffer_);
5201cb0ef41Sopenharmony_ci  tracker->TrackField("file_handle", this->file_handle_);
5211cb0ef41Sopenharmony_ci}
5221cb0ef41Sopenharmony_ci
5231cb0ef41Sopenharmony_ciFileHandleReadWrap::FileHandleReadWrap(FileHandle* handle, Local<Object> obj)
5241cb0ef41Sopenharmony_ci  : ReqWrap(handle->env(), obj, AsyncWrap::PROVIDER_FSREQCALLBACK),
5251cb0ef41Sopenharmony_ci    file_handle_(handle) {}
5261cb0ef41Sopenharmony_ci
5271cb0ef41Sopenharmony_ciint FileHandle::ReadStart() {
5281cb0ef41Sopenharmony_ci  if (!IsAlive() || IsClosing())
5291cb0ef41Sopenharmony_ci    return UV_EOF;
5301cb0ef41Sopenharmony_ci
5311cb0ef41Sopenharmony_ci  reading_ = true;
5321cb0ef41Sopenharmony_ci
5331cb0ef41Sopenharmony_ci  if (current_read_)
5341cb0ef41Sopenharmony_ci    return 0;
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ci  BaseObjectPtr<FileHandleReadWrap> read_wrap;
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ci  if (read_length_ == 0) {
5391cb0ef41Sopenharmony_ci    EmitRead(UV_EOF);
5401cb0ef41Sopenharmony_ci    return 0;
5411cb0ef41Sopenharmony_ci  }
5421cb0ef41Sopenharmony_ci
5431cb0ef41Sopenharmony_ci  {
5441cb0ef41Sopenharmony_ci    // Create a new FileHandleReadWrap or re-use one.
5451cb0ef41Sopenharmony_ci    // Either way, we need these two scopes for AsyncReset() or otherwise
5461cb0ef41Sopenharmony_ci    // for creating the new instance.
5471cb0ef41Sopenharmony_ci    HandleScope handle_scope(env()->isolate());
5481cb0ef41Sopenharmony_ci    AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(this);
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_ci    auto& freelist = binding_data_->file_handle_read_wrap_freelist;
5511cb0ef41Sopenharmony_ci    if (freelist.size() > 0) {
5521cb0ef41Sopenharmony_ci      read_wrap = std::move(freelist.back());
5531cb0ef41Sopenharmony_ci      freelist.pop_back();
5541cb0ef41Sopenharmony_ci      // Use a fresh async resource.
5551cb0ef41Sopenharmony_ci      // Lifetime is ensured via AsyncWrap::resource_.
5561cb0ef41Sopenharmony_ci      Local<Object> resource = Object::New(env()->isolate());
5571cb0ef41Sopenharmony_ci      USE(resource->Set(
5581cb0ef41Sopenharmony_ci          env()->context(), env()->handle_string(), read_wrap->object()));
5591cb0ef41Sopenharmony_ci      read_wrap->AsyncReset(resource);
5601cb0ef41Sopenharmony_ci      read_wrap->file_handle_ = this;
5611cb0ef41Sopenharmony_ci    } else {
5621cb0ef41Sopenharmony_ci      Local<Object> wrap_obj;
5631cb0ef41Sopenharmony_ci      if (!env()
5641cb0ef41Sopenharmony_ci               ->filehandlereadwrap_template()
5651cb0ef41Sopenharmony_ci               ->NewInstance(env()->context())
5661cb0ef41Sopenharmony_ci               .ToLocal(&wrap_obj)) {
5671cb0ef41Sopenharmony_ci        return UV_EBUSY;
5681cb0ef41Sopenharmony_ci      }
5691cb0ef41Sopenharmony_ci      read_wrap = MakeDetachedBaseObject<FileHandleReadWrap>(this, wrap_obj);
5701cb0ef41Sopenharmony_ci    }
5711cb0ef41Sopenharmony_ci  }
5721cb0ef41Sopenharmony_ci  int64_t recommended_read = 65536;
5731cb0ef41Sopenharmony_ci  if (read_length_ >= 0 && read_length_ <= recommended_read)
5741cb0ef41Sopenharmony_ci    recommended_read = read_length_;
5751cb0ef41Sopenharmony_ci
5761cb0ef41Sopenharmony_ci  read_wrap->buffer_ = EmitAlloc(recommended_read);
5771cb0ef41Sopenharmony_ci
5781cb0ef41Sopenharmony_ci  current_read_ = std::move(read_wrap);
5791cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_BEGIN0(UV_FS_READ, current_read_.get())
5801cb0ef41Sopenharmony_ci  current_read_->Dispatch(uv_fs_read,
5811cb0ef41Sopenharmony_ci                          fd_,
5821cb0ef41Sopenharmony_ci                          &current_read_->buffer_,
5831cb0ef41Sopenharmony_ci                          1,
5841cb0ef41Sopenharmony_ci                          read_offset_,
5851cb0ef41Sopenharmony_ci                          uv_fs_callback_t{[](uv_fs_t* req) {
5861cb0ef41Sopenharmony_ci    FileHandle* handle;
5871cb0ef41Sopenharmony_ci    {
5881cb0ef41Sopenharmony_ci      FileHandleReadWrap* req_wrap = FileHandleReadWrap::from_req(req);
5891cb0ef41Sopenharmony_ci      FS_ASYNC_TRACE_END1(
5901cb0ef41Sopenharmony_ci          req->fs_type, req_wrap, "result", static_cast<int>(req->result))
5911cb0ef41Sopenharmony_ci      handle = req_wrap->file_handle_;
5921cb0ef41Sopenharmony_ci      CHECK_EQ(handle->current_read_.get(), req_wrap);
5931cb0ef41Sopenharmony_ci    }
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_ci    // ReadStart() checks whether current_read_ is set to determine whether
5961cb0ef41Sopenharmony_ci    // a read is in progress. Moving it into a local variable makes sure that
5971cb0ef41Sopenharmony_ci    // the ReadStart() call below doesn't think we're still actively reading.
5981cb0ef41Sopenharmony_ci    BaseObjectPtr<FileHandleReadWrap> read_wrap =
5991cb0ef41Sopenharmony_ci        std::move(handle->current_read_);
6001cb0ef41Sopenharmony_ci
6011cb0ef41Sopenharmony_ci    ssize_t result = req->result;
6021cb0ef41Sopenharmony_ci    uv_buf_t buffer = read_wrap->buffer_;
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ci    uv_fs_req_cleanup(req);
6051cb0ef41Sopenharmony_ci
6061cb0ef41Sopenharmony_ci    // Push the read wrap back to the freelist, or let it be destroyed
6071cb0ef41Sopenharmony_ci    // once we’re exiting the current scope.
6081cb0ef41Sopenharmony_ci    constexpr size_t kWantedFreelistFill = 100;
6091cb0ef41Sopenharmony_ci    auto& freelist = handle->binding_data_->file_handle_read_wrap_freelist;
6101cb0ef41Sopenharmony_ci    if (freelist.size() < kWantedFreelistFill) {
6111cb0ef41Sopenharmony_ci      read_wrap->Reset();
6121cb0ef41Sopenharmony_ci      freelist.emplace_back(std::move(read_wrap));
6131cb0ef41Sopenharmony_ci    }
6141cb0ef41Sopenharmony_ci
6151cb0ef41Sopenharmony_ci    if (result >= 0) {
6161cb0ef41Sopenharmony_ci      // Read at most as many bytes as we originally planned to.
6171cb0ef41Sopenharmony_ci      if (handle->read_length_ >= 0 && handle->read_length_ < result)
6181cb0ef41Sopenharmony_ci        result = handle->read_length_;
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_ci      // If we read data and we have an expected length, decrease it by
6211cb0ef41Sopenharmony_ci      // how much we have read.
6221cb0ef41Sopenharmony_ci      if (handle->read_length_ >= 0)
6231cb0ef41Sopenharmony_ci        handle->read_length_ -= result;
6241cb0ef41Sopenharmony_ci
6251cb0ef41Sopenharmony_ci      // If we have an offset, increase it by how much we have read.
6261cb0ef41Sopenharmony_ci      if (handle->read_offset_ >= 0)
6271cb0ef41Sopenharmony_ci        handle->read_offset_ += result;
6281cb0ef41Sopenharmony_ci    }
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci    // Reading 0 bytes from a file always means EOF, or that we reached
6311cb0ef41Sopenharmony_ci    // the end of the requested range.
6321cb0ef41Sopenharmony_ci    if (result == 0)
6331cb0ef41Sopenharmony_ci      result = UV_EOF;
6341cb0ef41Sopenharmony_ci
6351cb0ef41Sopenharmony_ci    handle->EmitRead(result, buffer);
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ci    // Start over, if EmitRead() didn’t tell us to stop.
6381cb0ef41Sopenharmony_ci    if (handle->reading_)
6391cb0ef41Sopenharmony_ci      handle->ReadStart();
6401cb0ef41Sopenharmony_ci  }});
6411cb0ef41Sopenharmony_ci
6421cb0ef41Sopenharmony_ci  return 0;
6431cb0ef41Sopenharmony_ci}
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_ciint FileHandle::ReadStop() {
6461cb0ef41Sopenharmony_ci  reading_ = false;
6471cb0ef41Sopenharmony_ci  return 0;
6481cb0ef41Sopenharmony_ci}
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_citypedef SimpleShutdownWrap<ReqWrap<uv_fs_t>> FileHandleCloseWrap;
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ciShutdownWrap* FileHandle::CreateShutdownWrap(Local<Object> object) {
6531cb0ef41Sopenharmony_ci  return new FileHandleCloseWrap(this, object);
6541cb0ef41Sopenharmony_ci}
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ciint FileHandle::DoShutdown(ShutdownWrap* req_wrap) {
6571cb0ef41Sopenharmony_ci  if (closing_ || closed_) {
6581cb0ef41Sopenharmony_ci    req_wrap->Done(0);
6591cb0ef41Sopenharmony_ci    return 1;
6601cb0ef41Sopenharmony_ci  }
6611cb0ef41Sopenharmony_ci  FileHandleCloseWrap* wrap = static_cast<FileHandleCloseWrap*>(req_wrap);
6621cb0ef41Sopenharmony_ci  closing_ = true;
6631cb0ef41Sopenharmony_ci  CHECK_NE(fd_, -1);
6641cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_BEGIN0(UV_FS_CLOSE, wrap)
6651cb0ef41Sopenharmony_ci  wrap->Dispatch(uv_fs_close, fd_, uv_fs_callback_t{[](uv_fs_t* req) {
6661cb0ef41Sopenharmony_ci    FileHandleCloseWrap* wrap = static_cast<FileHandleCloseWrap*>(
6671cb0ef41Sopenharmony_ci        FileHandleCloseWrap::from_req(req));
6681cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_END1(
6691cb0ef41Sopenharmony_ci        req->fs_type, wrap, "result", static_cast<int>(req->result))
6701cb0ef41Sopenharmony_ci    FileHandle* handle = static_cast<FileHandle*>(wrap->stream());
6711cb0ef41Sopenharmony_ci    handle->AfterClose();
6721cb0ef41Sopenharmony_ci
6731cb0ef41Sopenharmony_ci    int result = static_cast<int>(req->result);
6741cb0ef41Sopenharmony_ci    uv_fs_req_cleanup(req);
6751cb0ef41Sopenharmony_ci    wrap->Done(result);
6761cb0ef41Sopenharmony_ci  }});
6771cb0ef41Sopenharmony_ci
6781cb0ef41Sopenharmony_ci  return 0;
6791cb0ef41Sopenharmony_ci}
6801cb0ef41Sopenharmony_ci
6811cb0ef41Sopenharmony_ci
6821cb0ef41Sopenharmony_civoid FSReqCallback::Reject(Local<Value> reject) {
6831cb0ef41Sopenharmony_ci  MakeCallback(env()->oncomplete_string(), 1, &reject);
6841cb0ef41Sopenharmony_ci}
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_civoid FSReqCallback::ResolveStat(const uv_stat_t* stat) {
6871cb0ef41Sopenharmony_ci  Resolve(FillGlobalStatsArray(binding_data(), use_bigint(), stat));
6881cb0ef41Sopenharmony_ci}
6891cb0ef41Sopenharmony_ci
6901cb0ef41Sopenharmony_civoid FSReqCallback::ResolveStatFs(const uv_statfs_t* stat) {
6911cb0ef41Sopenharmony_ci  Resolve(FillGlobalStatFsArray(binding_data(), use_bigint(), stat));
6921cb0ef41Sopenharmony_ci}
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_civoid FSReqCallback::Resolve(Local<Value> value) {
6951cb0ef41Sopenharmony_ci  Local<Value> argv[2] {
6961cb0ef41Sopenharmony_ci    Null(env()->isolate()),
6971cb0ef41Sopenharmony_ci    value
6981cb0ef41Sopenharmony_ci  };
6991cb0ef41Sopenharmony_ci  MakeCallback(env()->oncomplete_string(),
7001cb0ef41Sopenharmony_ci               value->IsUndefined() ? 1 : arraysize(argv),
7011cb0ef41Sopenharmony_ci               argv);
7021cb0ef41Sopenharmony_ci}
7031cb0ef41Sopenharmony_ci
7041cb0ef41Sopenharmony_civoid FSReqCallback::SetReturnValue(const FunctionCallbackInfo<Value>& args) {
7051cb0ef41Sopenharmony_ci  args.GetReturnValue().SetUndefined();
7061cb0ef41Sopenharmony_ci}
7071cb0ef41Sopenharmony_ci
7081cb0ef41Sopenharmony_civoid NewFSReqCallback(const FunctionCallbackInfo<Value>& args) {
7091cb0ef41Sopenharmony_ci  CHECK(args.IsConstructCall());
7101cb0ef41Sopenharmony_ci  BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
7111cb0ef41Sopenharmony_ci  new FSReqCallback(binding_data, args.This(), args[0]->IsTrue());
7121cb0ef41Sopenharmony_ci}
7131cb0ef41Sopenharmony_ci
7141cb0ef41Sopenharmony_ciFSReqAfterScope::FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req)
7151cb0ef41Sopenharmony_ci    : wrap_(wrap),
7161cb0ef41Sopenharmony_ci      req_(req),
7171cb0ef41Sopenharmony_ci      handle_scope_(wrap->env()->isolate()),
7181cb0ef41Sopenharmony_ci      context_scope_(wrap->env()->context()) {
7191cb0ef41Sopenharmony_ci  CHECK_EQ(wrap_->req(), req);
7201cb0ef41Sopenharmony_ci}
7211cb0ef41Sopenharmony_ci
7221cb0ef41Sopenharmony_ciFSReqAfterScope::~FSReqAfterScope() {
7231cb0ef41Sopenharmony_ci  Clear();
7241cb0ef41Sopenharmony_ci}
7251cb0ef41Sopenharmony_ci
7261cb0ef41Sopenharmony_civoid FSReqAfterScope::Clear() {
7271cb0ef41Sopenharmony_ci  if (!wrap_) return;
7281cb0ef41Sopenharmony_ci
7291cb0ef41Sopenharmony_ci  uv_fs_req_cleanup(wrap_->req());
7301cb0ef41Sopenharmony_ci  wrap_->Detach();
7311cb0ef41Sopenharmony_ci  wrap_.reset();
7321cb0ef41Sopenharmony_ci}
7331cb0ef41Sopenharmony_ci
7341cb0ef41Sopenharmony_ci// TODO(joyeecheung): create a normal context object, and
7351cb0ef41Sopenharmony_ci// construct the actual errors in the JS land using the context.
7361cb0ef41Sopenharmony_ci// The context should include fds for some fs APIs, currently they are
7371cb0ef41Sopenharmony_ci// missing in the error messages. The path, dest, syscall, fd, .etc
7381cb0ef41Sopenharmony_ci// can be put into the context before the binding is even invoked,
7391cb0ef41Sopenharmony_ci// the only information that has to come from the C++ layer is the
7401cb0ef41Sopenharmony_ci// error number (and possibly the syscall for abstraction),
7411cb0ef41Sopenharmony_ci// which is also why the errors should have been constructed
7421cb0ef41Sopenharmony_ci// in JS for more flexibility.
7431cb0ef41Sopenharmony_civoid FSReqAfterScope::Reject(uv_fs_t* req) {
7441cb0ef41Sopenharmony_ci  BaseObjectPtr<FSReqBase> wrap { wrap_ };
7451cb0ef41Sopenharmony_ci  Local<Value> exception = UVException(wrap_->env()->isolate(),
7461cb0ef41Sopenharmony_ci                                       static_cast<int>(req->result),
7471cb0ef41Sopenharmony_ci                                       wrap_->syscall(),
7481cb0ef41Sopenharmony_ci                                       nullptr,
7491cb0ef41Sopenharmony_ci                                       req->path,
7501cb0ef41Sopenharmony_ci                                       wrap_->data());
7511cb0ef41Sopenharmony_ci  Clear();
7521cb0ef41Sopenharmony_ci  wrap->Reject(exception);
7531cb0ef41Sopenharmony_ci}
7541cb0ef41Sopenharmony_ci
7551cb0ef41Sopenharmony_cibool FSReqAfterScope::Proceed() {
7561cb0ef41Sopenharmony_ci  if (!wrap_->env()->can_call_into_js()) {
7571cb0ef41Sopenharmony_ci    return false;
7581cb0ef41Sopenharmony_ci  }
7591cb0ef41Sopenharmony_ci
7601cb0ef41Sopenharmony_ci  if (req_->result < 0) {
7611cb0ef41Sopenharmony_ci    Reject(req_);
7621cb0ef41Sopenharmony_ci    return false;
7631cb0ef41Sopenharmony_ci  }
7641cb0ef41Sopenharmony_ci  return true;
7651cb0ef41Sopenharmony_ci}
7661cb0ef41Sopenharmony_ci
7671cb0ef41Sopenharmony_civoid AfterNoArgs(uv_fs_t* req) {
7681cb0ef41Sopenharmony_ci  FSReqBase* req_wrap = FSReqBase::from_req(req);
7691cb0ef41Sopenharmony_ci  FSReqAfterScope after(req_wrap, req);
7701cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_END1(
7711cb0ef41Sopenharmony_ci      req->fs_type, req_wrap, "result", static_cast<int>(req->result))
7721cb0ef41Sopenharmony_ci  if (after.Proceed())
7731cb0ef41Sopenharmony_ci    req_wrap->Resolve(Undefined(req_wrap->env()->isolate()));
7741cb0ef41Sopenharmony_ci}
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_civoid AfterStat(uv_fs_t* req) {
7771cb0ef41Sopenharmony_ci  FSReqBase* req_wrap = FSReqBase::from_req(req);
7781cb0ef41Sopenharmony_ci  FSReqAfterScope after(req_wrap, req);
7791cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_END1(
7801cb0ef41Sopenharmony_ci      req->fs_type, req_wrap, "result", static_cast<int>(req->result))
7811cb0ef41Sopenharmony_ci  if (after.Proceed()) {
7821cb0ef41Sopenharmony_ci    req_wrap->ResolveStat(&req->statbuf);
7831cb0ef41Sopenharmony_ci  }
7841cb0ef41Sopenharmony_ci}
7851cb0ef41Sopenharmony_ci
7861cb0ef41Sopenharmony_civoid AfterStatFs(uv_fs_t* req) {
7871cb0ef41Sopenharmony_ci  FSReqBase* req_wrap = FSReqBase::from_req(req);
7881cb0ef41Sopenharmony_ci  FSReqAfterScope after(req_wrap, req);
7891cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_END1(
7901cb0ef41Sopenharmony_ci      req->fs_type, req_wrap, "result", static_cast<int>(req->result))
7911cb0ef41Sopenharmony_ci  if (after.Proceed()) {
7921cb0ef41Sopenharmony_ci    req_wrap->ResolveStatFs(static_cast<uv_statfs_t*>(req->ptr));
7931cb0ef41Sopenharmony_ci  }
7941cb0ef41Sopenharmony_ci}
7951cb0ef41Sopenharmony_ci
7961cb0ef41Sopenharmony_civoid AfterInteger(uv_fs_t* req) {
7971cb0ef41Sopenharmony_ci  FSReqBase* req_wrap = FSReqBase::from_req(req);
7981cb0ef41Sopenharmony_ci  FSReqAfterScope after(req_wrap, req);
7991cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_END1(
8001cb0ef41Sopenharmony_ci      req->fs_type, req_wrap, "result", static_cast<int>(req->result))
8011cb0ef41Sopenharmony_ci  int result = static_cast<int>(req->result);
8021cb0ef41Sopenharmony_ci  if (result >= 0 && req_wrap->is_plain_open())
8031cb0ef41Sopenharmony_ci    req_wrap->env()->AddUnmanagedFd(result);
8041cb0ef41Sopenharmony_ci
8051cb0ef41Sopenharmony_ci  if (after.Proceed())
8061cb0ef41Sopenharmony_ci    req_wrap->Resolve(Integer::New(req_wrap->env()->isolate(), result));
8071cb0ef41Sopenharmony_ci}
8081cb0ef41Sopenharmony_ci
8091cb0ef41Sopenharmony_civoid AfterOpenFileHandle(uv_fs_t* req) {
8101cb0ef41Sopenharmony_ci  FSReqBase* req_wrap = FSReqBase::from_req(req);
8111cb0ef41Sopenharmony_ci  FSReqAfterScope after(req_wrap, req);
8121cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_END1(
8131cb0ef41Sopenharmony_ci      req->fs_type, req_wrap, "result", static_cast<int>(req->result))
8141cb0ef41Sopenharmony_ci  if (after.Proceed()) {
8151cb0ef41Sopenharmony_ci    FileHandle* fd = FileHandle::New(req_wrap->binding_data(),
8161cb0ef41Sopenharmony_ci                                     static_cast<int>(req->result));
8171cb0ef41Sopenharmony_ci    if (fd == nullptr) return;
8181cb0ef41Sopenharmony_ci    req_wrap->Resolve(fd->object());
8191cb0ef41Sopenharmony_ci  }
8201cb0ef41Sopenharmony_ci}
8211cb0ef41Sopenharmony_ci
8221cb0ef41Sopenharmony_ci// Reverse the logic applied by path.toNamespacedPath() to create a
8231cb0ef41Sopenharmony_ci// namespace-prefixed path.
8241cb0ef41Sopenharmony_civoid FromNamespacedPath(std::string* path) {
8251cb0ef41Sopenharmony_ci#ifdef _WIN32
8261cb0ef41Sopenharmony_ci  if (path->compare(0, 8, "\\\\?\\UNC\\", 8) == 0) {
8271cb0ef41Sopenharmony_ci    *path = path->substr(8);
8281cb0ef41Sopenharmony_ci    path->insert(0, "\\\\");
8291cb0ef41Sopenharmony_ci  } else if (path->compare(0, 4, "\\\\?\\", 4) == 0) {
8301cb0ef41Sopenharmony_ci    *path = path->substr(4);
8311cb0ef41Sopenharmony_ci  }
8321cb0ef41Sopenharmony_ci#endif
8331cb0ef41Sopenharmony_ci}
8341cb0ef41Sopenharmony_ci
8351cb0ef41Sopenharmony_civoid AfterMkdirp(uv_fs_t* req) {
8361cb0ef41Sopenharmony_ci  FSReqBase* req_wrap = FSReqBase::from_req(req);
8371cb0ef41Sopenharmony_ci  FSReqAfterScope after(req_wrap, req);
8381cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_END1(
8391cb0ef41Sopenharmony_ci      req->fs_type, req_wrap, "result", static_cast<int>(req->result))
8401cb0ef41Sopenharmony_ci  if (after.Proceed()) {
8411cb0ef41Sopenharmony_ci    std::string first_path(req_wrap->continuation_data()->first_path());
8421cb0ef41Sopenharmony_ci    if (first_path.empty())
8431cb0ef41Sopenharmony_ci      return req_wrap->Resolve(Undefined(req_wrap->env()->isolate()));
8441cb0ef41Sopenharmony_ci    FromNamespacedPath(&first_path);
8451cb0ef41Sopenharmony_ci    Local<Value> path;
8461cb0ef41Sopenharmony_ci    Local<Value> error;
8471cb0ef41Sopenharmony_ci    if (!StringBytes::Encode(req_wrap->env()->isolate(), first_path.c_str(),
8481cb0ef41Sopenharmony_ci                             req_wrap->encoding(),
8491cb0ef41Sopenharmony_ci                             &error).ToLocal(&path)) {
8501cb0ef41Sopenharmony_ci      return req_wrap->Reject(error);
8511cb0ef41Sopenharmony_ci    }
8521cb0ef41Sopenharmony_ci    return req_wrap->Resolve(path);
8531cb0ef41Sopenharmony_ci  }
8541cb0ef41Sopenharmony_ci}
8551cb0ef41Sopenharmony_ci
8561cb0ef41Sopenharmony_civoid AfterStringPath(uv_fs_t* req) {
8571cb0ef41Sopenharmony_ci  FSReqBase* req_wrap = FSReqBase::from_req(req);
8581cb0ef41Sopenharmony_ci  FSReqAfterScope after(req_wrap, req);
8591cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_END1(
8601cb0ef41Sopenharmony_ci      req->fs_type, req_wrap, "result", static_cast<int>(req->result))
8611cb0ef41Sopenharmony_ci  MaybeLocal<Value> link;
8621cb0ef41Sopenharmony_ci  Local<Value> error;
8631cb0ef41Sopenharmony_ci
8641cb0ef41Sopenharmony_ci  if (after.Proceed()) {
8651cb0ef41Sopenharmony_ci    link = StringBytes::Encode(req_wrap->env()->isolate(),
8661cb0ef41Sopenharmony_ci                               req->path,
8671cb0ef41Sopenharmony_ci                               req_wrap->encoding(),
8681cb0ef41Sopenharmony_ci                               &error);
8691cb0ef41Sopenharmony_ci    if (link.IsEmpty())
8701cb0ef41Sopenharmony_ci      req_wrap->Reject(error);
8711cb0ef41Sopenharmony_ci    else
8721cb0ef41Sopenharmony_ci      req_wrap->Resolve(link.ToLocalChecked());
8731cb0ef41Sopenharmony_ci  }
8741cb0ef41Sopenharmony_ci}
8751cb0ef41Sopenharmony_ci
8761cb0ef41Sopenharmony_civoid AfterStringPtr(uv_fs_t* req) {
8771cb0ef41Sopenharmony_ci  FSReqBase* req_wrap = FSReqBase::from_req(req);
8781cb0ef41Sopenharmony_ci  FSReqAfterScope after(req_wrap, req);
8791cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_END1(
8801cb0ef41Sopenharmony_ci      req->fs_type, req_wrap, "result", static_cast<int>(req->result))
8811cb0ef41Sopenharmony_ci  MaybeLocal<Value> link;
8821cb0ef41Sopenharmony_ci  Local<Value> error;
8831cb0ef41Sopenharmony_ci
8841cb0ef41Sopenharmony_ci  if (after.Proceed()) {
8851cb0ef41Sopenharmony_ci    link = StringBytes::Encode(req_wrap->env()->isolate(),
8861cb0ef41Sopenharmony_ci                               static_cast<const char*>(req->ptr),
8871cb0ef41Sopenharmony_ci                               req_wrap->encoding(),
8881cb0ef41Sopenharmony_ci                               &error);
8891cb0ef41Sopenharmony_ci    if (link.IsEmpty())
8901cb0ef41Sopenharmony_ci      req_wrap->Reject(error);
8911cb0ef41Sopenharmony_ci    else
8921cb0ef41Sopenharmony_ci      req_wrap->Resolve(link.ToLocalChecked());
8931cb0ef41Sopenharmony_ci  }
8941cb0ef41Sopenharmony_ci}
8951cb0ef41Sopenharmony_ci
8961cb0ef41Sopenharmony_civoid AfterScanDir(uv_fs_t* req) {
8971cb0ef41Sopenharmony_ci  FSReqBase* req_wrap = FSReqBase::from_req(req);
8981cb0ef41Sopenharmony_ci  FSReqAfterScope after(req_wrap, req);
8991cb0ef41Sopenharmony_ci  FS_ASYNC_TRACE_END1(
9001cb0ef41Sopenharmony_ci      req->fs_type, req_wrap, "result", static_cast<int>(req->result))
9011cb0ef41Sopenharmony_ci  if (!after.Proceed()) {
9021cb0ef41Sopenharmony_ci    return;
9031cb0ef41Sopenharmony_ci  }
9041cb0ef41Sopenharmony_ci
9051cb0ef41Sopenharmony_ci  Environment* env = req_wrap->env();
9061cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
9071cb0ef41Sopenharmony_ci  Local<Value> error;
9081cb0ef41Sopenharmony_ci  int r;
9091cb0ef41Sopenharmony_ci
9101cb0ef41Sopenharmony_ci  std::vector<Local<Value>> name_v;
9111cb0ef41Sopenharmony_ci  std::vector<Local<Value>> type_v;
9121cb0ef41Sopenharmony_ci
9131cb0ef41Sopenharmony_ci  const bool with_file_types = req_wrap->with_file_types();
9141cb0ef41Sopenharmony_ci
9151cb0ef41Sopenharmony_ci  for (;;) {
9161cb0ef41Sopenharmony_ci    uv_dirent_t ent;
9171cb0ef41Sopenharmony_ci
9181cb0ef41Sopenharmony_ci    r = uv_fs_scandir_next(req, &ent);
9191cb0ef41Sopenharmony_ci    if (r == UV_EOF)
9201cb0ef41Sopenharmony_ci      break;
9211cb0ef41Sopenharmony_ci    if (r != 0) {
9221cb0ef41Sopenharmony_ci      return req_wrap->Reject(
9231cb0ef41Sopenharmony_ci          UVException(isolate, r, nullptr, req_wrap->syscall(), req->path));
9241cb0ef41Sopenharmony_ci    }
9251cb0ef41Sopenharmony_ci
9261cb0ef41Sopenharmony_ci    Local<Value> filename;
9271cb0ef41Sopenharmony_ci    if (!StringBytes::Encode(isolate, ent.name, req_wrap->encoding(), &error)
9281cb0ef41Sopenharmony_ci             .ToLocal(&filename)) {
9291cb0ef41Sopenharmony_ci      return req_wrap->Reject(error);
9301cb0ef41Sopenharmony_ci    }
9311cb0ef41Sopenharmony_ci    name_v.push_back(filename);
9321cb0ef41Sopenharmony_ci
9331cb0ef41Sopenharmony_ci    if (with_file_types) type_v.emplace_back(Integer::New(isolate, ent.type));
9341cb0ef41Sopenharmony_ci  }
9351cb0ef41Sopenharmony_ci
9361cb0ef41Sopenharmony_ci  if (with_file_types) {
9371cb0ef41Sopenharmony_ci    Local<Value> result[] = {Array::New(isolate, name_v.data(), name_v.size()),
9381cb0ef41Sopenharmony_ci                             Array::New(isolate, type_v.data(), type_v.size())};
9391cb0ef41Sopenharmony_ci    req_wrap->Resolve(Array::New(isolate, result, arraysize(result)));
9401cb0ef41Sopenharmony_ci  } else {
9411cb0ef41Sopenharmony_ci    req_wrap->Resolve(Array::New(isolate, name_v.data(), name_v.size()));
9421cb0ef41Sopenharmony_ci  }
9431cb0ef41Sopenharmony_ci}
9441cb0ef41Sopenharmony_ci
9451cb0ef41Sopenharmony_civoid Access(const FunctionCallbackInfo<Value>& args) {
9461cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
9471cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
9481cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
9491cb0ef41Sopenharmony_ci
9501cb0ef41Sopenharmony_ci  const int argc = args.Length();
9511cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
9521cb0ef41Sopenharmony_ci
9531cb0ef41Sopenharmony_ci  CHECK(args[1]->IsInt32());
9541cb0ef41Sopenharmony_ci  int mode = args[1].As<Int32>()->Value();
9551cb0ef41Sopenharmony_ci
9561cb0ef41Sopenharmony_ci  BufferValue path(isolate, args[0]);
9571cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
9581cb0ef41Sopenharmony_ci
9591cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
9601cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // access(path, mode, req)
9611cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
9621cb0ef41Sopenharmony_ci        UV_FS_ACCESS, req_wrap_async, "path", TRACE_STR_COPY(*path))
9631cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "access", UTF8, AfterNoArgs,
9641cb0ef41Sopenharmony_ci              uv_fs_access, *path, mode);
9651cb0ef41Sopenharmony_ci  } else {  // access(path, mode, undefined, ctx)
9661cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
9671cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
9681cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(access);
9691cb0ef41Sopenharmony_ci    SyncCall(env, args[3], &req_wrap_sync, "access", uv_fs_access, *path, mode);
9701cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(access);
9711cb0ef41Sopenharmony_ci  }
9721cb0ef41Sopenharmony_ci}
9731cb0ef41Sopenharmony_ci
9741cb0ef41Sopenharmony_ci
9751cb0ef41Sopenharmony_civoid Close(const FunctionCallbackInfo<Value>& args) {
9761cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
9771cb0ef41Sopenharmony_ci
9781cb0ef41Sopenharmony_ci  const int argc = args.Length();
9791cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
9801cb0ef41Sopenharmony_ci
9811cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
9821cb0ef41Sopenharmony_ci  int fd = args[0].As<Int32>()->Value();
9831cb0ef41Sopenharmony_ci  env->RemoveUnmanagedFd(fd);
9841cb0ef41Sopenharmony_ci
9851cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 1);
9861cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // close(fd, req)
9871cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_CLOSE, req_wrap_async)
9881cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "close", UTF8, AfterNoArgs,
9891cb0ef41Sopenharmony_ci              uv_fs_close, fd);
9901cb0ef41Sopenharmony_ci  } else {  // close(fd, undefined, ctx)
9911cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 3);
9921cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
9931cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(close);
9941cb0ef41Sopenharmony_ci    SyncCall(env, args[2], &req_wrap_sync, "close", uv_fs_close, fd);
9951cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(close);
9961cb0ef41Sopenharmony_ci  }
9971cb0ef41Sopenharmony_ci}
9981cb0ef41Sopenharmony_ci
9991cb0ef41Sopenharmony_ci
10001cb0ef41Sopenharmony_ci// Used to speed up module loading. Returns an array [string, boolean]
10011cb0ef41Sopenharmony_cistatic void InternalModuleReadJSON(const FunctionCallbackInfo<Value>& args) {
10021cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
10031cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
10041cb0ef41Sopenharmony_ci  uv_loop_t* loop = env->event_loop();
10051cb0ef41Sopenharmony_ci
10061cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());
10071cb0ef41Sopenharmony_ci  node::Utf8Value path(isolate, args[0]);
10081cb0ef41Sopenharmony_ci
10091cb0ef41Sopenharmony_ci  if (strlen(*path) != path.length()) {
10101cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(Array::New(isolate));
10111cb0ef41Sopenharmony_ci    return;  // Contains a nul byte.
10121cb0ef41Sopenharmony_ci  }
10131cb0ef41Sopenharmony_ci  uv_fs_t open_req;
10141cb0ef41Sopenharmony_ci  const int fd = uv_fs_open(loop, &open_req, *path, O_RDONLY, 0, nullptr);
10151cb0ef41Sopenharmony_ci  uv_fs_req_cleanup(&open_req);
10161cb0ef41Sopenharmony_ci
10171cb0ef41Sopenharmony_ci  if (fd < 0) {
10181cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(Array::New(isolate));
10191cb0ef41Sopenharmony_ci    return;
10201cb0ef41Sopenharmony_ci  }
10211cb0ef41Sopenharmony_ci
10221cb0ef41Sopenharmony_ci  auto defer_close = OnScopeLeave([fd, loop]() {
10231cb0ef41Sopenharmony_ci    uv_fs_t close_req;
10241cb0ef41Sopenharmony_ci    CHECK_EQ(0, uv_fs_close(loop, &close_req, fd, nullptr));
10251cb0ef41Sopenharmony_ci    uv_fs_req_cleanup(&close_req);
10261cb0ef41Sopenharmony_ci  });
10271cb0ef41Sopenharmony_ci
10281cb0ef41Sopenharmony_ci  const size_t kBlockSize = 32 << 10;
10291cb0ef41Sopenharmony_ci  std::vector<char> chars;
10301cb0ef41Sopenharmony_ci  int64_t offset = 0;
10311cb0ef41Sopenharmony_ci  ssize_t numchars;
10321cb0ef41Sopenharmony_ci  do {
10331cb0ef41Sopenharmony_ci    const size_t start = chars.size();
10341cb0ef41Sopenharmony_ci    chars.resize(start + kBlockSize);
10351cb0ef41Sopenharmony_ci
10361cb0ef41Sopenharmony_ci    uv_buf_t buf;
10371cb0ef41Sopenharmony_ci    buf.base = &chars[start];
10381cb0ef41Sopenharmony_ci    buf.len = kBlockSize;
10391cb0ef41Sopenharmony_ci
10401cb0ef41Sopenharmony_ci    uv_fs_t read_req;
10411cb0ef41Sopenharmony_ci    numchars = uv_fs_read(loop, &read_req, fd, &buf, 1, offset, nullptr);
10421cb0ef41Sopenharmony_ci    uv_fs_req_cleanup(&read_req);
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ci    if (numchars < 0) {
10451cb0ef41Sopenharmony_ci      args.GetReturnValue().Set(Array::New(isolate));
10461cb0ef41Sopenharmony_ci      return;
10471cb0ef41Sopenharmony_ci    }
10481cb0ef41Sopenharmony_ci    offset += numchars;
10491cb0ef41Sopenharmony_ci  } while (static_cast<size_t>(numchars) == kBlockSize);
10501cb0ef41Sopenharmony_ci
10511cb0ef41Sopenharmony_ci  size_t start = 0;
10521cb0ef41Sopenharmony_ci  if (offset >= 3 && 0 == memcmp(chars.data(), "\xEF\xBB\xBF", 3)) {
10531cb0ef41Sopenharmony_ci    start = 3;  // Skip UTF-8 BOM.
10541cb0ef41Sopenharmony_ci  }
10551cb0ef41Sopenharmony_ci  const size_t size = offset - start;
10561cb0ef41Sopenharmony_ci
10571cb0ef41Sopenharmony_ci  // TODO(anonrig): Follow-up on removing the following changes for AIX.
10581cb0ef41Sopenharmony_ci  char* p = &chars[start];
10591cb0ef41Sopenharmony_ci  char* pe = &chars[size];
10601cb0ef41Sopenharmony_ci  char* pos[2];
10611cb0ef41Sopenharmony_ci  char** ppos = &pos[0];
10621cb0ef41Sopenharmony_ci
10631cb0ef41Sopenharmony_ci  while (p < pe) {
10641cb0ef41Sopenharmony_ci    char c = *p++;
10651cb0ef41Sopenharmony_ci    if (c == '\\' && p < pe && *p == '"') p++;
10661cb0ef41Sopenharmony_ci    if (c != '"') continue;
10671cb0ef41Sopenharmony_ci    *ppos++ = p;
10681cb0ef41Sopenharmony_ci    if (ppos < &pos[2]) continue;
10691cb0ef41Sopenharmony_ci    ppos = &pos[0];
10701cb0ef41Sopenharmony_ci
10711cb0ef41Sopenharmony_ci    char* s = &pos[0][0];
10721cb0ef41Sopenharmony_ci    char* se = &pos[1][-1];  // Exclude quote.
10731cb0ef41Sopenharmony_ci    size_t n = se - s;
10741cb0ef41Sopenharmony_ci
10751cb0ef41Sopenharmony_ci    if (n == 4) {
10761cb0ef41Sopenharmony_ci      if (0 == memcmp(s, "main", 4)) break;
10771cb0ef41Sopenharmony_ci      if (0 == memcmp(s, "name", 4)) break;
10781cb0ef41Sopenharmony_ci      if (0 == memcmp(s, "type", 4)) break;
10791cb0ef41Sopenharmony_ci    } else if (n == 7) {
10801cb0ef41Sopenharmony_ci      if (0 == memcmp(s, "exports", 7)) break;
10811cb0ef41Sopenharmony_ci      if (0 == memcmp(s, "imports", 7)) break;
10821cb0ef41Sopenharmony_ci    }
10831cb0ef41Sopenharmony_ci  }
10841cb0ef41Sopenharmony_ci
10851cb0ef41Sopenharmony_ci  Local<Value> return_value[] = {
10861cb0ef41Sopenharmony_ci      String::NewFromUtf8(
10871cb0ef41Sopenharmony_ci          isolate, &chars[start], v8::NewStringType::kNormal, size)
10881cb0ef41Sopenharmony_ci          .ToLocalChecked(),
10891cb0ef41Sopenharmony_ci      Boolean::New(isolate, p < pe ? true : false)};
10901cb0ef41Sopenharmony_ci
10911cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(
10921cb0ef41Sopenharmony_ci      Array::New(isolate, return_value, arraysize(return_value)));
10931cb0ef41Sopenharmony_ci}
10941cb0ef41Sopenharmony_ci
10951cb0ef41Sopenharmony_ci// Used to speed up module loading.  Returns 0 if the path refers to
10961cb0ef41Sopenharmony_ci// a file, 1 when it's a directory or < 0 on error (usually -ENOENT.)
10971cb0ef41Sopenharmony_ci// The speedup comes from not creating thousands of Stat and Error objects.
10981cb0ef41Sopenharmony_cistatic void InternalModuleStat(const FunctionCallbackInfo<Value>& args) {
10991cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
11001cb0ef41Sopenharmony_ci
11011cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());
11021cb0ef41Sopenharmony_ci  node::Utf8Value path(env->isolate(), args[0]);
11031cb0ef41Sopenharmony_ci
11041cb0ef41Sopenharmony_ci  uv_fs_t req;
11051cb0ef41Sopenharmony_ci  int rc = uv_fs_stat(env->event_loop(), &req, *path, nullptr);
11061cb0ef41Sopenharmony_ci  if (rc == 0) {
11071cb0ef41Sopenharmony_ci    const uv_stat_t* const s = static_cast<const uv_stat_t*>(req.ptr);
11081cb0ef41Sopenharmony_ci    rc = !!(s->st_mode & S_IFDIR);
11091cb0ef41Sopenharmony_ci  }
11101cb0ef41Sopenharmony_ci  uv_fs_req_cleanup(&req);
11111cb0ef41Sopenharmony_ci
11121cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(rc);
11131cb0ef41Sopenharmony_ci}
11141cb0ef41Sopenharmony_ci
11151cb0ef41Sopenharmony_cistatic void Stat(const FunctionCallbackInfo<Value>& args) {
11161cb0ef41Sopenharmony_ci  BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
11171cb0ef41Sopenharmony_ci  Environment* env = binding_data->env();
11181cb0ef41Sopenharmony_ci
11191cb0ef41Sopenharmony_ci  const int argc = args.Length();
11201cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
11211cb0ef41Sopenharmony_ci
11221cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
11231cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
11241cb0ef41Sopenharmony_ci
11251cb0ef41Sopenharmony_ci  bool use_bigint = args[1]->IsTrue();
11261cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2, use_bigint);
11271cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // stat(path, use_bigint, req)
11281cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
11291cb0ef41Sopenharmony_ci        UV_FS_STAT, req_wrap_async, "path", TRACE_STR_COPY(*path))
11301cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "stat", UTF8, AfterStat,
11311cb0ef41Sopenharmony_ci              uv_fs_stat, *path);
11321cb0ef41Sopenharmony_ci  } else {  // stat(path, use_bigint, undefined, ctx)
11331cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
11341cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
11351cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(stat);
11361cb0ef41Sopenharmony_ci    int err = SyncCall(env, args[3], &req_wrap_sync, "stat", uv_fs_stat, *path);
11371cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(stat);
11381cb0ef41Sopenharmony_ci    if (err != 0) {
11391cb0ef41Sopenharmony_ci      return;  // error info is in ctx
11401cb0ef41Sopenharmony_ci    }
11411cb0ef41Sopenharmony_ci
11421cb0ef41Sopenharmony_ci    Local<Value> arr = FillGlobalStatsArray(binding_data, use_bigint,
11431cb0ef41Sopenharmony_ci        static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
11441cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(arr);
11451cb0ef41Sopenharmony_ci  }
11461cb0ef41Sopenharmony_ci}
11471cb0ef41Sopenharmony_ci
11481cb0ef41Sopenharmony_cistatic void LStat(const FunctionCallbackInfo<Value>& args) {
11491cb0ef41Sopenharmony_ci  BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
11501cb0ef41Sopenharmony_ci  Environment* env = binding_data->env();
11511cb0ef41Sopenharmony_ci
11521cb0ef41Sopenharmony_ci  const int argc = args.Length();
11531cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
11541cb0ef41Sopenharmony_ci
11551cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
11561cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
11571cb0ef41Sopenharmony_ci
11581cb0ef41Sopenharmony_ci  bool use_bigint = args[1]->IsTrue();
11591cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2, use_bigint);
11601cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // lstat(path, use_bigint, req)
11611cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
11621cb0ef41Sopenharmony_ci        UV_FS_LSTAT, req_wrap_async, "path", TRACE_STR_COPY(*path))
11631cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "lstat", UTF8, AfterStat,
11641cb0ef41Sopenharmony_ci              uv_fs_lstat, *path);
11651cb0ef41Sopenharmony_ci  } else {  // lstat(path, use_bigint, undefined, ctx)
11661cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
11671cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
11681cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(lstat);
11691cb0ef41Sopenharmony_ci    int err = SyncCall(env, args[3], &req_wrap_sync, "lstat", uv_fs_lstat,
11701cb0ef41Sopenharmony_ci                       *path);
11711cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(lstat);
11721cb0ef41Sopenharmony_ci    if (err != 0) {
11731cb0ef41Sopenharmony_ci      return;  // error info is in ctx
11741cb0ef41Sopenharmony_ci    }
11751cb0ef41Sopenharmony_ci
11761cb0ef41Sopenharmony_ci    Local<Value> arr = FillGlobalStatsArray(binding_data, use_bigint,
11771cb0ef41Sopenharmony_ci        static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
11781cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(arr);
11791cb0ef41Sopenharmony_ci  }
11801cb0ef41Sopenharmony_ci}
11811cb0ef41Sopenharmony_ci
11821cb0ef41Sopenharmony_cistatic void FStat(const FunctionCallbackInfo<Value>& args) {
11831cb0ef41Sopenharmony_ci  BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
11841cb0ef41Sopenharmony_ci  Environment* env = binding_data->env();
11851cb0ef41Sopenharmony_ci
11861cb0ef41Sopenharmony_ci  const int argc = args.Length();
11871cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
11881cb0ef41Sopenharmony_ci
11891cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
11901cb0ef41Sopenharmony_ci  int fd = args[0].As<Int32>()->Value();
11911cb0ef41Sopenharmony_ci
11921cb0ef41Sopenharmony_ci  bool use_bigint = args[1]->IsTrue();
11931cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2, use_bigint);
11941cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // fstat(fd, use_bigint, req)
11951cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_FSTAT, req_wrap_async)
11961cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "fstat", UTF8, AfterStat,
11971cb0ef41Sopenharmony_ci              uv_fs_fstat, fd);
11981cb0ef41Sopenharmony_ci  } else {  // fstat(fd, use_bigint, undefined, ctx)
11991cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
12001cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
12011cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(fstat);
12021cb0ef41Sopenharmony_ci    int err = SyncCall(env, args[3], &req_wrap_sync, "fstat", uv_fs_fstat, fd);
12031cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(fstat);
12041cb0ef41Sopenharmony_ci    if (err != 0) {
12051cb0ef41Sopenharmony_ci      return;  // error info is in ctx
12061cb0ef41Sopenharmony_ci    }
12071cb0ef41Sopenharmony_ci
12081cb0ef41Sopenharmony_ci    Local<Value> arr = FillGlobalStatsArray(binding_data, use_bigint,
12091cb0ef41Sopenharmony_ci        static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
12101cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(arr);
12111cb0ef41Sopenharmony_ci  }
12121cb0ef41Sopenharmony_ci}
12131cb0ef41Sopenharmony_ci
12141cb0ef41Sopenharmony_cistatic void StatFs(const FunctionCallbackInfo<Value>& args) {
12151cb0ef41Sopenharmony_ci  BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
12161cb0ef41Sopenharmony_ci  Environment* env = binding_data->env();
12171cb0ef41Sopenharmony_ci
12181cb0ef41Sopenharmony_ci  const int argc = args.Length();
12191cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
12201cb0ef41Sopenharmony_ci
12211cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
12221cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
12231cb0ef41Sopenharmony_ci
12241cb0ef41Sopenharmony_ci  bool use_bigint = args[1]->IsTrue();
12251cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2, use_bigint);
12261cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // statfs(path, use_bigint, req)
12271cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
12281cb0ef41Sopenharmony_ci        UV_FS_STATFS, req_wrap_async, "path", TRACE_STR_COPY(*path))
12291cb0ef41Sopenharmony_ci    AsyncCall(env,
12301cb0ef41Sopenharmony_ci              req_wrap_async,
12311cb0ef41Sopenharmony_ci              args,
12321cb0ef41Sopenharmony_ci              "statfs",
12331cb0ef41Sopenharmony_ci              UTF8,
12341cb0ef41Sopenharmony_ci              AfterStatFs,
12351cb0ef41Sopenharmony_ci              uv_fs_statfs,
12361cb0ef41Sopenharmony_ci              *path);
12371cb0ef41Sopenharmony_ci  } else {  // statfs(path, use_bigint, undefined, ctx)
12381cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
12391cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
12401cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(statfs);
12411cb0ef41Sopenharmony_ci    int err =
12421cb0ef41Sopenharmony_ci        SyncCall(env, args[3], &req_wrap_sync, "statfs", uv_fs_statfs, *path);
12431cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(statfs);
12441cb0ef41Sopenharmony_ci    if (err != 0) {
12451cb0ef41Sopenharmony_ci      return;  // error info is in ctx
12461cb0ef41Sopenharmony_ci    }
12471cb0ef41Sopenharmony_ci
12481cb0ef41Sopenharmony_ci    Local<Value> arr = FillGlobalStatFsArray(
12491cb0ef41Sopenharmony_ci        binding_data,
12501cb0ef41Sopenharmony_ci        use_bigint,
12511cb0ef41Sopenharmony_ci        static_cast<const uv_statfs_t*>(req_wrap_sync.req.ptr));
12521cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(arr);
12531cb0ef41Sopenharmony_ci  }
12541cb0ef41Sopenharmony_ci}
12551cb0ef41Sopenharmony_ci
12561cb0ef41Sopenharmony_cistatic void Symlink(const FunctionCallbackInfo<Value>& args) {
12571cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
12581cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
12591cb0ef41Sopenharmony_ci
12601cb0ef41Sopenharmony_ci  const int argc = args.Length();
12611cb0ef41Sopenharmony_ci  CHECK_GE(argc, 4);
12621cb0ef41Sopenharmony_ci
12631cb0ef41Sopenharmony_ci  BufferValue target(isolate, args[0]);
12641cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*target);
12651cb0ef41Sopenharmony_ci  BufferValue path(isolate, args[1]);
12661cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
12671cb0ef41Sopenharmony_ci
12681cb0ef41Sopenharmony_ci  CHECK(args[2]->IsInt32());
12691cb0ef41Sopenharmony_ci  int flags = args[2].As<Int32>()->Value();
12701cb0ef41Sopenharmony_ci
12711cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
12721cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // symlink(target, path, flags, req)
12731cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN2(UV_FS_SYMLINK,
12741cb0ef41Sopenharmony_ci                          req_wrap_async,
12751cb0ef41Sopenharmony_ci                          "target",
12761cb0ef41Sopenharmony_ci                          TRACE_STR_COPY(*target),
12771cb0ef41Sopenharmony_ci                          "path",
12781cb0ef41Sopenharmony_ci                          TRACE_STR_COPY(*path))
12791cb0ef41Sopenharmony_ci    AsyncDestCall(env, req_wrap_async, args, "symlink", *path, path.length(),
12801cb0ef41Sopenharmony_ci                  UTF8, AfterNoArgs, uv_fs_symlink, *target, *path, flags);
12811cb0ef41Sopenharmony_ci  } else {  // symlink(target, path, flags, undefined, ctx)
12821cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
12831cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
12841cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(symlink);
12851cb0ef41Sopenharmony_ci    SyncCall(env, args[4], &req_wrap_sync, "symlink",
12861cb0ef41Sopenharmony_ci             uv_fs_symlink, *target, *path, flags);
12871cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(symlink);
12881cb0ef41Sopenharmony_ci  }
12891cb0ef41Sopenharmony_ci}
12901cb0ef41Sopenharmony_ci
12911cb0ef41Sopenharmony_cistatic void Link(const FunctionCallbackInfo<Value>& args) {
12921cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
12931cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
12941cb0ef41Sopenharmony_ci
12951cb0ef41Sopenharmony_ci  const int argc = args.Length();
12961cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
12971cb0ef41Sopenharmony_ci
12981cb0ef41Sopenharmony_ci  BufferValue src(isolate, args[0]);
12991cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*src);
13001cb0ef41Sopenharmony_ci
13011cb0ef41Sopenharmony_ci  BufferValue dest(isolate, args[1]);
13021cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*dest);
13031cb0ef41Sopenharmony_ci
13041cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
13051cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // link(src, dest, req)
13061cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN2(UV_FS_LINK,
13071cb0ef41Sopenharmony_ci                          req_wrap_async,
13081cb0ef41Sopenharmony_ci                          "src",
13091cb0ef41Sopenharmony_ci                          TRACE_STR_COPY(*src),
13101cb0ef41Sopenharmony_ci                          "dest",
13111cb0ef41Sopenharmony_ci                          TRACE_STR_COPY(*dest))
13121cb0ef41Sopenharmony_ci    AsyncDestCall(env, req_wrap_async, args, "link", *dest, dest.length(), UTF8,
13131cb0ef41Sopenharmony_ci                  AfterNoArgs, uv_fs_link, *src, *dest);
13141cb0ef41Sopenharmony_ci  } else {  // link(src, dest)
13151cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
13161cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
13171cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(link);
13181cb0ef41Sopenharmony_ci    SyncCall(env, args[3], &req_wrap_sync, "link",
13191cb0ef41Sopenharmony_ci             uv_fs_link, *src, *dest);
13201cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(link);
13211cb0ef41Sopenharmony_ci  }
13221cb0ef41Sopenharmony_ci}
13231cb0ef41Sopenharmony_ci
13241cb0ef41Sopenharmony_cistatic void ReadLink(const FunctionCallbackInfo<Value>& args) {
13251cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
13261cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
13271cb0ef41Sopenharmony_ci
13281cb0ef41Sopenharmony_ci  const int argc = args.Length();
13291cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
13301cb0ef41Sopenharmony_ci
13311cb0ef41Sopenharmony_ci  BufferValue path(isolate, args[0]);
13321cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
13331cb0ef41Sopenharmony_ci
13341cb0ef41Sopenharmony_ci  const enum encoding encoding = ParseEncoding(isolate, args[1], UTF8);
13351cb0ef41Sopenharmony_ci
13361cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
13371cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // readlink(path, encoding, req)
13381cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
13391cb0ef41Sopenharmony_ci        UV_FS_READLINK, req_wrap_async, "path", TRACE_STR_COPY(*path))
13401cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "readlink", encoding, AfterStringPtr,
13411cb0ef41Sopenharmony_ci              uv_fs_readlink, *path);
13421cb0ef41Sopenharmony_ci  } else {
13431cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
13441cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
13451cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(readlink);
13461cb0ef41Sopenharmony_ci    int err = SyncCall(env, args[3], &req_wrap_sync, "readlink",
13471cb0ef41Sopenharmony_ci                       uv_fs_readlink, *path);
13481cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(readlink);
13491cb0ef41Sopenharmony_ci    if (err < 0) {
13501cb0ef41Sopenharmony_ci      return;  // syscall failed, no need to continue, error info is in ctx
13511cb0ef41Sopenharmony_ci    }
13521cb0ef41Sopenharmony_ci    const char* link_path = static_cast<const char*>(req_wrap_sync.req.ptr);
13531cb0ef41Sopenharmony_ci
13541cb0ef41Sopenharmony_ci    Local<Value> error;
13551cb0ef41Sopenharmony_ci    MaybeLocal<Value> rc = StringBytes::Encode(isolate,
13561cb0ef41Sopenharmony_ci                                               link_path,
13571cb0ef41Sopenharmony_ci                                               encoding,
13581cb0ef41Sopenharmony_ci                                               &error);
13591cb0ef41Sopenharmony_ci    if (rc.IsEmpty()) {
13601cb0ef41Sopenharmony_ci      Local<Object> ctx = args[3].As<Object>();
13611cb0ef41Sopenharmony_ci      ctx->Set(env->context(), env->error_string(), error).Check();
13621cb0ef41Sopenharmony_ci      return;
13631cb0ef41Sopenharmony_ci    }
13641cb0ef41Sopenharmony_ci
13651cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(rc.ToLocalChecked());
13661cb0ef41Sopenharmony_ci  }
13671cb0ef41Sopenharmony_ci}
13681cb0ef41Sopenharmony_ci
13691cb0ef41Sopenharmony_cistatic void Rename(const FunctionCallbackInfo<Value>& args) {
13701cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
13711cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
13721cb0ef41Sopenharmony_ci
13731cb0ef41Sopenharmony_ci  const int argc = args.Length();
13741cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
13751cb0ef41Sopenharmony_ci
13761cb0ef41Sopenharmony_ci  BufferValue old_path(isolate, args[0]);
13771cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*old_path);
13781cb0ef41Sopenharmony_ci  BufferValue new_path(isolate, args[1]);
13791cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*new_path);
13801cb0ef41Sopenharmony_ci
13811cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
13821cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {
13831cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN2(UV_FS_RENAME,
13841cb0ef41Sopenharmony_ci                          req_wrap_async,
13851cb0ef41Sopenharmony_ci                          "old_path",
13861cb0ef41Sopenharmony_ci                          TRACE_STR_COPY(*old_path),
13871cb0ef41Sopenharmony_ci                          "new_path",
13881cb0ef41Sopenharmony_ci                          TRACE_STR_COPY(*new_path))
13891cb0ef41Sopenharmony_ci    AsyncDestCall(env, req_wrap_async, args, "rename", *new_path,
13901cb0ef41Sopenharmony_ci                  new_path.length(), UTF8, AfterNoArgs, uv_fs_rename,
13911cb0ef41Sopenharmony_ci                  *old_path, *new_path);
13921cb0ef41Sopenharmony_ci  } else {
13931cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
13941cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
13951cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(rename);
13961cb0ef41Sopenharmony_ci    SyncCall(env, args[3], &req_wrap_sync, "rename", uv_fs_rename,
13971cb0ef41Sopenharmony_ci             *old_path, *new_path);
13981cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(rename);
13991cb0ef41Sopenharmony_ci  }
14001cb0ef41Sopenharmony_ci}
14011cb0ef41Sopenharmony_ci
14021cb0ef41Sopenharmony_cistatic void FTruncate(const FunctionCallbackInfo<Value>& args) {
14031cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
14041cb0ef41Sopenharmony_ci
14051cb0ef41Sopenharmony_ci  const int argc = args.Length();
14061cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
14071cb0ef41Sopenharmony_ci
14081cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
14091cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
14101cb0ef41Sopenharmony_ci
14111cb0ef41Sopenharmony_ci  CHECK(IsSafeJsInt(args[1]));
14121cb0ef41Sopenharmony_ci  const int64_t len = args[1].As<Integer>()->Value();
14131cb0ef41Sopenharmony_ci
14141cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
14151cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {
14161cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_FTRUNCATE, req_wrap_async)
14171cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "ftruncate", UTF8, AfterNoArgs,
14181cb0ef41Sopenharmony_ci              uv_fs_ftruncate, fd, len);
14191cb0ef41Sopenharmony_ci  } else {
14201cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
14211cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
14221cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(ftruncate);
14231cb0ef41Sopenharmony_ci    SyncCall(env, args[3], &req_wrap_sync, "ftruncate", uv_fs_ftruncate, fd,
14241cb0ef41Sopenharmony_ci             len);
14251cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(ftruncate);
14261cb0ef41Sopenharmony_ci  }
14271cb0ef41Sopenharmony_ci}
14281cb0ef41Sopenharmony_ci
14291cb0ef41Sopenharmony_cistatic void Fdatasync(const FunctionCallbackInfo<Value>& args) {
14301cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
14311cb0ef41Sopenharmony_ci
14321cb0ef41Sopenharmony_ci  const int argc = args.Length();
14331cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
14341cb0ef41Sopenharmony_ci
14351cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
14361cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
14371cb0ef41Sopenharmony_ci
14381cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 1);
14391cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {
14401cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_FDATASYNC, req_wrap_async)
14411cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "fdatasync", UTF8, AfterNoArgs,
14421cb0ef41Sopenharmony_ci              uv_fs_fdatasync, fd);
14431cb0ef41Sopenharmony_ci  } else {
14441cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 3);
14451cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
14461cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(fdatasync);
14471cb0ef41Sopenharmony_ci    SyncCall(env, args[2], &req_wrap_sync, "fdatasync", uv_fs_fdatasync, fd);
14481cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(fdatasync);
14491cb0ef41Sopenharmony_ci  }
14501cb0ef41Sopenharmony_ci}
14511cb0ef41Sopenharmony_ci
14521cb0ef41Sopenharmony_cistatic void Fsync(const FunctionCallbackInfo<Value>& args) {
14531cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
14541cb0ef41Sopenharmony_ci
14551cb0ef41Sopenharmony_ci  const int argc = args.Length();
14561cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
14571cb0ef41Sopenharmony_ci
14581cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
14591cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
14601cb0ef41Sopenharmony_ci
14611cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 1);
14621cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {
14631cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_FSYNC, req_wrap_async)
14641cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "fsync", UTF8, AfterNoArgs,
14651cb0ef41Sopenharmony_ci              uv_fs_fsync, fd);
14661cb0ef41Sopenharmony_ci  } else {
14671cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 3);
14681cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
14691cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(fsync);
14701cb0ef41Sopenharmony_ci    SyncCall(env, args[2], &req_wrap_sync, "fsync", uv_fs_fsync, fd);
14711cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(fsync);
14721cb0ef41Sopenharmony_ci  }
14731cb0ef41Sopenharmony_ci}
14741cb0ef41Sopenharmony_ci
14751cb0ef41Sopenharmony_cistatic void Unlink(const FunctionCallbackInfo<Value>& args) {
14761cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
14771cb0ef41Sopenharmony_ci
14781cb0ef41Sopenharmony_ci  const int argc = args.Length();
14791cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
14801cb0ef41Sopenharmony_ci
14811cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
14821cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
14831cb0ef41Sopenharmony_ci
14841cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 1);
14851cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {
14861cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
14871cb0ef41Sopenharmony_ci        UV_FS_UNLINK, req_wrap_async, "path", TRACE_STR_COPY(*path))
14881cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "unlink", UTF8, AfterNoArgs,
14891cb0ef41Sopenharmony_ci              uv_fs_unlink, *path);
14901cb0ef41Sopenharmony_ci  } else {
14911cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 3);
14921cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
14931cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(unlink);
14941cb0ef41Sopenharmony_ci    SyncCall(env, args[2], &req_wrap_sync, "unlink", uv_fs_unlink, *path);
14951cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(unlink);
14961cb0ef41Sopenharmony_ci  }
14971cb0ef41Sopenharmony_ci}
14981cb0ef41Sopenharmony_ci
14991cb0ef41Sopenharmony_cistatic void RMDir(const FunctionCallbackInfo<Value>& args) {
15001cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
15011cb0ef41Sopenharmony_ci
15021cb0ef41Sopenharmony_ci  const int argc = args.Length();
15031cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
15041cb0ef41Sopenharmony_ci
15051cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
15061cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
15071cb0ef41Sopenharmony_ci
15081cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 1);  // rmdir(path, req)
15091cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {
15101cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
15111cb0ef41Sopenharmony_ci        UV_FS_RMDIR, req_wrap_async, "path", TRACE_STR_COPY(*path))
15121cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "rmdir", UTF8, AfterNoArgs,
15131cb0ef41Sopenharmony_ci              uv_fs_rmdir, *path);
15141cb0ef41Sopenharmony_ci  } else {  // rmdir(path, undefined, ctx)
15151cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 3);
15161cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
15171cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(rmdir);
15181cb0ef41Sopenharmony_ci    SyncCall(env, args[2], &req_wrap_sync, "rmdir",
15191cb0ef41Sopenharmony_ci             uv_fs_rmdir, *path);
15201cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(rmdir);
15211cb0ef41Sopenharmony_ci  }
15221cb0ef41Sopenharmony_ci}
15231cb0ef41Sopenharmony_ci
15241cb0ef41Sopenharmony_ciint MKDirpSync(uv_loop_t* loop,
15251cb0ef41Sopenharmony_ci               uv_fs_t* req,
15261cb0ef41Sopenharmony_ci               const std::string& path,
15271cb0ef41Sopenharmony_ci               int mode,
15281cb0ef41Sopenharmony_ci               uv_fs_cb cb) {
15291cb0ef41Sopenharmony_ci  FSReqWrapSync* req_wrap = ContainerOf(&FSReqWrapSync::req, req);
15301cb0ef41Sopenharmony_ci
15311cb0ef41Sopenharmony_ci  // on the first iteration of algorithm, stash state information.
15321cb0ef41Sopenharmony_ci  if (req_wrap->continuation_data() == nullptr) {
15331cb0ef41Sopenharmony_ci    req_wrap->set_continuation_data(
15341cb0ef41Sopenharmony_ci        std::make_unique<FSContinuationData>(req, mode, cb));
15351cb0ef41Sopenharmony_ci    req_wrap->continuation_data()->PushPath(std::move(path));
15361cb0ef41Sopenharmony_ci  }
15371cb0ef41Sopenharmony_ci
15381cb0ef41Sopenharmony_ci  while (req_wrap->continuation_data()->paths().size() > 0) {
15391cb0ef41Sopenharmony_ci    std::string next_path = req_wrap->continuation_data()->PopPath();
15401cb0ef41Sopenharmony_ci    int err = uv_fs_mkdir(loop, req, next_path.c_str(), mode, nullptr);
15411cb0ef41Sopenharmony_ci    while (true) {
15421cb0ef41Sopenharmony_ci      switch (err) {
15431cb0ef41Sopenharmony_ci        // Note: uv_fs_req_cleanup in terminal paths will be called by
15441cb0ef41Sopenharmony_ci        // ~FSReqWrapSync():
15451cb0ef41Sopenharmony_ci        case 0:
15461cb0ef41Sopenharmony_ci          req_wrap->continuation_data()->MaybeSetFirstPath(next_path);
15471cb0ef41Sopenharmony_ci          if (req_wrap->continuation_data()->paths().size() == 0) {
15481cb0ef41Sopenharmony_ci            return 0;
15491cb0ef41Sopenharmony_ci          }
15501cb0ef41Sopenharmony_ci          break;
15511cb0ef41Sopenharmony_ci        case UV_EACCES:
15521cb0ef41Sopenharmony_ci        case UV_ENOSPC:
15531cb0ef41Sopenharmony_ci        case UV_ENOTDIR:
15541cb0ef41Sopenharmony_ci        case UV_EPERM: {
15551cb0ef41Sopenharmony_ci          return err;
15561cb0ef41Sopenharmony_ci        }
15571cb0ef41Sopenharmony_ci        case UV_ENOENT: {
15581cb0ef41Sopenharmony_ci          std::string dirname = next_path.substr(0,
15591cb0ef41Sopenharmony_ci                                        next_path.find_last_of(kPathSeparator));
15601cb0ef41Sopenharmony_ci          if (dirname != next_path) {
15611cb0ef41Sopenharmony_ci            req_wrap->continuation_data()->PushPath(std::move(next_path));
15621cb0ef41Sopenharmony_ci            req_wrap->continuation_data()->PushPath(std::move(dirname));
15631cb0ef41Sopenharmony_ci          } else if (req_wrap->continuation_data()->paths().size() == 0) {
15641cb0ef41Sopenharmony_ci            err = UV_EEXIST;
15651cb0ef41Sopenharmony_ci            continue;
15661cb0ef41Sopenharmony_ci          }
15671cb0ef41Sopenharmony_ci          break;
15681cb0ef41Sopenharmony_ci        }
15691cb0ef41Sopenharmony_ci        default:
15701cb0ef41Sopenharmony_ci          uv_fs_req_cleanup(req);
15711cb0ef41Sopenharmony_ci          int orig_err = err;
15721cb0ef41Sopenharmony_ci          err = uv_fs_stat(loop, req, next_path.c_str(), nullptr);
15731cb0ef41Sopenharmony_ci          if (err == 0 && !S_ISDIR(req->statbuf.st_mode)) {
15741cb0ef41Sopenharmony_ci            uv_fs_req_cleanup(req);
15751cb0ef41Sopenharmony_ci            if (orig_err == UV_EEXIST &&
15761cb0ef41Sopenharmony_ci              req_wrap->continuation_data()->paths().size() > 0) {
15771cb0ef41Sopenharmony_ci              return UV_ENOTDIR;
15781cb0ef41Sopenharmony_ci            }
15791cb0ef41Sopenharmony_ci            return UV_EEXIST;
15801cb0ef41Sopenharmony_ci          }
15811cb0ef41Sopenharmony_ci          if (err < 0) return err;
15821cb0ef41Sopenharmony_ci          break;
15831cb0ef41Sopenharmony_ci      }
15841cb0ef41Sopenharmony_ci      break;
15851cb0ef41Sopenharmony_ci    }
15861cb0ef41Sopenharmony_ci    uv_fs_req_cleanup(req);
15871cb0ef41Sopenharmony_ci  }
15881cb0ef41Sopenharmony_ci
15891cb0ef41Sopenharmony_ci  return 0;
15901cb0ef41Sopenharmony_ci}
15911cb0ef41Sopenharmony_ci
15921cb0ef41Sopenharmony_ciint MKDirpAsync(uv_loop_t* loop,
15931cb0ef41Sopenharmony_ci                uv_fs_t* req,
15941cb0ef41Sopenharmony_ci                const char* path,
15951cb0ef41Sopenharmony_ci                int mode,
15961cb0ef41Sopenharmony_ci                uv_fs_cb cb) {
15971cb0ef41Sopenharmony_ci  FSReqBase* req_wrap = FSReqBase::from_req(req);
15981cb0ef41Sopenharmony_ci  // on the first iteration of algorithm, stash state information.
15991cb0ef41Sopenharmony_ci  if (req_wrap->continuation_data() == nullptr) {
16001cb0ef41Sopenharmony_ci    req_wrap->set_continuation_data(
16011cb0ef41Sopenharmony_ci        std::make_unique<FSContinuationData>(req, mode, cb));
16021cb0ef41Sopenharmony_ci    req_wrap->continuation_data()->PushPath(std::move(path));
16031cb0ef41Sopenharmony_ci  }
16041cb0ef41Sopenharmony_ci
16051cb0ef41Sopenharmony_ci  // on each iteration of algorithm, mkdir directory on top of stack.
16061cb0ef41Sopenharmony_ci  std::string next_path = req_wrap->continuation_data()->PopPath();
16071cb0ef41Sopenharmony_ci  int err = uv_fs_mkdir(loop, req, next_path.c_str(), mode,
16081cb0ef41Sopenharmony_ci                        uv_fs_callback_t{[](uv_fs_t* req) {
16091cb0ef41Sopenharmony_ci    FSReqBase* req_wrap = FSReqBase::from_req(req);
16101cb0ef41Sopenharmony_ci    Environment* env = req_wrap->env();
16111cb0ef41Sopenharmony_ci    uv_loop_t* loop = env->event_loop();
16121cb0ef41Sopenharmony_ci    std::string path = req->path;
16131cb0ef41Sopenharmony_ci    int err = static_cast<int>(req->result);
16141cb0ef41Sopenharmony_ci
16151cb0ef41Sopenharmony_ci    while (true) {
16161cb0ef41Sopenharmony_ci      switch (err) {
16171cb0ef41Sopenharmony_ci        // Note: uv_fs_req_cleanup in terminal paths will be called by
16181cb0ef41Sopenharmony_ci        // FSReqAfterScope::~FSReqAfterScope()
16191cb0ef41Sopenharmony_ci        case 0: {
16201cb0ef41Sopenharmony_ci          if (req_wrap->continuation_data()->paths().size() == 0) {
16211cb0ef41Sopenharmony_ci            req_wrap->continuation_data()->MaybeSetFirstPath(path);
16221cb0ef41Sopenharmony_ci            req_wrap->continuation_data()->Done(0);
16231cb0ef41Sopenharmony_ci          } else {
16241cb0ef41Sopenharmony_ci            req_wrap->continuation_data()->MaybeSetFirstPath(path);
16251cb0ef41Sopenharmony_ci            uv_fs_req_cleanup(req);
16261cb0ef41Sopenharmony_ci            MKDirpAsync(loop, req, path.c_str(),
16271cb0ef41Sopenharmony_ci                        req_wrap->continuation_data()->mode(), nullptr);
16281cb0ef41Sopenharmony_ci          }
16291cb0ef41Sopenharmony_ci          break;
16301cb0ef41Sopenharmony_ci        }
16311cb0ef41Sopenharmony_ci        case UV_EACCES:
16321cb0ef41Sopenharmony_ci        case UV_ENOTDIR:
16331cb0ef41Sopenharmony_ci        case UV_EPERM: {
16341cb0ef41Sopenharmony_ci          req_wrap->continuation_data()->Done(err);
16351cb0ef41Sopenharmony_ci          break;
16361cb0ef41Sopenharmony_ci        }
16371cb0ef41Sopenharmony_ci        case UV_ENOENT: {
16381cb0ef41Sopenharmony_ci          std::string dirname = path.substr(0,
16391cb0ef41Sopenharmony_ci                                            path.find_last_of(kPathSeparator));
16401cb0ef41Sopenharmony_ci          if (dirname != path) {
16411cb0ef41Sopenharmony_ci            req_wrap->continuation_data()->PushPath(path);
16421cb0ef41Sopenharmony_ci            req_wrap->continuation_data()->PushPath(std::move(dirname));
16431cb0ef41Sopenharmony_ci          } else if (req_wrap->continuation_data()->paths().size() == 0) {
16441cb0ef41Sopenharmony_ci            err = UV_EEXIST;
16451cb0ef41Sopenharmony_ci            continue;
16461cb0ef41Sopenharmony_ci          }
16471cb0ef41Sopenharmony_ci          uv_fs_req_cleanup(req);
16481cb0ef41Sopenharmony_ci          MKDirpAsync(loop, req, path.c_str(),
16491cb0ef41Sopenharmony_ci                      req_wrap->continuation_data()->mode(), nullptr);
16501cb0ef41Sopenharmony_ci          break;
16511cb0ef41Sopenharmony_ci        }
16521cb0ef41Sopenharmony_ci        default:
16531cb0ef41Sopenharmony_ci          uv_fs_req_cleanup(req);
16541cb0ef41Sopenharmony_ci          // Stash err for use in the callback.
16551cb0ef41Sopenharmony_ci          req->data = reinterpret_cast<void*>(static_cast<intptr_t>(err));
16561cb0ef41Sopenharmony_ci          int err = uv_fs_stat(loop, req, path.c_str(),
16571cb0ef41Sopenharmony_ci                               uv_fs_callback_t{[](uv_fs_t* req) {
16581cb0ef41Sopenharmony_ci            FSReqBase* req_wrap = FSReqBase::from_req(req);
16591cb0ef41Sopenharmony_ci            int err = static_cast<int>(req->result);
16601cb0ef41Sopenharmony_ci            if (reinterpret_cast<intptr_t>(req->data) == UV_EEXIST &&
16611cb0ef41Sopenharmony_ci                  req_wrap->continuation_data()->paths().size() > 0) {
16621cb0ef41Sopenharmony_ci              if (err == 0 && S_ISDIR(req->statbuf.st_mode)) {
16631cb0ef41Sopenharmony_ci                Environment* env = req_wrap->env();
16641cb0ef41Sopenharmony_ci                uv_loop_t* loop = env->event_loop();
16651cb0ef41Sopenharmony_ci                std::string path = req->path;
16661cb0ef41Sopenharmony_ci                uv_fs_req_cleanup(req);
16671cb0ef41Sopenharmony_ci                MKDirpAsync(loop, req, path.c_str(),
16681cb0ef41Sopenharmony_ci                            req_wrap->continuation_data()->mode(), nullptr);
16691cb0ef41Sopenharmony_ci                return;
16701cb0ef41Sopenharmony_ci              }
16711cb0ef41Sopenharmony_ci              err = UV_ENOTDIR;
16721cb0ef41Sopenharmony_ci            }
16731cb0ef41Sopenharmony_ci            // verify that the path pointed to is actually a directory.
16741cb0ef41Sopenharmony_ci            if (err == 0 && !S_ISDIR(req->statbuf.st_mode)) err = UV_EEXIST;
16751cb0ef41Sopenharmony_ci            req_wrap->continuation_data()->Done(err);
16761cb0ef41Sopenharmony_ci          }});
16771cb0ef41Sopenharmony_ci          if (err < 0) req_wrap->continuation_data()->Done(err);
16781cb0ef41Sopenharmony_ci          break;
16791cb0ef41Sopenharmony_ci      }
16801cb0ef41Sopenharmony_ci      break;
16811cb0ef41Sopenharmony_ci    }
16821cb0ef41Sopenharmony_ci  }});
16831cb0ef41Sopenharmony_ci
16841cb0ef41Sopenharmony_ci  return err;
16851cb0ef41Sopenharmony_ci}
16861cb0ef41Sopenharmony_ci
16871cb0ef41Sopenharmony_ciint CallMKDirpSync(Environment* env, const FunctionCallbackInfo<Value>& args,
16881cb0ef41Sopenharmony_ci                   FSReqWrapSync* req_wrap, const char* path, int mode) {
16891cb0ef41Sopenharmony_ci  env->PrintSyncTrace();
16901cb0ef41Sopenharmony_ci  int err = MKDirpSync(env->event_loop(), &req_wrap->req, path, mode,
16911cb0ef41Sopenharmony_ci                       nullptr);
16921cb0ef41Sopenharmony_ci  if (err < 0) {
16931cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context = env->context();
16941cb0ef41Sopenharmony_ci    v8::Local<v8::Object> ctx_obj = args[4].As<v8::Object>();
16951cb0ef41Sopenharmony_ci    v8::Isolate* isolate = env->isolate();
16961cb0ef41Sopenharmony_ci    ctx_obj->Set(context,
16971cb0ef41Sopenharmony_ci                 env->errno_string(),
16981cb0ef41Sopenharmony_ci                 v8::Integer::New(isolate, err)).Check();
16991cb0ef41Sopenharmony_ci    ctx_obj->Set(context,
17001cb0ef41Sopenharmony_ci                 env->syscall_string(),
17011cb0ef41Sopenharmony_ci                 OneByteString(isolate, "mkdir")).Check();
17021cb0ef41Sopenharmony_ci  }
17031cb0ef41Sopenharmony_ci  return err;
17041cb0ef41Sopenharmony_ci}
17051cb0ef41Sopenharmony_ci
17061cb0ef41Sopenharmony_cistatic void MKDir(const FunctionCallbackInfo<Value>& args) {
17071cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
17081cb0ef41Sopenharmony_ci
17091cb0ef41Sopenharmony_ci  const int argc = args.Length();
17101cb0ef41Sopenharmony_ci  CHECK_GE(argc, 4);
17111cb0ef41Sopenharmony_ci
17121cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
17131cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
17141cb0ef41Sopenharmony_ci
17151cb0ef41Sopenharmony_ci  CHECK(args[1]->IsInt32());
17161cb0ef41Sopenharmony_ci  const int mode = args[1].As<Int32>()->Value();
17171cb0ef41Sopenharmony_ci
17181cb0ef41Sopenharmony_ci  CHECK(args[2]->IsBoolean());
17191cb0ef41Sopenharmony_ci  bool mkdirp = args[2]->IsTrue();
17201cb0ef41Sopenharmony_ci
17211cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
17221cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // mkdir(path, mode, req)
17231cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
17241cb0ef41Sopenharmony_ci        UV_FS_UNLINK, req_wrap_async, "path", TRACE_STR_COPY(*path))
17251cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "mkdir", UTF8,
17261cb0ef41Sopenharmony_ci              mkdirp ? AfterMkdirp : AfterNoArgs,
17271cb0ef41Sopenharmony_ci              mkdirp ? MKDirpAsync : uv_fs_mkdir, *path, mode);
17281cb0ef41Sopenharmony_ci  } else {  // mkdir(path, mode, undefined, ctx)
17291cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
17301cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
17311cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(mkdir);
17321cb0ef41Sopenharmony_ci    if (mkdirp) {
17331cb0ef41Sopenharmony_ci      int err = CallMKDirpSync(env, args, &req_wrap_sync, *path, mode);
17341cb0ef41Sopenharmony_ci      if (err == 0 &&
17351cb0ef41Sopenharmony_ci          !req_wrap_sync.continuation_data()->first_path().empty()) {
17361cb0ef41Sopenharmony_ci        Local<Value> error;
17371cb0ef41Sopenharmony_ci        std::string first_path(req_wrap_sync.continuation_data()->first_path());
17381cb0ef41Sopenharmony_ci        FromNamespacedPath(&first_path);
17391cb0ef41Sopenharmony_ci        MaybeLocal<Value> path = StringBytes::Encode(env->isolate(),
17401cb0ef41Sopenharmony_ci                                                     first_path.c_str(),
17411cb0ef41Sopenharmony_ci                                                     UTF8, &error);
17421cb0ef41Sopenharmony_ci        if (path.IsEmpty()) {
17431cb0ef41Sopenharmony_ci          Local<Object> ctx = args[4].As<Object>();
17441cb0ef41Sopenharmony_ci          ctx->Set(env->context(), env->error_string(), error).Check();
17451cb0ef41Sopenharmony_ci          return;
17461cb0ef41Sopenharmony_ci        }
17471cb0ef41Sopenharmony_ci        args.GetReturnValue().Set(path.ToLocalChecked());
17481cb0ef41Sopenharmony_ci      }
17491cb0ef41Sopenharmony_ci    } else {
17501cb0ef41Sopenharmony_ci      SyncCall(env, args[4], &req_wrap_sync, "mkdir",
17511cb0ef41Sopenharmony_ci               uv_fs_mkdir, *path, mode);
17521cb0ef41Sopenharmony_ci    }
17531cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(mkdir);
17541cb0ef41Sopenharmony_ci  }
17551cb0ef41Sopenharmony_ci}
17561cb0ef41Sopenharmony_ci
17571cb0ef41Sopenharmony_cistatic void RealPath(const FunctionCallbackInfo<Value>& args) {
17581cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
17591cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
17601cb0ef41Sopenharmony_ci
17611cb0ef41Sopenharmony_ci  const int argc = args.Length();
17621cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
17631cb0ef41Sopenharmony_ci
17641cb0ef41Sopenharmony_ci  BufferValue path(isolate, args[0]);
17651cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
17661cb0ef41Sopenharmony_ci
17671cb0ef41Sopenharmony_ci  const enum encoding encoding = ParseEncoding(isolate, args[1], UTF8);
17681cb0ef41Sopenharmony_ci
17691cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
17701cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // realpath(path, encoding, req)
17711cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
17721cb0ef41Sopenharmony_ci        UV_FS_REALPATH, req_wrap_async, "path", TRACE_STR_COPY(*path))
17731cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "realpath", encoding, AfterStringPtr,
17741cb0ef41Sopenharmony_ci              uv_fs_realpath, *path);
17751cb0ef41Sopenharmony_ci  } else {  // realpath(path, encoding, undefined, ctx)
17761cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
17771cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
17781cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(realpath);
17791cb0ef41Sopenharmony_ci    int err = SyncCall(env, args[3], &req_wrap_sync, "realpath",
17801cb0ef41Sopenharmony_ci                       uv_fs_realpath, *path);
17811cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(realpath);
17821cb0ef41Sopenharmony_ci    if (err < 0) {
17831cb0ef41Sopenharmony_ci      return;  // syscall failed, no need to continue, error info is in ctx
17841cb0ef41Sopenharmony_ci    }
17851cb0ef41Sopenharmony_ci
17861cb0ef41Sopenharmony_ci    const char* link_path = static_cast<const char*>(req_wrap_sync.req.ptr);
17871cb0ef41Sopenharmony_ci
17881cb0ef41Sopenharmony_ci    Local<Value> error;
17891cb0ef41Sopenharmony_ci    MaybeLocal<Value> rc = StringBytes::Encode(isolate,
17901cb0ef41Sopenharmony_ci                                               link_path,
17911cb0ef41Sopenharmony_ci                                               encoding,
17921cb0ef41Sopenharmony_ci                                               &error);
17931cb0ef41Sopenharmony_ci    if (rc.IsEmpty()) {
17941cb0ef41Sopenharmony_ci      Local<Object> ctx = args[3].As<Object>();
17951cb0ef41Sopenharmony_ci      ctx->Set(env->context(), env->error_string(), error).Check();
17961cb0ef41Sopenharmony_ci      return;
17971cb0ef41Sopenharmony_ci    }
17981cb0ef41Sopenharmony_ci
17991cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(rc.ToLocalChecked());
18001cb0ef41Sopenharmony_ci  }
18011cb0ef41Sopenharmony_ci}
18021cb0ef41Sopenharmony_ci
18031cb0ef41Sopenharmony_cistatic void ReadDir(const FunctionCallbackInfo<Value>& args) {
18041cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
18051cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
18061cb0ef41Sopenharmony_ci
18071cb0ef41Sopenharmony_ci  const int argc = args.Length();
18081cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
18091cb0ef41Sopenharmony_ci
18101cb0ef41Sopenharmony_ci  BufferValue path(isolate, args[0]);
18111cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
18121cb0ef41Sopenharmony_ci
18131cb0ef41Sopenharmony_ci  const enum encoding encoding = ParseEncoding(isolate, args[1], UTF8);
18141cb0ef41Sopenharmony_ci
18151cb0ef41Sopenharmony_ci  bool with_types = args[2]->IsTrue();
18161cb0ef41Sopenharmony_ci
18171cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
18181cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // readdir(path, encoding, withTypes, req)
18191cb0ef41Sopenharmony_ci    req_wrap_async->set_with_file_types(with_types);
18201cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
18211cb0ef41Sopenharmony_ci        UV_FS_SCANDIR, req_wrap_async, "path", TRACE_STR_COPY(*path))
18221cb0ef41Sopenharmony_ci    AsyncCall(env,
18231cb0ef41Sopenharmony_ci              req_wrap_async,
18241cb0ef41Sopenharmony_ci              args,
18251cb0ef41Sopenharmony_ci              "scandir",
18261cb0ef41Sopenharmony_ci              encoding,
18271cb0ef41Sopenharmony_ci              AfterScanDir,
18281cb0ef41Sopenharmony_ci              uv_fs_scandir,
18291cb0ef41Sopenharmony_ci              *path,
18301cb0ef41Sopenharmony_ci              0 /*flags*/);
18311cb0ef41Sopenharmony_ci  } else {  // readdir(path, encoding, withTypes, undefined, ctx)
18321cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
18331cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
18341cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(readdir);
18351cb0ef41Sopenharmony_ci    int err = SyncCall(env, args[4], &req_wrap_sync, "scandir",
18361cb0ef41Sopenharmony_ci                       uv_fs_scandir, *path, 0 /*flags*/);
18371cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(readdir);
18381cb0ef41Sopenharmony_ci    if (err < 0) {
18391cb0ef41Sopenharmony_ci      return;  // syscall failed, no need to continue, error info is in ctx
18401cb0ef41Sopenharmony_ci    }
18411cb0ef41Sopenharmony_ci
18421cb0ef41Sopenharmony_ci    CHECK_GE(req_wrap_sync.req.result, 0);
18431cb0ef41Sopenharmony_ci    int r;
18441cb0ef41Sopenharmony_ci    std::vector<Local<Value>> name_v;
18451cb0ef41Sopenharmony_ci    std::vector<Local<Value>> type_v;
18461cb0ef41Sopenharmony_ci
18471cb0ef41Sopenharmony_ci    for (;;) {
18481cb0ef41Sopenharmony_ci      uv_dirent_t ent;
18491cb0ef41Sopenharmony_ci
18501cb0ef41Sopenharmony_ci      r = uv_fs_scandir_next(&(req_wrap_sync.req), &ent);
18511cb0ef41Sopenharmony_ci      if (r == UV_EOF)
18521cb0ef41Sopenharmony_ci        break;
18531cb0ef41Sopenharmony_ci      if (r != 0) {
18541cb0ef41Sopenharmony_ci        Local<Object> ctx = args[4].As<Object>();
18551cb0ef41Sopenharmony_ci        ctx->Set(env->context(), env->errno_string(),
18561cb0ef41Sopenharmony_ci                 Integer::New(isolate, r)).Check();
18571cb0ef41Sopenharmony_ci        ctx->Set(env->context(), env->syscall_string(),
18581cb0ef41Sopenharmony_ci                 OneByteString(isolate, "readdir")).Check();
18591cb0ef41Sopenharmony_ci        return;
18601cb0ef41Sopenharmony_ci      }
18611cb0ef41Sopenharmony_ci
18621cb0ef41Sopenharmony_ci      Local<Value> error;
18631cb0ef41Sopenharmony_ci      MaybeLocal<Value> filename = StringBytes::Encode(isolate,
18641cb0ef41Sopenharmony_ci                                                       ent.name,
18651cb0ef41Sopenharmony_ci                                                       encoding,
18661cb0ef41Sopenharmony_ci                                                       &error);
18671cb0ef41Sopenharmony_ci
18681cb0ef41Sopenharmony_ci      if (filename.IsEmpty()) {
18691cb0ef41Sopenharmony_ci        Local<Object> ctx = args[4].As<Object>();
18701cb0ef41Sopenharmony_ci        ctx->Set(env->context(), env->error_string(), error).Check();
18711cb0ef41Sopenharmony_ci        return;
18721cb0ef41Sopenharmony_ci      }
18731cb0ef41Sopenharmony_ci
18741cb0ef41Sopenharmony_ci      name_v.push_back(filename.ToLocalChecked());
18751cb0ef41Sopenharmony_ci
18761cb0ef41Sopenharmony_ci      if (with_types) {
18771cb0ef41Sopenharmony_ci        type_v.emplace_back(Integer::New(isolate, ent.type));
18781cb0ef41Sopenharmony_ci      }
18791cb0ef41Sopenharmony_ci    }
18801cb0ef41Sopenharmony_ci
18811cb0ef41Sopenharmony_ci
18821cb0ef41Sopenharmony_ci    Local<Array> names = Array::New(isolate, name_v.data(), name_v.size());
18831cb0ef41Sopenharmony_ci    if (with_types) {
18841cb0ef41Sopenharmony_ci      Local<Value> result[] = {
18851cb0ef41Sopenharmony_ci        names,
18861cb0ef41Sopenharmony_ci        Array::New(isolate, type_v.data(), type_v.size())
18871cb0ef41Sopenharmony_ci      };
18881cb0ef41Sopenharmony_ci      args.GetReturnValue().Set(Array::New(isolate, result, arraysize(result)));
18891cb0ef41Sopenharmony_ci    } else {
18901cb0ef41Sopenharmony_ci      args.GetReturnValue().Set(names);
18911cb0ef41Sopenharmony_ci    }
18921cb0ef41Sopenharmony_ci  }
18931cb0ef41Sopenharmony_ci}
18941cb0ef41Sopenharmony_ci
18951cb0ef41Sopenharmony_cistatic void Open(const FunctionCallbackInfo<Value>& args) {
18961cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
18971cb0ef41Sopenharmony_ci
18981cb0ef41Sopenharmony_ci  const int argc = args.Length();
18991cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
19001cb0ef41Sopenharmony_ci
19011cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
19021cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
19031cb0ef41Sopenharmony_ci
19041cb0ef41Sopenharmony_ci  CHECK(args[1]->IsInt32());
19051cb0ef41Sopenharmony_ci  const int flags = args[1].As<Int32>()->Value();
19061cb0ef41Sopenharmony_ci
19071cb0ef41Sopenharmony_ci  CHECK(args[2]->IsInt32());
19081cb0ef41Sopenharmony_ci  const int mode = args[2].As<Int32>()->Value();
19091cb0ef41Sopenharmony_ci
19101cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
19111cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // open(path, flags, mode, req)
19121cb0ef41Sopenharmony_ci    req_wrap_async->set_is_plain_open(true);
19131cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
19141cb0ef41Sopenharmony_ci        UV_FS_OPEN, req_wrap_async, "path", TRACE_STR_COPY(*path))
19151cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "open", UTF8, AfterInteger,
19161cb0ef41Sopenharmony_ci              uv_fs_open, *path, flags, mode);
19171cb0ef41Sopenharmony_ci  } else {  // open(path, flags, mode, undefined, ctx)
19181cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
19191cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
19201cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(open);
19211cb0ef41Sopenharmony_ci    int result = SyncCall(env, args[4], &req_wrap_sync, "open",
19221cb0ef41Sopenharmony_ci                          uv_fs_open, *path, flags, mode);
19231cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(open);
19241cb0ef41Sopenharmony_ci    if (result >= 0) env->AddUnmanagedFd(result);
19251cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(result);
19261cb0ef41Sopenharmony_ci  }
19271cb0ef41Sopenharmony_ci}
19281cb0ef41Sopenharmony_ci
19291cb0ef41Sopenharmony_cistatic void OpenFileHandle(const FunctionCallbackInfo<Value>& args) {
19301cb0ef41Sopenharmony_ci  BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
19311cb0ef41Sopenharmony_ci  Environment* env = binding_data->env();
19321cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
19331cb0ef41Sopenharmony_ci
19341cb0ef41Sopenharmony_ci  const int argc = args.Length();
19351cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
19361cb0ef41Sopenharmony_ci
19371cb0ef41Sopenharmony_ci  BufferValue path(isolate, args[0]);
19381cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
19391cb0ef41Sopenharmony_ci
19401cb0ef41Sopenharmony_ci  CHECK(args[1]->IsInt32());
19411cb0ef41Sopenharmony_ci  const int flags = args[1].As<Int32>()->Value();
19421cb0ef41Sopenharmony_ci
19431cb0ef41Sopenharmony_ci  CHECK(args[2]->IsInt32());
19441cb0ef41Sopenharmony_ci  const int mode = args[2].As<Int32>()->Value();
19451cb0ef41Sopenharmony_ci
19461cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
19471cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // openFileHandle(path, flags, mode, req)
19481cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
19491cb0ef41Sopenharmony_ci        UV_FS_OPEN, req_wrap_async, "path", TRACE_STR_COPY(*path))
19501cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "open", UTF8, AfterOpenFileHandle,
19511cb0ef41Sopenharmony_ci              uv_fs_open, *path, flags, mode);
19521cb0ef41Sopenharmony_ci  } else {  // openFileHandle(path, flags, mode, undefined, ctx)
19531cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
19541cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
19551cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(open);
19561cb0ef41Sopenharmony_ci    int result = SyncCall(env, args[4], &req_wrap_sync, "open",
19571cb0ef41Sopenharmony_ci                          uv_fs_open, *path, flags, mode);
19581cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(open);
19591cb0ef41Sopenharmony_ci    if (result < 0) {
19601cb0ef41Sopenharmony_ci      return;  // syscall failed, no need to continue, error info is in ctx
19611cb0ef41Sopenharmony_ci    }
19621cb0ef41Sopenharmony_ci    FileHandle* fd = FileHandle::New(binding_data, result);
19631cb0ef41Sopenharmony_ci    if (fd == nullptr) return;
19641cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(fd->object());
19651cb0ef41Sopenharmony_ci  }
19661cb0ef41Sopenharmony_ci}
19671cb0ef41Sopenharmony_ci
19681cb0ef41Sopenharmony_cistatic void CopyFile(const FunctionCallbackInfo<Value>& args) {
19691cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
19701cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
19711cb0ef41Sopenharmony_ci
19721cb0ef41Sopenharmony_ci  const int argc = args.Length();
19731cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
19741cb0ef41Sopenharmony_ci
19751cb0ef41Sopenharmony_ci  BufferValue src(isolate, args[0]);
19761cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*src);
19771cb0ef41Sopenharmony_ci
19781cb0ef41Sopenharmony_ci  BufferValue dest(isolate, args[1]);
19791cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*dest);
19801cb0ef41Sopenharmony_ci
19811cb0ef41Sopenharmony_ci  CHECK(args[2]->IsInt32());
19821cb0ef41Sopenharmony_ci  const int flags = args[2].As<Int32>()->Value();
19831cb0ef41Sopenharmony_ci
19841cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
19851cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // copyFile(src, dest, flags, req)
19861cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN2(UV_FS_COPYFILE,
19871cb0ef41Sopenharmony_ci                          req_wrap_async,
19881cb0ef41Sopenharmony_ci                          "src",
19891cb0ef41Sopenharmony_ci                          TRACE_STR_COPY(*src),
19901cb0ef41Sopenharmony_ci                          "dest",
19911cb0ef41Sopenharmony_ci                          TRACE_STR_COPY(*dest))
19921cb0ef41Sopenharmony_ci    AsyncDestCall(env, req_wrap_async, args, "copyfile",
19931cb0ef41Sopenharmony_ci                  *dest, dest.length(), UTF8, AfterNoArgs,
19941cb0ef41Sopenharmony_ci                  uv_fs_copyfile, *src, *dest, flags);
19951cb0ef41Sopenharmony_ci  } else {  // copyFile(src, dest, flags, undefined, ctx)
19961cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
19971cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
19981cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(copyfile);
19991cb0ef41Sopenharmony_ci    SyncCall(env, args[4], &req_wrap_sync, "copyfile",
20001cb0ef41Sopenharmony_ci             uv_fs_copyfile, *src, *dest, flags);
20011cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(copyfile);
20021cb0ef41Sopenharmony_ci  }
20031cb0ef41Sopenharmony_ci}
20041cb0ef41Sopenharmony_ci
20051cb0ef41Sopenharmony_ci
20061cb0ef41Sopenharmony_ci// Wrapper for write(2).
20071cb0ef41Sopenharmony_ci//
20081cb0ef41Sopenharmony_ci// bytesWritten = write(fd, buffer, offset, length, position, callback)
20091cb0ef41Sopenharmony_ci// 0 fd        integer. file descriptor
20101cb0ef41Sopenharmony_ci// 1 buffer    the data to write
20111cb0ef41Sopenharmony_ci// 2 offset    where in the buffer to start from
20121cb0ef41Sopenharmony_ci// 3 length    how much to write
20131cb0ef41Sopenharmony_ci// 4 position  if integer, position to write at in the file.
20141cb0ef41Sopenharmony_ci//             if null, write from the current position
20151cb0ef41Sopenharmony_cistatic void WriteBuffer(const FunctionCallbackInfo<Value>& args) {
20161cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
20171cb0ef41Sopenharmony_ci
20181cb0ef41Sopenharmony_ci  const int argc = args.Length();
20191cb0ef41Sopenharmony_ci  CHECK_GE(argc, 4);
20201cb0ef41Sopenharmony_ci
20211cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
20221cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
20231cb0ef41Sopenharmony_ci
20241cb0ef41Sopenharmony_ci  CHECK(Buffer::HasInstance(args[1]));
20251cb0ef41Sopenharmony_ci  Local<Object> buffer_obj = args[1].As<Object>();
20261cb0ef41Sopenharmony_ci  char* buffer_data = Buffer::Data(buffer_obj);
20271cb0ef41Sopenharmony_ci  size_t buffer_length = Buffer::Length(buffer_obj);
20281cb0ef41Sopenharmony_ci
20291cb0ef41Sopenharmony_ci  CHECK(IsSafeJsInt(args[2]));
20301cb0ef41Sopenharmony_ci  const int64_t off_64 = args[2].As<Integer>()->Value();
20311cb0ef41Sopenharmony_ci  CHECK_GE(off_64, 0);
20321cb0ef41Sopenharmony_ci  CHECK_LE(static_cast<uint64_t>(off_64), buffer_length);
20331cb0ef41Sopenharmony_ci  const size_t off = static_cast<size_t>(off_64);
20341cb0ef41Sopenharmony_ci
20351cb0ef41Sopenharmony_ci  CHECK(args[3]->IsInt32());
20361cb0ef41Sopenharmony_ci  const size_t len = static_cast<size_t>(args[3].As<Int32>()->Value());
20371cb0ef41Sopenharmony_ci  CHECK(Buffer::IsWithinBounds(off, len, buffer_length));
20381cb0ef41Sopenharmony_ci  CHECK_LE(len, buffer_length);
20391cb0ef41Sopenharmony_ci  CHECK_GE(off + len, off);
20401cb0ef41Sopenharmony_ci
20411cb0ef41Sopenharmony_ci  const int64_t pos = GetOffset(args[4]);
20421cb0ef41Sopenharmony_ci
20431cb0ef41Sopenharmony_ci  char* buf = buffer_data + off;
20441cb0ef41Sopenharmony_ci  uv_buf_t uvbuf = uv_buf_init(buf, len);
20451cb0ef41Sopenharmony_ci
20461cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 5);
20471cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // write(fd, buffer, off, len, pos, req)
20481cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_WRITE, req_wrap_async)
20491cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "write", UTF8, AfterInteger,
20501cb0ef41Sopenharmony_ci              uv_fs_write, fd, &uvbuf, 1, pos);
20511cb0ef41Sopenharmony_ci  } else {  // write(fd, buffer, off, len, pos, undefined, ctx)
20521cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 7);
20531cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
20541cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(write);
20551cb0ef41Sopenharmony_ci    int bytesWritten = SyncCall(env, args[6], &req_wrap_sync, "write",
20561cb0ef41Sopenharmony_ci                                uv_fs_write, fd, &uvbuf, 1, pos);
20571cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten);
20581cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(bytesWritten);
20591cb0ef41Sopenharmony_ci  }
20601cb0ef41Sopenharmony_ci}
20611cb0ef41Sopenharmony_ci
20621cb0ef41Sopenharmony_ci
20631cb0ef41Sopenharmony_ci// Wrapper for writev(2).
20641cb0ef41Sopenharmony_ci//
20651cb0ef41Sopenharmony_ci// bytesWritten = writev(fd, chunks, position, callback)
20661cb0ef41Sopenharmony_ci// 0 fd        integer. file descriptor
20671cb0ef41Sopenharmony_ci// 1 chunks    array of buffers to write
20681cb0ef41Sopenharmony_ci// 2 position  if integer, position to write at in the file.
20691cb0ef41Sopenharmony_ci//             if null, write from the current position
20701cb0ef41Sopenharmony_cistatic void WriteBuffers(const FunctionCallbackInfo<Value>& args) {
20711cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
20721cb0ef41Sopenharmony_ci
20731cb0ef41Sopenharmony_ci  const int argc = args.Length();
20741cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
20751cb0ef41Sopenharmony_ci
20761cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
20771cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
20781cb0ef41Sopenharmony_ci
20791cb0ef41Sopenharmony_ci  CHECK(args[1]->IsArray());
20801cb0ef41Sopenharmony_ci  Local<Array> chunks = args[1].As<Array>();
20811cb0ef41Sopenharmony_ci
20821cb0ef41Sopenharmony_ci  int64_t pos = GetOffset(args[2]);
20831cb0ef41Sopenharmony_ci
20841cb0ef41Sopenharmony_ci  MaybeStackBuffer<uv_buf_t> iovs(chunks->Length());
20851cb0ef41Sopenharmony_ci
20861cb0ef41Sopenharmony_ci  for (uint32_t i = 0; i < iovs.length(); i++) {
20871cb0ef41Sopenharmony_ci    Local<Value> chunk = chunks->Get(env->context(), i).ToLocalChecked();
20881cb0ef41Sopenharmony_ci    CHECK(Buffer::HasInstance(chunk));
20891cb0ef41Sopenharmony_ci    iovs[i] = uv_buf_init(Buffer::Data(chunk), Buffer::Length(chunk));
20901cb0ef41Sopenharmony_ci  }
20911cb0ef41Sopenharmony_ci
20921cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
20931cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // writeBuffers(fd, chunks, pos, req)
20941cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_WRITE, req_wrap_async)
20951cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "write", UTF8, AfterInteger,
20961cb0ef41Sopenharmony_ci              uv_fs_write, fd, *iovs, iovs.length(), pos);
20971cb0ef41Sopenharmony_ci  } else {  // writeBuffers(fd, chunks, pos, undefined, ctx)
20981cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
20991cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
21001cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(write);
21011cb0ef41Sopenharmony_ci    int bytesWritten = SyncCall(env, args[4], &req_wrap_sync, "write",
21021cb0ef41Sopenharmony_ci                                uv_fs_write, fd, *iovs, iovs.length(), pos);
21031cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten);
21041cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(bytesWritten);
21051cb0ef41Sopenharmony_ci  }
21061cb0ef41Sopenharmony_ci}
21071cb0ef41Sopenharmony_ci
21081cb0ef41Sopenharmony_ci
21091cb0ef41Sopenharmony_ci// Wrapper for write(2).
21101cb0ef41Sopenharmony_ci//
21111cb0ef41Sopenharmony_ci// bytesWritten = write(fd, string, position, enc, callback)
21121cb0ef41Sopenharmony_ci// 0 fd        integer. file descriptor
21131cb0ef41Sopenharmony_ci// 1 string    non-buffer values are converted to strings
21141cb0ef41Sopenharmony_ci// 2 position  if integer, position to write at in the file.
21151cb0ef41Sopenharmony_ci//             if null, write from the current position
21161cb0ef41Sopenharmony_ci// 3 enc       encoding of string
21171cb0ef41Sopenharmony_cistatic void WriteString(const FunctionCallbackInfo<Value>& args) {
21181cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
21191cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
21201cb0ef41Sopenharmony_ci
21211cb0ef41Sopenharmony_ci  const int argc = args.Length();
21221cb0ef41Sopenharmony_ci  CHECK_GE(argc, 4);
21231cb0ef41Sopenharmony_ci
21241cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
21251cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
21261cb0ef41Sopenharmony_ci
21271cb0ef41Sopenharmony_ci  const int64_t pos = GetOffset(args[2]);
21281cb0ef41Sopenharmony_ci
21291cb0ef41Sopenharmony_ci  const auto enc = ParseEncoding(isolate, args[3], UTF8);
21301cb0ef41Sopenharmony_ci
21311cb0ef41Sopenharmony_ci  Local<Value> value = args[1];
21321cb0ef41Sopenharmony_ci  char* buf = nullptr;
21331cb0ef41Sopenharmony_ci  size_t len;
21341cb0ef41Sopenharmony_ci
21351cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 4);
21361cb0ef41Sopenharmony_ci  const bool is_async = req_wrap_async != nullptr;
21371cb0ef41Sopenharmony_ci
21381cb0ef41Sopenharmony_ci  // Avoid copying the string when it is externalized but only when:
21391cb0ef41Sopenharmony_ci  // 1. The target encoding is compatible with the string's encoding, and
21401cb0ef41Sopenharmony_ci  // 2. The write is synchronous, otherwise the string might get neutered
21411cb0ef41Sopenharmony_ci  //    while the request is in flight, and
21421cb0ef41Sopenharmony_ci  // 3. For UCS2, when the host system is little-endian.  Big-endian systems
21431cb0ef41Sopenharmony_ci  //    need to call StringBytes::Write() to ensure proper byte swapping.
21441cb0ef41Sopenharmony_ci  // The const_casts are conceptually sound: memory is read but not written.
21451cb0ef41Sopenharmony_ci  if (!is_async && value->IsString()) {
21461cb0ef41Sopenharmony_ci    auto string = value.As<String>();
21471cb0ef41Sopenharmony_ci    if ((enc == ASCII || enc == LATIN1) && string->IsExternalOneByte()) {
21481cb0ef41Sopenharmony_ci      auto ext = string->GetExternalOneByteStringResource();
21491cb0ef41Sopenharmony_ci      buf = const_cast<char*>(ext->data());
21501cb0ef41Sopenharmony_ci      len = ext->length();
21511cb0ef41Sopenharmony_ci    } else if (enc == UCS2 && IsLittleEndian() && string->IsExternalTwoByte()) {
21521cb0ef41Sopenharmony_ci      auto ext = string->GetExternalStringResource();
21531cb0ef41Sopenharmony_ci      buf = reinterpret_cast<char*>(const_cast<uint16_t*>(ext->data()));
21541cb0ef41Sopenharmony_ci      len = ext->length() * sizeof(*ext->data());
21551cb0ef41Sopenharmony_ci    }
21561cb0ef41Sopenharmony_ci  }
21571cb0ef41Sopenharmony_ci
21581cb0ef41Sopenharmony_ci  if (is_async) {  // write(fd, string, pos, enc, req)
21591cb0ef41Sopenharmony_ci    CHECK_NOT_NULL(req_wrap_async);
21601cb0ef41Sopenharmony_ci    if (!StringBytes::StorageSize(isolate, value, enc).To(&len)) return;
21611cb0ef41Sopenharmony_ci    FSReqBase::FSReqBuffer& stack_buffer =
21621cb0ef41Sopenharmony_ci        req_wrap_async->Init("write", len, enc);
21631cb0ef41Sopenharmony_ci    // StorageSize may return too large a char, so correct the actual length
21641cb0ef41Sopenharmony_ci    // by the write size
21651cb0ef41Sopenharmony_ci    len = StringBytes::Write(isolate, *stack_buffer, len, args[1], enc);
21661cb0ef41Sopenharmony_ci    stack_buffer.SetLengthAndZeroTerminate(len);
21671cb0ef41Sopenharmony_ci    uv_buf_t uvbuf = uv_buf_init(*stack_buffer, len);
21681cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_WRITE, req_wrap_async)
21691cb0ef41Sopenharmony_ci    int err = req_wrap_async->Dispatch(uv_fs_write,
21701cb0ef41Sopenharmony_ci                                       fd,
21711cb0ef41Sopenharmony_ci                                       &uvbuf,
21721cb0ef41Sopenharmony_ci                                       1,
21731cb0ef41Sopenharmony_ci                                       pos,
21741cb0ef41Sopenharmony_ci                                       AfterInteger);
21751cb0ef41Sopenharmony_ci    if (err < 0) {
21761cb0ef41Sopenharmony_ci      uv_fs_t* uv_req = req_wrap_async->req();
21771cb0ef41Sopenharmony_ci      uv_req->result = err;
21781cb0ef41Sopenharmony_ci      uv_req->path = nullptr;
21791cb0ef41Sopenharmony_ci      AfterInteger(uv_req);  // after may delete req_wrap_async if there is
21801cb0ef41Sopenharmony_ci                             // an error
21811cb0ef41Sopenharmony_ci    } else {
21821cb0ef41Sopenharmony_ci      req_wrap_async->SetReturnValue(args);
21831cb0ef41Sopenharmony_ci    }
21841cb0ef41Sopenharmony_ci  } else {  // write(fd, string, pos, enc, undefined, ctx)
21851cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 6);
21861cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
21871cb0ef41Sopenharmony_ci    FSReqBase::FSReqBuffer stack_buffer;
21881cb0ef41Sopenharmony_ci    if (buf == nullptr) {
21891cb0ef41Sopenharmony_ci      if (!StringBytes::StorageSize(isolate, value, enc).To(&len))
21901cb0ef41Sopenharmony_ci        return;
21911cb0ef41Sopenharmony_ci      stack_buffer.AllocateSufficientStorage(len + 1);
21921cb0ef41Sopenharmony_ci      // StorageSize may return too large a char, so correct the actual length
21931cb0ef41Sopenharmony_ci      // by the write size
21941cb0ef41Sopenharmony_ci      len = StringBytes::Write(isolate, *stack_buffer,
21951cb0ef41Sopenharmony_ci                               len, args[1], enc);
21961cb0ef41Sopenharmony_ci      stack_buffer.SetLengthAndZeroTerminate(len);
21971cb0ef41Sopenharmony_ci      buf = *stack_buffer;
21981cb0ef41Sopenharmony_ci    }
21991cb0ef41Sopenharmony_ci    uv_buf_t uvbuf = uv_buf_init(buf, len);
22001cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(write);
22011cb0ef41Sopenharmony_ci    int bytesWritten = SyncCall(env, args[5], &req_wrap_sync, "write",
22021cb0ef41Sopenharmony_ci                                uv_fs_write, fd, &uvbuf, 1, pos);
22031cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten);
22041cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(bytesWritten);
22051cb0ef41Sopenharmony_ci  }
22061cb0ef41Sopenharmony_ci}
22071cb0ef41Sopenharmony_ci
22081cb0ef41Sopenharmony_ci
22091cb0ef41Sopenharmony_ci/*
22101cb0ef41Sopenharmony_ci * Wrapper for read(2).
22111cb0ef41Sopenharmony_ci *
22121cb0ef41Sopenharmony_ci * bytesRead = fs.read(fd, buffer, offset, length, position)
22131cb0ef41Sopenharmony_ci *
22141cb0ef41Sopenharmony_ci * 0 fd        int32. file descriptor
22151cb0ef41Sopenharmony_ci * 1 buffer    instance of Buffer
22161cb0ef41Sopenharmony_ci * 2 offset    int64. offset to start reading into inside buffer
22171cb0ef41Sopenharmony_ci * 3 length    int32. length to read
22181cb0ef41Sopenharmony_ci * 4 position  int64. file position - -1 for current position
22191cb0ef41Sopenharmony_ci */
22201cb0ef41Sopenharmony_cistatic void Read(const FunctionCallbackInfo<Value>& args) {
22211cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
22221cb0ef41Sopenharmony_ci
22231cb0ef41Sopenharmony_ci  const int argc = args.Length();
22241cb0ef41Sopenharmony_ci  CHECK_GE(argc, 5);
22251cb0ef41Sopenharmony_ci
22261cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
22271cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
22281cb0ef41Sopenharmony_ci
22291cb0ef41Sopenharmony_ci  CHECK(Buffer::HasInstance(args[1]));
22301cb0ef41Sopenharmony_ci  Local<Object> buffer_obj = args[1].As<Object>();
22311cb0ef41Sopenharmony_ci  char* buffer_data = Buffer::Data(buffer_obj);
22321cb0ef41Sopenharmony_ci  size_t buffer_length = Buffer::Length(buffer_obj);
22331cb0ef41Sopenharmony_ci
22341cb0ef41Sopenharmony_ci  CHECK(IsSafeJsInt(args[2]));
22351cb0ef41Sopenharmony_ci  const int64_t off_64 = args[2].As<Integer>()->Value();
22361cb0ef41Sopenharmony_ci  CHECK_GE(off_64, 0);
22371cb0ef41Sopenharmony_ci  CHECK_LT(static_cast<uint64_t>(off_64), buffer_length);
22381cb0ef41Sopenharmony_ci  const size_t off = static_cast<size_t>(off_64);
22391cb0ef41Sopenharmony_ci
22401cb0ef41Sopenharmony_ci  CHECK(args[3]->IsInt32());
22411cb0ef41Sopenharmony_ci  const size_t len = static_cast<size_t>(args[3].As<Int32>()->Value());
22421cb0ef41Sopenharmony_ci  CHECK(Buffer::IsWithinBounds(off, len, buffer_length));
22431cb0ef41Sopenharmony_ci
22441cb0ef41Sopenharmony_ci  CHECK(IsSafeJsInt(args[4]) || args[4]->IsBigInt());
22451cb0ef41Sopenharmony_ci  const int64_t pos = args[4]->IsNumber() ?
22461cb0ef41Sopenharmony_ci                      args[4].As<Integer>()->Value() :
22471cb0ef41Sopenharmony_ci                      args[4].As<BigInt>()->Int64Value();
22481cb0ef41Sopenharmony_ci
22491cb0ef41Sopenharmony_ci  char* buf = buffer_data + off;
22501cb0ef41Sopenharmony_ci  uv_buf_t uvbuf = uv_buf_init(buf, len);
22511cb0ef41Sopenharmony_ci
22521cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 5);
22531cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // read(fd, buffer, offset, len, pos, req)
22541cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_READ, req_wrap_async)
22551cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "read", UTF8, AfterInteger,
22561cb0ef41Sopenharmony_ci              uv_fs_read, fd, &uvbuf, 1, pos);
22571cb0ef41Sopenharmony_ci  } else {  // read(fd, buffer, offset, len, pos, undefined, ctx)
22581cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 7);
22591cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
22601cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(read);
22611cb0ef41Sopenharmony_ci    const int bytesRead = SyncCall(env, args[6], &req_wrap_sync, "read",
22621cb0ef41Sopenharmony_ci                                   uv_fs_read, fd, &uvbuf, 1, pos);
22631cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(read, "bytesRead", bytesRead);
22641cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(bytesRead);
22651cb0ef41Sopenharmony_ci  }
22661cb0ef41Sopenharmony_ci}
22671cb0ef41Sopenharmony_ci
22681cb0ef41Sopenharmony_ci
22691cb0ef41Sopenharmony_ci// Wrapper for readv(2).
22701cb0ef41Sopenharmony_ci//
22711cb0ef41Sopenharmony_ci// bytesRead = fs.readv(fd, buffers[, position], callback)
22721cb0ef41Sopenharmony_ci// 0 fd        integer. file descriptor
22731cb0ef41Sopenharmony_ci// 1 buffers   array of buffers to read
22741cb0ef41Sopenharmony_ci// 2 position  if integer, position to read at in the file.
22751cb0ef41Sopenharmony_ci//             if null, read from the current position
22761cb0ef41Sopenharmony_cistatic void ReadBuffers(const FunctionCallbackInfo<Value>& args) {
22771cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
22781cb0ef41Sopenharmony_ci
22791cb0ef41Sopenharmony_ci  const int argc = args.Length();
22801cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
22811cb0ef41Sopenharmony_ci
22821cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
22831cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
22841cb0ef41Sopenharmony_ci
22851cb0ef41Sopenharmony_ci  CHECK(args[1]->IsArray());
22861cb0ef41Sopenharmony_ci  Local<Array> buffers = args[1].As<Array>();
22871cb0ef41Sopenharmony_ci
22881cb0ef41Sopenharmony_ci  int64_t pos = GetOffset(args[2]);  // -1 if not a valid JS int
22891cb0ef41Sopenharmony_ci
22901cb0ef41Sopenharmony_ci  MaybeStackBuffer<uv_buf_t> iovs(buffers->Length());
22911cb0ef41Sopenharmony_ci
22921cb0ef41Sopenharmony_ci  // Init uv buffers from ArrayBufferViews
22931cb0ef41Sopenharmony_ci  for (uint32_t i = 0; i < iovs.length(); i++) {
22941cb0ef41Sopenharmony_ci    Local<Value> buffer = buffers->Get(env->context(), i).ToLocalChecked();
22951cb0ef41Sopenharmony_ci    CHECK(Buffer::HasInstance(buffer));
22961cb0ef41Sopenharmony_ci    iovs[i] = uv_buf_init(Buffer::Data(buffer), Buffer::Length(buffer));
22971cb0ef41Sopenharmony_ci  }
22981cb0ef41Sopenharmony_ci
22991cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
23001cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // readBuffers(fd, buffers, pos, req)
23011cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_READ, req_wrap_async)
23021cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "read", UTF8, AfterInteger,
23031cb0ef41Sopenharmony_ci              uv_fs_read, fd, *iovs, iovs.length(), pos);
23041cb0ef41Sopenharmony_ci  } else {  // readBuffers(fd, buffers, undefined, ctx)
23051cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
23061cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
23071cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(read);
23081cb0ef41Sopenharmony_ci    int bytesRead = SyncCall(env, /* ctx */ args[4], &req_wrap_sync, "read",
23091cb0ef41Sopenharmony_ci                             uv_fs_read, fd, *iovs, iovs.length(), pos);
23101cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(read, "bytesRead", bytesRead);
23111cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(bytesRead);
23121cb0ef41Sopenharmony_ci  }
23131cb0ef41Sopenharmony_ci}
23141cb0ef41Sopenharmony_ci
23151cb0ef41Sopenharmony_ci
23161cb0ef41Sopenharmony_ci/* fs.chmod(path, mode);
23171cb0ef41Sopenharmony_ci * Wrapper for chmod(1) / EIO_CHMOD
23181cb0ef41Sopenharmony_ci */
23191cb0ef41Sopenharmony_cistatic void Chmod(const FunctionCallbackInfo<Value>& args) {
23201cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
23211cb0ef41Sopenharmony_ci
23221cb0ef41Sopenharmony_ci  const int argc = args.Length();
23231cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
23241cb0ef41Sopenharmony_ci
23251cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
23261cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
23271cb0ef41Sopenharmony_ci
23281cb0ef41Sopenharmony_ci  CHECK(args[1]->IsInt32());
23291cb0ef41Sopenharmony_ci  int mode = args[1].As<Int32>()->Value();
23301cb0ef41Sopenharmony_ci
23311cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
23321cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // chmod(path, mode, req)
23331cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
23341cb0ef41Sopenharmony_ci        UV_FS_CHMOD, req_wrap_async, "path", TRACE_STR_COPY(*path))
23351cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "chmod", UTF8, AfterNoArgs,
23361cb0ef41Sopenharmony_ci              uv_fs_chmod, *path, mode);
23371cb0ef41Sopenharmony_ci  } else {  // chmod(path, mode, undefined, ctx)
23381cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
23391cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
23401cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(chmod);
23411cb0ef41Sopenharmony_ci    SyncCall(env, args[3], &req_wrap_sync, "chmod",
23421cb0ef41Sopenharmony_ci             uv_fs_chmod, *path, mode);
23431cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(chmod);
23441cb0ef41Sopenharmony_ci  }
23451cb0ef41Sopenharmony_ci}
23461cb0ef41Sopenharmony_ci
23471cb0ef41Sopenharmony_ci
23481cb0ef41Sopenharmony_ci/* fs.fchmod(fd, mode);
23491cb0ef41Sopenharmony_ci * Wrapper for fchmod(1) / EIO_FCHMOD
23501cb0ef41Sopenharmony_ci */
23511cb0ef41Sopenharmony_cistatic void FChmod(const FunctionCallbackInfo<Value>& args) {
23521cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
23531cb0ef41Sopenharmony_ci
23541cb0ef41Sopenharmony_ci  const int argc = args.Length();
23551cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
23561cb0ef41Sopenharmony_ci
23571cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
23581cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
23591cb0ef41Sopenharmony_ci
23601cb0ef41Sopenharmony_ci  CHECK(args[1]->IsInt32());
23611cb0ef41Sopenharmony_ci  const int mode = args[1].As<Int32>()->Value();
23621cb0ef41Sopenharmony_ci
23631cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
23641cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // fchmod(fd, mode, req)
23651cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_FCHMOD, req_wrap_async)
23661cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "fchmod", UTF8, AfterNoArgs,
23671cb0ef41Sopenharmony_ci              uv_fs_fchmod, fd, mode);
23681cb0ef41Sopenharmony_ci  } else {  // fchmod(fd, mode, undefined, ctx)
23691cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
23701cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
23711cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(fchmod);
23721cb0ef41Sopenharmony_ci    SyncCall(env, args[3], &req_wrap_sync, "fchmod",
23731cb0ef41Sopenharmony_ci             uv_fs_fchmod, fd, mode);
23741cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(fchmod);
23751cb0ef41Sopenharmony_ci  }
23761cb0ef41Sopenharmony_ci}
23771cb0ef41Sopenharmony_ci
23781cb0ef41Sopenharmony_ci
23791cb0ef41Sopenharmony_ci/* fs.chown(path, uid, gid);
23801cb0ef41Sopenharmony_ci * Wrapper for chown(1) / EIO_CHOWN
23811cb0ef41Sopenharmony_ci */
23821cb0ef41Sopenharmony_cistatic void Chown(const FunctionCallbackInfo<Value>& args) {
23831cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
23841cb0ef41Sopenharmony_ci
23851cb0ef41Sopenharmony_ci  const int argc = args.Length();
23861cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
23871cb0ef41Sopenharmony_ci
23881cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
23891cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
23901cb0ef41Sopenharmony_ci
23911cb0ef41Sopenharmony_ci  CHECK(IsSafeJsInt(args[1]));
23921cb0ef41Sopenharmony_ci  const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Integer>()->Value());
23931cb0ef41Sopenharmony_ci
23941cb0ef41Sopenharmony_ci  CHECK(IsSafeJsInt(args[2]));
23951cb0ef41Sopenharmony_ci  const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Integer>()->Value());
23961cb0ef41Sopenharmony_ci
23971cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
23981cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // chown(path, uid, gid, req)
23991cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
24001cb0ef41Sopenharmony_ci        UV_FS_CHOWN, req_wrap_async, "path", TRACE_STR_COPY(*path))
24011cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "chown", UTF8, AfterNoArgs,
24021cb0ef41Sopenharmony_ci              uv_fs_chown, *path, uid, gid);
24031cb0ef41Sopenharmony_ci  } else {  // chown(path, uid, gid, undefined, ctx)
24041cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
24051cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
24061cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(chown);
24071cb0ef41Sopenharmony_ci    SyncCall(env, args[4], &req_wrap_sync, "chown",
24081cb0ef41Sopenharmony_ci             uv_fs_chown, *path, uid, gid);
24091cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(chown);
24101cb0ef41Sopenharmony_ci  }
24111cb0ef41Sopenharmony_ci}
24121cb0ef41Sopenharmony_ci
24131cb0ef41Sopenharmony_ci
24141cb0ef41Sopenharmony_ci/* fs.fchown(fd, uid, gid);
24151cb0ef41Sopenharmony_ci * Wrapper for fchown(1) / EIO_FCHOWN
24161cb0ef41Sopenharmony_ci */
24171cb0ef41Sopenharmony_cistatic void FChown(const FunctionCallbackInfo<Value>& args) {
24181cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
24191cb0ef41Sopenharmony_ci
24201cb0ef41Sopenharmony_ci  const int argc = args.Length();
24211cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
24221cb0ef41Sopenharmony_ci
24231cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
24241cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
24251cb0ef41Sopenharmony_ci
24261cb0ef41Sopenharmony_ci  CHECK(IsSafeJsInt(args[1]));
24271cb0ef41Sopenharmony_ci  const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Integer>()->Value());
24281cb0ef41Sopenharmony_ci
24291cb0ef41Sopenharmony_ci  CHECK(IsSafeJsInt(args[2]));
24301cb0ef41Sopenharmony_ci  const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Integer>()->Value());
24311cb0ef41Sopenharmony_ci
24321cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
24331cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // fchown(fd, uid, gid, req)
24341cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_FCHOWN, req_wrap_async)
24351cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "fchown", UTF8, AfterNoArgs,
24361cb0ef41Sopenharmony_ci              uv_fs_fchown, fd, uid, gid);
24371cb0ef41Sopenharmony_ci  } else {  // fchown(fd, uid, gid, undefined, ctx)
24381cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
24391cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
24401cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(fchown);
24411cb0ef41Sopenharmony_ci    SyncCall(env, args[4], &req_wrap_sync, "fchown",
24421cb0ef41Sopenharmony_ci             uv_fs_fchown, fd, uid, gid);
24431cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(fchown);
24441cb0ef41Sopenharmony_ci  }
24451cb0ef41Sopenharmony_ci}
24461cb0ef41Sopenharmony_ci
24471cb0ef41Sopenharmony_ci
24481cb0ef41Sopenharmony_cistatic void LChown(const FunctionCallbackInfo<Value>& args) {
24491cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
24501cb0ef41Sopenharmony_ci
24511cb0ef41Sopenharmony_ci  const int argc = args.Length();
24521cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
24531cb0ef41Sopenharmony_ci
24541cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
24551cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
24561cb0ef41Sopenharmony_ci
24571cb0ef41Sopenharmony_ci  CHECK(IsSafeJsInt(args[1]));
24581cb0ef41Sopenharmony_ci  const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Integer>()->Value());
24591cb0ef41Sopenharmony_ci
24601cb0ef41Sopenharmony_ci  CHECK(IsSafeJsInt(args[2]));
24611cb0ef41Sopenharmony_ci  const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Integer>()->Value());
24621cb0ef41Sopenharmony_ci
24631cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
24641cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // lchown(path, uid, gid, req)
24651cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
24661cb0ef41Sopenharmony_ci        UV_FS_LCHOWN, req_wrap_async, "path", TRACE_STR_COPY(*path))
24671cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "lchown", UTF8, AfterNoArgs,
24681cb0ef41Sopenharmony_ci              uv_fs_lchown, *path, uid, gid);
24691cb0ef41Sopenharmony_ci  } else {  // lchown(path, uid, gid, undefined, ctx)
24701cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
24711cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
24721cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(lchown);
24731cb0ef41Sopenharmony_ci    SyncCall(env, args[4], &req_wrap_sync, "lchown",
24741cb0ef41Sopenharmony_ci             uv_fs_lchown, *path, uid, gid);
24751cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(lchown);
24761cb0ef41Sopenharmony_ci  }
24771cb0ef41Sopenharmony_ci}
24781cb0ef41Sopenharmony_ci
24791cb0ef41Sopenharmony_ci
24801cb0ef41Sopenharmony_cistatic void UTimes(const FunctionCallbackInfo<Value>& args) {
24811cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
24821cb0ef41Sopenharmony_ci
24831cb0ef41Sopenharmony_ci  const int argc = args.Length();
24841cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
24851cb0ef41Sopenharmony_ci
24861cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
24871cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
24881cb0ef41Sopenharmony_ci
24891cb0ef41Sopenharmony_ci  CHECK(args[1]->IsNumber());
24901cb0ef41Sopenharmony_ci  const double atime = args[1].As<Number>()->Value();
24911cb0ef41Sopenharmony_ci
24921cb0ef41Sopenharmony_ci  CHECK(args[2]->IsNumber());
24931cb0ef41Sopenharmony_ci  const double mtime = args[2].As<Number>()->Value();
24941cb0ef41Sopenharmony_ci
24951cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
24961cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // utimes(path, atime, mtime, req)
24971cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
24981cb0ef41Sopenharmony_ci        UV_FS_UTIME, req_wrap_async, "path", TRACE_STR_COPY(*path))
24991cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "utime", UTF8, AfterNoArgs,
25001cb0ef41Sopenharmony_ci              uv_fs_utime, *path, atime, mtime);
25011cb0ef41Sopenharmony_ci  } else {  // utimes(path, atime, mtime, undefined, ctx)
25021cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
25031cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
25041cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(utimes);
25051cb0ef41Sopenharmony_ci    SyncCall(env, args[4], &req_wrap_sync, "utime",
25061cb0ef41Sopenharmony_ci             uv_fs_utime, *path, atime, mtime);
25071cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(utimes);
25081cb0ef41Sopenharmony_ci  }
25091cb0ef41Sopenharmony_ci}
25101cb0ef41Sopenharmony_ci
25111cb0ef41Sopenharmony_cistatic void FUTimes(const FunctionCallbackInfo<Value>& args) {
25121cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
25131cb0ef41Sopenharmony_ci
25141cb0ef41Sopenharmony_ci  const int argc = args.Length();
25151cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
25161cb0ef41Sopenharmony_ci
25171cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
25181cb0ef41Sopenharmony_ci  const int fd = args[0].As<Int32>()->Value();
25191cb0ef41Sopenharmony_ci
25201cb0ef41Sopenharmony_ci  CHECK(args[1]->IsNumber());
25211cb0ef41Sopenharmony_ci  const double atime = args[1].As<Number>()->Value();
25221cb0ef41Sopenharmony_ci
25231cb0ef41Sopenharmony_ci  CHECK(args[2]->IsNumber());
25241cb0ef41Sopenharmony_ci  const double mtime = args[2].As<Number>()->Value();
25251cb0ef41Sopenharmony_ci
25261cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
25271cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // futimes(fd, atime, mtime, req)
25281cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN0(UV_FS_FUTIME, req_wrap_async)
25291cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "futime", UTF8, AfterNoArgs,
25301cb0ef41Sopenharmony_ci              uv_fs_futime, fd, atime, mtime);
25311cb0ef41Sopenharmony_ci  } else {  // futimes(fd, atime, mtime, undefined, ctx)
25321cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
25331cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
25341cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(futimes);
25351cb0ef41Sopenharmony_ci    SyncCall(env, args[4], &req_wrap_sync, "futime",
25361cb0ef41Sopenharmony_ci             uv_fs_futime, fd, atime, mtime);
25371cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(futimes);
25381cb0ef41Sopenharmony_ci  }
25391cb0ef41Sopenharmony_ci}
25401cb0ef41Sopenharmony_ci
25411cb0ef41Sopenharmony_cistatic void LUTimes(const FunctionCallbackInfo<Value>& args) {
25421cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
25431cb0ef41Sopenharmony_ci
25441cb0ef41Sopenharmony_ci  const int argc = args.Length();
25451cb0ef41Sopenharmony_ci  CHECK_GE(argc, 3);
25461cb0ef41Sopenharmony_ci
25471cb0ef41Sopenharmony_ci  BufferValue path(env->isolate(), args[0]);
25481cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*path);
25491cb0ef41Sopenharmony_ci
25501cb0ef41Sopenharmony_ci  CHECK(args[1]->IsNumber());
25511cb0ef41Sopenharmony_ci  const double atime = args[1].As<Number>()->Value();
25521cb0ef41Sopenharmony_ci
25531cb0ef41Sopenharmony_ci  CHECK(args[2]->IsNumber());
25541cb0ef41Sopenharmony_ci  const double mtime = args[2].As<Number>()->Value();
25551cb0ef41Sopenharmony_ci
25561cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 3);
25571cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // lutimes(path, atime, mtime, req)
25581cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
25591cb0ef41Sopenharmony_ci        UV_FS_LUTIME, req_wrap_async, "path", TRACE_STR_COPY(*path))
25601cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "lutime", UTF8, AfterNoArgs,
25611cb0ef41Sopenharmony_ci              uv_fs_lutime, *path, atime, mtime);
25621cb0ef41Sopenharmony_ci  } else {  // lutimes(path, atime, mtime, undefined, ctx)
25631cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 5);
25641cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
25651cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(lutimes);
25661cb0ef41Sopenharmony_ci    SyncCall(env, args[4], &req_wrap_sync, "lutime",
25671cb0ef41Sopenharmony_ci             uv_fs_lutime, *path, atime, mtime);
25681cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(lutimes);
25691cb0ef41Sopenharmony_ci  }
25701cb0ef41Sopenharmony_ci}
25711cb0ef41Sopenharmony_ci
25721cb0ef41Sopenharmony_cistatic void Mkdtemp(const FunctionCallbackInfo<Value>& args) {
25731cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
25741cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
25751cb0ef41Sopenharmony_ci
25761cb0ef41Sopenharmony_ci  const int argc = args.Length();
25771cb0ef41Sopenharmony_ci  CHECK_GE(argc, 2);
25781cb0ef41Sopenharmony_ci
25791cb0ef41Sopenharmony_ci  BufferValue tmpl(isolate, args[0]);
25801cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(*tmpl);
25811cb0ef41Sopenharmony_ci
25821cb0ef41Sopenharmony_ci  const enum encoding encoding = ParseEncoding(isolate, args[1], UTF8);
25831cb0ef41Sopenharmony_ci
25841cb0ef41Sopenharmony_ci  FSReqBase* req_wrap_async = GetReqWrap(args, 2);
25851cb0ef41Sopenharmony_ci  if (req_wrap_async != nullptr) {  // mkdtemp(tmpl, encoding, req)
25861cb0ef41Sopenharmony_ci    FS_ASYNC_TRACE_BEGIN1(
25871cb0ef41Sopenharmony_ci        UV_FS_MKDTEMP, req_wrap_async, "path", TRACE_STR_COPY(*tmpl))
25881cb0ef41Sopenharmony_ci    AsyncCall(env, req_wrap_async, args, "mkdtemp", encoding, AfterStringPath,
25891cb0ef41Sopenharmony_ci              uv_fs_mkdtemp, *tmpl);
25901cb0ef41Sopenharmony_ci  } else {  // mkdtemp(tmpl, encoding, undefined, ctx)
25911cb0ef41Sopenharmony_ci    CHECK_EQ(argc, 4);
25921cb0ef41Sopenharmony_ci    FSReqWrapSync req_wrap_sync;
25931cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_BEGIN(mkdtemp);
25941cb0ef41Sopenharmony_ci    SyncCall(env, args[3], &req_wrap_sync, "mkdtemp",
25951cb0ef41Sopenharmony_ci             uv_fs_mkdtemp, *tmpl);
25961cb0ef41Sopenharmony_ci    FS_SYNC_TRACE_END(mkdtemp);
25971cb0ef41Sopenharmony_ci    const char* path = req_wrap_sync.req.path;
25981cb0ef41Sopenharmony_ci
25991cb0ef41Sopenharmony_ci    Local<Value> error;
26001cb0ef41Sopenharmony_ci    MaybeLocal<Value> rc =
26011cb0ef41Sopenharmony_ci        StringBytes::Encode(isolate, path, encoding, &error);
26021cb0ef41Sopenharmony_ci    if (rc.IsEmpty()) {
26031cb0ef41Sopenharmony_ci      Local<Object> ctx = args[3].As<Object>();
26041cb0ef41Sopenharmony_ci      ctx->Set(env->context(), env->error_string(), error).Check();
26051cb0ef41Sopenharmony_ci      return;
26061cb0ef41Sopenharmony_ci    }
26071cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(rc.ToLocalChecked());
26081cb0ef41Sopenharmony_ci  }
26091cb0ef41Sopenharmony_ci}
26101cb0ef41Sopenharmony_ci
26111cb0ef41Sopenharmony_civoid BindingData::MemoryInfo(MemoryTracker* tracker) const {
26121cb0ef41Sopenharmony_ci  tracker->TrackField("stats_field_array", stats_field_array);
26131cb0ef41Sopenharmony_ci  tracker->TrackField("stats_field_bigint_array", stats_field_bigint_array);
26141cb0ef41Sopenharmony_ci  tracker->TrackField("statfs_field_array", statfs_field_array);
26151cb0ef41Sopenharmony_ci  tracker->TrackField("statfs_field_bigint_array", statfs_field_bigint_array);
26161cb0ef41Sopenharmony_ci  tracker->TrackField("file_handle_read_wrap_freelist",
26171cb0ef41Sopenharmony_ci                      file_handle_read_wrap_freelist);
26181cb0ef41Sopenharmony_ci}
26191cb0ef41Sopenharmony_ci
26201cb0ef41Sopenharmony_ciBindingData::BindingData(Realm* realm, v8::Local<v8::Object> wrap)
26211cb0ef41Sopenharmony_ci    : SnapshotableObject(realm, wrap, type_int),
26221cb0ef41Sopenharmony_ci      stats_field_array(realm->isolate(), kFsStatsBufferLength),
26231cb0ef41Sopenharmony_ci      stats_field_bigint_array(realm->isolate(), kFsStatsBufferLength),
26241cb0ef41Sopenharmony_ci      statfs_field_array(realm->isolate(), kFsStatFsBufferLength),
26251cb0ef41Sopenharmony_ci      statfs_field_bigint_array(realm->isolate(), kFsStatFsBufferLength) {
26261cb0ef41Sopenharmony_ci  Isolate* isolate = realm->isolate();
26271cb0ef41Sopenharmony_ci  Local<Context> context = realm->context();
26281cb0ef41Sopenharmony_ci  wrap->Set(context,
26291cb0ef41Sopenharmony_ci            FIXED_ONE_BYTE_STRING(isolate, "statValues"),
26301cb0ef41Sopenharmony_ci            stats_field_array.GetJSArray())
26311cb0ef41Sopenharmony_ci      .Check();
26321cb0ef41Sopenharmony_ci
26331cb0ef41Sopenharmony_ci  wrap->Set(context,
26341cb0ef41Sopenharmony_ci            FIXED_ONE_BYTE_STRING(isolate, "bigintStatValues"),
26351cb0ef41Sopenharmony_ci            stats_field_bigint_array.GetJSArray())
26361cb0ef41Sopenharmony_ci      .Check();
26371cb0ef41Sopenharmony_ci
26381cb0ef41Sopenharmony_ci  wrap->Set(context,
26391cb0ef41Sopenharmony_ci            FIXED_ONE_BYTE_STRING(isolate, "statFsValues"),
26401cb0ef41Sopenharmony_ci            statfs_field_array.GetJSArray())
26411cb0ef41Sopenharmony_ci      .Check();
26421cb0ef41Sopenharmony_ci
26431cb0ef41Sopenharmony_ci  wrap->Set(context,
26441cb0ef41Sopenharmony_ci            FIXED_ONE_BYTE_STRING(isolate, "bigintStatFsValues"),
26451cb0ef41Sopenharmony_ci            statfs_field_bigint_array.GetJSArray())
26461cb0ef41Sopenharmony_ci      .Check();
26471cb0ef41Sopenharmony_ci}
26481cb0ef41Sopenharmony_ci
26491cb0ef41Sopenharmony_civoid BindingData::Deserialize(Local<Context> context,
26501cb0ef41Sopenharmony_ci                              Local<Object> holder,
26511cb0ef41Sopenharmony_ci                              int index,
26521cb0ef41Sopenharmony_ci                              InternalFieldInfoBase* info) {
26531cb0ef41Sopenharmony_ci  DCHECK_EQ(index, BaseObject::kEmbedderType);
26541cb0ef41Sopenharmony_ci  HandleScope scope(context->GetIsolate());
26551cb0ef41Sopenharmony_ci  Realm* realm = Realm::GetCurrent(context);
26561cb0ef41Sopenharmony_ci  BindingData* binding = realm->AddBindingData<BindingData>(context, holder);
26571cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(binding);
26581cb0ef41Sopenharmony_ci}
26591cb0ef41Sopenharmony_ci
26601cb0ef41Sopenharmony_cibool BindingData::PrepareForSerialization(Local<Context> context,
26611cb0ef41Sopenharmony_ci                                          v8::SnapshotCreator* creator) {
26621cb0ef41Sopenharmony_ci  CHECK(file_handle_read_wrap_freelist.empty());
26631cb0ef41Sopenharmony_ci  // We'll just re-initialize the buffers in the constructor since their
26641cb0ef41Sopenharmony_ci  // contents can be thrown away once consumed in the previous call.
26651cb0ef41Sopenharmony_ci  stats_field_array.Release();
26661cb0ef41Sopenharmony_ci  stats_field_bigint_array.Release();
26671cb0ef41Sopenharmony_ci  statfs_field_array.Release();
26681cb0ef41Sopenharmony_ci  statfs_field_bigint_array.Release();
26691cb0ef41Sopenharmony_ci  // Return true because we need to maintain the reference to the binding from
26701cb0ef41Sopenharmony_ci  // JS land.
26711cb0ef41Sopenharmony_ci  return true;
26721cb0ef41Sopenharmony_ci}
26731cb0ef41Sopenharmony_ci
26741cb0ef41Sopenharmony_ciInternalFieldInfoBase* BindingData::Serialize(int index) {
26751cb0ef41Sopenharmony_ci  DCHECK_EQ(index, BaseObject::kEmbedderType);
26761cb0ef41Sopenharmony_ci  InternalFieldInfo* info =
26771cb0ef41Sopenharmony_ci      InternalFieldInfoBase::New<InternalFieldInfo>(type());
26781cb0ef41Sopenharmony_ci  return info;
26791cb0ef41Sopenharmony_ci}
26801cb0ef41Sopenharmony_ci
26811cb0ef41Sopenharmony_civoid Initialize(Local<Object> target,
26821cb0ef41Sopenharmony_ci                Local<Value> unused,
26831cb0ef41Sopenharmony_ci                Local<Context> context,
26841cb0ef41Sopenharmony_ci                void* priv) {
26851cb0ef41Sopenharmony_ci  Realm* realm = Realm::GetCurrent(context);
26861cb0ef41Sopenharmony_ci  Environment* env = realm->env();
26871cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
26881cb0ef41Sopenharmony_ci  BindingData* const binding_data =
26891cb0ef41Sopenharmony_ci      realm->AddBindingData<BindingData>(context, target);
26901cb0ef41Sopenharmony_ci  if (binding_data == nullptr) return;
26911cb0ef41Sopenharmony_ci
26921cb0ef41Sopenharmony_ci  SetMethod(context, target, "access", Access);
26931cb0ef41Sopenharmony_ci  SetMethod(context, target, "close", Close);
26941cb0ef41Sopenharmony_ci  SetMethod(context, target, "open", Open);
26951cb0ef41Sopenharmony_ci  SetMethod(context, target, "openFileHandle", OpenFileHandle);
26961cb0ef41Sopenharmony_ci  SetMethod(context, target, "read", Read);
26971cb0ef41Sopenharmony_ci  SetMethod(context, target, "readBuffers", ReadBuffers);
26981cb0ef41Sopenharmony_ci  SetMethod(context, target, "fdatasync", Fdatasync);
26991cb0ef41Sopenharmony_ci  SetMethod(context, target, "fsync", Fsync);
27001cb0ef41Sopenharmony_ci  SetMethod(context, target, "rename", Rename);
27011cb0ef41Sopenharmony_ci  SetMethod(context, target, "ftruncate", FTruncate);
27021cb0ef41Sopenharmony_ci  SetMethod(context, target, "rmdir", RMDir);
27031cb0ef41Sopenharmony_ci  SetMethod(context, target, "mkdir", MKDir);
27041cb0ef41Sopenharmony_ci  SetMethod(context, target, "readdir", ReadDir);
27051cb0ef41Sopenharmony_ci  SetMethod(context, target, "internalModuleReadJSON", InternalModuleReadJSON);
27061cb0ef41Sopenharmony_ci  SetMethod(context, target, "internalModuleStat", InternalModuleStat);
27071cb0ef41Sopenharmony_ci  SetMethod(context, target, "stat", Stat);
27081cb0ef41Sopenharmony_ci  SetMethod(context, target, "lstat", LStat);
27091cb0ef41Sopenharmony_ci  SetMethod(context, target, "fstat", FStat);
27101cb0ef41Sopenharmony_ci  SetMethod(context, target, "statfs", StatFs);
27111cb0ef41Sopenharmony_ci  SetMethod(context, target, "link", Link);
27121cb0ef41Sopenharmony_ci  SetMethod(context, target, "symlink", Symlink);
27131cb0ef41Sopenharmony_ci  SetMethod(context, target, "readlink", ReadLink);
27141cb0ef41Sopenharmony_ci  SetMethod(context, target, "unlink", Unlink);
27151cb0ef41Sopenharmony_ci  SetMethod(context, target, "writeBuffer", WriteBuffer);
27161cb0ef41Sopenharmony_ci  SetMethod(context, target, "writeBuffers", WriteBuffers);
27171cb0ef41Sopenharmony_ci  SetMethod(context, target, "writeString", WriteString);
27181cb0ef41Sopenharmony_ci  SetMethod(context, target, "realpath", RealPath);
27191cb0ef41Sopenharmony_ci  SetMethod(context, target, "copyFile", CopyFile);
27201cb0ef41Sopenharmony_ci
27211cb0ef41Sopenharmony_ci  SetMethod(context, target, "chmod", Chmod);
27221cb0ef41Sopenharmony_ci  SetMethod(context, target, "fchmod", FChmod);
27231cb0ef41Sopenharmony_ci
27241cb0ef41Sopenharmony_ci  SetMethod(context, target, "chown", Chown);
27251cb0ef41Sopenharmony_ci  SetMethod(context, target, "fchown", FChown);
27261cb0ef41Sopenharmony_ci  SetMethod(context, target, "lchown", LChown);
27271cb0ef41Sopenharmony_ci
27281cb0ef41Sopenharmony_ci  SetMethod(context, target, "utimes", UTimes);
27291cb0ef41Sopenharmony_ci  SetMethod(context, target, "futimes", FUTimes);
27301cb0ef41Sopenharmony_ci  SetMethod(context, target, "lutimes", LUTimes);
27311cb0ef41Sopenharmony_ci
27321cb0ef41Sopenharmony_ci  SetMethod(context, target, "mkdtemp", Mkdtemp);
27331cb0ef41Sopenharmony_ci
27341cb0ef41Sopenharmony_ci  target
27351cb0ef41Sopenharmony_ci      ->Set(context,
27361cb0ef41Sopenharmony_ci            FIXED_ONE_BYTE_STRING(isolate, "kFsStatsFieldsNumber"),
27371cb0ef41Sopenharmony_ci            Integer::New(
27381cb0ef41Sopenharmony_ci                isolate,
27391cb0ef41Sopenharmony_ci                static_cast<int32_t>(FsStatsOffset::kFsStatsFieldsNumber)))
27401cb0ef41Sopenharmony_ci      .Check();
27411cb0ef41Sopenharmony_ci
27421cb0ef41Sopenharmony_ci  StatWatcher::Initialize(env, target);
27431cb0ef41Sopenharmony_ci
27441cb0ef41Sopenharmony_ci  // Create FunctionTemplate for FSReqCallback
27451cb0ef41Sopenharmony_ci  Local<FunctionTemplate> fst = NewFunctionTemplate(isolate, NewFSReqCallback);
27461cb0ef41Sopenharmony_ci  fst->InstanceTemplate()->SetInternalFieldCount(
27471cb0ef41Sopenharmony_ci      FSReqBase::kInternalFieldCount);
27481cb0ef41Sopenharmony_ci  fst->Inherit(AsyncWrap::GetConstructorTemplate(env));
27491cb0ef41Sopenharmony_ci  SetConstructorFunction(context, target, "FSReqCallback", fst);
27501cb0ef41Sopenharmony_ci
27511cb0ef41Sopenharmony_ci  // Create FunctionTemplate for FileHandleReadWrap. There’s no need
27521cb0ef41Sopenharmony_ci  // to do anything in the constructor, so we only store the instance template.
27531cb0ef41Sopenharmony_ci  Local<FunctionTemplate> fh_rw = FunctionTemplate::New(isolate);
27541cb0ef41Sopenharmony_ci  fh_rw->InstanceTemplate()->SetInternalFieldCount(
27551cb0ef41Sopenharmony_ci      FSReqBase::kInternalFieldCount);
27561cb0ef41Sopenharmony_ci  fh_rw->Inherit(AsyncWrap::GetConstructorTemplate(env));
27571cb0ef41Sopenharmony_ci  Local<String> fhWrapString =
27581cb0ef41Sopenharmony_ci      FIXED_ONE_BYTE_STRING(isolate, "FileHandleReqWrap");
27591cb0ef41Sopenharmony_ci  fh_rw->SetClassName(fhWrapString);
27601cb0ef41Sopenharmony_ci  env->set_filehandlereadwrap_template(
27611cb0ef41Sopenharmony_ci      fst->InstanceTemplate());
27621cb0ef41Sopenharmony_ci
27631cb0ef41Sopenharmony_ci  // Create Function Template for FSReqPromise
27641cb0ef41Sopenharmony_ci  Local<FunctionTemplate> fpt = FunctionTemplate::New(isolate);
27651cb0ef41Sopenharmony_ci  fpt->Inherit(AsyncWrap::GetConstructorTemplate(env));
27661cb0ef41Sopenharmony_ci  Local<String> promiseString =
27671cb0ef41Sopenharmony_ci      FIXED_ONE_BYTE_STRING(isolate, "FSReqPromise");
27681cb0ef41Sopenharmony_ci  fpt->SetClassName(promiseString);
27691cb0ef41Sopenharmony_ci  Local<ObjectTemplate> fpo = fpt->InstanceTemplate();
27701cb0ef41Sopenharmony_ci  fpo->SetInternalFieldCount(FSReqBase::kInternalFieldCount);
27711cb0ef41Sopenharmony_ci  env->set_fsreqpromise_constructor_template(fpo);
27721cb0ef41Sopenharmony_ci
27731cb0ef41Sopenharmony_ci  // Create FunctionTemplate for FileHandle
27741cb0ef41Sopenharmony_ci  Local<FunctionTemplate> fd = NewFunctionTemplate(isolate, FileHandle::New);
27751cb0ef41Sopenharmony_ci  fd->Inherit(AsyncWrap::GetConstructorTemplate(env));
27761cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, fd, "close", FileHandle::Close);
27771cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, fd, "releaseFD", FileHandle::ReleaseFD);
27781cb0ef41Sopenharmony_ci  Local<ObjectTemplate> fdt = fd->InstanceTemplate();
27791cb0ef41Sopenharmony_ci  fdt->SetInternalFieldCount(FileHandle::kInternalFieldCount);
27801cb0ef41Sopenharmony_ci  StreamBase::AddMethods(env, fd);
27811cb0ef41Sopenharmony_ci  SetConstructorFunction(context, target, "FileHandle", fd);
27821cb0ef41Sopenharmony_ci  env->set_fd_constructor_template(fdt);
27831cb0ef41Sopenharmony_ci
27841cb0ef41Sopenharmony_ci  // Create FunctionTemplate for FileHandle::CloseReq
27851cb0ef41Sopenharmony_ci  Local<FunctionTemplate> fdclose = FunctionTemplate::New(isolate);
27861cb0ef41Sopenharmony_ci  fdclose->SetClassName(FIXED_ONE_BYTE_STRING(isolate,
27871cb0ef41Sopenharmony_ci                        "FileHandleCloseReq"));
27881cb0ef41Sopenharmony_ci  fdclose->Inherit(AsyncWrap::GetConstructorTemplate(env));
27891cb0ef41Sopenharmony_ci  Local<ObjectTemplate> fdcloset = fdclose->InstanceTemplate();
27901cb0ef41Sopenharmony_ci  fdcloset->SetInternalFieldCount(FSReqBase::kInternalFieldCount);
27911cb0ef41Sopenharmony_ci  env->set_fdclose_constructor_template(fdcloset);
27921cb0ef41Sopenharmony_ci
27931cb0ef41Sopenharmony_ci  target->Set(context,
27941cb0ef41Sopenharmony_ci              FIXED_ONE_BYTE_STRING(isolate, "kUsePromises"),
27951cb0ef41Sopenharmony_ci              env->fs_use_promises_symbol()).Check();
27961cb0ef41Sopenharmony_ci}
27971cb0ef41Sopenharmony_ci
27981cb0ef41Sopenharmony_ciBindingData* FSReqBase::binding_data() {
27991cb0ef41Sopenharmony_ci  return binding_data_.get();
28001cb0ef41Sopenharmony_ci}
28011cb0ef41Sopenharmony_ci
28021cb0ef41Sopenharmony_civoid RegisterExternalReferences(ExternalReferenceRegistry* registry) {
28031cb0ef41Sopenharmony_ci  registry->Register(Access);
28041cb0ef41Sopenharmony_ci  StatWatcher::RegisterExternalReferences(registry);
28051cb0ef41Sopenharmony_ci
28061cb0ef41Sopenharmony_ci  registry->Register(Close);
28071cb0ef41Sopenharmony_ci  registry->Register(Open);
28081cb0ef41Sopenharmony_ci  registry->Register(OpenFileHandle);
28091cb0ef41Sopenharmony_ci  registry->Register(Read);
28101cb0ef41Sopenharmony_ci  registry->Register(ReadBuffers);
28111cb0ef41Sopenharmony_ci  registry->Register(Fdatasync);
28121cb0ef41Sopenharmony_ci  registry->Register(Fsync);
28131cb0ef41Sopenharmony_ci  registry->Register(Rename);
28141cb0ef41Sopenharmony_ci  registry->Register(FTruncate);
28151cb0ef41Sopenharmony_ci  registry->Register(RMDir);
28161cb0ef41Sopenharmony_ci  registry->Register(MKDir);
28171cb0ef41Sopenharmony_ci  registry->Register(ReadDir);
28181cb0ef41Sopenharmony_ci  registry->Register(InternalModuleReadJSON);
28191cb0ef41Sopenharmony_ci  registry->Register(InternalModuleStat);
28201cb0ef41Sopenharmony_ci  registry->Register(Stat);
28211cb0ef41Sopenharmony_ci  registry->Register(LStat);
28221cb0ef41Sopenharmony_ci  registry->Register(FStat);
28231cb0ef41Sopenharmony_ci  registry->Register(StatFs);
28241cb0ef41Sopenharmony_ci  registry->Register(Link);
28251cb0ef41Sopenharmony_ci  registry->Register(Symlink);
28261cb0ef41Sopenharmony_ci  registry->Register(ReadLink);
28271cb0ef41Sopenharmony_ci  registry->Register(Unlink);
28281cb0ef41Sopenharmony_ci  registry->Register(WriteBuffer);
28291cb0ef41Sopenharmony_ci  registry->Register(WriteBuffers);
28301cb0ef41Sopenharmony_ci  registry->Register(WriteString);
28311cb0ef41Sopenharmony_ci  registry->Register(RealPath);
28321cb0ef41Sopenharmony_ci  registry->Register(CopyFile);
28331cb0ef41Sopenharmony_ci
28341cb0ef41Sopenharmony_ci  registry->Register(Chmod);
28351cb0ef41Sopenharmony_ci  registry->Register(FChmod);
28361cb0ef41Sopenharmony_ci
28371cb0ef41Sopenharmony_ci  registry->Register(Chown);
28381cb0ef41Sopenharmony_ci  registry->Register(FChown);
28391cb0ef41Sopenharmony_ci  registry->Register(LChown);
28401cb0ef41Sopenharmony_ci
28411cb0ef41Sopenharmony_ci  registry->Register(UTimes);
28421cb0ef41Sopenharmony_ci  registry->Register(FUTimes);
28431cb0ef41Sopenharmony_ci  registry->Register(LUTimes);
28441cb0ef41Sopenharmony_ci
28451cb0ef41Sopenharmony_ci  registry->Register(Mkdtemp);
28461cb0ef41Sopenharmony_ci  registry->Register(NewFSReqCallback);
28471cb0ef41Sopenharmony_ci
28481cb0ef41Sopenharmony_ci  registry->Register(FileHandle::New);
28491cb0ef41Sopenharmony_ci  registry->Register(FileHandle::Close);
28501cb0ef41Sopenharmony_ci  registry->Register(FileHandle::ReleaseFD);
28511cb0ef41Sopenharmony_ci  StreamBase::RegisterExternalReferences(registry);
28521cb0ef41Sopenharmony_ci}
28531cb0ef41Sopenharmony_ci
28541cb0ef41Sopenharmony_ci}  // namespace fs
28551cb0ef41Sopenharmony_ci
28561cb0ef41Sopenharmony_ci}  // end namespace node
28571cb0ef41Sopenharmony_ci
28581cb0ef41Sopenharmony_ciNODE_BINDING_CONTEXT_AWARE_INTERNAL(fs, node::fs::Initialize)
28591cb0ef41Sopenharmony_ciNODE_BINDING_EXTERNAL_REFERENCE(fs, node::fs::RegisterExternalReferences)
2860