• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "stat_entity.h"
17 #include "stat_n_exporter.h"
18 
19 #include <cstdio>
20 #include <cstdlib>
21 #include <cstring>
22 #include <memory>
23 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
24 #include <sys/xattr.h>
25 #endif
26 
27 #include "file_utils.h"
28 #include "filemgmt_libhilog.h"
29 
30 namespace OHOS::FileManagement::ModuleFileIO {
31 using namespace std;
32 using namespace OHOS::FileManagement::LibN;
33 
CheckStatMode(napi_env env,napi_callback_info info,mode_t mode)34 static napi_value CheckStatMode(napi_env env, napi_callback_info info, mode_t mode)
35 {
36     NFuncArg funcArg(env, info);
37     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
38         HILOGE("Number of arguments unmatched");
39         NError(EINVAL).ThrowErr(env);
40         return nullptr;
41     }
42 
43     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
44     if (!statEntity) {
45         HILOGE("Failed to get stat entity");
46         return nullptr;
47     }
48 
49     bool check = (statEntity->stat_.st_mode & S_IFMT) == mode;
50     return NVal::CreateBool(env, check).val_;
51 }
52 
IsBlockDevice(napi_env env,napi_callback_info info)53 napi_value StatNExporter::IsBlockDevice(napi_env env, napi_callback_info info)
54 {
55     return CheckStatMode(env, info, S_IFBLK);
56 }
57 
IsCharacterDevice(napi_env env,napi_callback_info info)58 napi_value StatNExporter::IsCharacterDevice(napi_env env, napi_callback_info info)
59 {
60     return CheckStatMode(env, info, S_IFCHR);
61 }
62 
IsDirectory(napi_env env,napi_callback_info info)63 napi_value StatNExporter::IsDirectory(napi_env env, napi_callback_info info)
64 {
65     return CheckStatMode(env, info, S_IFDIR);
66 }
67 
IsFIFO(napi_env env,napi_callback_info info)68 napi_value StatNExporter::IsFIFO(napi_env env, napi_callback_info info)
69 {
70     return CheckStatMode(env, info, S_IFIFO);
71 }
72 
IsFile(napi_env env,napi_callback_info info)73 napi_value StatNExporter::IsFile(napi_env env, napi_callback_info info)
74 {
75     return CheckStatMode(env, info, S_IFREG);
76 }
77 
IsSocket(napi_env env,napi_callback_info info)78 napi_value StatNExporter::IsSocket(napi_env env, napi_callback_info info)
79 {
80     return CheckStatMode(env, info, S_IFSOCK);
81 }
82 
IsSymbolicLink(napi_env env,napi_callback_info info)83 napi_value StatNExporter::IsSymbolicLink(napi_env env, napi_callback_info info)
84 {
85     return CheckStatMode(env, info, S_IFLNK);
86 }
87 
GetIno(napi_env env,napi_callback_info info)88 napi_value StatNExporter::GetIno(napi_env env, napi_callback_info info)
89 {
90     NFuncArg funcArg(env, info);
91     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
92         HILOGE("Number of arguments unmatched");
93         NError(EINVAL).ThrowErr(env);
94         return nullptr;
95     }
96 
97     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
98     if (!statEntity) {
99         HILOGE("Failed to get stat entity");
100         return nullptr;
101     }
102 
103     return NVal::CreateBigInt64(env, statEntity->stat_.st_ino).val_;
104 }
105 
GetMode(napi_env env,napi_callback_info info)106 napi_value StatNExporter::GetMode(napi_env env, napi_callback_info info)
107 {
108     NFuncArg funcArg(env, info);
109     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
110         HILOGE("Number of arguments unmatched");
111         NError(EINVAL).ThrowErr(env);
112         return nullptr;
113     }
114 
115     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
116     if (!statEntity) {
117         HILOGE("Failed to get stat entity");
118         return nullptr;
119     }
120 
121     return NVal::CreateInt64(env, statEntity->stat_.st_mode & S_PERMISSION).val_;
122 }
123 
GetUid(napi_env env,napi_callback_info info)124 napi_value StatNExporter::GetUid(napi_env env, napi_callback_info info)
125 {
126     NFuncArg funcArg(env, info);
127     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
128         HILOGE("Number of arguments unmatched");
129         NError(EINVAL).ThrowErr(env);
130         return nullptr;
131     }
132 
133     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
134     if (!statEntity) {
135         HILOGE("Failed to get stat entity");
136         return nullptr;
137     }
138 
139     return NVal::CreateInt64(env, statEntity->stat_.st_uid).val_;
140 }
141 
GetGid(napi_env env,napi_callback_info info)142 napi_value StatNExporter::GetGid(napi_env env, napi_callback_info info)
143 {
144     NFuncArg funcArg(env, info);
145     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
146         HILOGE("Number of arguments unmatched");
147         NError(EINVAL).ThrowErr(env);
148         return nullptr;
149     }
150 
151     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
152     if (!statEntity) {
153         HILOGE("Failed to get stat entity");
154         return nullptr;
155     }
156 
157     return NVal::CreateInt64(env, statEntity->stat_.st_gid).val_;
158 }
159 
GetSize(napi_env env,napi_callback_info info)160 napi_value StatNExporter::GetSize(napi_env env, napi_callback_info info)
161 {
162     NFuncArg funcArg(env, info);
163     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
164         HILOGE("Number of arguments unmatched");
165         NError(EINVAL).ThrowErr(env);
166         return nullptr;
167     }
168 
169     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
170     if (!statEntity) {
171         HILOGE("Failed to get stat entity");
172         return nullptr;
173     }
174 
175     return NVal::CreateInt64(env, statEntity->stat_.st_size).val_;
176 }
177 
GetAtime(napi_env env,napi_callback_info info)178 napi_value StatNExporter::GetAtime(napi_env env, napi_callback_info info)
179 {
180     NFuncArg funcArg(env, info);
181     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
182         HILOGE("Number of arguments unmatched");
183         NError(EINVAL).ThrowErr(env);
184         return nullptr;
185     }
186 
187     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
188     if (!statEntity) {
189         HILOGE("Failed to get stat entity");
190         return nullptr;
191     }
192 
193     return NVal::CreateInt64(env, static_cast<int64_t>(statEntity->stat_.st_atim.tv_sec)).val_;
194 }
195 
GetMtime(napi_env env,napi_callback_info info)196 napi_value StatNExporter::GetMtime(napi_env env, napi_callback_info info)
197 {
198     NFuncArg funcArg(env, info);
199     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
200         HILOGE("Number of arguments unmatched");
201         NError(EINVAL).ThrowErr(env);
202         return nullptr;
203     }
204 
205     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
206     if (!statEntity) {
207         HILOGE("Failed to get stat entity");
208         return nullptr;
209     }
210 
211     return NVal::CreateInt64(env, static_cast<int64_t>(statEntity->stat_.st_mtim.tv_sec)).val_;
212 }
213 
GetCtime(napi_env env,napi_callback_info info)214 napi_value StatNExporter::GetCtime(napi_env env, napi_callback_info info)
215 {
216     NFuncArg funcArg(env, info);
217     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
218         HILOGE("Number of arguments unmatched");
219         NError(EINVAL).ThrowErr(env);
220         return nullptr;
221     }
222 
223     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
224     if (!statEntity) {
225         HILOGE("Failed to get stat entity");
226         return nullptr;
227     }
228 
229     return NVal::CreateInt64(env, static_cast<int64_t>(statEntity->stat_.st_ctim.tv_sec)).val_;
230 }
231 
GetAtimeNs(napi_env env,napi_callback_info info)232 napi_value StatNExporter::GetAtimeNs(napi_env env, napi_callback_info info)
233 {
234     NFuncArg funcArg(env, info);
235     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
236         HILOGE("Number of arguments unmatched");
237         NError(EINVAL).ThrowErr(env);
238         return nullptr;
239     }
240 
241     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
242     if (!statEntity) {
243         HILOGE("Failed to get stat entity");
244         NError(UNKROWN_ERR).ThrowErr(env);
245         return nullptr;
246     }
247 
248     return NVal::CreateBigIntUint64(env, static_cast<uint64_t>
249         (statEntity->stat_.st_atim.tv_sec * SECOND_TO_NANOSECOND +
250          statEntity->stat_.st_atim.tv_nsec)).val_;
251 }
252 
GetMtimeNs(napi_env env,napi_callback_info info)253 napi_value StatNExporter::GetMtimeNs(napi_env env, napi_callback_info info)
254 {
255     NFuncArg funcArg(env, info);
256     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
257         HILOGE("Number of arguments unmatched");
258         NError(EINVAL).ThrowErr(env);
259         return nullptr;
260     }
261 
262     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
263     if (!statEntity) {
264         HILOGE("Failed to get stat entity");
265         NError(UNKROWN_ERR).ThrowErr(env);
266         return nullptr;
267     }
268 
269     return NVal::CreateBigIntUint64(env, static_cast<uint64_t>
270         (statEntity->stat_.st_mtim.tv_sec * SECOND_TO_NANOSECOND +
271          statEntity->stat_.st_mtim.tv_nsec)).val_;
272 }
273 
GetCtimeNs(napi_env env,napi_callback_info info)274 napi_value StatNExporter::GetCtimeNs(napi_env env, napi_callback_info info)
275 {
276     NFuncArg funcArg(env, info);
277     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
278         HILOGE("Number of arguments unmatched");
279         NError(EINVAL).ThrowErr(env);
280         return nullptr;
281     }
282 
283     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
284     if (!statEntity) {
285         HILOGE("Failed to get stat entity");
286         NError(UNKROWN_ERR).ThrowErr(env);
287         return nullptr;
288     }
289 
290     return NVal::CreateBigIntUint64(env, static_cast<uint64_t>
291         (statEntity->stat_.st_ctim.tv_sec * SECOND_TO_NANOSECOND +
292          statEntity->stat_.st_ctim.tv_nsec)).val_;
293 }
294 
295 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
GetLocation(napi_env env,napi_callback_info info)296 napi_value StatNExporter::GetLocation(napi_env env, napi_callback_info info)
297 {
298     NFuncArg funcArg(env, info);
299     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
300         HILOGE("Number of arguments unmatched");
301         NError(EINVAL).ThrowErr(env);
302         return nullptr;
303     }
304 
305     auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
306     if (!statEntity) {
307         HILOGE("Failed to get stat entity");
308         return nullptr;
309     }
310     std::unique_ptr<char[]> value = CreateUniquePtr<char[]>(MAX_ATTR_NAME);
311     if (value == nullptr) {
312         HILOGE("Getxattr memory out, errno is %{public}d", errno);
313         NError(ENOMEM).ThrowErr(env);
314         return nullptr;
315     }
316 
317     ssize_t size = 0;
318     if (statEntity->fileInfo_->isPath) {
319         size = getxattr(statEntity->fileInfo_->path.get(), CLOUD_LOCATION_ATTR.c_str(), value.get(), MAX_ATTR_NAME);
320     } else {
321         size = fgetxattr(statEntity->fileInfo_->fdg->GetFD(), CLOUD_LOCATION_ATTR.c_str(), value.get(), MAX_ATTR_NAME);
322     }
323     Location defaultLocation = LOCAL;
324     if (size <= 0) {
325         if (errno != ENODATA && errno != EOPNOTSUPP) {
326             HILOGE("Getxattr value failed, errno is %{public}d", errno);
327         }
328         return NVal::CreateInt32(env, static_cast<int32_t>(defaultLocation)).val_;
329     }
330     std::string location = string(value.get(), static_cast<size_t>(size));
331     if (!std::all_of(location.begin(), location.end(), ::isdigit)) {
332         HILOGE("Getxattr location is not all digit!");
333         return NVal::CreateInt32(env, static_cast<int32_t>(defaultLocation)).val_;
334     }
335     defaultLocation = static_cast<Location>(atoi(location.c_str()));
336     return NVal::CreateInt32(env, static_cast<int32_t>(defaultLocation)).val_;
337 }
338 #endif
339 
Constructor(napi_env env,napi_callback_info info)340 napi_value StatNExporter::Constructor(napi_env env, napi_callback_info info)
341 {
342     NFuncArg funcArg(env, info);
343     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
344         HILOGE("Number of arguments unmatched");
345         NError(EINVAL).ThrowErr(env);
346         return nullptr;
347     }
348 
349     auto statEntity = CreateUniquePtr<StatEntity>();
350     if (statEntity == nullptr) {
351         HILOGE("Failed to request heap memory.");
352         NError(ENOMEM).ThrowErr(env);
353         return nullptr;
354     }
355     if (!NClass::SetEntityFor<StatEntity>(env, funcArg.GetThisVar(), move(statEntity))) {
356         HILOGE("Failed to set stat entity");
357         NError(EINVAL).ThrowErr(env);
358         return nullptr;
359     }
360     return funcArg.GetThisVar();
361 }
362 
Export()363 bool StatNExporter::Export()
364 {
365     vector<napi_property_descriptor> props = {
366         NVal::DeclareNapiFunction("isBlockDevice", IsBlockDevice),
367         NVal::DeclareNapiFunction("isCharacterDevice", IsCharacterDevice),
368         NVal::DeclareNapiFunction("isDirectory", IsDirectory),
369         NVal::DeclareNapiFunction("isFIFO", IsFIFO),
370         NVal::DeclareNapiFunction("isFile", IsFile),
371         NVal::DeclareNapiFunction("isSocket", IsSocket),
372         NVal::DeclareNapiFunction("isSymbolicLink", IsSymbolicLink),
373 
374         NVal::DeclareNapiGetter("ino", GetIno),
375         NVal::DeclareNapiGetter("mode", GetMode),
376         NVal::DeclareNapiGetter("uid", GetUid),
377         NVal::DeclareNapiGetter("gid", GetGid),
378         NVal::DeclareNapiGetter("size", GetSize),
379         NVal::DeclareNapiGetter("atime", GetAtime),
380         NVal::DeclareNapiGetter("mtime", GetMtime),
381         NVal::DeclareNapiGetter("ctime", GetCtime),
382         NVal::DeclareNapiGetter("atimeNs", GetAtimeNs),
383         NVal::DeclareNapiGetter("mtimeNs", GetMtimeNs),
384         NVal::DeclareNapiGetter("ctimeNs", GetCtimeNs),
385 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
386         NVal::DeclareNapiGetter("location", GetLocation),
387 #endif
388     };
389 
390 #ifdef WIN_PLATFORM
391     string className = GetNExporterName();
392 #else
393     string className = GetClassName();
394 #endif
395     bool succ = false;
396     napi_value classValue = nullptr;
397     tie(succ, classValue) = NClass::DefineClass(exports_.env_, className, StatNExporter::Constructor,
398         std::move(props));
399     if (!succ) {
400         HILOGE("Failed to define class");
401         NError(EIO).ThrowErr(exports_.env_);
402         return false;
403     }
404     succ = NClass::SaveClass(exports_.env_, className, classValue);
405     if (!succ) {
406         HILOGE("Failed to save class");
407         NError(EIO).ThrowErr(exports_.env_);
408         return false;
409     }
410 
411     return exports_.AddProp(className, classValue);
412 }
413 
414 #ifdef WIN_PLATFORM
GetNExporterName()415 string StatNExporter::GetNExporterName()
416 #else
417 string StatNExporter::GetClassName()
418 #endif
419 {
420     return StatNExporter::className_;
421 }
422 
StatNExporter(napi_env env,napi_value exports)423 StatNExporter::StatNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
424 
~StatNExporter()425 StatNExporter::~StatNExporter() {}
426 } // namespace OHOS::FileManagement::ModuleFileIO