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