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