Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/nodejs/src/node_file.h
1 #ifndef SRC_NODE_FILE_H_ 2 #define SRC_NODE_FILE_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include <optional> 7 #include "aliased_buffer.h" 8 #include "node_messaging.h" 9 #include "node_snapshotable.h" 10 #include "stream_base.h" 11 12 namespace node { 13 namespace fs { 14 15 class FileHandleReadWrap; 16 17 enum class FsStatsOffset { 18 kDev = 0, 19 kMode, 20 kNlink, 21 kUid, 22 kGid, 23 kRdev, 24 kBlkSize, 25 kIno, 26 kSize, 27 kBlocks, 28 kATimeSec, 29 kATimeNsec, 30 kMTimeSec, 31 kMTimeNsec, 32 kCTimeSec, 33 kCTimeNsec, 34 kBirthTimeSec, 35 kBirthTimeNsec, 36 kFsStatsFieldsNumber 37 }; 38 39 // Stat fields buffers contain twice the number of entries in an uv_stat_t 40 // because `fs.StatWatcher` needs room to store 2 `fs.Stats` instances. 41 constexpr size_t kFsStatsBufferLength = 42 static_cast<size_t>(FsStatsOffset::kFsStatsFieldsNumber) * 2; 43 44 enum class FsStatFsOffset { 45 kType = 0, 46 kBSize, 47 kBlocks, 48 kBFree, 49 kBAvail, 50 kFiles, 51 kFFree, 52 kFsStatFsFieldsNumber 53 }; 54 55 constexpr size_t kFsStatFsBufferLength = 56 static_cast<size_t>(FsStatFsOffset::kFsStatFsFieldsNumber); 57 58 class BindingData : public SnapshotableObject { 59 public: 60 struct InternalFieldInfo : public node::InternalFieldInfoBase { 61 AliasedBufferIndex stats_field_array; 62 AliasedBufferIndex stats_field_bigint_array; 63 AliasedBufferIndex statfs_field_array; 64 AliasedBufferIndex statfs_field_bigint_array; 65 }; 66 67 enum class FilePathIsFileReturnType { 68 kIsFile = 0, 69 kIsNotFile, 70 kThrowInsufficientPermissions 71 }; 72 73 explicit BindingData(Realm* realm, 74 v8::Local<v8::Object> wrap, 75 InternalFieldInfo* info = nullptr); 76 77 AliasedFloat64Array stats_field_array; 78 AliasedBigInt64Array stats_field_bigint_array; 79 80 AliasedFloat64Array statfs_field_array; 81 AliasedBigInt64Array statfs_field_bigint_array; 82 83 std::vector<BaseObjectPtr<FileHandleReadWrap>> 84 file_handle_read_wrap_freelist; 85 86 SERIALIZABLE_OBJECT_METHODS() 87 SET_BINDING_ID(fs_binding_data) 88 89 static void LegacyMainResolve( 90 const v8::FunctionCallbackInfo<v8::Value>& args); 91 92 static void CreatePerIsolateProperties(IsolateData* isolate_data, 93 v8::Local<v8::ObjectTemplate> ctor); 94 static void RegisterExternalReferences(ExternalReferenceRegistry* registry); 95 96 void MemoryInfo(MemoryTracker* tracker) const override; 97 SET_SELF_SIZE(BindingData) 98 SET_MEMORY_INFO_NAME(BindingData) 99 100 private: 101 InternalFieldInfo* internal_field_info_ = nullptr; 102 103 static FilePathIsFileReturnType FilePathIsFile(Environment* env, 104 const std::string& file_path); 105 }; 106 107 // structure used to store state during a complex operation, e.g., mkdirp. 108 class FSContinuationData : public MemoryRetainer { 109 public: 110 inline FSContinuationData(uv_fs_t* req, int mode, uv_fs_cb done_cb); 111 112 inline void PushPath(std::string&& path); 113 inline void PushPath(const std::string& path); 114 inline std::string PopPath(); 115 // Used by mkdirp to track the first path created: 116 inline void MaybeSetFirstPath(const std::string& path); 117 inline void Done(int result); 118 119 int mode() const { return mode_; } 120 const std::vector<std::string>& paths() const { return paths_; } 121 const std::string& first_path() const { return first_path_; } 122 123 void MemoryInfo(MemoryTracker* tracker) const override; 124 SET_MEMORY_INFO_NAME(FSContinuationData) 125 SET_SELF_SIZE(FSContinuationData) 126 127 private: 128 uv_fs_cb done_cb_; 129 uv_fs_t* req_; 130 int mode_; 131 std::vector<std::string> paths_; 132 std::string first_path_; 133 }; 134 135 class FSReqBase : public ReqWrap<uv_fs_t> { 136 public: 137 typedef MaybeStackBuffer<char, 64> FSReqBuffer; 138 139 inline FSReqBase(BindingData* binding_data, 140 v8::Local<v8::Object> req, 141 AsyncWrap::ProviderType type, 142 bool use_bigint); 143 ~FSReqBase() override; 144 145 inline void Init(const char* syscall, 146 const char* data, 147 size_t len, 148 enum encoding encoding); 149 inline FSReqBuffer& Init(const char* syscall, size_t len, 150 enum encoding encoding); 151 152 virtual void Reject(v8::Local<v8::Value> reject) = 0; 153 virtual void Resolve(v8::Local<v8::Value> value) = 0; 154 virtual void ResolveStat(const uv_stat_t* stat) = 0; 155 virtual void ResolveStatFs(const uv_statfs_t* stat) = 0; 156 virtual void SetReturnValue( 157 const v8::FunctionCallbackInfo<v8::Value>& args) = 0; 158 159 const char* syscall() const { return syscall_; } 160 const char* data() const { return has_data_ ? *buffer_ : nullptr; } 161 enum encoding encoding() const { return encoding_; } 162 bool use_bigint() const { return use_bigint_; } 163 bool is_plain_open() const { return is_plain_open_; } 164 bool with_file_types() const { return with_file_types_; } 165 166 void set_is_plain_open(bool value) { is_plain_open_ = value; } 167 void set_with_file_types(bool value) { with_file_types_ = value; } 168 169 FSContinuationData* continuation_data() const { 170 return continuation_data_.get(); 171 } 172 void set_continuation_data(std::unique_ptr<FSContinuationData> data) { 173 continuation_data_ = std::move(data); 174 } 175 176 static FSReqBase* from_req(uv_fs_t* req) { 177 return static_cast<FSReqBase*>(ReqWrap::from_req(req)); 178 } 179 180 FSReqBase(const FSReqBase&) = delete; 181 FSReqBase& operator=(const FSReqBase&) = delete; 182 183 void MemoryInfo(MemoryTracker* tracker) const override; 184 185 BindingData* binding_data(); 186 187 private: 188 std::unique_ptr<FSContinuationData> continuation_data_; 189 enum encoding encoding_ = UTF8; 190 bool has_data_ = false; 191 bool use_bigint_ = false; 192 bool is_plain_open_ = false; 193 bool with_file_types_ = false; 194 const char* syscall_ = nullptr; 195 196 BaseObjectPtr<BindingData> binding_data_; 197 198 // Typically, the content of buffer_ is something like a file name, so 199 // something around 64 bytes should be enough. 200 FSReqBuffer buffer_; 201 }; 202 203 class FSReqCallback final : public FSReqBase { 204 public: 205 inline FSReqCallback(BindingData* binding_data, 206 v8::Local<v8::Object> req, 207 bool use_bigint); 208 209 void Reject(v8::Local<v8::Value> reject) override; 210 void Resolve(v8::Local<v8::Value> value) override; 211 void ResolveStat(const uv_stat_t* stat) override; 212 void ResolveStatFs(const uv_statfs_t* stat) override; 213 void SetReturnValue(const v8::FunctionCallbackInfo<v8::Value>& args) override; 214 215 SET_MEMORY_INFO_NAME(FSReqCallback) 216 SET_SELF_SIZE(FSReqCallback) 217 218 FSReqCallback(const FSReqCallback&) = delete; 219 FSReqCallback& operator=(const FSReqCallback&) = delete; 220 }; 221 222 template <typename NativeT, typename V8T> 223 void FillStatsArray(AliasedBufferBase<NativeT, V8T>* fields, 224 const uv_stat_t* s, 225 const size_t offset = 0); 226 227 inline v8::Local<v8::Value> FillGlobalStatsArray(BindingData* binding_data, 228 const bool use_bigint, 229 const uv_stat_t* s, 230 const bool second = false); 231 232 template <typename NativeT, typename V8T> 233 void FillStatFsArray(AliasedBufferBase<NativeT, V8T>* fields, 234 const uv_statfs_t* s); 235 236 inline v8::Local<v8::Value> FillGlobalStatFsArray(BindingData* binding_data, 237 const bool use_bigint, 238 const uv_statfs_t* s); 239 240 template <typename AliasedBufferT> 241 class FSReqPromise final : public FSReqBase { 242 public: 243 static inline FSReqPromise* New(BindingData* binding_data, 244 bool use_bigint); 245 inline ~FSReqPromise() override; 246 247 inline void Reject(v8::Local<v8::Value> reject) override; 248 inline void Resolve(v8::Local<v8::Value> value) override; 249 inline void ResolveStat(const uv_stat_t* stat) override; 250 inline void ResolveStatFs(const uv_statfs_t* stat) override; 251 inline void SetReturnValue( 252 const v8::FunctionCallbackInfo<v8::Value>& args) override; 253 inline void MemoryInfo(MemoryTracker* tracker) const override; 254 255 SET_MEMORY_INFO_NAME(FSReqPromise) 256 SET_SELF_SIZE(FSReqPromise) 257 258 FSReqPromise(const FSReqPromise&) = delete; 259 FSReqPromise& operator=(const FSReqPromise&) = delete; 260 FSReqPromise(const FSReqPromise&&) = delete; 261 FSReqPromise& operator=(const FSReqPromise&&) = delete; 262 263 private: 264 inline FSReqPromise(BindingData* binding_data, 265 v8::Local<v8::Object> obj, 266 bool use_bigint); 267 268 bool finished_ = false; 269 AliasedBufferT stats_field_array_; 270 AliasedBufferT statfs_field_array_; 271 }; 272 273 class FSReqAfterScope final { 274 public: 275 FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req); 276 ~FSReqAfterScope(); 277 void Clear(); 278 279 bool Proceed(); 280 281 void Reject(uv_fs_t* req); 282 283 FSReqAfterScope(const FSReqAfterScope&) = delete; 284 FSReqAfterScope& operator=(const FSReqAfterScope&) = delete; 285 FSReqAfterScope(const FSReqAfterScope&&) = delete; 286 FSReqAfterScope& operator=(const FSReqAfterScope&&) = delete; 287 288 private: 289 BaseObjectPtr<FSReqBase> wrap_; 290 uv_fs_t* req_ = nullptr; 291 v8::HandleScope handle_scope_; 292 v8::Context::Scope context_scope_; 293 }; 294 295 class FileHandle; 296 297 // A request wrap specifically for uv_fs_read()s scheduled for reading 298 // from a FileHandle. 299 class FileHandleReadWrap final : public ReqWrap<uv_fs_t> { 300 public: 301 FileHandleReadWrap(FileHandle* handle, v8::Local<v8::Object> obj); 302 ~FileHandleReadWrap() override; 303 304 static inline FileHandleReadWrap* from_req(uv_fs_t* req) { 305 return static_cast<FileHandleReadWrap*>(ReqWrap::from_req(req)); 306 } 307 308 void MemoryInfo(MemoryTracker* tracker) const override; 309 SET_MEMORY_INFO_NAME(FileHandleReadWrap) 310 SET_SELF_SIZE(FileHandleReadWrap) 311 312 private: 313 FileHandle* file_handle_; 314 uv_buf_t buffer_; 315 316 friend class FileHandle; 317 }; 318 319 // A wrapper for a file descriptor that will automatically close the fd when 320 // the object is garbage collected 321 class FileHandle final : public AsyncWrap, public StreamBase { 322 public: 323 enum InternalFields { 324 kFileHandleBaseField = StreamBase::kInternalFieldCount, 325 kClosingPromiseSlot, 326 kInternalFieldCount 327 }; 328 329 static FileHandle* New(BindingData* binding_data, 330 int fd, 331 v8::Local<v8::Object> obj = v8::Local<v8::Object>(), 332 std::optional<int64_t> maybeOffset = std::nullopt, 333 std::optional<int64_t> maybeLength = std::nullopt); 334 ~FileHandle() override; 335 336 static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 337 338 int GetFD() override { return fd_; } 339 340 int Release(); 341 342 // Will asynchronously close the FD and return a Promise that will 343 // be resolved once closing is complete. 344 static void Close(const v8::FunctionCallbackInfo<v8::Value>& args); 345 346 // Releases ownership of the FD. 347 static void ReleaseFD(const v8::FunctionCallbackInfo<v8::Value>& args); 348 349 // StreamBase interface: 350 int ReadStart() override; 351 int ReadStop() override; 352 353 bool IsAlive() override { return !closed_; } 354 bool IsClosing() override { return closing_; } 355 AsyncWrap* GetAsyncWrap() override { return this; } 356 357 // In the case of file streams, shutting down corresponds to closing. 358 ShutdownWrap* CreateShutdownWrap(v8::Local<v8::Object> object) override; 359 int DoShutdown(ShutdownWrap* req_wrap) override; 360 361 int DoWrite(WriteWrap* w, 362 uv_buf_t* bufs, 363 size_t count, 364 uv_stream_t* send_handle) override; 365 366 void MemoryInfo(MemoryTracker* tracker) const override; 367 368 SET_MEMORY_INFO_NAME(FileHandle) 369 SET_SELF_SIZE(FileHandle) 370 371 FileHandle(const FileHandle&) = delete; 372 FileHandle& operator=(const FileHandle&) = delete; 373 FileHandle(const FileHandle&&) = delete; 374 FileHandle& operator=(const FileHandle&&) = delete; 375 376 BaseObject::TransferMode GetTransferMode() const override; 377 std::unique_ptr<worker::TransferData> TransferForMessaging() override; 378 379 private: 380 class TransferData : public worker::TransferData { 381 public: 382 explicit TransferData(int fd); 383 ~TransferData(); 384 385 BaseObjectPtr<BaseObject> Deserialize( 386 Environment* env, 387 v8::Local<v8::Context> context, 388 std::unique_ptr<worker::TransferData> self) override; 389 390 SET_NO_MEMORY_INFO() 391 SET_MEMORY_INFO_NAME(FileHandleTransferData) 392 SET_SELF_SIZE(TransferData) 393 394 private: 395 int fd_; 396 }; 397 398 FileHandle(BindingData* binding_data, v8::Local<v8::Object> obj, int fd); 399 400 // Synchronous close that emits a warning 401 void Close(); 402 void AfterClose(); 403 404 class CloseReq final : public ReqWrap<uv_fs_t> { 405 public: 406 CloseReq(Environment* env, 407 v8::Local<v8::Object> obj, 408 v8::Local<v8::Promise> promise, 409 v8::Local<v8::Value> ref); 410 ~CloseReq() override; 411 412 FileHandle* file_handle(); 413 414 void MemoryInfo(MemoryTracker* tracker) const override; 415 416 SET_MEMORY_INFO_NAME(CloseReq) 417 SET_SELF_SIZE(CloseReq) 418 419 void Resolve(); 420 421 void Reject(v8::Local<v8::Value> reason); 422 423 static CloseReq* from_req(uv_fs_t* req) { 424 return static_cast<CloseReq*>(ReqWrap::from_req(req)); 425 } 426 427 CloseReq(const CloseReq&) = delete; 428 CloseReq& operator=(const CloseReq&) = delete; 429 CloseReq(const CloseReq&&) = delete; 430 CloseReq& operator=(const CloseReq&&) = delete; 431 432 private: 433 v8::Global<v8::Promise> promise_{}; 434 v8::Global<v8::Value> ref_{}; 435 }; 436 437 // Asynchronous close 438 v8::MaybeLocal<v8::Promise> ClosePromise(); 439 440 int fd_; 441 bool closing_ = false; 442 bool closed_ = false; 443 bool reading_ = false; 444 int64_t read_offset_ = -1; 445 int64_t read_length_ = -1; 446 447 BaseObjectPtr<FileHandleReadWrap> current_read_; 448 449 BaseObjectPtr<BindingData> binding_data_; 450 }; 451 452 int MKDirpSync(uv_loop_t* loop, 453 uv_fs_t* req, 454 const std::string& path, 455 int mode, 456 uv_fs_cb cb = nullptr); 457 458 class FSReqWrapSync { 459 public: 460 FSReqWrapSync(const char* syscall = nullptr, 461 const char* path = nullptr, 462 const char* dest = nullptr) 463 : syscall_p(syscall), path_p(path), dest_p(dest) {} 464 ~FSReqWrapSync() { uv_fs_req_cleanup(&req); } 465 466 uv_fs_t req; 467 const char* syscall_p; 468 const char* path_p; 469 const char* dest_p; 470 471 FSReqWrapSync(const FSReqWrapSync&) = delete; 472 FSReqWrapSync& operator=(const FSReqWrapSync&) = delete; 473 474 // TODO(joyeecheung): move these out of FSReqWrapSync and into a special 475 // class for mkdirp 476 FSContinuationData* continuation_data() const { 477 return continuation_data_.get(); 478 } 479 void set_continuation_data(std::unique_ptr<FSContinuationData> data) { 480 continuation_data_ = std::move(data); 481 } 482 483 private: 484 std::unique_ptr<FSContinuationData> continuation_data_; 485 }; 486 487 // TODO(addaleax): Currently, callers check the return value and assume 488 // that nullptr indicates a synchronous call, rather than a failure. 489 // Failure conditions should be disambiguated and handled appropriately. 490 inline FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo<v8::Value>& args, 491 int index, 492 bool use_bigint = false); 493 494 // Returns nullptr if the operation fails from the start. 495 template <typename Func, typename... Args> 496 inline FSReqBase* AsyncDestCall(Environment* env, FSReqBase* req_wrap, 497 const v8::FunctionCallbackInfo<v8::Value>& args, 498 const char* syscall, const char* dest, 499 size_t len, enum encoding enc, uv_fs_cb after, 500 Func fn, Args... fn_args); 501 502 // Returns nullptr if the operation fails from the start. 503 template <typename Func, typename... Args> 504 inline FSReqBase* AsyncCall(Environment* env, 505 FSReqBase* req_wrap, 506 const v8::FunctionCallbackInfo<v8::Value>& args, 507 const char* syscall, enum encoding enc, 508 uv_fs_cb after, Func fn, Args... fn_args); 509 510 // Template counterpart of SYNC_CALL, except that it only puts 511 // the error number and the syscall in the context instead of 512 // creating an error in the C++ land. 513 // ctx must be checked using value->IsObject() before being passed. 514 template <typename Func, typename... Args> 515 inline int SyncCall(Environment* env, v8::Local<v8::Value> ctx, 516 FSReqWrapSync* req_wrap, const char* syscall, 517 Func fn, Args... args); 518 519 // Similar to SyncCall but throws immediately if there is an error. 520 template <typename Predicate, typename Func, typename... Args> 521 int SyncCallAndThrowIf(Predicate should_throw, 522 Environment* env, 523 FSReqWrapSync* req_wrap, 524 Func fn, 525 Args... args); 526 template <typename Func, typename... Args> 527 int SyncCallAndThrowOnError(Environment* env, 528 FSReqWrapSync* req_wrap, 529 Func fn, 530 Args... args); 531 } // namespace fs 532 533 } // namespace node 534 535 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 536 537 #endif // SRC_NODE_FILE_H_