GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_file.h Lines: 41 52 78.8 %
Date: 2022-08-16 04:20:39 Branches: 2 2 100.0 %

Line Branch Exec Source
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 "aliased_buffer.h"
7
#include "node_messaging.h"
8
#include "node_snapshotable.h"
9
#include "stream_base.h"
10
11
namespace node {
12
namespace fs {
13
14
class FileHandleReadWrap;
15
16
class BindingData : public SnapshotableObject {
17
 public:
18
  explicit BindingData(Environment* env, v8::Local<v8::Object> wrap);
19
20
  AliasedFloat64Array stats_field_array;
21
  AliasedBigInt64Array stats_field_bigint_array;
22
23
  std::vector<BaseObjectPtr<FileHandleReadWrap>>
24
      file_handle_read_wrap_freelist;
25
26
  using InternalFieldInfo = InternalFieldInfoBase;
27
  SERIALIZABLE_OBJECT_METHODS()
28
  static constexpr FastStringKey type_name{"node::fs::BindingData"};
29
  static constexpr EmbedderObjectType type_int =
30
      EmbedderObjectType::k_fs_binding_data;
31
32
  void MemoryInfo(MemoryTracker* tracker) const override;
33
24
  SET_SELF_SIZE(BindingData)
34
24
  SET_MEMORY_INFO_NAME(BindingData)
35
};
36
37
// structure used to store state during a complex operation, e.g., mkdirp.
38
class FSContinuationData : public MemoryRetainer {
39
 public:
40
  inline FSContinuationData(uv_fs_t* req, int mode, uv_fs_cb done_cb);
41
42
  inline void PushPath(std::string&& path);
43
  inline void PushPath(const std::string& path);
44
  inline std::string PopPath();
45
  // Used by mkdirp to track the first path created:
46
  inline void MaybeSetFirstPath(const std::string& path);
47
  inline void Done(int result);
48
49
444
  int mode() const { return mode_; }
50
13506
  const std::vector<std::string>& paths() const { return paths_; }
51
910
  const std::string& first_path() const { return first_path_; }
52
53
  void MemoryInfo(MemoryTracker* tracker) const override;
54
  SET_MEMORY_INFO_NAME(FSContinuationData)
55
  SET_SELF_SIZE(FSContinuationData)
56
57
 private:
58
  uv_fs_cb done_cb_;
59
  uv_fs_t* req_;
60
  int mode_;
61
  std::vector<std::string> paths_;
62
  std::string first_path_;
63
};
64
65
114132
class FSReqBase : public ReqWrap<uv_fs_t> {
66
 public:
67
  typedef MaybeStackBuffer<char, 64> FSReqBuffer;
68
69
  inline FSReqBase(BindingData* binding_data,
70
                   v8::Local<v8::Object> req,
71
                   AsyncWrap::ProviderType type,
72
                   bool use_bigint);
73
  ~FSReqBase() override;
74
75
  inline void Init(const char* syscall,
76
                   const char* data,
77
                   size_t len,
78
                   enum encoding encoding);
79
  inline FSReqBuffer& Init(const char* syscall, size_t len,
80
                           enum encoding encoding);
81
82
  virtual void Reject(v8::Local<v8::Value> reject) = 0;
83
  virtual void Resolve(v8::Local<v8::Value> value) = 0;
84
  virtual void ResolveStat(const uv_stat_t* stat) = 0;
85
  virtual void SetReturnValue(
86
      const v8::FunctionCallbackInfo<v8::Value>& args) = 0;
87
88
5212
  const char* syscall() const { return syscall_; }
89
5212
  const char* data() const { return has_data_ ? *buffer_ : nullptr; }
90
8004
  enum encoding encoding() const { return encoding_; }
91
2519
  bool use_bigint() const { return use_bigint_; }
92
38067
  bool is_plain_open() const { return is_plain_open_; }
93
215
  bool with_file_types() const { return with_file_types_; }
94
95
5624
  void set_is_plain_open(bool value) { is_plain_open_ = value; }
96
222
  void set_with_file_types(bool value) { with_file_types_ = value; }
97
98
4482
  FSContinuationData* continuation_data() const {
99
4482
    return continuation_data_.get();
100
  }
101
360
  void set_continuation_data(std::unique_ptr<FSContinuationData> data) {
102
360
    continuation_data_ = std::move(data);
103
360
  }
104
105
58929
  static FSReqBase* from_req(uv_fs_t* req) {
106
58929
    return static_cast<FSReqBase*>(ReqWrap::from_req(req));
107
  }
108
109
  FSReqBase(const FSReqBase&) = delete;
110
  FSReqBase& operator=(const FSReqBase&) = delete;
111
112
  void MemoryInfo(MemoryTracker* tracker) const override;
113
114
  BindingData* binding_data();
115
116
 private:
117
  std::unique_ptr<FSContinuationData> continuation_data_;
118
  enum encoding encoding_ = UTF8;
119
  bool has_data_ = false;
120
  bool use_bigint_ = false;
121
  bool is_plain_open_ = false;
122
  bool with_file_types_ = false;
123
  const char* syscall_ = nullptr;
124
125
  BaseObjectPtr<BindingData> binding_data_;
126
127
  // Typically, the content of buffer_ is something like a file name, so
128
  // something around 64 bytes should be enough.
129
  FSReqBuffer buffer_;
130
};
131
132
class FSReqCallback final : public FSReqBase {
133
 public:
134
  inline FSReqCallback(BindingData* binding_data,
135
                       v8::Local<v8::Object> req,
136
                       bool use_bigint);
137
138
  void Reject(v8::Local<v8::Value> reject) override;
139
  void Resolve(v8::Local<v8::Value> value) override;
140
  void ResolveStat(const uv_stat_t* stat) override;
141
  void SetReturnValue(const v8::FunctionCallbackInfo<v8::Value>& args) override;
142
143
13
  SET_MEMORY_INFO_NAME(FSReqCallback)
144
1
  SET_SELF_SIZE(FSReqCallback)
145
146
  FSReqCallback(const FSReqCallback&) = delete;
147
  FSReqCallback& operator=(const FSReqCallback&) = delete;
148
};
149
150
template <typename NativeT, typename V8T>
151
void FillStatsArray(AliasedBufferBase<NativeT, V8T>* fields,
152
                    const uv_stat_t* s,
153
                    const size_t offset = 0);
154
155
inline v8::Local<v8::Value> FillGlobalStatsArray(BindingData* binding_data,
156
                                                 const bool use_bigint,
157
                                                 const uv_stat_t* s,
158
                                                 const bool second = false);
159
160
template <typename AliasedBufferT>
161
class FSReqPromise final : public FSReqBase {
162
 public:
163
  static inline FSReqPromise* New(BindingData* binding_data,
164
                                  bool use_bigint);
165
  inline ~FSReqPromise() override;
166
167
  inline void Reject(v8::Local<v8::Value> reject) override;
168
  inline void Resolve(v8::Local<v8::Value> value) override;
169
  inline void ResolveStat(const uv_stat_t* stat) override;
170
  inline void SetReturnValue(
171
      const v8::FunctionCallbackInfo<v8::Value>& args) override;
172
  inline void MemoryInfo(MemoryTracker* tracker) const override;
173
174
2
  SET_MEMORY_INFO_NAME(FSReqPromise)
175
1
  SET_SELF_SIZE(FSReqPromise)
176
177
  FSReqPromise(const FSReqPromise&) = delete;
178
  FSReqPromise& operator=(const FSReqPromise&) = delete;
179
  FSReqPromise(const FSReqPromise&&) = delete;
180
  FSReqPromise& operator=(const FSReqPromise&&) = delete;
181
182
 private:
183
  inline FSReqPromise(BindingData* binding_data,
184
                      v8::Local<v8::Object> obj,
185
                      bool use_bigint);
186
187
  bool finished_ = false;
188
  AliasedBufferT stats_field_array_;
189
};
190
191
class FSReqAfterScope final {
192
 public:
193
  FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req);
194
  ~FSReqAfterScope();
195
  void Clear();
196
197
  bool Proceed();
198
199
  void Reject(uv_fs_t* req);
200
201
  FSReqAfterScope(const FSReqAfterScope&) = delete;
202
  FSReqAfterScope& operator=(const FSReqAfterScope&) = delete;
203
  FSReqAfterScope(const FSReqAfterScope&&) = delete;
204
  FSReqAfterScope& operator=(const FSReqAfterScope&&) = delete;
205
206
 private:
207
  BaseObjectPtr<FSReqBase> wrap_;
208
  uv_fs_t* req_ = nullptr;
209
  v8::HandleScope handle_scope_;
210
  v8::Context::Scope context_scope_;
211
};
212
213
class FileHandle;
214
215
// A request wrap specifically for uv_fs_read()s scheduled for reading
216
// from a FileHandle.
217
72
class FileHandleReadWrap final : public ReqWrap<uv_fs_t> {
218
 public:
219
  FileHandleReadWrap(FileHandle* handle, v8::Local<v8::Object> obj);
220
  ~FileHandleReadWrap() override;
221
222
213
  static inline FileHandleReadWrap* from_req(uv_fs_t* req) {
223
213
    return static_cast<FileHandleReadWrap*>(ReqWrap::from_req(req));
224
  }
225
226
  void MemoryInfo(MemoryTracker* tracker) const override;
227
  SET_MEMORY_INFO_NAME(FileHandleReadWrap)
228
  SET_SELF_SIZE(FileHandleReadWrap)
229
230
 private:
231
  FileHandle* file_handle_;
232
  uv_buf_t buffer_;
233
234
  friend class FileHandle;
235
};
236
237
// A wrapper for a file descriptor that will automatically close the fd when
238
// the object is garbage collected
239
class FileHandle final : public AsyncWrap, public StreamBase {
240
 public:
241
  enum InternalFields {
242
    kFileHandleBaseField = StreamBase::kInternalFieldCount,
243
    kClosingPromiseSlot,
244
    kInternalFieldCount
245
  };
246
247
  static FileHandle* New(BindingData* binding_data,
248
                         int fd,
249
                         v8::Local<v8::Object> obj = v8::Local<v8::Object>());
250
  ~FileHandle() override;
251
252
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
253
254
1327
  int GetFD() override { return fd_; }
255
256
  // Will asynchronously close the FD and return a Promise that will
257
  // be resolved once closing is complete.
258
  static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
259
260
  // Releases ownership of the FD.
261
  static void ReleaseFD(const v8::FunctionCallbackInfo<v8::Value>& args);
262
263
  // StreamBase interface:
264
  int ReadStart() override;
265
  int ReadStop() override;
266
267
1572
  bool IsAlive() override { return !closed_; }
268
227
  bool IsClosing() override { return closing_; }
269
1415
  AsyncWrap* GetAsyncWrap() override { return this; }
270
271
  // In the case of file streams, shutting down corresponds to closing.
272
  ShutdownWrap* CreateShutdownWrap(v8::Local<v8::Object> object) override;
273
  int DoShutdown(ShutdownWrap* req_wrap) override;
274
275
  int DoWrite(WriteWrap* w,
276
              uv_buf_t* bufs,
277
              size_t count,
278
              uv_stream_t* send_handle) override;
279
280
  void MemoryInfo(MemoryTracker* tracker) const override;
281
282
  SET_MEMORY_INFO_NAME(FileHandle)
283
  SET_SELF_SIZE(FileHandle)
284
285
  FileHandle(const FileHandle&) = delete;
286
  FileHandle& operator=(const FileHandle&) = delete;
287
  FileHandle(const FileHandle&&) = delete;
288
  FileHandle& operator=(const FileHandle&&) = delete;
289
290
  TransferMode GetTransferMode() const override;
291
  std::unique_ptr<worker::TransferData> TransferForMessaging() override;
292
293
 private:
294
  class TransferData : public worker::TransferData {
295
   public:
296
    explicit TransferData(int fd);
297
    ~TransferData();
298
299
    BaseObjectPtr<BaseObject> Deserialize(
300
        Environment* env,
301
        v8::Local<v8::Context> context,
302
        std::unique_ptr<worker::TransferData> self) override;
303
304
    SET_NO_MEMORY_INFO()
305
    SET_MEMORY_INFO_NAME(FileHandleTransferData)
306
    SET_SELF_SIZE(TransferData)
307
308
   private:
309
    int fd_;
310
  };
311
312
  FileHandle(BindingData* binding_data, v8::Local<v8::Object> obj, int fd);
313
314
  // Synchronous close that emits a warning
315
  void Close();
316
  void AfterClose();
317
318
  class CloseReq final : public ReqWrap<uv_fs_t> {
319
   public:
320
    CloseReq(Environment* env,
321
             v8::Local<v8::Object> obj,
322
             v8::Local<v8::Promise> promise,
323
             v8::Local<v8::Value> ref);
324
    ~CloseReq() override;
325
326
    FileHandle* file_handle();
327
328
    void MemoryInfo(MemoryTracker* tracker) const override;
329
330
    SET_MEMORY_INFO_NAME(CloseReq)
331
    SET_SELF_SIZE(CloseReq)
332
333
    void Resolve();
334
335
    void Reject(v8::Local<v8::Value> reason);
336
337
1306
    static CloseReq* from_req(uv_fs_t* req) {
338
1306
      return static_cast<CloseReq*>(ReqWrap::from_req(req));
339
    }
340
341
    CloseReq(const CloseReq&) = delete;
342
    CloseReq& operator=(const CloseReq&) = delete;
343
    CloseReq(const CloseReq&&) = delete;
344
    CloseReq& operator=(const CloseReq&&) = delete;
345
346
   private:
347
    v8::Global<v8::Promise> promise_{};
348
    v8::Global<v8::Value> ref_{};
349
  };
350
351
  // Asynchronous close
352
  v8::MaybeLocal<v8::Promise> ClosePromise();
353
354
  int fd_;
355
  bool closing_ = false;
356
  bool closed_ = false;
357
  bool reading_ = false;
358
  int64_t read_offset_ = -1;
359
  int64_t read_length_ = -1;
360
361
  BaseObjectPtr<FileHandleReadWrap> current_read_;
362
363
  BaseObjectPtr<BindingData> binding_data_;
364
};
365
366
int MKDirpSync(uv_loop_t* loop,
367
               uv_fs_t* req,
368
               const std::string& path,
369
               int mode,
370
               uv_fs_cb cb = nullptr);
371
372
class FSReqWrapSync {
373
 public:
374
732324
  FSReqWrapSync() = default;
375
732324
  ~FSReqWrapSync() { uv_fs_req_cleanup(&req); }
376
  uv_fs_t req;
377
378
33211
  FSContinuationData* continuation_data() const {
379
33211
    return continuation_data_.get();
380
  }
381
6352
  void set_continuation_data(std::unique_ptr<FSContinuationData> data) {
382
6352
    continuation_data_ = std::move(data);
383
6352
  }
384
385
  FSReqWrapSync(const FSReqWrapSync&) = delete;
386
  FSReqWrapSync& operator=(const FSReqWrapSync&) = delete;
387
388
 private:
389
  std::unique_ptr<FSContinuationData> continuation_data_;
390
};
391
392
// TODO(addaleax): Currently, callers check the return value and assume
393
// that nullptr indicates a synchronous call, rather than a failure.
394
// Failure conditions should be disambiguated and handled appropriately.
395
inline FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo<v8::Value>& args,
396
                             int index,
397
                             bool use_bigint = false);
398
399
// Returns nullptr if the operation fails from the start.
400
template <typename Func, typename... Args>
401
inline FSReqBase* AsyncDestCall(Environment* env, FSReqBase* req_wrap,
402
                                const v8::FunctionCallbackInfo<v8::Value>& args,
403
                                const char* syscall, const char* dest,
404
                                size_t len, enum encoding enc, uv_fs_cb after,
405
                                Func fn, Args... fn_args);
406
407
// Returns nullptr if the operation fails from the start.
408
template <typename Func, typename... Args>
409
inline FSReqBase* AsyncCall(Environment* env,
410
                            FSReqBase* req_wrap,
411
                            const v8::FunctionCallbackInfo<v8::Value>& args,
412
                            const char* syscall, enum encoding enc,
413
                            uv_fs_cb after, Func fn, Args... fn_args);
414
415
// Template counterpart of SYNC_CALL, except that it only puts
416
// the error number and the syscall in the context instead of
417
// creating an error in the C++ land.
418
// ctx must be checked using value->IsObject() before being passed.
419
template <typename Func, typename... Args>
420
inline int SyncCall(Environment* env, v8::Local<v8::Value> ctx,
421
                    FSReqWrapSync* req_wrap, const char* syscall,
422
                    Func fn, Args... args);
423
424
}  // namespace fs
425
426
}  // namespace node
427
428
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
429
430
#endif  // SRC_NODE_FILE_H_