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