Viewing file: node_file.h (12.2 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#ifndef SRC_NODE_FILE_H_ #define SRC_NODE_FILE_H_
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#include "node.h" #include "aliased_buffer.h" #include "node_messaging.h" #include "stream_base.h" #include <iostream>
namespace node { namespace fs {
// 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(Environment* env, 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 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_; }
void set_is_plain_open(bool value) { is_plain_open_ = 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;
private: std::unique_ptr<FSContinuationData> continuation_data_; enum encoding encoding_ = UTF8; bool has_data_ = false; bool use_bigint_ = false; bool is_plain_open_ = false; const char* syscall_ = nullptr;
// 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(Environment* env, 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 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(Environment* env, const bool use_bigint, const uv_stat_t* s, const bool second = false);
template <typename AliasedBufferT> class FSReqPromise final : public FSReqBase { public: static inline FSReqPromise* New(Environment* env, 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 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(Environment* env, v8::Local<v8::Object> obj, bool use_bigint);
bool finished_ = false; AliasedBufferT stats_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: static FileHandle* New(Environment* env, int fd, v8::Local<v8::Object> obj = v8::Local<v8::Object>()); ~FileHandle() override;
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
int GetFD() override { return fd_; }
// 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;
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(Environment* env, 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; int64_t read_offset_ = -1; int64_t read_length_ = -1;
bool reading_ = false; std::unique_ptr<FileHandleReadWrap> current_read_ = nullptr; };
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() = default; ~FSReqWrapSync() { uv_fs_req_cleanup(&req); } uv_fs_t req;
FSContinuationData* continuation_data() const { return continuation_data_.get(); } void set_continuation_data(std::unique_ptr<FSContinuationData> data) { continuation_data_ = std::move(data); }
FSReqWrapSync(const FSReqWrapSync&) = delete; FSReqWrapSync& operator=(const FSReqWrapSync&) = delete;
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(Environment* env, v8::Local<v8::Value> value, 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);
} // namespace fs
} // namespace node
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#endif // SRC_NODE_FILE_H_
|