GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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 "node.h" |
||
7 |
#include "stream_base.h" |
||
8 |
#include "req_wrap-inl.h" |
||
9 |
#include <iostream> |
||
10 |
|||
11 |
namespace node { |
||
12 |
|||
13 |
using v8::Context; |
||
14 |
using v8::FunctionCallbackInfo; |
||
15 |
using v8::HandleScope; |
||
16 |
using v8::Local; |
||
17 |
using v8::MaybeLocal; |
||
18 |
using v8::Object; |
||
19 |
using v8::Promise; |
||
20 |
using v8::Undefined; |
||
21 |
using v8::Value; |
||
22 |
|||
23 |
namespace fs { |
||
24 |
|||
25 |
// structure used to store state during a complex operation, e.g., mkdirp. |
||
26 |
✗✓ | 5093 |
class FSContinuationData : public MemoryRetainer { |
27 |
public: |
||
28 |
5083 |
FSContinuationData(uv_fs_t* req, int mode, uv_fs_cb done_cb) |
|
29 |
5083 |
: req(req), mode(mode), done_cb(done_cb) { |
|
30 |
5083 |
} |
|
31 |
|||
32 |
uv_fs_t* req; |
||
33 |
int mode; |
||
34 |
std::vector<std::string> paths{}; |
||
35 |
|||
36 |
72 |
void PushPath(std::string&& path) { |
|
37 |
72 |
paths.emplace_back(std::move(path)); |
|
38 |
72 |
} |
|
39 |
|||
40 |
5073 |
void PushPath(const std::string& path) { |
|
41 |
5073 |
paths.push_back(path); |
|
42 |
5073 |
} |
|
43 |
|||
44 |
5145 |
std::string PopPath() { |
|
45 |
✗✓ | 5145 |
CHECK_GT(paths.size(), 0); |
46 |
5145 |
std::string path = std::move(paths.back()); |
|
47 |
5145 |
paths.pop_back(); |
|
48 |
5145 |
return path; |
|
49 |
} |
||
50 |
|||
51 |
10 |
void Done(int result) { |
|
52 |
10 |
req->result = result; |
|
53 |
10 |
done_cb(req); |
|
54 |
10 |
} |
|
55 |
|||
56 |
void MemoryInfo(MemoryTracker* tracker) const override { |
||
57 |
tracker->TrackField("paths", paths); |
||
58 |
} |
||
59 |
|||
60 |
SET_MEMORY_INFO_NAME(FSContinuationData) |
||
61 |
SET_SELF_SIZE(FSContinuationData) |
||
62 |
|||
63 |
private: |
||
64 |
uv_fs_cb done_cb; |
||
65 |
}; |
||
66 |
|||
67 |
✗✓ | 61348 |
class FSReqBase : public ReqWrap<uv_fs_t> { |
68 |
public: |
||
69 |
typedef MaybeStackBuffer<char, 64> FSReqBuffer; |
||
70 |
std::unique_ptr<FSContinuationData> continuation_data = nullptr; |
||
71 |
|||
72 |
61358 |
FSReqBase(Environment* env, Local<Object> req, AsyncWrap::ProviderType type, |
|
73 |
bool use_bigint) |
||
74 |
61358 |
: ReqWrap(env, req, type), use_bigint_(use_bigint) { |
|
75 |
61358 |
} |
|
76 |
|||
77 |
61197 |
void Init(const char* syscall, |
|
78 |
const char* data, |
||
79 |
size_t len, |
||
80 |
enum encoding encoding) { |
||
81 |
61197 |
syscall_ = syscall; |
|
82 |
61197 |
encoding_ = encoding; |
|
83 |
|||
84 |
✓✓ | 61197 |
if (data != nullptr) { |
85 |
✗✓ | 370 |
CHECK(!has_data_); |
86 |
370 |
buffer_.AllocateSufficientStorage(len + 1); |
|
87 |
370 |
buffer_.SetLengthAndZeroTerminate(len); |
|
88 |
370 |
memcpy(*buffer_, data, len); |
|
89 |
370 |
has_data_ = true; |
|
90 |
} |
||
91 |
61197 |
} |
|
92 |
|||
93 |
142 |
FSReqBuffer& Init(const char* syscall, size_t len, |
|
94 |
enum encoding encoding) { |
||
95 |
142 |
syscall_ = syscall; |
|
96 |
142 |
encoding_ = encoding; |
|
97 |
|||
98 |
142 |
buffer_.AllocateSufficientStorage(len + 1); |
|
99 |
142 |
has_data_ = false; // so that the data does not show up in error messages |
|
100 |
142 |
return buffer_; |
|
101 |
} |
||
102 |
|||
103 |
virtual void Reject(Local<Value> reject) = 0; |
||
104 |
virtual void Resolve(Local<Value> value) = 0; |
||
105 |
virtual void ResolveStat(const uv_stat_t* stat) = 0; |
||
106 |
virtual void SetReturnValue(const FunctionCallbackInfo<Value>& args) = 0; |
||
107 |
|||
108 |
5117 |
const char* syscall() const { return syscall_; } |
|
109 |
✓✓ | 5117 |
const char* data() const { return has_data_ ? *buffer_ : nullptr; } |
110 |
5986 |
enum encoding encoding() const { return encoding_; } |
|
111 |
|||
112 |
5859 |
bool use_bigint() const { return use_bigint_; } |
|
113 |
|||
114 |
61387 |
static FSReqBase* from_req(uv_fs_t* req) { |
|
115 |
61387 |
return static_cast<FSReqBase*>(ReqWrap::from_req(req)); |
|
116 |
} |
||
117 |
|||
118 |
FSReqBase(const FSReqBase&) = delete; |
||
119 |
FSReqBase& operator=(const FSReqBase&) = delete; |
||
120 |
|||
121 |
private: |
||
122 |
enum encoding encoding_ = UTF8; |
||
123 |
bool has_data_ = false; |
||
124 |
const char* syscall_ = nullptr; |
||
125 |
bool use_bigint_ = false; |
||
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 |
✗✓ | 120264 |
class FSReqCallback : public FSReqBase { |
133 |
public: |
||
134 |
60142 |
FSReqCallback(Environment* env, Local<Object> req, bool use_bigint) |
|
135 |
60142 |
: FSReqBase(env, req, AsyncWrap::PROVIDER_FSREQCALLBACK, use_bigint) { } |
|
136 |
|||
137 |
void Reject(Local<Value> reject) override; |
||
138 |
void Resolve(Local<Value> value) override; |
||
139 |
void ResolveStat(const uv_stat_t* stat) override; |
||
140 |
void SetReturnValue(const FunctionCallbackInfo<Value>& args) override; |
||
141 |
|||
142 |
1 |
void MemoryInfo(MemoryTracker* tracker) const override { |
|
143 |
1 |
tracker->TrackField("continuation_data", continuation_data); |
|
144 |
1 |
} |
|
145 |
|||
146 |
1 |
SET_MEMORY_INFO_NAME(FSReqCallback) |
|
147 |
1 |
SET_SELF_SIZE(FSReqCallback) |
|
148 |
|||
149 |
FSReqCallback(const FSReqCallback&) = delete; |
||
150 |
FSReqCallback& operator=(const FSReqCallback&) = delete; |
||
151 |
}; |
||
152 |
|||
153 |
template <typename NativeT, typename V8T> |
||
154 |
203379 |
constexpr void FillStatsArray(AliasedBufferBase<NativeT, V8T>* fields, |
|
155 |
const uv_stat_t* s, |
||
156 |
const size_t offset = 0) { |
||
157 |
#define SET_FIELD_WITH_STAT(stat_offset, stat) \ |
||
158 |
fields->SetValue(offset + static_cast<size_t>(FsStatsOffset::stat_offset), \ |
||
159 |
static_cast<NativeT>(stat)) |
||
160 |
|||
161 |
#define SET_FIELD_WITH_TIME_STAT(stat_offset, stat) \ |
||
162 |
/* NOLINTNEXTLINE(runtime/int) */ \ |
||
163 |
SET_FIELD_WITH_STAT(stat_offset, static_cast<unsigned long>(stat)) |
||
164 |
|||
165 |
203379 |
SET_FIELD_WITH_STAT(kDev, s->st_dev); |
|
166 |
203379 |
SET_FIELD_WITH_STAT(kMode, s->st_mode); |
|
167 |
203379 |
SET_FIELD_WITH_STAT(kNlink, s->st_nlink); |
|
168 |
203379 |
SET_FIELD_WITH_STAT(kUid, s->st_uid); |
|
169 |
203379 |
SET_FIELD_WITH_STAT(kGid, s->st_gid); |
|
170 |
203379 |
SET_FIELD_WITH_STAT(kRdev, s->st_rdev); |
|
171 |
203379 |
SET_FIELD_WITH_STAT(kBlkSize, s->st_blksize); |
|
172 |
203379 |
SET_FIELD_WITH_STAT(kIno, s->st_ino); |
|
173 |
203379 |
SET_FIELD_WITH_STAT(kSize, s->st_size); |
|
174 |
203379 |
SET_FIELD_WITH_STAT(kBlocks, s->st_blocks); |
|
175 |
|||
176 |
203379 |
SET_FIELD_WITH_TIME_STAT(kATimeSec, s->st_atim.tv_sec); |
|
177 |
203379 |
SET_FIELD_WITH_TIME_STAT(kATimeNsec, s->st_atim.tv_nsec); |
|
178 |
203379 |
SET_FIELD_WITH_TIME_STAT(kMTimeSec, s->st_mtim.tv_sec); |
|
179 |
203379 |
SET_FIELD_WITH_TIME_STAT(kMTimeNsec, s->st_mtim.tv_nsec); |
|
180 |
203379 |
SET_FIELD_WITH_TIME_STAT(kCTimeSec, s->st_ctim.tv_sec); |
|
181 |
203379 |
SET_FIELD_WITH_TIME_STAT(kCTimeNsec, s->st_ctim.tv_nsec); |
|
182 |
203379 |
SET_FIELD_WITH_TIME_STAT(kBirthTimeSec, s->st_birthtim.tv_sec); |
|
183 |
203379 |
SET_FIELD_WITH_TIME_STAT(kBirthTimeNsec, s->st_birthtim.tv_nsec); |
|
184 |
|||
185 |
#undef SET_FIELD_WITH_TIME_STAT |
||
186 |
#undef SET_FIELD_WITH_STAT |
||
187 |
203379 |
} |
|
188 |
|||
189 |
203065 |
inline Local<Value> FillGlobalStatsArray(Environment* env, |
|
190 |
const bool use_bigint, |
||
191 |
const uv_stat_t* s, |
||
192 |
const bool second = false) { |
||
193 |
const ptrdiff_t offset = |
||
194 |
✓✓ | 203065 |
second ? static_cast<ptrdiff_t>(FsStatsOffset::kFsStatsFieldsNumber) : 0; |
195 |
✓✓ | 203065 |
if (use_bigint) { |
196 |
10 |
auto* const arr = env->fs_stats_field_bigint_array(); |
|
197 |
10 |
FillStatsArray(arr, s, offset); |
|
198 |
20 |
return arr->GetJSArray(); |
|
199 |
} else { |
||
200 |
203055 |
auto* const arr = env->fs_stats_field_array(); |
|
201 |
203055 |
FillStatsArray(arr, s, offset); |
|
202 |
406110 |
return arr->GetJSArray(); |
|
203 |
} |
||
204 |
} |
||
205 |
|||
206 |
template <typename AliasedBufferT> |
||
207 |
class FSReqPromise : public FSReqBase { |
||
208 |
public: |
||
209 |
1216 |
static FSReqPromise* New(Environment* env, bool use_bigint) { |
|
210 |
v8::Local<Object> obj; |
||
211 |
✗✓✗✓ |
2432 |
if (!env->fsreqpromise_constructor_template() |
212 |
3648 |
->NewInstance(env->context()) |
|
213 |
3648 |
.ToLocal(&obj)) { |
|
214 |
return nullptr; |
||
215 |
} |
||
216 |
v8::Local<v8::Promise::Resolver> resolver; |
||
217 |
✓✗✗✓ ✓✗✗✓ ✓✗✗✓ ✓✗✗✓ |
6080 |
if (!v8::Promise::Resolver::New(env->context()).ToLocal(&resolver) || |
218 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
6080 |
obj->Set(env->context(), env->promise_string(), resolver).IsNothing()) { |
219 |
return nullptr; |
||
220 |
} |
||
221 |
1216 |
return new FSReqPromise(env, obj, use_bigint); |
|
222 |
} |
||
223 |
|||
224 |
2432 |
~FSReqPromise() override { |
|
225 |
// Validate that the promise was explicitly resolved or rejected. |
||
226 |
✗✓✗✓ |
1216 |
CHECK(finished_); |
227 |
✗✗✓✓ |
3648 |
} |
228 |
|||
229 |
77 |
void Reject(Local<Value> reject) override { |
|
230 |
77 |
finished_ = true; |
|
231 |
77 |
HandleScope scope(env()->isolate()); |
|
232 |
154 |
InternalCallbackScope callback_scope(this); |
|
233 |
Local<Value> value = |
||
234 |
77 |
object()->Get(env()->context(), |
|
235 |
385 |
env()->promise_string()).ToLocalChecked(); |
|
236 |
77 |
Local<Promise::Resolver> resolver = value.As<Promise::Resolver>(); |
|
237 |
308 |
USE(resolver->Reject(env()->context(), reject).FromJust()); |
|
238 |
77 |
} |
|
239 |
|||
240 |
1139 |
void Resolve(Local<Value> value) override { |
|
241 |
1139 |
finished_ = true; |
|
242 |
1139 |
HandleScope scope(env()->isolate()); |
|
243 |
2278 |
InternalCallbackScope callback_scope(this); |
|
244 |
Local<Value> val = |
||
245 |
1139 |
object()->Get(env()->context(), |
|
246 |
5695 |
env()->promise_string()).ToLocalChecked(); |
|
247 |
1139 |
Local<Promise::Resolver> resolver = val.As<Promise::Resolver>(); |
|
248 |
4556 |
USE(resolver->Resolve(env()->context(), value).FromJust()); |
|
249 |
1139 |
} |
|
250 |
|||
251 |
314 |
void ResolveStat(const uv_stat_t* stat) override { |
|
252 |
314 |
FillStatsArray(&stats_field_array_, stat); |
|
253 |
628 |
Resolve(stats_field_array_.GetJSArray()); |
|
254 |
314 |
} |
|
255 |
|||
256 |
1216 |
void SetReturnValue(const FunctionCallbackInfo<Value>& args) override { |
|
257 |
Local<Value> val = |
||
258 |
1216 |
object()->Get(env()->context(), |
|
259 |
6080 |
env()->promise_string()).ToLocalChecked(); |
|
260 |
1216 |
Local<Promise::Resolver> resolver = val.As<Promise::Resolver>(); |
|
261 |
3648 |
args.GetReturnValue().Set(resolver->GetPromise()); |
|
262 |
1216 |
} |
|
263 |
|||
264 |
3 |
void MemoryInfo(MemoryTracker* tracker) const override { |
|
265 |
3 |
tracker->TrackField("stats_field_array", stats_field_array_); |
|
266 |
3 |
tracker->TrackField("continuation_data", continuation_data); |
|
267 |
3 |
} |
|
268 |
|||
269 |
3 |
SET_MEMORY_INFO_NAME(FSReqPromise) |
|
270 |
3 |
SET_SELF_SIZE(FSReqPromise) |
|
271 |
|||
272 |
FSReqPromise(const FSReqPromise&) = delete; |
||
273 |
FSReqPromise& operator=(const FSReqPromise&) = delete; |
||
274 |
FSReqPromise(const FSReqPromise&&) = delete; |
||
275 |
FSReqPromise& operator=(const FSReqPromise&&) = delete; |
||
276 |
|||
277 |
private: |
||
278 |
1216 |
FSReqPromise(Environment* env, v8::Local<v8::Object> obj, bool use_bigint) |
|
279 |
: FSReqBase(env, obj, AsyncWrap::PROVIDER_FSREQPROMISE, use_bigint), |
||
280 |
stats_field_array_( |
||
281 |
env->isolate(), |
||
282 |
1216 |
static_cast<size_t>(FsStatsOffset::kFsStatsFieldsNumber)) {} |
|
283 |
|||
284 |
bool finished_ = false; |
||
285 |
AliasedBufferT stats_field_array_; |
||
286 |
}; |
||
287 |
|||
288 |
class FSReqAfterScope { |
||
289 |
public: |
||
290 |
FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req); |
||
291 |
~FSReqAfterScope(); |
||
292 |
|||
293 |
bool Proceed(); |
||
294 |
|||
295 |
void Reject(uv_fs_t* req); |
||
296 |
|||
297 |
FSReqAfterScope(const FSReqAfterScope&) = delete; |
||
298 |
FSReqAfterScope& operator=(const FSReqAfterScope&) = delete; |
||
299 |
FSReqAfterScope(const FSReqAfterScope&&) = delete; |
||
300 |
FSReqAfterScope& operator=(const FSReqAfterScope&&) = delete; |
||
301 |
|||
302 |
private: |
||
303 |
FSReqBase* wrap_ = nullptr; |
||
304 |
uv_fs_t* req_ = nullptr; |
||
305 |
HandleScope handle_scope_; |
||
306 |
Context::Scope context_scope_; |
||
307 |
}; |
||
308 |
|||
309 |
class FileHandle; |
||
310 |
|||
311 |
// A request wrap specifically for uv_fs_read()s scheduled for reading |
||
312 |
// from a FileHandle. |
||
313 |
✗✓ | 30 |
class FileHandleReadWrap : public ReqWrap<uv_fs_t> { |
314 |
public: |
||
315 |
FileHandleReadWrap(FileHandle* handle, v8::Local<v8::Object> obj); |
||
316 |
|||
317 |
221 |
static inline FileHandleReadWrap* from_req(uv_fs_t* req) { |
|
318 |
221 |
return static_cast<FileHandleReadWrap*>(ReqWrap::from_req(req)); |
|
319 |
} |
||
320 |
|||
321 |
void MemoryInfo(MemoryTracker* tracker) const override; |
||
322 |
2 |
SET_MEMORY_INFO_NAME(FileHandleReadWrap) |
|
323 |
2 |
SET_SELF_SIZE(FileHandleReadWrap) |
|
324 |
|||
325 |
private: |
||
326 |
FileHandle* file_handle_; |
||
327 |
uv_buf_t buffer_; |
||
328 |
|||
329 |
friend class FileHandle; |
||
330 |
}; |
||
331 |
|||
332 |
// A wrapper for a file descriptor that will automatically close the fd when |
||
333 |
// the object is garbage collected |
||
334 |
class FileHandle : public AsyncWrap, public StreamBase { |
||
335 |
public: |
||
336 |
static FileHandle* New(Environment* env, |
||
337 |
int fd, |
||
338 |
v8::Local<v8::Object> obj = v8::Local<v8::Object>()); |
||
339 |
~FileHandle() override; |
||
340 |
|||
341 |
static void New(const v8::FunctionCallbackInfo<v8::Value>& args); |
||
342 |
|||
343 |
int fd() const { return fd_; } |
||
344 |
|||
345 |
// Will asynchronously close the FD and return a Promise that will |
||
346 |
// be resolved once closing is complete. |
||
347 |
static void Close(const FunctionCallbackInfo<Value>& args); |
||
348 |
|||
349 |
// Releases ownership of the FD. |
||
350 |
static void ReleaseFD(const FunctionCallbackInfo<Value>& args); |
||
351 |
|||
352 |
// StreamBase interface: |
||
353 |
int ReadStart() override; |
||
354 |
int ReadStop() override; |
||
355 |
|||
356 |
227 |
bool IsAlive() override { return !closed_; } |
|
357 |
227 |
bool IsClosing() override { return closing_; } |
|
358 |
312 |
AsyncWrap* GetAsyncWrap() override { return this; } |
|
359 |
|||
360 |
// In the case of file streams, shutting down corresponds to closing. |
||
361 |
ShutdownWrap* CreateShutdownWrap(v8::Local<v8::Object> object) override; |
||
362 |
int DoShutdown(ShutdownWrap* req_wrap) override; |
||
363 |
|||
364 |
int DoWrite(WriteWrap* w, |
||
365 |
uv_buf_t* bufs, |
||
366 |
size_t count, |
||
367 |
uv_stream_t* send_handle) override { |
||
368 |
return UV_ENOSYS; // Not implemented (yet). |
||
369 |
} |
||
370 |
|||
371 |
2 |
void MemoryInfo(MemoryTracker* tracker) const override { |
|
372 |
2 |
tracker->TrackField("current_read", current_read_); |
|
373 |
2 |
} |
|
374 |
|||
375 |
2 |
SET_MEMORY_INFO_NAME(FileHandle) |
|
376 |
2 |
SET_SELF_SIZE(FileHandle) |
|
377 |
|||
378 |
FileHandle(const FileHandle&) = delete; |
||
379 |
FileHandle& operator=(const FileHandle&) = delete; |
||
380 |
FileHandle(const FileHandle&&) = delete; |
||
381 |
FileHandle& operator=(const FileHandle&&) = delete; |
||
382 |
|||
383 |
private: |
||
384 |
FileHandle(Environment* env, v8::Local<v8::Object> obj, int fd); |
||
385 |
|||
386 |
// Synchronous close that emits a warning |
||
387 |
void Close(); |
||
388 |
void AfterClose(); |
||
389 |
|||
390 |
class CloseReq : public ReqWrap<uv_fs_t> { |
||
391 |
public: |
||
392 |
255 |
CloseReq(Environment* env, |
|
393 |
Local<Object> obj, |
||
394 |
Local<Promise> promise, |
||
395 |
Local<Value> ref) |
||
396 |
510 |
: ReqWrap(env, obj, AsyncWrap::PROVIDER_FILEHANDLECLOSEREQ) { |
|
397 |
255 |
promise_.Reset(env->isolate(), promise); |
|
398 |
255 |
ref_.Reset(env->isolate(), ref); |
|
399 |
255 |
} |
|
400 |
|||
401 |
1275 |
~CloseReq() override { |
|
402 |
255 |
uv_fs_req_cleanup(req()); |
|
403 |
255 |
promise_.Reset(); |
|
404 |
255 |
ref_.Reset(); |
|
405 |
✗✓ | 510 |
} |
406 |
|||
407 |
FileHandle* file_handle(); |
||
408 |
|||
409 |
void MemoryInfo(MemoryTracker* tracker) const override { |
||
410 |
tracker->TrackField("promise", promise_); |
||
411 |
tracker->TrackField("ref", ref_); |
||
412 |
} |
||
413 |
|||
414 |
SET_MEMORY_INFO_NAME(CloseReq) |
||
415 |
SET_SELF_SIZE(CloseReq) |
||
416 |
|||
417 |
void Resolve(); |
||
418 |
|||
419 |
void Reject(Local<Value> reason); |
||
420 |
|||
421 |
255 |
static CloseReq* from_req(uv_fs_t* req) { |
|
422 |
255 |
return static_cast<CloseReq*>(ReqWrap::from_req(req)); |
|
423 |
} |
||
424 |
|||
425 |
CloseReq(const CloseReq&) = delete; |
||
426 |
CloseReq& operator=(const CloseReq&) = delete; |
||
427 |
CloseReq(const CloseReq&&) = delete; |
||
428 |
CloseReq& operator=(const CloseReq&&) = delete; |
||
429 |
|||
430 |
private: |
||
431 |
v8::Global<Promise> promise_{}; |
||
432 |
v8::Global<Value> ref_{}; |
||
433 |
}; |
||
434 |
|||
435 |
// Asynchronous close |
||
436 |
inline MaybeLocal<Promise> ClosePromise(); |
||
437 |
|||
438 |
int fd_; |
||
439 |
bool closing_ = false; |
||
440 |
bool closed_ = false; |
||
441 |
int64_t read_offset_ = -1; |
||
442 |
int64_t read_length_ = -1; |
||
443 |
|||
444 |
bool reading_ = false; |
||
445 |
std::unique_ptr<FileHandleReadWrap> current_read_ = nullptr; |
||
446 |
}; |
||
447 |
|||
448 |
int MKDirpSync(uv_loop_t* loop, |
||
449 |
uv_fs_t* req, |
||
450 |
const std::string& path, |
||
451 |
int mode, |
||
452 |
uv_fs_cb cb = nullptr); |
||
453 |
} // namespace fs |
||
454 |
|||
455 |
} // namespace node |
||
456 |
|||
457 |
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
||
458 |
|||
459 |
#endif // SRC_NODE_FILE_H_ |
Generated by: GCOVR (Version 3.4) |