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 "read_dir.h"
17
18 #include <dirent.h>
19 #include <memory>
20 #include <string>
21 #include <tuple>
22
23 #include "../../common/napi/n_async/n_async_work_callback.h"
24 #include "../../common/napi/n_async/n_async_work_promise.h"
25 #include "../../common/napi/n_class.h"
26 #include "../../common/napi/n_func_arg.h"
27 #include "../../common/napi/n_val.h"
28 #include "../../common/uni_error.h"
29
30 namespace OHOS {
31 namespace DistributedFS {
32 namespace ModuleFileIO {
33 using namespace std;
34
ParseJsPath(napi_env env,napi_value pathFromJs)35 static tuple<bool, unique_ptr<char[]>> ParseJsPath(napi_env env, napi_value pathFromJs)
36 {
37 auto [succ, path, ignore] = NVal(env, pathFromJs).ToUTF8StringPath();
38 return {succ, move(path)};
39 }
40
VerifyFilePath(char * path)41 static bool VerifyFilePath(char* path)
42 {
43 return strcmp(path, ".") != 0 && strcmp(path, "..") != 0;
44 }
45
Sync(napi_env env,napi_callback_info info)46 napi_value ReadDir::Sync(napi_env env, napi_callback_info info)
47 {
48 NFuncArg funcArg(env, info);
49 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
50 return nullptr;
51 }
52 auto [succ, path] = ParseJsPath(env, funcArg[NARG_POS::FIRST]);
53 if (!succ) {
54 UniError(EINVAL).ThrowErr(env, "Invalid path");
55 return nullptr;
56 }
57 unique_ptr<DIR, function<void(DIR *)>> dir = { opendir(path.get()), closedir };
58 if (!dir) {
59 UniError(errno).ThrowErr(env);
60 return nullptr;
61 }
62 vector<string> dirFiles;
63 struct dirent* entry = readdir(dir.get());
64 while (entry) {
65 if (VerifyFilePath(entry->d_name)) {
66 dirFiles.push_back(entry->d_name);
67 }
68 entry = readdir(dir.get());
69 }
70 return NVal::CreateArrayString(env, dirFiles).val_;
71 }
72
73 struct ReadDirArgs {
74 vector<string> dirFiles;
ReadDirArgsOHOS::DistributedFS::ModuleFileIO::ReadDirArgs75 explicit ReadDirArgs()
76 {
77 dirFiles = vector<string>();
78 }
79 ~ReadDirArgs() = default;
80 };
81
Async(napi_env env,napi_callback_info info)82 napi_value ReadDir::Async(napi_env env, napi_callback_info info)
83 {
84 NFuncArg funcArg(env, info);
85 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
86 UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
87 return nullptr;
88 }
89 string path;
90 auto [succ, tmp] = ParseJsPath(env, funcArg[NARG_POS::FIRST]);
91 if (!succ) {
92 UniError(EINVAL).ThrowErr(env, "Invalid path");
93 return nullptr;
94 }
95 path = tmp.get();
96 auto arg = make_shared<ReadDirArgs>();
97 auto cbExec = [arg, path](napi_env env) -> UniError {
98 unique_ptr<DIR, function<void(DIR *)>> dir = { opendir(path.c_str()), closedir };
99 if (!dir) {
100 return UniError(errno);
101 }
102 struct dirent* entry = readdir(dir.get());
103 vector<string> dirnames;
104 while (entry) {
105 if (VerifyFilePath(entry->d_name)) {
106 dirnames.push_back(entry->d_name);
107 }
108 entry = readdir(dir.get());
109 }
110 arg->dirFiles = dirnames;
111 return UniError(ERRNO_NOERR);
112 };
113 auto cbCompl = [arg](napi_env env, UniError err) -> NVal {
114 if (err) {
115 return { env, err.GetNapiErr(env) };
116 } else {
117 return NVal::CreateArrayString(env, arg->dirFiles);
118 }
119 };
120
121 NVal thisVar(env, funcArg.GetThisVar());
122 if (funcArg.GetArgc() == NARG_CNT::ONE) {
123 return NAsyncWorkPromise(env, thisVar).Schedule(readdirProcedureName, cbExec, cbCompl).val_;
124 } else {
125 NVal cb(env, funcArg[NARG_POS::SECOND]);
126 return NAsyncWorkCallback(env, thisVar, cb).Schedule(readdirProcedureName, cbExec, cbCompl).val_;
127 }
128 }
129 } // namespace ModuleFileIO
130 } // namespace DistributedFS
131 } // namespace OHOS