%PDF- %PDF-
Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/src/ |
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/src/node_file.h |
#ifndef SRC_NODE_FILE_H_ #define SRC_NODE_FILE_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include <optional> #include "aliased_buffer.h" #include "node_messaging.h" #include "node_snapshotable.h" #include "stream_base.h" namespace node { namespace fs { class FileHandleReadWrap; enum class FsStatsOffset { kDev = 0, kMode, kNlink, kUid, kGid, kRdev, kBlkSize, kIno, kSize, kBlocks, kATimeSec, kATimeNsec, kMTimeSec, kMTimeNsec, kCTimeSec, kCTimeNsec, kBirthTimeSec, kBirthTimeNsec, kFsStatsFieldsNumber }; // Stat fields buffers contain twice the number of entries in an uv_stat_t // because `fs.StatWatcher` needs room to store 2 `fs.Stats` instances. constexpr size_t kFsStatsBufferLength = static_cast<size_t>(FsStatsOffset::kFsStatsFieldsNumber) * 2; enum class FsStatFsOffset { kType = 0, kBSize, kBlocks, kBFree, kBAvail, kFiles, kFFree, kFsStatFsFieldsNumber }; constexpr size_t kFsStatFsBufferLength = static_cast<size_t>(FsStatFsOffset::kFsStatFsFieldsNumber); class BindingData : public SnapshotableObject { public: struct InternalFieldInfo : public node::InternalFieldInfoBase { AliasedBufferIndex stats_field_array; AliasedBufferIndex stats_field_bigint_array; AliasedBufferIndex statfs_field_array; AliasedBufferIndex statfs_field_bigint_array; }; enum class FilePathIsFileReturnType { kIsFile = 0, kIsNotFile, kThrowInsufficientPermissions }; explicit BindingData(Realm* realm, v8::Local<v8::Object> wrap, InternalFieldInfo* info = nullptr); AliasedFloat64Array stats_field_array; AliasedBigInt64Array stats_field_bigint_array; AliasedFloat64Array statfs_field_array; AliasedBigInt64Array statfs_field_bigint_array; std::vector<BaseObjectPtr<FileHandleReadWrap>> file_handle_read_wrap_freelist; SERIALIZABLE_OBJECT_METHODS() SET_BINDING_ID(fs_binding_data) static void LegacyMainResolve( const v8::FunctionCallbackInfo<v8::Value>& args); static void CreatePerIsolateProperties(IsolateData* isolate_data, v8::Local<v8::ObjectTemplate> ctor); static void RegisterExternalReferences(ExternalReferenceRegistry* registry); void MemoryInfo(MemoryTracker* tracker) const override; SET_SELF_SIZE(BindingData) SET_MEMORY_INFO_NAME(BindingData) private: InternalFieldInfo* internal_field_info_ = nullptr; static FilePathIsFileReturnType FilePathIsFile(Environment* env, const std::string& file_path); }; // structure used to store state during a complex operation, e.g., mkdirp. class FSContinuationData : public MemoryRetainer { public: inline FSContinuationData(uv_fs_t* req, int mode, uv_fs_cb done_cb); inline void PushPath(std::string&& path); inline void PushPath(const std::string& path); inline std::string PopPath(); // Used by mkdirp to track the first path created: inline void MaybeSetFirstPath(const std::string& path); inline void Done(int result); int mode() const { return mode_; } const std::vector<std::string>& paths() const { return paths_; } const std::string& first_path() const { return first_path_; } void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(FSContinuationData) SET_SELF_SIZE(FSContinuationData) private: uv_fs_cb done_cb_; uv_fs_t* req_; int mode_; std::vector<std::string> paths_; std::string first_path_; }; class FSReqBase : public ReqWrap<uv_fs_t> { public: typedef MaybeStackBuffer<char, 64> FSReqBuffer; inline FSReqBase(BindingData* binding_data, v8::Local<v8::Object> req, AsyncWrap::ProviderType type, bool use_bigint); ~FSReqBase() override; inline void Init(const char* syscall, const char* data, size_t len, enum encoding encoding); inline FSReqBuffer& Init(const char* syscall, size_t len, enum encoding encoding); virtual void Reject(v8::Local<v8::Value> reject) = 0; virtual void Resolve(v8::Local<v8::Value> value) = 0; virtual void ResolveStat(const uv_stat_t* stat) = 0; virtual void ResolveStatFs(const uv_statfs_t* stat) = 0; virtual void SetReturnValue( const v8::FunctionCallbackInfo<v8::Value>& args) = 0; const char* syscall() const { return syscall_; } const char* data() const { return has_data_ ? *buffer_ : nullptr; } enum encoding encoding() const { return encoding_; } bool use_bigint() const { return use_bigint_; } bool is_plain_open() const { return is_plain_open_; } bool with_file_types() const { return with_file_types_; } void set_is_plain_open(bool value) { is_plain_open_ = value; } void set_with_file_types(bool value) { with_file_types_ = value; } FSContinuationData* continuation_data() const { return continuation_data_.get(); } void set_continuation_data(std::unique_ptr<FSContinuationData> data) { continuation_data_ = std::move(data); } static FSReqBase* from_req(uv_fs_t* req) { return static_cast<FSReqBase*>(ReqWrap::from_req(req)); } FSReqBase(const FSReqBase&) = delete; FSReqBase& operator=(const FSReqBase&) = delete; void MemoryInfo(MemoryTracker* tracker) const override; BindingData* binding_data(); private: std::unique_ptr<FSContinuationData> continuation_data_; enum encoding encoding_ = UTF8; bool has_data_ = false; bool use_bigint_ = false; bool is_plain_open_ = false; bool with_file_types_ = false; const char* syscall_ = nullptr; BaseObjectPtr<BindingData> binding_data_; // Typically, the content of buffer_ is something like a file name, so // something around 64 bytes should be enough. FSReqBuffer buffer_; }; class FSReqCallback final : public FSReqBase { public: inline FSReqCallback(BindingData* binding_data, v8::Local<v8::Object> req, bool use_bigint); void Reject(v8::Local<v8::Value> reject) override; void Resolve(v8::Local<v8::Value> value) override; void ResolveStat(const uv_stat_t* stat) override; void ResolveStatFs(const uv_statfs_t* stat) override; void SetReturnValue(const v8::FunctionCallbackInfo<v8::Value>& args) override; SET_MEMORY_INFO_NAME(FSReqCallback) SET_SELF_SIZE(FSReqCallback) FSReqCallback(const FSReqCallback&) = delete; FSReqCallback& operator=(const FSReqCallback&) = delete; }; template <typename NativeT, typename V8T> void FillStatsArray(AliasedBufferBase<NativeT, V8T>* fields, const uv_stat_t* s, const size_t offset = 0); inline v8::Local<v8::Value> FillGlobalStatsArray(BindingData* binding_data, const bool use_bigint, const uv_stat_t* s, const bool second = false); template <typename NativeT, typename V8T> void FillStatFsArray(AliasedBufferBase<NativeT, V8T>* fields, const uv_statfs_t* s); inline v8::Local<v8::Value> FillGlobalStatFsArray(BindingData* binding_data, const bool use_bigint, const uv_statfs_t* s); template <typename AliasedBufferT> class FSReqPromise final : public FSReqBase { public: static inline FSReqPromise* New(BindingData* binding_data, bool use_bigint); inline ~FSReqPromise() override; inline void Reject(v8::Local<v8::Value> reject) override; inline void Resolve(v8::Local<v8::Value> value) override; inline void ResolveStat(const uv_stat_t* stat) override; inline void ResolveStatFs(const uv_statfs_t* stat) override; inline void SetReturnValue( const v8::FunctionCallbackInfo<v8::Value>& args) override; inline void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(FSReqPromise) SET_SELF_SIZE(FSReqPromise) FSReqPromise(const FSReqPromise&) = delete; FSReqPromise& operator=(const FSReqPromise&) = delete; FSReqPromise(const FSReqPromise&&) = delete; FSReqPromise& operator=(const FSReqPromise&&) = delete; private: inline FSReqPromise(BindingData* binding_data, v8::Local<v8::Object> obj, bool use_bigint); bool finished_ = false; AliasedBufferT stats_field_array_; AliasedBufferT statfs_field_array_; }; class FSReqAfterScope final { public: FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req); ~FSReqAfterScope(); void Clear(); bool Proceed(); void Reject(uv_fs_t* req); FSReqAfterScope(const FSReqAfterScope&) = delete; FSReqAfterScope& operator=(const FSReqAfterScope&) = delete; FSReqAfterScope(const FSReqAfterScope&&) = delete; FSReqAfterScope& operator=(const FSReqAfterScope&&) = delete; private: BaseObjectPtr<FSReqBase> wrap_; uv_fs_t* req_ = nullptr; v8::HandleScope handle_scope_; v8::Context::Scope context_scope_; }; class FileHandle; // A request wrap specifically for uv_fs_read()s scheduled for reading // from a FileHandle. class FileHandleReadWrap final : public ReqWrap<uv_fs_t> { public: FileHandleReadWrap(FileHandle* handle, v8::Local<v8::Object> obj); ~FileHandleReadWrap() override; static inline FileHandleReadWrap* from_req(uv_fs_t* req) { return static_cast<FileHandleReadWrap*>(ReqWrap::from_req(req)); } void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(FileHandleReadWrap) SET_SELF_SIZE(FileHandleReadWrap) private: FileHandle* file_handle_; uv_buf_t buffer_; friend class FileHandle; }; // A wrapper for a file descriptor that will automatically close the fd when // the object is garbage collected class FileHandle final : public AsyncWrap, public StreamBase { public: enum InternalFields { kFileHandleBaseField = StreamBase::kInternalFieldCount, kClosingPromiseSlot, kInternalFieldCount }; static FileHandle* New(BindingData* binding_data, int fd, v8::Local<v8::Object> obj = v8::Local<v8::Object>(), std::optional<int64_t> maybeOffset = std::nullopt, std::optional<int64_t> maybeLength = std::nullopt); ~FileHandle() override; static void New(const v8::FunctionCallbackInfo<v8::Value>& args); int GetFD() override { return fd_; } int Release(); // Will asynchronously close the FD and return a Promise that will // be resolved once closing is complete. static void Close(const v8::FunctionCallbackInfo<v8::Value>& args); // Releases ownership of the FD. static void ReleaseFD(const v8::FunctionCallbackInfo<v8::Value>& args); // StreamBase interface: int ReadStart() override; int ReadStop() override; bool IsAlive() override { return !closed_; } bool IsClosing() override { return closing_; } AsyncWrap* GetAsyncWrap() override { return this; } // In the case of file streams, shutting down corresponds to closing. ShutdownWrap* CreateShutdownWrap(v8::Local<v8::Object> object) override; int DoShutdown(ShutdownWrap* req_wrap) override; int DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count, uv_stream_t* send_handle) override; void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(FileHandle) SET_SELF_SIZE(FileHandle) FileHandle(const FileHandle&) = delete; FileHandle& operator=(const FileHandle&) = delete; FileHandle(const FileHandle&&) = delete; FileHandle& operator=(const FileHandle&&) = delete; BaseObject::TransferMode GetTransferMode() const override; std::unique_ptr<worker::TransferData> TransferForMessaging() override; private: class TransferData : public worker::TransferData { public: explicit TransferData(int fd); ~TransferData(); BaseObjectPtr<BaseObject> Deserialize( Environment* env, v8::Local<v8::Context> context, std::unique_ptr<worker::TransferData> self) override; SET_NO_MEMORY_INFO() SET_MEMORY_INFO_NAME(FileHandleTransferData) SET_SELF_SIZE(TransferData) private: int fd_; }; FileHandle(BindingData* binding_data, v8::Local<v8::Object> obj, int fd); // Synchronous close that emits a warning void Close(); void AfterClose(); class CloseReq final : public ReqWrap<uv_fs_t> { public: CloseReq(Environment* env, v8::Local<v8::Object> obj, v8::Local<v8::Promise> promise, v8::Local<v8::Value> ref); ~CloseReq() override; FileHandle* file_handle(); void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(CloseReq) SET_SELF_SIZE(CloseReq) void Resolve(); void Reject(v8::Local<v8::Value> reason); static CloseReq* from_req(uv_fs_t* req) { return static_cast<CloseReq*>(ReqWrap::from_req(req)); } CloseReq(const CloseReq&) = delete; CloseReq& operator=(const CloseReq&) = delete; CloseReq(const CloseReq&&) = delete; CloseReq& operator=(const CloseReq&&) = delete; private: v8::Global<v8::Promise> promise_{}; v8::Global<v8::Value> ref_{}; }; // Asynchronous close v8::MaybeLocal<v8::Promise> ClosePromise(); int fd_; bool closing_ = false; bool closed_ = false; bool reading_ = false; int64_t read_offset_ = -1; int64_t read_length_ = -1; BaseObjectPtr<FileHandleReadWrap> current_read_; BaseObjectPtr<BindingData> binding_data_; }; int MKDirpSync(uv_loop_t* loop, uv_fs_t* req, const std::string& path, int mode, uv_fs_cb cb = nullptr); class FSReqWrapSync { public: FSReqWrapSync(const char* syscall = nullptr, const char* path = nullptr, const char* dest = nullptr) : syscall_p(syscall), path_p(path), dest_p(dest) {} ~FSReqWrapSync() { uv_fs_req_cleanup(&req); } uv_fs_t req; const char* syscall_p; const char* path_p; const char* dest_p; FSReqWrapSync(const FSReqWrapSync&) = delete; FSReqWrapSync& operator=(const FSReqWrapSync&) = delete; // TODO(joyeecheung): move these out of FSReqWrapSync and into a special // class for mkdirp FSContinuationData* continuation_data() const { return continuation_data_.get(); } void set_continuation_data(std::unique_ptr<FSContinuationData> data) { continuation_data_ = std::move(data); } private: std::unique_ptr<FSContinuationData> continuation_data_; }; // TODO(addaleax): Currently, callers check the return value and assume // that nullptr indicates a synchronous call, rather than a failure. // Failure conditions should be disambiguated and handled appropriately. inline FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo<v8::Value>& args, int index, bool use_bigint = false); // Returns nullptr if the operation fails from the start. template <typename Func, typename... Args> inline FSReqBase* AsyncDestCall(Environment* env, FSReqBase* req_wrap, const v8::FunctionCallbackInfo<v8::Value>& args, const char* syscall, const char* dest, size_t len, enum encoding enc, uv_fs_cb after, Func fn, Args... fn_args); // Returns nullptr if the operation fails from the start. template <typename Func, typename... Args> inline FSReqBase* AsyncCall(Environment* env, FSReqBase* req_wrap, const v8::FunctionCallbackInfo<v8::Value>& args, const char* syscall, enum encoding enc, uv_fs_cb after, Func fn, Args... fn_args); // Template counterpart of SYNC_CALL, except that it only puts // the error number and the syscall in the context instead of // creating an error in the C++ land. // ctx must be checked using value->IsObject() before being passed. template <typename Func, typename... Args> inline int SyncCall(Environment* env, v8::Local<v8::Value> ctx, FSReqWrapSync* req_wrap, const char* syscall, Func fn, Args... args); // Similar to SyncCall but throws immediately if there is an error. template <typename Predicate, typename Func, typename... Args> int SyncCallAndThrowIf(Predicate should_throw, Environment* env, FSReqWrapSync* req_wrap, Func fn, Args... args); template <typename Func, typename... Args> int SyncCallAndThrowOnError(Environment* env, FSReqWrapSync* req_wrap, Func fn, Args... args); } // namespace fs } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_FILE_H_