• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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 "common_func.h"
21 #include "file_utils.h"
22 #include "randomaccessfile_entity.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     std::unique_ptr<char[]> guardWriteStr_ = nullptr;
279     int actLen = 0;
AsyncIORafWriteArgOHOS::FileManagement::ModuleFileIO::AsyncIORafWriteArg280     explicit AsyncIORafWriteArg(NVal refWriteArrayBuf) : rafRefWriteArrayBuf(refWriteArrayBuf) {}
AsyncIORafWriteArgOHOS::FileManagement::ModuleFileIO::AsyncIORafWriteArg281     explicit AsyncIORafWriteArg(std::unique_ptr<char[]> &&guardWriteStr) : guardWriteStr_(move(guardWriteStr)) {}
282     ~AsyncIORafWriteArg() = default;
283 };
284 
WriteExec(napi_env env,NFuncArg & funcArg,RandomAccessFileEntity * rafEntity)285 static napi_value WriteExec(napi_env env, NFuncArg &funcArg, RandomAccessFileEntity* rafEntity)
286 {
287     bool succ = false;
288     void *buf = nullptr;
289     size_t len = 0;
290     int64_t offset = 0;
291     unique_ptr<char[]> bufGuard = nullptr;
292     tie(succ, bufGuard, buf, len, offset) =
293         CommonFunc::GetWriteArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
294     if (!succ) {
295         HILOGE("Invalid buffer/options");
296         NError(EINVAL).ThrowErr(env);
297         return nullptr;
298     }
299 
300     auto arg = CreateSharedPtr<AsyncIORafWriteArg>(move(bufGuard));
301     if (arg == nullptr) {
302         HILOGE("Failed to request heap memory.");
303         NError(ENOMEM).ThrowErr(env);
304         return nullptr;
305     }
306     offset = CalculateOffset(offset, rafEntity->filePointer);
307     auto cbExec = [env, arg, buf, len, fd = rafEntity->fd.get()->GetFD(), offset, rafEntity]() -> NError {
308         if (!rafEntity || !rafEntity->fd.get()) {
309             HILOGE("RandomAccessFile has been closed in write cbExec possibly");
310             return NError(EIO);
311         }
312         int writeLen = DoWriteRAF(env, buf, len, fd, offset);
313         if (writeLen < 0) {
314             HILOGE("Failed to write file for %{public}d", writeLen);
315             return NError(writeLen);
316         }
317         arg->actLen = writeLen;
318         rafEntity->filePointer = offset + writeLen;
319         return NError(ERRNO_NOERR);
320     };
321 
322     auto cbCompl = [arg](napi_env env, NError err) -> NVal {
323         if (err) {
324             return { env, err.GetNapiErr(env) };
325         }
326         return { NVal::CreateInt64(env, arg->actLen) };
327     };
328 
329     NVal thisVar(env, funcArg.GetThisVar());
330     if (funcArg.GetArgc() == NARG_CNT::ONE || (funcArg.GetArgc() == NARG_CNT::TWO &&
331         !NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function))) {
332         return NAsyncWorkPromise(env, thisVar).Schedule(writeProcedureName, cbExec, cbCompl).val_;
333     } else {
334         int cbIdx = ((funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::THIRD);
335         NVal cb(env, funcArg[cbIdx]);
336         return NAsyncWorkCallback(env, thisVar, cb).Schedule(writeProcedureName, cbExec, cbCompl).val_;
337     }
338 }
339 
Write(napi_env env,napi_callback_info info)340 napi_value RandomAccessFileNExporter::Write(napi_env env, napi_callback_info info)
341 {
342     NFuncArg funcArg(env, info);
343     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
344         HILOGE("Number of arguments unmatched");
345         NError(EINVAL).ThrowErr(env);
346         return nullptr;
347     }
348     auto[succ, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
349     if (!succ) {
350         HILOGE("Failed to get entity of RandomAccessFile");
351         NError(EIO).ThrowErr(env);
352         return nullptr;
353     }
354     return WriteExec(env, funcArg, rafEntity);
355 }
356 
CloseFd(int fd)357 static NError CloseFd(int fd)
358 {
359     std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> close_req = {
360         new uv_fs_t, CommonFunc::fs_req_cleanup };
361     if (!close_req) {
362         HILOGE("Failed to request heap memory.");
363         return NError(ENOMEM);
364     }
365     int ret = uv_fs_close(nullptr, close_req.get(), fd, nullptr);
366     if (ret < 0) {
367         HILOGE("Failed to close file with ret: %{public}d", ret);
368         return NError(ret);
369     }
370     return NError(ERRNO_NOERR);
371 }
372 
CloseSync(napi_env env,napi_callback_info info)373 napi_value RandomAccessFileNExporter::CloseSync(napi_env env, napi_callback_info info)
374 {
375     NFuncArg funcArg(env, info);
376     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
377         HILOGE("Number of arguments unmatched");
378         NError(EINVAL).ThrowErr(env);
379         return nullptr;
380     }
381     auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
382     if (!succEntity) {
383         HILOGE("Failed to get entity of RandomAccessFile");
384         NError(EIO).ThrowErr(env);
385         return nullptr;
386     }
387     auto err = CloseFd(rafEntity->fd.get()->GetFD());
388     if (err) {
389         err.ThrowErr(env);
390         return nullptr;
391     }
392     auto fp = NClass::RemoveEntityOfFinal<RandomAccessFileEntity>(env, funcArg.GetThisVar());
393     if (!fp) {
394         HILOGE("Failed to remove entity of RandomAccessFile");
395         NError(EIO).ThrowErr(env);
396         return nullptr;
397     }
398     return NVal::CreateUndefined(env).val_;
399 }
400 
Constructor(napi_env env,napi_callback_info info)401 napi_value RandomAccessFileNExporter::Constructor(napi_env env, napi_callback_info info)
402 {
403     NFuncArg funcArg(env, info);
404     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
405         HILOGE("Number of arguments unmatched");
406         NError(EINVAL).ThrowErr(env);
407         return nullptr;
408     }
409 
410     auto rafEntity = CreateUniquePtr<RandomAccessFileEntity>();
411     if (rafEntity == nullptr) {
412         HILOGE("Failed to request heap memory.");
413         NError(ENOMEM).ThrowErr(env);
414         return nullptr;
415     }
416     if (!NClass::SetEntityFor<RandomAccessFileEntity>(env, funcArg.GetThisVar(), move(rafEntity))) {
417         HILOGE("INNER BUG. Failed to wrap entity for obj RandomAccessFile");
418         NError(EIO).ThrowErr(env);
419         return nullptr;
420     }
421     return funcArg.GetThisVar();
422 }
423 
CreateStream(napi_env env,const string & streamName,RandomAccessFileEntity * rafEntity,int flags)424 static napi_value CreateStream(napi_env env, const string &streamName, RandomAccessFileEntity *rafEntity, int flags)
425 {
426     auto dstFd = dup(rafEntity->fd.get()->GetFD());
427     if (dstFd < 0) {
428         HILOGE("Failed to get valid fd, fail reason: %{public}s, fd: %{public}d", strerror(errno),
429                rafEntity->fd.get()->GetFD());
430         NError(errno).ThrowErr(env);
431         return nullptr;
432     }
433 
434     string path = "/proc/self/fd/" + to_string(dstFd);
435     auto buf = CreateUniquePtr<char[]>(BUF_SIZE);
436     int readLinkRes = readlink(path.c_str(), buf.get(), BUF_SIZE);
437     if (readLinkRes < 0) {
438         HILOGE("Failed to readlink uri, errno=%{public}d", errno);
439         close(dstFd);
440         NError(errno).ThrowErr(env);
441         return nullptr;
442     }
443     close(dstFd);
444 
445     napi_value filePath = NVal::CreateUTF8String(env, string(buf.get())).val_;
446     const char moduleName[] = "@ohos.file.streamrw";
447     napi_value streamrw;
448     napi_load_module(env, moduleName, &streamrw);
449     napi_value constructor = nullptr;
450     napi_get_named_property(env, streamrw, streamName.c_str(), &constructor);
451     napi_value streamObj = nullptr;
452 
453     NVal options = NVal::CreateObject(env);
454     if (rafEntity->start >= 0) {
455         options.AddProp("start", NVal::CreateInt64(env, rafEntity->start).val_);
456     }
457     if (rafEntity->end >= 0 && streamName == READ_STREAM_CLASS) {
458         options.AddProp("end", NVal::CreateInt64(env, rafEntity->end).val_);
459     }
460     if (streamName == WRITE_STREAM_CLASS) {
461         options.AddProp("mode", NVal::CreateInt32(env, flags).val_);
462     }
463 
464     napi_value argv[NARG_CNT::TWO] = {filePath, options.val_};
465     napi_status status = napi_new_instance(env, constructor, NARG_CNT::TWO, argv, &streamObj);
466     if (status != napi_ok) {
467         HILOGE("create stream obj fail");
468         return nullptr;
469     }
470 
471     return NVal(env, streamObj).val_;
472 }
473 
GetReadStream(napi_env env,napi_callback_info info)474 napi_value RandomAccessFileNExporter::GetReadStream(napi_env env, napi_callback_info info)
475 {
476     NFuncArg funcArg(env, info);
477     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
478         HILOGE("Number of arguments unmatched");
479         NError(EINVAL).ThrowErr(env);
480         return nullptr;
481     }
482     auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
483     if (!succEntity) {
484         HILOGE("Failed to get entity of RandomAccessFile");
485         NError(EIO).ThrowErr(env);
486         return nullptr;
487     }
488 
489     int flags = fcntl(rafEntity->fd.get()->GetFD(), F_GETFL);
490     unsigned int uflags = static_cast<unsigned int>(flags);
491     if (((uflags & O_ACCMODE) != O_RDONLY) && ((uflags & O_ACCMODE) != O_RDWR)) {
492         HILOGE("Failed to check Permission");
493         NError(EACCES).ThrowErr(env);
494         return nullptr;
495     }
496 
497     return CreateStream(env, READ_STREAM_CLASS, rafEntity, flags);
498 }
499 
GetWriteStream(napi_env env,napi_callback_info info)500 napi_value RandomAccessFileNExporter::GetWriteStream(napi_env env, napi_callback_info info)
501 {
502     NFuncArg funcArg(env, info);
503     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
504         HILOGE("Number of arguments unmatched");
505         NError(EINVAL).ThrowErr(env);
506         return nullptr;
507     }
508     auto [succEntity, rafEntity] = GetRAFEntity(env, funcArg.GetThisVar());
509     if (!succEntity) {
510         HILOGE("Failed to get entity of RandomAccessFile");
511         NError(EIO).ThrowErr(env);
512         return nullptr;
513     }
514 
515     int flags = fcntl(rafEntity->fd.get()->GetFD(), F_GETFL);
516     unsigned int uflags = static_cast<unsigned int>(flags);
517     if (((uflags & O_ACCMODE) != O_WRONLY) && ((uflags & O_ACCMODE) != O_RDWR)) {
518         HILOGE("Failed to check Permission");
519         NError(EACCES).ThrowErr(env);
520         return nullptr;
521     }
522 
523     return CreateStream(env, WRITE_STREAM_CLASS, rafEntity, flags);
524 }
525 
Export()526 bool RandomAccessFileNExporter::Export()
527 {
528     vector<napi_property_descriptor> props = {
529         NVal::DeclareNapiFunction("read", Read),
530         NVal::DeclareNapiFunction("readSync", ReadSync),
531         NVal::DeclareNapiFunction("write", Write),
532         NVal::DeclareNapiFunction("writeSync", WriteSync),
533         NVal::DeclareNapiFunction("setFilePointer", SetFilePointerSync),
534         NVal::DeclareNapiFunction("close", CloseSync),
535         NVal::DeclareNapiFunction("getReadStream", GetReadStream),
536         NVal::DeclareNapiFunction("getWriteStream", GetWriteStream),
537         NVal::DeclareNapiGetter("fd", GetFD),
538         NVal::DeclareNapiGetter("filePointer", GetFPointer),
539     };
540 
541     string className = GetClassName();
542     bool succ = false;
543     napi_value classValue = nullptr;
544     tie(succ, classValue) = NClass::DefineClass(exports_.env_, className,
545         RandomAccessFileNExporter::Constructor, move(props));
546     if (!succ) {
547         HILOGE("INNER BUG. Failed to define class");
548         NError(EIO).ThrowErr(exports_.env_);
549         return false;
550     }
551     succ = NClass::SaveClass(exports_.env_, className, classValue);
552     if (!succ) {
553         HILOGE("INNER BUG. Failed to define class");
554         NError(EIO).ThrowErr(exports_.env_);
555         return false;
556     }
557 
558     return exports_.AddProp(className, classValue);
559 }
560 
GetClassName()561 string RandomAccessFileNExporter::GetClassName()
562 {
563     return RandomAccessFileNExporter::className_;
564 }
565 
RandomAccessFileNExporter(napi_env env,napi_value exports)566 RandomAccessFileNExporter::RandomAccessFileNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
567 
~RandomAccessFileNExporter()568 RandomAccessFileNExporter::~RandomAccessFileNExporter() {}
569 } // namespace ModuleFileIO
570 } // namespace FileManagement
571 } // namespace OHOS