1 /*
2 * Copyright (c) 2022-2023 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 #include "stat.h"
16
17 #include <memory>
18 #include <tuple>
19
20 #include "class_stat/stat_entity.h"
21 #include "class_stat/stat_n_exporter.h"
22 #include "common_func.h"
23 #include "file_utils.h"
24 #include "filemgmt_libhilog.h"
25
26 namespace OHOS::FileManagement::ModuleFileIO {
27 using namespace std;
28 using namespace OHOS::FileManagement::LibN;
29
ParseJsFile(napi_env env,napi_value pathOrFdFromJsArg)30 static tuple<bool, FileInfo> ParseJsFile(napi_env env, napi_value pathOrFdFromJsArg)
31 {
32 auto [isPath, path, ignore] = NVal(env, pathOrFdFromJsArg).ToUTF8String();
33 if (isPath) {
34 return { true, FileInfo { true, move(path), {} } };
35 }
36 auto [isFd, fd] = NVal(env, pathOrFdFromJsArg).ToInt32();
37 if (isFd) {
38 if (fd < 0) {
39 HILOGE("Invalid fd");
40 NError(EINVAL).ThrowErr(env);
41 return { false, FileInfo { false, {}, {} } };
42 }
43 auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(fd, false);
44 if (fdg == nullptr) {
45 HILOGE("Failed to request heap memory.");
46 NError(ENOMEM).ThrowErr(env);
47 return { false, FileInfo { false, {}, {} } };
48 }
49 return { true, FileInfo { false, {}, move(fdg) } };
50 }
51 HILOGE("Invalid parameter");
52 NError(EINVAL).ThrowErr(env);
53 return { false, FileInfo { false, {}, {} } };
54 };
55
CheckFsStat(const FileInfo & fileInfo,uv_fs_t * req)56 static NError CheckFsStat(const FileInfo &fileInfo, uv_fs_t* req)
57 {
58 if (fileInfo.isPath) {
59 int ret = uv_fs_stat(nullptr, req, fileInfo.path.get(), nullptr);
60 if (ret < 0) {
61 HILOGE("Failed to stat file with path");
62 return NError(ret);
63 }
64 } else {
65 int ret = uv_fs_fstat(nullptr, req, fileInfo.fdg->GetFD(), nullptr);
66 if (ret < 0) {
67 HILOGE("Failed to stat file with fd");
68 return NError(ret);
69 }
70 }
71 return NError(ERRNO_NOERR);
72 }
73
Sync(napi_env env,napi_callback_info info)74 napi_value Stat::Sync(napi_env env, napi_callback_info info)
75 {
76 NFuncArg funcArg(env, info);
77 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
78 HILOGE("Number of arguments unmatched");
79 NError(EINVAL).ThrowErr(env);
80 return nullptr;
81 }
82 auto [succ, fileInfo] = ParseJsFile(env, funcArg[NARG_POS::FIRST]);
83 if (!succ) {
84 return nullptr;
85 }
86
87 std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> stat_req = {
88 new (std::nothrow) uv_fs_t, CommonFunc::fs_req_cleanup };
89 if (!stat_req) {
90 HILOGE("Failed to request heap memory.");
91 NError(ENOMEM).ThrowErr(env);
92 return nullptr;
93 }
94 auto err = CheckFsStat(fileInfo, stat_req.get());
95 if (err) {
96 err.ThrowErr(env);
97 return nullptr;
98 }
99
100 auto stat = CommonFunc::InstantiateStat(env, stat_req->statbuf).val_;
101 return stat;
102 }
103
Async(napi_env env,napi_callback_info info)104 napi_value Stat::Async(napi_env env, napi_callback_info info)
105 {
106 NFuncArg funcArg(env, info);
107 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
108 HILOGE("Number of arguments unmatched");
109 NError(EINVAL).ThrowErr(env);
110 return nullptr;
111 }
112 auto [succ, fileInfo] = ParseJsFile(env, funcArg[NARG_POS::FIRST]);
113 if (!succ) {
114 return nullptr;
115 }
116 auto arg = CreateSharedPtr<StatEntity>();
117 if (arg == nullptr) {
118 HILOGE("Failed to request heap memory.");
119 NError(ENOMEM).ThrowErr(env);
120 return nullptr;
121 }
122 auto cbExec = [arg, fileInfo = make_shared<FileInfo>(move(fileInfo))]() -> NError {
123 std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> stat_req = {
124 new (std::nothrow) uv_fs_t, CommonFunc::fs_req_cleanup };
125 if (!stat_req) {
126 HILOGE("Failed to request heap memory.");
127 return NError(ENOMEM);
128 }
129 auto err = CheckFsStat(*fileInfo, stat_req.get());
130 if (err) {
131 return err;
132 }
133 arg->stat_ = stat_req->statbuf;
134 return NError(ERRNO_NOERR);
135 };
136 auto cbCompl = [arg](napi_env env, NError err) -> NVal {
137 if (err) {
138 return { env, err.GetNapiErr(env) };
139 }
140 auto stat = CommonFunc::InstantiateStat(env, arg->stat_);
141 return stat;
142 };
143 NVal thisVar(env, funcArg.GetThisVar());
144 if (funcArg.GetArgc() == NARG_CNT::ONE) {
145 return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_STAT_NAME, cbExec, cbCompl).val_;
146 } else {
147 NVal cb(env, funcArg[NARG_POS::SECOND]);
148 return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_STAT_NAME, cbExec, cbCompl).val_;
149 }
150 }
151 } // namespace OHOS::FileManagement::ModuleFileIO