1 /*
2  * Copyright (c) 2021-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 "stat_n_exporter.h"
17 
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 #include <memory>
22 #include <sstream>
23 
24 #include "securec.h"
25 #include "../../common/log.h"
26 #include "../../common/napi/n_async/n_async_work_callback.h"
27 #include "../../common/napi/n_async/n_async_work_promise.h"
28 #include "../../common/napi/n_class.h"
29 #include "../../common/napi/n_func_arg.h"
30 #include "../../common/uni_error.h"
31 #include "stat_entity.h"
32 
33 namespace OHOS {
34 namespace DistributedFS {
35 namespace ModuleFileIO {
36 using namespace std;
37 
CheckStatMode(napi_env env,napi_callback_info info,mode_t mode)38 static napi_value CheckStatMode(napi_env env, napi_callback_info info, mode_t mode)
39 {
40     NFuncArg funcArg(env, info);
41     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
42         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
43         return nullptr;
44     }
45 
46     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
47     if (!statEntity) {
48         return nullptr;
49     }
50 
51     bool check = (statEntity->stat_.st_mode & S_IFMT) == mode;
52     return NVal::CreateBool(env, check).val_;
53 }
54 
IsBlockDevice(napi_env env,napi_callback_info info)55 napi_value StatNExporter::IsBlockDevice(napi_env env, napi_callback_info info)
56 {
57     return CheckStatMode(env, info, S_IFBLK);
58 }
59 
IsCharacterDevice(napi_env env,napi_callback_info info)60 napi_value StatNExporter::IsCharacterDevice(napi_env env, napi_callback_info info)
61 {
62     return CheckStatMode(env, info, S_IFCHR);
63 }
64 
IsDirectory(napi_env env,napi_callback_info info)65 napi_value StatNExporter::IsDirectory(napi_env env, napi_callback_info info)
66 {
67     return CheckStatMode(env, info, S_IFDIR);
68 }
69 
IsFIFO(napi_env env,napi_callback_info info)70 napi_value StatNExporter::IsFIFO(napi_env env, napi_callback_info info)
71 {
72     return CheckStatMode(env, info, S_IFIFO);
73 }
74 
IsFile(napi_env env,napi_callback_info info)75 napi_value StatNExporter::IsFile(napi_env env, napi_callback_info info)
76 {
77     return CheckStatMode(env, info, S_IFREG);
78 }
79 
IsSocket(napi_env env,napi_callback_info info)80 napi_value StatNExporter::IsSocket(napi_env env, napi_callback_info info)
81 {
82     return CheckStatMode(env, info, S_IFSOCK);
83 }
84 
IsSymbolicLink(napi_env env,napi_callback_info info)85 napi_value StatNExporter::IsSymbolicLink(napi_env env, napi_callback_info info)
86 {
87     return CheckStatMode(env, info, S_IFLNK);
88 }
89 
GetDev(napi_env env,napi_callback_info info)90 napi_value StatNExporter::GetDev(napi_env env, napi_callback_info info)
91 {
92     NFuncArg funcArg(env, info);
93     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
94         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
95         return nullptr;
96     }
97 
98     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
99     if (!statEntity) {
100         return nullptr;
101     }
102 
103     return NVal::CreateInt64(env, statEntity->stat_.st_dev).val_;
104 }
105 
GetIno(napi_env env,napi_callback_info info)106 napi_value StatNExporter::GetIno(napi_env env, napi_callback_info info)
107 {
108     NFuncArg funcArg(env, info);
109     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
110         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
111         return nullptr;
112     }
113 
114     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
115     if (!statEntity) {
116         return nullptr;
117     }
118 
119     return NVal::CreateBigInt64(env, statEntity->stat_.st_ino).val_;
120 }
121 
GetMode(napi_env env,napi_callback_info info)122 napi_value StatNExporter::GetMode(napi_env env, napi_callback_info info)
123 {
124     NFuncArg funcArg(env, info);
125     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
126         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
127         return nullptr;
128     }
129 
130     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
131     if (!statEntity) {
132         return nullptr;
133     }
134 
135     return NVal::CreateInt64(env, statEntity->stat_.st_mode).val_;
136 }
137 
GetNlink(napi_env env,napi_callback_info info)138 napi_value StatNExporter::GetNlink(napi_env env, napi_callback_info info)
139 {
140     NFuncArg funcArg(env, info);
141     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
142         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
143         return nullptr;
144     }
145 
146     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
147     if (!statEntity) {
148         return nullptr;
149     }
150 
151     return NVal::CreateInt64(env, statEntity->stat_.st_nlink).val_;
152 }
153 
GetUid(napi_env env,napi_callback_info info)154 napi_value StatNExporter::GetUid(napi_env env, napi_callback_info info)
155 {
156     NFuncArg funcArg(env, info);
157     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
158         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
159         return nullptr;
160     }
161 
162     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
163     if (!statEntity) {
164         return nullptr;
165     }
166 
167     return NVal::CreateInt64(env, statEntity->stat_.st_uid).val_;
168 }
169 
GetGid(napi_env env,napi_callback_info info)170 napi_value StatNExporter::GetGid(napi_env env, napi_callback_info info)
171 {
172     NFuncArg funcArg(env, info);
173     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
174         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
175         return nullptr;
176     }
177 
178     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
179     if (!statEntity) {
180         return nullptr;
181     }
182 
183     return NVal::CreateInt64(env, statEntity->stat_.st_gid).val_;
184 }
185 
GetRdev(napi_env env,napi_callback_info info)186 napi_value StatNExporter::GetRdev(napi_env env, napi_callback_info info)
187 {
188     NFuncArg funcArg(env, info);
189     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
190         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
191         return nullptr;
192     }
193 
194     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
195     if (!statEntity) {
196         return nullptr;
197     }
198 
199     return NVal::CreateInt64(env, statEntity->stat_.st_rdev).val_;
200 }
201 
GetSize(napi_env env,napi_callback_info info)202 napi_value StatNExporter::GetSize(napi_env env, napi_callback_info info)
203 {
204     NFuncArg funcArg(env, info);
205     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
206         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
207         return nullptr;
208     }
209 
210     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
211     if (!statEntity) {
212         return nullptr;
213     }
214 
215     return NVal::CreateInt64(env, statEntity->stat_.st_size).val_;
216 }
217 
GetBlksize(napi_env env,napi_callback_info info)218 napi_value StatNExporter::GetBlksize(napi_env env, napi_callback_info info)
219 {
220     NFuncArg funcArg(env, info);
221     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
222         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
223         return nullptr;
224     }
225 
226     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
227     if (!statEntity) {
228         return nullptr;
229     }
230 
231     return NVal::CreateInt64(env, statEntity->stat_.st_blksize).val_;
232 }
233 
GetBlocks(napi_env env,napi_callback_info info)234 napi_value StatNExporter::GetBlocks(napi_env env, napi_callback_info info)
235 {
236     NFuncArg funcArg(env, info);
237     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
238         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
239         return nullptr;
240     }
241 
242     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
243     if (!statEntity) {
244         return nullptr;
245     }
246 
247     return NVal::CreateInt64(env, statEntity->stat_.st_blocks).val_;
248 }
249 
GetAtime(napi_env env,napi_callback_info info)250 napi_value StatNExporter::GetAtime(napi_env env, napi_callback_info info)
251 {
252     NFuncArg funcArg(env, info);
253     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
254         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
255         return nullptr;
256     }
257 
258     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
259     if (!statEntity) {
260         return nullptr;
261     }
262 
263     return NVal::CreateInt64(env, statEntity->stat_.st_atim.tv_sec).val_;
264 }
265 
GetMtime(napi_env env,napi_callback_info info)266 napi_value StatNExporter::GetMtime(napi_env env, napi_callback_info info)
267 {
268     NFuncArg funcArg(env, info);
269     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
270         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
271         return nullptr;
272     }
273 
274     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
275     if (!statEntity) {
276         return nullptr;
277     }
278 
279     return NVal::CreateInt64(env, statEntity->stat_.st_mtim.tv_sec).val_;
280 }
281 
GetCtime(napi_env env,napi_callback_info info)282 napi_value StatNExporter::GetCtime(napi_env env, napi_callback_info info)
283 {
284     NFuncArg funcArg(env, info);
285     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
286         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
287         return nullptr;
288     }
289 
290     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
291     if (!statEntity) {
292         return nullptr;
293     }
294 
295     return NVal::CreateInt64(env, statEntity->stat_.st_ctim.tv_sec).val_;
296 }
297 
Constructor(napi_env env,napi_callback_info info)298 napi_value StatNExporter::Constructor(napi_env env, napi_callback_info info)
299 {
300     NFuncArg funcArg(env, info);
301     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
302         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
303         return nullptr;
304     }
305 
306     unique_ptr<StatEntity> statEntity = make_unique<StatEntity>();
307     if (!NClass::SetEntityFor<StatEntity>(env, funcArg.GetThisVar(), move(statEntity))) {
308         UniError(EIO).ThrowErr(env, "INNER BUG. Failed to wrap entity for obj stat");
309         return nullptr;
310     }
311     return funcArg.GetThisVar();
312 }
313 
Export()314 bool StatNExporter::Export()
315 {
316     vector<napi_property_descriptor> props = {
317         NVal::DeclareNapiFunction("isBlockDevice", IsBlockDevice),
318         NVal::DeclareNapiFunction("isCharacterDevice", IsCharacterDevice),
319         NVal::DeclareNapiFunction("isDirectory", IsDirectory),
320         NVal::DeclareNapiFunction("isFIFO", IsFIFO),
321         NVal::DeclareNapiFunction("isFile", IsFile),
322         NVal::DeclareNapiFunction("isSocket", IsSocket),
323         NVal::DeclareNapiFunction("isSymbolicLink", IsSymbolicLink),
324 
325         NVal::DeclareNapiGetter("dev", GetDev),
326         NVal::DeclareNapiGetter("ino", GetIno),
327         NVal::DeclareNapiGetter("mode", GetMode),
328         NVal::DeclareNapiGetter("nlink", GetNlink),
329         NVal::DeclareNapiGetter("uid", GetUid),
330         NVal::DeclareNapiGetter("gid", GetGid),
331         NVal::DeclareNapiGetter("rdev", GetRdev),
332         NVal::DeclareNapiGetter("size", GetSize),
333         NVal::DeclareNapiGetter("blksize", GetBlksize),
334         NVal::DeclareNapiGetter("blocks", GetBlocks),
335         NVal::DeclareNapiGetter("atime", GetAtime),
336         NVal::DeclareNapiGetter("mtime", GetMtime),
337         NVal::DeclareNapiGetter("ctime", GetCtime),
338     };
339 
340     string className = GetClassName();
341     bool succ = false;
342     napi_value classValue = nullptr;
343     tie(succ, classValue) = NClass::DefineClass(exports_.env_, className, StatNExporter::Constructor, std::move(props));
344     if (!succ) {
345         UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to define class");
346         return false;
347     }
348     succ = NClass::SaveClass(exports_.env_, className, classValue);
349     if (!succ) {
350         UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to save class");
351         return false;
352     }
353 
354     return exports_.AddProp(className, classValue);
355 }
356 
GetClassName()357 string StatNExporter::GetClassName()
358 {
359     return StatNExporter::className_;
360 }
361 
StatNExporter(napi_env env,napi_value exports)362 StatNExporter::StatNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
363 
~StatNExporter()364 StatNExporter::~StatNExporter() {}
365 } // namespace ModuleFileIO
366 } // namespace DistributedFS
367 } // namespace OHOS
368