1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "randomaccessfile_n_exporter.h"
17
18 #include <fcntl.h>
19
20 #include "file_utils.h"
21 #include "randomaccessfile_entity.h"
22 #include "../common_func.h"
23
24 namespace OHOS {
25 namespace FileManagement {
26 namespace ModuleFileIO {
27 using namespace std;
28 using namespace OHOS::FileManagement::LibN;
29 const int BUF_SIZE = 1024;
30 const string READ_STREAM_CLASS = "ReadStream";
31 const string WRITE_STREAM_CLASS = "WriteStream";
32
GetRAFEntity(napi_env env,napi_value raf_entity)33 static tuple<bool, RandomAccessFileEntity*> GetRAFEntity(napi_env env, napi_value raf_entity)
34 {
35 auto rafEntity = NClass::GetEntityOf<RandomAccessFileEntity>(env, raf_entity);
36 if (!rafEntity) {
37 return { false, nullptr };
38 }
39 return { true, rafEntity };
40 }
41
DoReadRAF(napi_env env,void * buf,size_t len,int fd,int64_t offset)42 static int DoReadRAF(napi_env env, void* buf, size_t len, int fd, int64_t offset)
43 {
44 std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> read_req = {
45 new (nothrow) uv_fs_t, CommonFunc::fs_req_cleanup };
46 if (read_req == nullptr) {
47 HILOGE("Failed to request heap memory.");
48 return ENOMEM;
49 }
50 uv_buf_t iov = uv_buf_init(static_cast<char *>(buf), len);
51 int ret = uv_fs_read(nullptr, read_req.get(), fd, &iov, 1, offset, nullptr);
52 return ret;
53 }
54
DoWriteRAF(napi_env env,void * buf,size_t len,int fd,int64_t offset)55 static int DoWriteRAF(napi_env env, void* buf, size_t len, int fd, int64_t offset)
56 {
57 std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> write_req = {
58 new (nothrow) uv_fs_t, CommonFunc::fs_req_cleanup };
59 if (write_req == nullptr) {
60 HILOGE("Failed to request heap memory.");
61 return ENOMEM;
62 }
63 uv_buf_t iov = uv_buf_init(static_cast<char *>(buf), len);
64 int ret = uv_fs_write(nullptr, write_req.get(), fd, &iov, 1, offset, nullptr);
65 return ret;
66 }
67
GetFD(napi_env env,napi_callback_info info)68 napi_value RandomAccessFileNExporter::GetFD(napi_env env, napi_callback_info info)
69 {
70 NFuncArg funcArg(env, info);
71 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
72 HILOGE("Number of arguments unmatched");
73 NError(EINVAL).ThrowErr(env);
74 return nullptr;
75 }
76 auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
77 if (!succEntity) {
78 HILOGE("Failed to get entity of RandomAccessFile");
79 NError(EIO).ThrowErr(env);
80 return nullptr;
81 }
82 return NVal::CreateInt32(env, rafEntity->fd.get()->GetFD()).val_;
83 }
84
GetFPointer(napi_env env,napi_callback_info info)85 napi_value RandomAccessFileNExporter::GetFPointer(napi_env env, napi_callback_info info)
86 {
87 NFuncArg funcArg(env, info);
88 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
89 HILOGE("Number of arguments unmatched");
90 NError(EINVAL).ThrowErr(env);
91 return nullptr;
92 }
93 auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
94 if (!succEntity) {
95 HILOGE("Failed to get entity of RandomAccessFile");
96 NError(EIO).ThrowErr(env);
97 return nullptr;
98 }
99 return NVal::CreateInt64(env, rafEntity->filePointer).val_;
100 }
101
SetFilePointerSync(napi_env env,napi_callback_info info)102 napi_value RandomAccessFileNExporter::SetFilePointerSync(napi_env env, napi_callback_info info)
103 {
104 NFuncArg funcArg(env, info);
105 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
106 HILOGE("Number of arguments unmatched");
107 NError(EINVAL).ThrowErr(env);
108 return nullptr;
109 }
110 auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
111 if (!succEntity) {
112 HILOGE("Failed to get entity of RandomAccessFile");
113 NError(EIO).ThrowErr(env);
114 return nullptr;
115 }
116 auto [succ, fp] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt64();
117 if (!succ) {
118 HILOGE("Invalid filePointer");
119 NError(EINVAL).ThrowErr(env);
120 return nullptr;
121 }
122 rafEntity->filePointer = fp;
123 return NVal::CreateUndefined(env).val_;
124 }
125
CalculateOffset(int64_t offset,int64_t fPointer)126 static int64_t CalculateOffset(int64_t offset, int64_t fPointer)
127 {
128 if (offset < 0) {
129 HILOGD("No specified offset provided");
130 offset = fPointer;
131 } else {
132 offset += fPointer;
133 }
134 return offset;
135 }
136
ReadSync(napi_env env,napi_callback_info info)137 napi_value RandomAccessFileNExporter::ReadSync(napi_env env, napi_callback_info info)
138 {
139 NFuncArg funcArg(env, info);
140 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
141 HILOGE("Number of arguments unmatched");
142 NError(EINVAL).ThrowErr(env);
143 return nullptr;
144 }
145 auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
146 if (!succEntity) {
147 HILOGE("Failed to get entity of RandomAccessFile");
148 NError(EIO).ThrowErr(env);
149 return nullptr;
150 }
151 auto [succ, buf, len, offset] =
152 CommonFunc::GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
153 if (!succ) {
154 HILOGE("Invalid buffer/options");
155 NError(EINVAL).ThrowErr(env);
156 return nullptr;
157 }
158 offset = CalculateOffset(offset, rafEntity->filePointer);
159 int actLen = DoReadRAF(env, buf, len, rafEntity->fd.get()->GetFD(), offset);
160 if (actLen < 0) {
161 HILOGE("Failed to read file for %{public}d", actLen);
162 NError(actLen).ThrowErr(env);
163 return nullptr;
164 }
165 rafEntity->filePointer = offset + actLen;
166 return NVal::CreateInt64(env, actLen).val_;
167 }
168
169 struct AsyncIORafReadArg {
170 int lenRead { 0 };
171 NRef rafRefReadBuf;
172
AsyncIORafReadArgOHOS::FileManagement::ModuleFileIO::AsyncIORafReadArg173 explicit AsyncIORafReadArg(NVal jsReadBuf) : rafRefReadBuf(jsReadBuf) {}
174 ~AsyncIORafReadArg() = default;
175 };
176
ReadExec(napi_env env,NFuncArg & funcArg,RandomAccessFileEntity * rafEntity)177 static napi_value ReadExec(napi_env env, NFuncArg &funcArg, RandomAccessFileEntity* rafEntity)
178 {
179 bool succ = false;
180 void *buf = nullptr;
181 size_t len = 0;
182 int64_t offset = 0;
183 tie(succ, buf, len, offset) = CommonFunc::GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
184 if (!succ) {
185 HILOGE("Invalid buffer/options");
186 NError(EINVAL).ThrowErr(env);
187 return nullptr;
188 }
189
190 auto arg = CreateSharedPtr<AsyncIORafReadArg>(NVal(env, funcArg[NARG_POS::FIRST]));
191 if (arg == nullptr) {
192 HILOGE("Failed to request heap memory.");
193 NError(ENOMEM).ThrowErr(env);
194 return nullptr;
195 }
196 offset = CalculateOffset(offset, rafEntity->filePointer);
197 auto cbExec = [env, arg, buf, len, offset, rafEntity]() -> NError {
198 if (!rafEntity || !rafEntity->fd.get()) {
199 HILOGE("RandomAccessFile has been closed in read cbExec possibly");
200 return NError(EIO);
201 }
202 int actLen = DoReadRAF(env, buf, len, rafEntity->fd.get()->GetFD(), offset);
203 if (actLen < 0) {
204 return NError(actLen);
205 }
206 arg->lenRead = actLen;
207 rafEntity->filePointer = offset + actLen;
208 return NError(ERRNO_NOERR);
209 };
210 auto cbCompl = [arg](napi_env env, NError err) -> NVal {
211 if (err) {
212 return { env, err.GetNapiErr(env) };
213 }
214 return { NVal::CreateInt64(env, static_cast<int64_t>(arg->lenRead)) };
215 };
216
217 NVal thisVar(env, funcArg.GetThisVar());
218 if (funcArg.GetArgc() == NARG_CNT::ONE || (funcArg.GetArgc() == NARG_CNT::TWO &&
219 !NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function))) {
220 return NAsyncWorkPromise(env, thisVar).Schedule(readProcedureName, cbExec, cbCompl).val_;
221 } else {
222 int cbIdx = ((funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::THIRD);
223 NVal cb(env, funcArg[cbIdx]);
224 return NAsyncWorkCallback(env, thisVar, cb).Schedule(readProcedureName, cbExec, cbCompl).val_;
225 }
226 }
227
Read(napi_env env,napi_callback_info info)228 napi_value RandomAccessFileNExporter::Read(napi_env env, napi_callback_info info)
229 {
230 NFuncArg funcArg(env, info);
231 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
232 HILOGE("Number of arguments unmatched");
233 NError(EINVAL).ThrowErr(env);
234 return nullptr;
235 }
236 auto[succ, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
237 if (!succ) {
238 HILOGE("Failed to get entity of RandomAccessFile");
239 NError(EIO).ThrowErr(env);
240 return nullptr;
241 }
242 return ReadExec(env, funcArg, rafEntity);
243 }
244
WriteSync(napi_env env,napi_callback_info info)245 napi_value RandomAccessFileNExporter::WriteSync(napi_env env, napi_callback_info info)
246 {
247 NFuncArg funcArg(env, info);
248 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
249 HILOGE("Number of arguments unmatched");
250 NError(EINVAL).ThrowErr(env);
251 return nullptr;
252 }
253 auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
254 if (!succEntity) {
255 HILOGE("Failed to get entity of RandomAccessFile");
256 NError(EIO).ThrowErr(env);
257 return nullptr;
258 }
259 auto [succ, ignore, buf, len, offset] =
260 CommonFunc::GetWriteArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
261 if (!succ) {
262 HILOGE("Invalid buffer/options");
263 NError(EINVAL).ThrowErr(env);
264 return nullptr;
265 }
266 offset = CalculateOffset(offset, rafEntity->filePointer);
267 int writeLen = DoWriteRAF(env, buf, len, rafEntity->fd.get()->GetFD(), offset);
268 if (writeLen < 0) {
269 NError(writeLen).ThrowErr(env);
270 return nullptr;
271 }
272 rafEntity->filePointer = offset + writeLen;
273 return NVal::CreateInt64(env, writeLen).val_;
274 }
275
276 struct AsyncIORafWriteArg {
277 NRef rafRefWriteArrayBuf;
278 int actLen = 0;
AsyncIORafWriteArgOHOS::FileManagement::ModuleFileIO::AsyncIORafWriteArg279 explicit AsyncIORafWriteArg(NVal refWriteArrayBuf) : rafRefWriteArrayBuf(refWriteArrayBuf) {}
280 ~AsyncIORafWriteArg() = default;
281 };
282
WriteExec(napi_env env,NFuncArg & funcArg,RandomAccessFileEntity * rafEntity)283 static napi_value WriteExec(napi_env env, NFuncArg &funcArg, RandomAccessFileEntity* rafEntity)
284 {
285 bool succ = false;
286 void *buf = nullptr;
287 size_t len = 0;
288 int64_t offset = 0;
289 tie(succ, ignore, buf, len, offset) =
290 CommonFunc::GetWriteArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
291 if (!succ) {
292 HILOGE("Invalid buffer/options");
293 NError(EINVAL).ThrowErr(env);
294 return nullptr;
295 }
296
297 auto arg = CreateSharedPtr<AsyncIORafWriteArg>(NVal(env, funcArg[NARG_POS::FIRST]));
298 if (arg == nullptr) {
299 HILOGE("Failed to request heap memory.");
300 NError(ENOMEM).ThrowErr(env);
301 return nullptr;
302 }
303 offset = CalculateOffset(offset, rafEntity->filePointer);
304 auto cbExec = [env, arg, buf, len, fd = rafEntity->fd.get()->GetFD(), offset, rafEntity]() -> NError {
305 if (!rafEntity || !rafEntity->fd.get()) {
306 HILOGE("RandomAccessFile has been closed in write cbExec possibly");
307 return NError(EIO);
308 }
309 int writeLen = DoWriteRAF(env, buf, len, fd, offset);
310 if (writeLen < 0) {
311 HILOGE("Failed to write file for %{public}d", writeLen);
312 return NError(writeLen);
313 }
314 arg->actLen = writeLen;
315 rafEntity->filePointer = offset + writeLen;
316 return NError(ERRNO_NOERR);
317 };
318
319 auto cbCompl = [arg](napi_env env, NError err) -> NVal {
320 if (err) {
321 return { env, err.GetNapiErr(env) };
322 } else {
323 return { NVal::CreateInt64(env, arg->actLen) };
324 }
325 };
326
327 NVal thisVar(env, funcArg.GetThisVar());
328 if (funcArg.GetArgc() == NARG_CNT::ONE || (funcArg.GetArgc() == NARG_CNT::TWO &&
329 !NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function))) {
330 return NAsyncWorkPromise(env, thisVar).Schedule(writeProcedureName, cbExec, cbCompl).val_;
331 } else {
332 int cbIdx = ((funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::THIRD);
333 NVal cb(env, funcArg[cbIdx]);
334 return NAsyncWorkCallback(env, thisVar, cb).Schedule(writeProcedureName, cbExec, cbCompl).val_;
335 }
336 }
337
Write(napi_env env,napi_callback_info info)338 napi_value RandomAccessFileNExporter::Write(napi_env env, napi_callback_info info)
339 {
340 NFuncArg funcArg(env, info);
341 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
342 HILOGE("Number of arguments unmatched");
343 NError(EINVAL).ThrowErr(env);
344 return nullptr;
345 }
346 auto[succ, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
347 if (!succ) {
348 HILOGE("Failed to get entity of RandomAccessFile");
349 NError(EIO).ThrowErr(env);
350 return nullptr;
351 }
352 return WriteExec(env, funcArg, rafEntity);
353 }
354
CloseFd(int fd)355 static NError CloseFd(int fd)
356 {
357 std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> close_req = {
358 new uv_fs_t, CommonFunc::fs_req_cleanup };
359 if (!close_req) {
360 HILOGE("Failed to request heap memory.");
361 return NError(ENOMEM);
362 }
363 int ret = uv_fs_close(nullptr, close_req.get(), fd, nullptr);
364 if (ret < 0) {
365 HILOGE("Failed to close file with ret: %{public}d", ret);
366 return NError(ret);
367 }
368 return NError(ERRNO_NOERR);
369 }
370
CloseSync(napi_env env,napi_callback_info info)371 napi_value RandomAccessFileNExporter::CloseSync(napi_env env, napi_callback_info info)
372 {
373 NFuncArg funcArg(env, info);
374 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
375 HILOGE("Number of arguments unmatched");
376 NError(EINVAL).ThrowErr(env);
377 return nullptr;
378 }
379 auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
380 if (!succEntity) {
381 HILOGE("Failed to get entity of RandomAccessFile");
382 NError(EIO).ThrowErr(env);
383 return nullptr;
384 }
385 auto err = CloseFd(rafEntity->fd.get()->GetFD());
386 if (err) {
387 err.ThrowErr(env);
388 return nullptr;
389 }
390 auto fp = NClass::RemoveEntityOfFinal<RandomAccessFileEntity>(env, funcArg.GetThisVar());
391 if (!fp) {
392 HILOGE("Failed to remove entity of RandomAccessFile");
393 NError(EIO).ThrowErr(env);
394 return nullptr;
395 }
396 return NVal::CreateUndefined(env).val_;
397 }
398
Constructor(napi_env env,napi_callback_info info)399 napi_value RandomAccessFileNExporter::Constructor(napi_env env, napi_callback_info info)
400 {
401 NFuncArg funcArg(env, info);
402 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
403 HILOGE("Number of arguments unmatched");
404 NError(EINVAL).ThrowErr(env);
405 return nullptr;
406 }
407
408 auto rafEntity = CreateUniquePtr<RandomAccessFileEntity>();
409 if (rafEntity == nullptr) {
410 HILOGE("Failed to request heap memory.");
411 NError(ENOMEM).ThrowErr(env);
412 return nullptr;
413 }
414 if (!NClass::SetEntityFor<RandomAccessFileEntity>(env, funcArg.GetThisVar(), move(rafEntity))) {
415 HILOGE("INNER BUG. Failed to wrap entity for obj RandomAccessFile");
416 NError(EIO).ThrowErr(env);
417 return nullptr;
418 }
419 return funcArg.GetThisVar();
420 }
421
CreateStream(napi_env env,const string & streamName,RandomAccessFileEntity * rafEntity,int flags)422 static napi_value CreateStream(napi_env env, const string &streamName, RandomAccessFileEntity *rafEntity, int flags)
423 {
424 auto dstFd = dup(rafEntity->fd.get()->GetFD());
425 if (dstFd < 0) {
426 HILOGE("Failed to get valid fd, fail reason: %{public}s, fd: %{public}d", strerror(errno),
427 rafEntity->fd.get()->GetFD());
428 NError(errno).ThrowErr(env);
429 return nullptr;
430 }
431
432 string path = "/proc/self/fd/" + to_string(dstFd);
433 auto buf = CreateUniquePtr<char[]>(BUF_SIZE);
434 int readLinkRes = readlink(path.c_str(), buf.get(), BUF_SIZE);
435 if (readLinkRes < 0) {
436 HILOGE("Failed to readlink uri, errno=%{public}d", errno);
437 close(dstFd);
438 NError(errno).ThrowErr(env);
439 return nullptr;
440 }
441 close(dstFd);
442
443 napi_value filePath = NVal::CreateUTF8String(env, string(buf.get())).val_;
444 const char moduleName[] = "@ohos.file.streamrw";
445 napi_value streamrw;
446 napi_load_module(env, moduleName, &streamrw);
447 napi_value constructor = nullptr;
448 napi_get_named_property(env, streamrw, streamName.c_str(), &constructor);
449 napi_value streamObj = nullptr;
450
451 NVal options = NVal::CreateObject(env);
452 if (rafEntity->start >= 0) {
453 options.AddProp("start", NVal::CreateInt64(env, rafEntity->start).val_);
454 }
455 if (rafEntity->end >= 0 && streamName == READ_STREAM_CLASS) {
456 options.AddProp("end", NVal::CreateInt64(env, rafEntity->end).val_);
457 }
458 if (streamName == WRITE_STREAM_CLASS) {
459 options.AddProp("mode", NVal::CreateInt32(env, flags).val_);
460 }
461
462 napi_value argv[NARG_CNT::TWO] = {filePath, options.val_};
463 napi_status status = napi_new_instance(env, constructor, NARG_CNT::TWO, argv, &streamObj);
464 if (status != napi_ok) {
465 HILOGE("create stream obj fail");
466 return nullptr;
467 }
468
469 return NVal(env, streamObj).val_;
470 }
471
GetReadStream(napi_env env,napi_callback_info info)472 napi_value RandomAccessFileNExporter::GetReadStream(napi_env env, napi_callback_info info)
473 {
474 NFuncArg funcArg(env, info);
475 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
476 HILOGE("Number of arguments unmatched");
477 NError(EINVAL).ThrowErr(env);
478 return nullptr;
479 }
480 auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
481 if (!succEntity) {
482 HILOGE("Failed to get entity of RandomAccessFile");
483 NError(EIO).ThrowErr(env);
484 return nullptr;
485 }
486
487 int flags = fcntl(rafEntity->fd.get()->GetFD(), F_GETFL);
488 unsigned int uflags = static_cast<unsigned int>(flags);
489 if (((uflags & O_ACCMODE) != O_RDONLY) && ((uflags & O_ACCMODE) != O_RDWR)) {
490 HILOGE("Failed to check Permission");
491 NError(EACCES).ThrowErr(env);
492 return nullptr;
493 }
494
495 return CreateStream(env, READ_STREAM_CLASS, rafEntity, flags);
496 }
497
GetWriteStream(napi_env env,napi_callback_info info)498 napi_value RandomAccessFileNExporter::GetWriteStream(napi_env env, napi_callback_info info)
499 {
500 NFuncArg funcArg(env, info);
501 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
502 HILOGE("Number of arguments unmatched");
503 NError(EINVAL).ThrowErr(env);
504 return nullptr;
505 }
506 auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
507 if (!succEntity) {
508 HILOGE("Failed to get entity of RandomAccessFile");
509 NError(EIO).ThrowErr(env);
510 return nullptr;
511 }
512
513 int flags = fcntl(rafEntity->fd.get()->GetFD(), F_GETFL);
514 unsigned int uflags = static_cast<unsigned int>(flags);
515 if (((uflags & O_ACCMODE) != O_WRONLY) && ((uflags & O_ACCMODE) != O_RDWR)) {
516 HILOGE("Failed to check Permission");
517 NError(EACCES).ThrowErr(env);
518 return nullptr;
519 }
520
521 return CreateStream(env, WRITE_STREAM_CLASS, rafEntity, flags);
522 }
523
Export()524 bool RandomAccessFileNExporter::Export()
525 {
526 vector<napi_property_descriptor> props = {
527 NVal::DeclareNapiFunction("read", Read),
528 NVal::DeclareNapiFunction("readSync", ReadSync),
529 NVal::DeclareNapiFunction("write", Write),
530 NVal::DeclareNapiFunction("writeSync", WriteSync),
531 NVal::DeclareNapiFunction("setFilePointer", SetFilePointerSync),
532 NVal::DeclareNapiFunction("close", CloseSync),
533 NVal::DeclareNapiFunction("getReadStream", GetReadStream),
534 NVal::DeclareNapiFunction("getWriteStream", GetWriteStream),
535 NVal::DeclareNapiGetter("fd", GetFD),
536 NVal::DeclareNapiGetter("filePointer", GetFPointer),
537 };
538
539 string className = GetClassName();
540 bool succ = false;
541 napi_value classValue = nullptr;
542 tie(succ, classValue) = NClass::DefineClass(exports_.env_, className,
543 RandomAccessFileNExporter::Constructor, move(props));
544 if (!succ) {
545 HILOGE("INNER BUG. Failed to define class");
546 NError(EIO).ThrowErr(exports_.env_);
547 return false;
548 }
549 succ = NClass::SaveClass(exports_.env_, className, classValue);
550 if (!succ) {
551 HILOGE("INNER BUG. Failed to define class");
552 NError(EIO).ThrowErr(exports_.env_);
553 return false;
554 }
555
556 return exports_.AddProp(className, classValue);
557 }
558
GetClassName()559 string RandomAccessFileNExporter::GetClassName()
560 {
561 return RandomAccessFileNExporter::className_;
562 }
563
RandomAccessFileNExporter(napi_env env,napi_value exports)564 RandomAccessFileNExporter::RandomAccessFileNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
565
~RandomAccessFileNExporter()566 RandomAccessFileNExporter::~RandomAccessFileNExporter() {}
567 } // namespace ModuleFileIO
568 } // namespace FileManagement
569 } // namespace OHOS