1 /*
2 * Copyright (C) 2022 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 "napi_fileaccess_helper.h"
17
18 #include <cstring>
19 #include <utility>
20 #include <vector>
21
22 #include "file_access_framework_errno.h"
23 #include "file_access_helper.h"
24 #include "file_info_entity.h"
25 #include "filemgmt_libn.h"
26 #include "hilog_wrapper.h"
27 #include "ifile_access_notify.h"
28 #include "napi_base_context.h"
29 #include "napi_common_fileaccess.h"
30 #include "napi_file_info_exporter.h"
31 #include "napi_notify_callback.h"
32 #include "napi_root_iterator_exporter.h"
33 #include "root_iterator_entity.h"
34 #include "securec.h"
35 #include "uri.h"
36
37 using namespace OHOS::AAFwk;
38 using namespace OHOS::AppExecFwk;
39 using namespace OHOS::FileManagement::LibN;
40
41 namespace OHOS {
42 namespace FileAccessFwk {
43 namespace {
44 const std::string FILEACCESS_CLASS_NAME = "FileAccessHelper";
45 static napi_ref g_constructorRef = nullptr;
46 constexpr uint32_t INITIAL_REFCOUNT = 1;
47 }
48
49 std::list<std::shared_ptr<FileAccessHelper>> g_fileAccessHelperList;
50
FileAccessHelperConstructor(napi_env env,napi_callback_info info)51 static napi_value FileAccessHelperConstructor(napi_env env, napi_callback_info info)
52 {
53 NFuncArg funcArg(env, info);
54 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
55 NError(EINVAL).ThrowErr(env);
56 return nullptr;
57 }
58
59 napi_value thisVar = funcArg.GetThisVar();
60 std::pair<std::shared_ptr<FileAccessHelper>, int> createResult{nullptr, ERR_OK};
61 bool isStageMode = false;
62 napi_status status = AbilityRuntime::IsStageContext(env, funcArg.GetArg(PARAM0), isStageMode);
63 if (status != napi_ok || !isStageMode) {
64 HILOG_INFO("No support FA Model");
65 NError(EINVAL).ThrowErr(env);
66 return nullptr;
67 }
68
69 auto context = OHOS::AbilityRuntime::GetStageModeContext(env, funcArg.GetArg(PARAM0));
70 if (context == nullptr) {
71 HILOG_ERROR("FileAccessHelperConstructor: failed to get native context");
72 NError(E_GETRESULT).ThrowErr(env);
73 return nullptr;
74 }
75
76 if (funcArg.GetArgc() == NARG_CNT::ONE) {
77 createResult = FileAccessHelper::Creator(context);
78 } else if (funcArg.GetArgc() == NARG_CNT::TWO) {
79 std::vector<AAFwk::Want> wants;
80 bool suss = UnwrapArrayWantFromJS(env, funcArg.GetArg(PARAM1), wants);
81 if (!suss) {
82 HILOG_ERROR("UnwrapArrayWantFromJS failed to get native wants");
83 NError(E_GETRESULT).ThrowErr(env);
84 return nullptr;
85 }
86 createResult = FileAccessHelper::Creator(context, wants);
87 }
88 if (createResult.first == nullptr || createResult.second != ERR_OK) {
89 HILOG_ERROR("FileAccessHelperConstructor: Creator failed ret=%{public}d", createResult.second);
90 NError(createResult.second).ThrowErr(env);
91 return nullptr;
92 }
93 g_fileAccessHelperList.emplace_back(createResult.first);
94
95 auto finalize = [](napi_env env, void *data, void *hint) {
96 FileAccessHelper *objectInfo = static_cast<FileAccessHelper *>(data);
97 if (objectInfo != nullptr) {
98 objectInfo->Release();
99 g_fileAccessHelperList.remove_if([objectInfo](const std::shared_ptr<FileAccessHelper> &fileAccessHelper) {
100 return objectInfo == fileAccessHelper.get();
101 });
102 objectInfo = nullptr;
103 }
104 };
105 if (napi_wrap(env, thisVar, createResult.first.get(), finalize, nullptr, nullptr) != napi_ok) {
106 finalize(env, createResult.first.get(), nullptr);
107 NError(E_GETRESULT).ThrowErr(env);
108 return nullptr;
109 }
110 return thisVar;
111 }
112
AcquireFileAccessHelperWrap(napi_env env,napi_callback_info info)113 napi_value AcquireFileAccessHelperWrap(napi_env env, napi_callback_info info)
114 {
115 NFuncArg funcArg(env, info);
116 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
117 NError(EINVAL).ThrowErr(env);
118 return nullptr;
119 }
120
121 napi_value result = nullptr;
122 napi_value cons = nullptr;
123 if (funcArg.GetArgc() == NARG_CNT::ONE) {
124 size_t requireArgc = ARGS_ONE;
125 size_t argc = ARGS_ONE;
126 napi_value args[ARGS_ONE] = {nullptr};
127 if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
128 return nullptr;
129 }
130
131 if (argc > requireArgc || napi_get_reference_value(env, g_constructorRef, &cons) != napi_ok) {
132 HILOG_ERROR("Wrong argument count%{public}zu. or g_constructorRef reference is fail", argc);
133 return nullptr;
134 }
135
136 if (napi_new_instance(env, cons, ARGS_ONE, args, &result) != napi_ok) {
137 return nullptr;
138 }
139 } else if (funcArg.GetArgc() == NARG_CNT::TWO) {
140 size_t requireArgc = ARGS_TWO;
141 size_t argc = ARGS_TWO;
142 napi_value args[ARGS_TWO] = {nullptr};
143 if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
144 return nullptr;
145 }
146
147 if (argc > requireArgc || napi_get_reference_value(env, g_constructorRef, &cons) != napi_ok) {
148 HILOG_ERROR("Wrong argument count%{public}zu. or g_constructorRef reference is fail", argc);
149 return nullptr;
150 }
151
152 if (napi_new_instance(env, cons, ARGS_TWO, args, &result) != napi_ok) {
153 return nullptr;
154 }
155 }
156
157 if (!IsTypeForNapiValue(env, result, napi_object)) {
158 HILOG_ERROR("IsTypeForNapiValue isn`t object");
159 return nullptr;
160 }
161
162 FileAccessHelper *fileAccessHelper = nullptr;
163 if (napi_unwrap(env, result, (void **)&fileAccessHelper) != napi_ok) {
164 HILOG_ERROR("Faild to get fileAccessHelper");
165 return nullptr;
166 }
167
168 if (fileAccessHelper == nullptr) {
169 HILOG_ERROR("fileAccessHelper is nullptr");
170 return nullptr;
171 }
172
173 return result;
174 }
175
NAPI_CreateFileAccessHelper(napi_env env,napi_callback_info info)176 napi_value NAPI_CreateFileAccessHelper(napi_env env, napi_callback_info info)
177 {
178 napi_value ret = AcquireFileAccessHelperWrap(env, info);
179 if (ret == nullptr) {
180 ret = WrapVoidToJS(env);
181 }
182 return ret;
183 }
184
NAPI_GetFileAccessAbilityInfo(napi_env env,napi_callback_info info)185 napi_value NAPI_GetFileAccessAbilityInfo(napi_env env, napi_callback_info info)
186 {
187 NFuncArg funcArg(env, info);
188 if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
189 NError(EINVAL).ThrowErr(env);
190 return nullptr;
191 }
192
193 auto result = std::make_shared<std::vector<AAFwk::Want>>();
194 if (result == nullptr) {
195 NError(E_GETRESULT).ThrowErr(env);
196 return nullptr;
197 }
198
199 auto cbExec = [result]() -> NError {
200 int ret = FileAccessHelper::GetRegisteredFileAccessExtAbilityInfo(*result);
201 return NError(ret);
202 };
203 auto cbComplete = [result](napi_env env, NError err) -> NVal {
204 if (err) {
205 return { env, err.GetNapiErr(env) };
206 }
207 napi_value jsArray = WrapArrayWantToJS(env, *result);
208 return {env, jsArray};
209 };
210 const std::string procedureName = "getFileAccessAbilityInfo";
211 NVal thisVar(env, funcArg.GetThisVar());
212 if (funcArg.GetArgc() == NARG_CNT::ZERO) {
213 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
214 }
215 NVal cb(env, funcArg[NARG_POS::FIRST]);
216 if (!cb.TypeIs(napi_function)) {
217 NError(EINVAL).ThrowErr(env);
218 return nullptr;
219 }
220 return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
221 }
222
FileAccessHelperInit(napi_env env,napi_value exports)223 napi_value FileAccessHelperInit(napi_env env, napi_value exports)
224 {
225 napi_property_descriptor properties[] = {
226 DECLARE_NAPI_FUNCTION("openFile", NAPI_OpenFile),
227 DECLARE_NAPI_FUNCTION("mkDir", NAPI_Mkdir),
228 DECLARE_NAPI_FUNCTION("createFile", NAPI_CreateFile),
229 DECLARE_NAPI_FUNCTION("delete", NAPI_Delete),
230 DECLARE_NAPI_FUNCTION("move", NAPI_Move),
231 DECLARE_NAPI_FUNCTION("rename", NAPI_Rename),
232 DECLARE_NAPI_FUNCTION("getRoots", NAPI_GetRoots),
233 DECLARE_NAPI_FUNCTION("access", NAPI_Access),
234 DECLARE_NAPI_FUNCTION("uriToFileInfo", NAPI_UriToFileInfo),
235 DECLARE_NAPI_FUNCTION("on", NAPI_On),
236 DECLARE_NAPI_FUNCTION("off", NAPI_Off)
237 };
238 napi_value cons = nullptr;
239 NAPI_CALL(env,
240 napi_define_class(env,
241 FILEACCESS_CLASS_NAME.c_str(),
242 NAPI_AUTO_LENGTH,
243 FileAccessHelperConstructor,
244 nullptr,
245 sizeof(properties) / sizeof(*properties),
246 properties,
247 &cons));
248 g_fileAccessHelperList.clear();
249 NAPI_CALL(env, napi_create_reference(env, cons, INITIAL_REFCOUNT, &g_constructorRef));
250 NAPI_CALL(env, napi_set_named_property(env, exports, FILEACCESS_CLASS_NAME.c_str(), cons));
251
252 napi_property_descriptor export_properties[] = {
253 DECLARE_NAPI_FUNCTION("createFileAccessHelper", NAPI_CreateFileAccessHelper),
254 DECLARE_NAPI_FUNCTION("getFileAccessAbilityInfo", NAPI_GetFileAccessAbilityInfo),
255 };
256 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(export_properties) / sizeof(export_properties[0]),
257 export_properties));
258 return exports;
259 }
260
InitOpenFlags(napi_env env,napi_value exports)261 void InitOpenFlags(napi_env env, napi_value exports)
262 {
263 char propertyName[] = "OPENFLAGS";
264 napi_property_descriptor desc[] = {
265 DECLARE_NAPI_STATIC_PROPERTY("READ", NVal::CreateInt32(env, READ).val_),
266 DECLARE_NAPI_STATIC_PROPERTY("WRITE", NVal::CreateInt32(env, WRITE).val_),
267 DECLARE_NAPI_STATIC_PROPERTY("WRITE_READ", NVal::CreateInt32(env, WRITE_READ).val_)
268 };
269 napi_value obj = nullptr;
270 napi_create_object(env, &obj);
271 napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
272 napi_set_named_property(env, exports, propertyName, obj);
273 }
274
GetFileAccessHelper(napi_env env,napi_value thisVar)275 static FileAccessHelper *GetFileAccessHelper(napi_env env, napi_value thisVar)
276 {
277 if (thisVar == nullptr) {
278 NError(EINVAL).ThrowErr(env);
279 return nullptr;
280 }
281
282 FileAccessHelper *fileAccessHelper = nullptr;
283 if (napi_unwrap(env, thisVar, (void **)&fileAccessHelper) != napi_ok) {
284 NError(E_GETRESULT).ThrowErr(env);
285 return nullptr;
286 }
287
288 if (fileAccessHelper == nullptr) {
289 NError(E_GETRESULT).ThrowErr(env);
290 return nullptr;
291 }
292 return fileAccessHelper;
293 }
294
GetReadArg(napi_env env,napi_value sourceFile,napi_value targetParent)295 static std::tuple<bool, std::unique_ptr<char[]>, std::unique_ptr<char[]>> GetReadArg(napi_env env,
296 napi_value sourceFile,
297 napi_value targetParent)
298 {
299 bool succ = false;
300 std::unique_ptr<char[]> uri = nullptr;
301 std::unique_ptr<char[]> name = nullptr;
302 std::tie(succ, uri, std::ignore) = NVal(env, sourceFile).ToUTF8String();
303 if (!succ) {
304 NError(EINVAL).ThrowErr(env);
305 return { false, std::move(uri), std::move(name) };
306 }
307
308 std::tie(succ, name, std::ignore) = NVal(env, targetParent).ToUTF8String();
309 if (!succ) {
310 NError(EINVAL).ThrowErr(env);
311 return { false, std::move(uri), std::move(name) };
312 }
313
314 return { true, std::move(uri), std::move(name) };
315 }
316
NAPI_OpenFile(napi_env env,napi_callback_info info)317 napi_value NAPI_OpenFile(napi_env env, napi_callback_info info)
318 {
319 NFuncArg funcArg(env, info);
320 if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
321 NError(EINVAL).ThrowErr(env);
322 return nullptr;
323 }
324
325 bool succ = false;
326 std::unique_ptr<char[]> uri;
327 std::tie(succ, uri, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
328 if (!succ) {
329 NError(EINVAL).ThrowErr(env);
330 return nullptr;
331 }
332
333 int flags;
334 std::tie(succ, flags) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
335 if (!succ) {
336 NError(EINVAL).ThrowErr(env);
337 return nullptr;
338 }
339
340 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
341 if (fileAccessHelper == nullptr) {
342 return nullptr;
343 }
344
345 auto result = std::make_shared<int>();
346 if (result == nullptr) {
347 NError(E_GETRESULT).ThrowErr(env);
348 return nullptr;
349 }
350
351 string uriString(uri.get());
352 auto cbExec = [uriString, flags, result, fileAccessHelper]() -> NError {
353 OHOS::Uri uri(uriString);
354 int ret = fileAccessHelper->OpenFile(uri, flags, *result);
355 return NError(ret);
356 };
357 auto cbComplete = [result](napi_env env, NError err) -> NVal {
358 if (err) {
359 return { env, err.GetNapiErr(env) };
360 }
361 return { NVal::CreateInt32(env, *result) };
362 };
363
364 const std::string procedureName = "openFile";
365 NVal thisVar(env, funcArg.GetThisVar());
366 if (funcArg.GetArgc() == NARG_CNT::TWO) {
367 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
368 }
369
370 NVal cb(env, funcArg[NARG_POS::THIRD]);
371 if (!cb.TypeIs(napi_function)) {
372 NError(EINVAL).ThrowErr(env);
373 return nullptr;
374 }
375 return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
376 }
377
NAPI_CreateFile(napi_env env,napi_callback_info info)378 napi_value NAPI_CreateFile(napi_env env, napi_callback_info info)
379 {
380 NFuncArg funcArg(env, info);
381 if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
382 NError(EINVAL).ThrowErr(env);
383 return nullptr;
384 }
385
386 bool succ = false;
387 std::unique_ptr<char[]> uri;
388 std::unique_ptr<char[]> displayName;
389 std::tie(succ, uri, displayName) = GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
390 if (!succ) {
391 return nullptr;
392 }
393
394 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
395 if (fileAccessHelper == nullptr) {
396 return nullptr;
397 }
398
399 auto result = std::make_shared<string>();
400 if (result == nullptr) {
401 NError(E_GETRESULT).ThrowErr(env);
402 return nullptr;
403 }
404
405 string uriString(uri.get());
406 string name(displayName.get());
407 auto cbExec = [uriString, name, result, fileAccessHelper]() -> NError {
408 OHOS::Uri uri(uriString);
409 std::string newFile = "";
410 OHOS::Uri newFileUri(newFile);
411 int ret = fileAccessHelper->CreateFile(uri, name, newFileUri);
412 *result = newFileUri.ToString();
413 return NError(ret);
414 };
415 auto cbComplete = [result](napi_env env, NError err) -> NVal {
416 if (err) {
417 return { env, err.GetNapiErr(env) };
418 }
419 return { NVal::CreateUTF8String(env, *result) };
420 };
421 const std::string procedureName = "createFile";
422 NVal thisVar(env, funcArg.GetThisVar());
423 if (funcArg.GetArgc() == NARG_CNT::TWO) {
424 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
425 }
426
427 NVal cb(env, funcArg[NARG_POS::THIRD]);
428 if (!cb.TypeIs(napi_function)) {
429 NError(EINVAL).ThrowErr(env);
430 return nullptr;
431 }
432 return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
433 }
434
NAPI_Mkdir(napi_env env,napi_callback_info info)435 napi_value NAPI_Mkdir(napi_env env, napi_callback_info info)
436 {
437 NFuncArg funcArg(env, info);
438 if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
439 NError(EINVAL).ThrowErr(env);
440 return nullptr;
441 }
442
443 bool succ = false;
444 std::unique_ptr<char[]> uri;
445 std::unique_ptr<char[]> displayName;
446 std::tie(succ, uri, displayName) = GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
447 if (!succ) {
448 return nullptr;
449 }
450
451 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
452 if (fileAccessHelper == nullptr) {
453 return nullptr;
454 }
455
456 auto result = std::make_shared<string>();
457 if (result == nullptr) {
458 NError(E_GETRESULT).ThrowErr(env);
459 return nullptr;
460 }
461
462 string uriString(uri.get());
463 string name(displayName.get());
464 auto cbExec = [uriString, name, result, fileAccessHelper]() -> NError {
465 OHOS::Uri uri(uriString);
466 std::string newFile = "";
467 OHOS::Uri newFileUri(newFile);
468 int ret = fileAccessHelper->Mkdir(uri, name, newFileUri);
469 *result = newFileUri.ToString();
470 return NError(ret);
471 };
472 auto cbComplete = [result](napi_env env, NError err) -> NVal {
473 if (err) {
474 return { env, err.GetNapiErr(env) };
475 }
476 return { NVal::CreateUTF8String(env, *result) };
477 };
478 const std::string procedureName = "mkdir";
479 NVal thisVar(env, funcArg.GetThisVar());
480 if (funcArg.GetArgc() == NARG_CNT::TWO) {
481 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
482 }
483
484 NVal cb(env, funcArg[NARG_POS::THIRD]);
485 if (!cb.TypeIs(napi_function)) {
486 NError(EINVAL).ThrowErr(env);
487 return nullptr;
488 }
489 return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
490 }
491
NAPI_Delete(napi_env env,napi_callback_info info)492 napi_value NAPI_Delete(napi_env env, napi_callback_info info)
493 {
494 NFuncArg funcArg(env, info);
495 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
496 NError(EINVAL).ThrowErr(env);
497 return nullptr;
498 }
499
500 bool succ = false;
501 std::unique_ptr<char[]> uri;
502 std::tie(succ, uri, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
503 if (!succ) {
504 NError(EINVAL).ThrowErr(env);
505 return nullptr;
506 }
507
508 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
509 if (fileAccessHelper == nullptr) {
510 return nullptr;
511 }
512
513 auto result = std::make_shared<int>();
514 if (result == nullptr) {
515 NError(E_GETRESULT).ThrowErr(env);
516 return nullptr;
517 }
518
519 string uriString(uri.get());
520 auto cbExec = [uriString, result, fileAccessHelper]() -> NError {
521 OHOS::Uri uri(uriString);
522 *result = fileAccessHelper->Delete(uri);
523 return NError(*result);
524 };
525 auto cbComplete = [result](napi_env env, NError err) -> NVal {
526 if (err) {
527 return { env, err.GetNapiErr(env) };
528 }
529 return { NVal::CreateInt32(env, ERRNO_NOERR) };
530 };
531
532 const std::string procedureName = "delete";
533 NVal thisVar(env, funcArg.GetThisVar());
534 if (funcArg.GetArgc() == NARG_CNT::ONE) {
535 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
536 }
537
538 NVal cb(env, funcArg[NARG_POS::SECOND]);
539 if (!cb.TypeIs(napi_function)) {
540 NError(EINVAL).ThrowErr(env);
541 return nullptr;
542 }
543 return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
544 }
545
NAPI_Move(napi_env env,napi_callback_info info)546 napi_value NAPI_Move(napi_env env, napi_callback_info info)
547 {
548 NFuncArg funcArg(env, info);
549 if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
550 NError(EINVAL).ThrowErr(env);
551 return nullptr;
552 }
553
554 bool succ = false;
555 std::unique_ptr<char[]> sourceFile;
556 std::unique_ptr<char[]> targetParent;
557 std::tie(succ, sourceFile, targetParent) = GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
558 if (!succ) {
559 return nullptr;
560 }
561
562 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
563 if (fileAccessHelper == nullptr) {
564 return nullptr;
565 }
566
567 auto result = std::make_shared<string>();
568 if (result == nullptr) {
569 NError(E_GETRESULT).ThrowErr(env);
570 return nullptr;
571 }
572
573 string sourceFileString(sourceFile.get());
574 string targetParentString(targetParent.get());
575 auto cbExec = [sourceFileString, targetParentString, result, fileAccessHelper]() -> NError {
576 OHOS::Uri uri(sourceFileString);
577 OHOS::Uri targetParentUri(targetParentString);
578 std::string newFile = "";
579 OHOS::Uri newFileUri(newFile);
580 int ret = fileAccessHelper->Move(uri, targetParentUri, newFileUri);
581 *result = newFileUri.ToString();
582 return NError(ret);
583 };
584 auto cbComplete = [result](napi_env env, NError err) -> NVal {
585 if (err) {
586 return { env, err.GetNapiErr(env) };
587 }
588 return { NVal::CreateUTF8String(env, *result) };
589 };
590 const std::string procedureName = "move";
591 NVal thisVar(env, funcArg.GetThisVar());
592 if (funcArg.GetArgc() == NARG_CNT::TWO) {
593 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
594 }
595
596 NVal cb(env, funcArg[NARG_POS::THIRD]);
597 if (!cb.TypeIs(napi_function)) {
598 NError(EINVAL).ThrowErr(env);
599 return nullptr;
600 }
601 return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
602 }
603
NAPI_Rename(napi_env env,napi_callback_info info)604 napi_value NAPI_Rename(napi_env env, napi_callback_info info)
605 {
606 NFuncArg funcArg(env, info);
607 if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
608 NError(EINVAL).ThrowErr(env);
609 return nullptr;
610 }
611
612 bool succ = false;
613 std::unique_ptr<char[]> uri;
614 std::unique_ptr<char[]> displayName;
615 std::tie(succ, uri, displayName) = GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
616 if (!succ) {
617 return nullptr;
618 }
619
620 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
621 if (fileAccessHelper == nullptr) {
622 return nullptr;
623 }
624
625 auto result = std::make_shared<string>();
626 if (result == nullptr) {
627 NError(E_GETRESULT).ThrowErr(env);
628 return nullptr;
629 }
630
631 string uriString(uri.get());
632 string name(displayName.get());
633 auto cbExec = [uriString, name, result, fileAccessHelper]() -> NError {
634 OHOS::Uri uri(uriString);
635 std::string newFile = "";
636 OHOS::Uri newFileUri(newFile);
637 int ret = fileAccessHelper->Rename(uri, name, newFileUri);
638 *result = newFileUri.ToString();
639 return NError(ret);
640 };
641 auto cbComplete = [result](napi_env env, NError err) -> NVal {
642 if (err) {
643 return { env, err.GetNapiErr(env) };
644 }
645 return { NVal::CreateUTF8String(env, *result) };
646 };
647 const std::string procedureName = "rename";
648 NVal thisVar(env, funcArg.GetThisVar());
649 if (funcArg.GetArgc() == NARG_CNT::TWO) {
650 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
651 }
652
653 NVal cb(env, funcArg[NARG_POS::THIRD]);
654 if (!cb.TypeIs(napi_function)) {
655 NError(EINVAL).ThrowErr(env);
656 return nullptr;
657 }
658 return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
659 }
660
MakeGetRootsResult(napi_env & env,FileAccessHelper * helper,std::vector<RootInfo> & rootInfoVec,NVal & nVal)661 static int MakeGetRootsResult(napi_env &env, FileAccessHelper *helper, std::vector<RootInfo> &rootInfoVec, NVal &nVal)
662 {
663 auto objRootIterator = NClass::InstantiateClass(env, NapiRootIteratorExporter::className_, {});
664 if (objRootIterator == nullptr) {
665 HILOG_INFO("Cannot instantiate class NapiRootIteratorExporter");
666 return E_GETRESULT;
667 }
668
669 auto rootIteratorEntity = NClass::GetEntityOf<RootIteratorEntity>(env, objRootIterator);
670 if (rootIteratorEntity == nullptr) {
671 HILOG_INFO("Cannot get the entity of RootIteratorEntity");
672 return E_GETRESULT;
673 }
674
675 std::lock_guard<std::mutex> lock(rootIteratorEntity->entityOperateMutex);
676 rootIteratorEntity->fileAccessHelper = helper;
677 rootIteratorEntity->devVec = std::move(rootInfoVec);
678 rootIteratorEntity->pos = 0;
679 nVal = { env, objRootIterator };
680
681 return ERR_OK;
682 }
683
NAPI_GetRoots(napi_env env,napi_callback_info info)684 napi_value NAPI_GetRoots(napi_env env, napi_callback_info info)
685 {
686 NFuncArg funcArg(env, info);
687 if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
688 NError(EINVAL).ThrowErr(env);
689 return nullptr;
690 }
691
692 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
693 if (fileAccessHelper == nullptr) {
694 NError(E_GETRESULT).ThrowErr(env);
695 return nullptr;
696 }
697
698 auto result = std::make_shared<std::vector<RootInfo>>();
699 if (result == nullptr) {
700 NError(E_GETRESULT).ThrowErr(env);
701 return nullptr;
702 }
703
704 auto cbExec = [result, fileAccessHelper]() -> NError {
705 int ret = fileAccessHelper->GetRoots(*result);
706 return NError(ret);
707 };
708 auto cbComplete = [fileAccessHelper, result](napi_env env, NError err) -> NVal {
709 if (err) {
710 return { env, err.GetNapiErr(env) };
711 }
712
713 NVal nVal;
714 int ret = MakeGetRootsResult(env, fileAccessHelper, *result, nVal);
715 if (ret != ERR_OK) {
716 return { env, NError([ret]() -> std::tuple<uint32_t, std::string> {
717 return { ret, "Make GetRoots Result fail" };
718 }).GetNapiErr(env) };
719 }
720
721 return nVal;
722 };
723
724 const std::string procedureName = "getRoots";
725 NVal thisVar(env, funcArg.GetThisVar());
726 if (funcArg.GetArgc() == NARG_CNT::ZERO) {
727 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
728 }
729
730 NVal cb(env, funcArg[NARG_POS::FIRST]);
731 if (!cb.TypeIs(napi_function)) {
732 NError(EINVAL).ThrowErr(env);
733 return nullptr;
734 }
735 return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
736 }
737
NAPI_Access(napi_env env,napi_callback_info info)738 napi_value NAPI_Access(napi_env env, napi_callback_info info)
739 {
740 NFuncArg funcArg(env, info);
741 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
742 NError(EINVAL).ThrowErr(env);
743 return nullptr;
744 }
745
746 bool succ = false;
747 std::unique_ptr<char[]> uri;
748 std::tie(succ, uri, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
749 if (!succ) {
750 NError(EINVAL).ThrowErr(env);
751 return nullptr;
752 }
753
754 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
755 if (fileAccessHelper == nullptr) {
756 return nullptr;
757 }
758
759 auto result = std::make_shared<bool>();
760 string uriString(uri.get());
761 auto cbExec = [uriString, result, fileAccessHelper]() -> NError {
762 OHOS::Uri uri(uriString);
763 bool isExist = false;
764 int ret = fileAccessHelper->Access(uri, isExist);
765 *result = isExist;
766 return NError(ret);
767 };
768 auto cbComplete = [result](napi_env env, NError err) -> NVal {
769 if (err) {
770 return { env, err.GetNapiErr(env) };
771 }
772 return { NVal::CreateBool(env, *result) };
773 };
774
775 const std::string procedureName = "access";
776 NVal thisVar(env, funcArg.GetThisVar());
777 if (funcArg.GetArgc() == NARG_CNT::ONE) {
778 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
779 }
780 NVal cb(env, funcArg[NARG_POS::SECOND]);
781 if (!cb.TypeIs(napi_function)) {
782 NError(EINVAL).ThrowErr(env);
783 return nullptr;
784 }
785 return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
786 }
787
MakeFileInfoResult(napi_env & env,FileAccessHelper * helper,FileInfo & fileinfo,NVal & nVal)788 static int MakeFileInfoResult(napi_env &env, FileAccessHelper *helper, FileInfo &fileinfo, NVal &nVal)
789 {
790 auto objFileInfo = NClass::InstantiateClass(env, NapiFileInfoExporter::className_, {});
791 if (objFileInfo == nullptr) {
792 HILOG_INFO("Cannot instantiate class NapiFileInfoExporter");
793 return E_GETRESULT;
794 }
795
796 auto fileInfoEntity = NClass::GetEntityOf<FileInfoEntity>(env, objFileInfo);
797 if (fileInfoEntity == nullptr) {
798 HILOG_INFO("Cannot get the entity of fileInfoEntity");
799 return E_GETRESULT;
800 }
801 fileInfoEntity->fileAccessHelper = helper;
802 fileInfoEntity->fileInfo = std::move(fileinfo);
803 nVal = { env, objFileInfo };
804
805 return ERR_OK;
806 }
807
NAPI_UriToFileInfo(napi_env env,napi_callback_info info)808 napi_value NAPI_UriToFileInfo(napi_env env, napi_callback_info info)
809 {
810 NFuncArg funcArg(env, info);
811 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
812 NError(EINVAL).ThrowErr(env);
813 return nullptr;
814 }
815
816 bool succ = false;
817 std::unique_ptr<char[]> uri;
818 std::tie(succ, uri, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
819 if (!succ) {
820 NError(EINVAL).ThrowErr(env);
821 return nullptr;
822 }
823
824 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
825 if (fileAccessHelper == nullptr) {
826 return nullptr;
827 }
828
829 auto result = std::make_shared<FileInfo>();
830 if (result == nullptr) {
831 NError(E_GETRESULT).ThrowErr(env);
832 return nullptr;
833 }
834
835 string uriString(uri.get());
836 auto cbExec = [uriString, result, fileAccessHelper]() -> NError {
837 OHOS::Uri uri(uriString);
838 int ret = fileAccessHelper->UriToFileInfo(uri, *result);
839 return NError(ret);
840 };
841 auto cbComplete = [fileAccessHelper, result](napi_env env, NError err) -> NVal {
842 if (err) {
843 return { env, err.GetNapiErr(env) };
844 }
845
846 NVal nVal;
847 int ret = MakeFileInfoResult(env, fileAccessHelper, *result, nVal);
848 if (ret != ERR_OK) {
849 return { env, NError([ret]() -> std::tuple<uint32_t, std::string> {
850 return { ret, "Make FileInfo Result fail" };
851 }).GetNapiErr(env) };
852 }
853
854 return nVal;
855 };
856
857 const std::string procedureName = "uriToFileInfo";
858 NVal thisVar(env, funcArg.GetThisVar());
859 if (funcArg.GetArgc() == NARG_CNT::ONE) {
860 return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
861 }
862 NVal cb(env, funcArg[NARG_POS::SECOND]);
863 if (!cb.TypeIs(napi_function)) {
864 NError(EINVAL).ThrowErr(env);
865 return nullptr;
866 }
867 return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
868 }
869
NAPI_On(napi_env env,napi_callback_info info)870 napi_value NAPI_On(napi_env env, napi_callback_info info)
871 {
872 NFuncArg funcArg(env, info);
873 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
874 NError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
875 return nullptr;
876 }
877
878 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
879 if (fileAccessHelper == nullptr) {
880 NError(EINVAL).ThrowErr(env, "Get FileAccessHelper fail");
881 return nullptr;
882 }
883
884 napi_value napiCallback = funcArg[NARG_POS::FIRST];
885 if (!NVal(env, napiCallback).TypeIs(napi_function)) {
886 NError(EINVAL).ThrowErr(env, "Argument must be function");
887 return nullptr;
888 }
889
890 std::shared_ptr<INotifyCallback> callback = std::make_shared<NapiNotifyCallback>(env, napiCallback);
891 if (callback == nullptr) {
892 NError(EINVAL).ThrowErr(env, "new NapiNotifyCallback fail.");
893 return nullptr;
894 }
895
896 auto retCode = fileAccessHelper->On(callback);
897 if (retCode != ERR_OK) {
898 NError(retCode).ThrowErr(env, "FileAccessHelper::On fail.");
899 return nullptr;
900 }
901 return NVal::CreateUndefined(env).val_;
902 }
903
NAPI_Off(napi_env env,napi_callback_info info)904 napi_value NAPI_Off(napi_env env, napi_callback_info info)
905 {
906 NFuncArg funcArg(env, info);
907 if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
908 NError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
909 return nullptr;
910 }
911
912 FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar());
913 if (fileAccessHelper == nullptr) {
914 NError(EINVAL).ThrowErr(env, "Get FileAccessHelper fail");
915 return nullptr;
916 }
917
918 auto retCode = fileAccessHelper->Off();
919 if (retCode != ERR_OK) {
920 NError(retCode).ThrowErr(env, "FileAccessHelper::Off fail.");
921 return nullptr;
922 }
923 return NVal::CreateUndefined(env).val_;
924 }
925 } // namespace FileAccessFwk
926 } // namespace OHOS