• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "file_entity.h"
17 #include "file_n_exporter.h"
18 
19 #include <cstdio>
20 #include <cstdlib>
21 #include <cstring>
22 #include <memory>
23 #include <sys/file.h>
24 
25 #include "filemgmt_libhilog.h"
26 #include "filemgmt_libn.h"
27 #include "../common_func.h"
28 
29 namespace OHOS {
30 namespace FileManagement {
31 namespace ModuleFileIO {
32 using namespace std;
33 using namespace OHOS::FileManagement::LibN;
34 
GetFileEntity(napi_env env,napi_value raf_entity)35 static FileEntity *GetFileEntity(napi_env env, napi_value raf_entity)
36 {
37     auto rafEntity = NClass::GetEntityOf<FileEntity>(env, raf_entity);
38     if (!rafEntity) {
39         HILOGE("Failed to get file entity");
40         NError(EINVAL).ThrowErr(env);
41         return nullptr;
42     }
43     if (!rafEntity->fd_) {
44         HILOGE("rafEntity fd is not exist");
45         NError(EINVAL).ThrowErr(env);
46         return nullptr;
47     }
48     return rafEntity;
49 }
50 
GetFD(napi_env env,napi_callback_info info)51 napi_value FileNExporter::GetFD(napi_env env, napi_callback_info info)
52 {
53     NFuncArg funcArg(env, info);
54     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
55         HILOGE("Number of arguments unmatched");
56         NError(EINVAL).ThrowErr(env);
57         return nullptr;
58     }
59     auto rafEntity = GetFileEntity(env, funcArg.GetThisVar());
60     if (!rafEntity) {
61         HILOGE("Failed to get file entity");
62         return nullptr;
63     }
64     return NVal::CreateInt32(env, rafEntity->fd_.get()->GetFD()).val_;
65 }
66 
GetExclusive(napi_env env,NFuncArg & funcArg,bool & exclusive)67 static bool GetExclusive(napi_env env, NFuncArg &funcArg, bool &exclusive)
68 {
69     bool succ = true;
70     if (funcArg.GetArgc() >= NARG_CNT::ONE && !(NVal(env, funcArg[NARG_POS::FIRST]).TypeIs(napi_function))) {
71         if (NVal(env, funcArg[NARG_POS::FIRST]).TypeIs(napi_boolean)) {
72             tie(succ, exclusive) = NVal(env, funcArg[NARG_POS::FIRST]).ToBool();
73             if (!succ) {
74                 HILOGE("Invalid exclusive");
75                 NError(EINVAL).ThrowErr(env);
76             }
77         } else {
78             HILOGE("Invalid exclusive");
79             NError(EINVAL).ThrowErr(env);
80             succ = false;
81         }
82     }
83     return succ;
84 }
85 
Lock(napi_env env,napi_callback_info info)86 napi_value FileNExporter::Lock(napi_env env, napi_callback_info info)
87 {
88     NFuncArg funcArg(env, info);
89     if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::TWO)) {
90         HILOGE("Number of arguments unmatched");
91         NError(EINVAL).ThrowErr(env);
92         return nullptr;
93     }
94 
95     auto fileEntity = GetFileEntity(env, funcArg.GetThisVar());
96     if (!fileEntity) {
97         HILOGE("Failed to get file entity");
98         NError(EINVAL).ThrowErr(env);
99         return nullptr;
100     }
101 
102     bool exclusive = false;
103     if (!GetExclusive(env, funcArg, exclusive)) {
104         return nullptr;
105     }
106     auto cbExec = [exclusive, fileEntity]() -> NError {
107         int ret = 0;
108         auto mode = exclusive ? LOCK_EX : LOCK_SH;
109         ret = flock(fileEntity->fd_.get()->GetFD(), mode);
110         if (ret < 0) {
111             HILOGE("Failed to lock file");
112             return NError(errno);
113         } else {
114             return NError(ERRNO_NOERR);
115         }
116     };
117 
118     auto cbCompl = [](napi_env env, NError err) -> NVal {
119         if (err) {
120             return { env, err.GetNapiErr(env) };
121         }
122         return NVal::CreateUndefined(env);
123     };
124 
125     NVal thisVar(env, funcArg.GetThisVar());
126     if (funcArg.GetArgc() == NARG_CNT::ZERO || (funcArg.GetArgc() == NARG_CNT::ONE &&
127         NVal(env, funcArg[NARG_POS::FIRST]).TypeIs(napi_boolean))) {
128         return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_LOCK_NAME, cbExec, cbCompl).val_;
129     } else {
130         int cbIdx = ((funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::FIRST);
131         NVal cb(env, funcArg[cbIdx]);
132         return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_LOCK_NAME, cbExec, cbCompl).val_;
133     }
134 }
135 
TryLock(napi_env env,napi_callback_info info)136 napi_value FileNExporter::TryLock(napi_env env, napi_callback_info info)
137 {
138     NFuncArg funcArg(env, info);
139     if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
140         HILOGE("Number of arguments unmatched");
141         NError(EINVAL).ThrowErr(env);
142         return nullptr;
143     }
144 
145     auto fileEntity = GetFileEntity(env, funcArg.GetThisVar());
146     if (!fileEntity) {
147         HILOGE("Failed to get file entity");
148         NError(EINVAL).ThrowErr(env);
149         return nullptr;
150     }
151 
152     bool exclusive = false;
153     if (!GetExclusive(env, funcArg, exclusive)) {
154         return nullptr;
155     }
156 
157     int ret = 0;
158     auto mode = exclusive ? LOCK_EX : LOCK_SH;
159     ret = flock(fileEntity->fd_.get()->GetFD(), mode | LOCK_NB);
160     if (ret < 0) {
161         HILOGE("Failed to try to lock file");
162         NError(errno).ThrowErr(env);
163     }
164 
165     return NVal::CreateUndefined(env).val_;
166 }
167 
UnLock(napi_env env,napi_callback_info info)168 napi_value FileNExporter::UnLock(napi_env env, napi_callback_info info)
169 {
170     NFuncArg funcArg(env, info);
171     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
172         HILOGE("Number of arguments unmatched");
173         NError(EINVAL).ThrowErr(env);
174         return nullptr;
175     }
176 
177     auto fileEntity = GetFileEntity(env, funcArg.GetThisVar());
178     if (!fileEntity) {
179         HILOGE("Failed to get file entity");
180         NError(EINVAL).ThrowErr(env);
181         return nullptr;
182     }
183 
184     int ret = 0;
185     ret = flock(fileEntity->fd_.get()->GetFD(), LOCK_UN);
186     if (ret < 0) {
187         HILOGE("Failed to unlock file");
188         NError(errno).ThrowErr(env);
189         return nullptr;
190     }
191     return NVal::CreateUndefined(env).val_;
192 }
193 
Constructor(napi_env env,napi_callback_info info)194 napi_value FileNExporter::Constructor(napi_env env, napi_callback_info info)
195 {
196     NFuncArg funcArg(env, info);
197     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
198         HILOGE("Number of arguments unmatched");
199         NError(EINVAL).ThrowErr(env);
200         return nullptr;
201     }
202 
203     auto rafEntity = make_unique<FileEntity>();
204     if (!NClass::SetEntityFor<FileEntity>(env, funcArg.GetThisVar(), move(rafEntity))) {
205         HILOGE("Failed to set file entity");
206         NError(EIO).ThrowErr(env);
207         return nullptr;
208     }
209     return funcArg.GetThisVar();
210 }
211 
Export()212 bool FileNExporter::Export()
213 {
214     vector<napi_property_descriptor> props = {
215         NVal::DeclareNapiGetter("fd", GetFD),
216         NVal::DeclareNapiFunction("lock", Lock),
217         NVal::DeclareNapiFunction("tryLock", TryLock),
218         NVal::DeclareNapiFunction("unlock", UnLock),
219     };
220 
221     string className = GetClassName();
222     bool succ = false;
223     napi_value classValue = nullptr;
224     tie(succ, classValue) = NClass::DefineClass(exports_.env_, className,
225         FileNExporter::Constructor, move(props));
226     if (!succ) {
227         HILOGE("Define class exceptions");
228         NError(EIO).ThrowErr(exports_.env_);
229         return false;
230     }
231     succ = NClass::SaveClass(exports_.env_, className, classValue);
232     if (!succ) {
233         HILOGE("Save class exceptions");
234         NError(EIO).ThrowErr(exports_.env_);
235         return false;
236     }
237 
238     return exports_.AddProp(className, classValue);
239 }
240 
GetClassName()241 string FileNExporter::GetClassName()
242 {
243     return FileNExporter::className_;
244 }
245 
FileNExporter(napi_env env,napi_value exports)246 FileNExporter::FileNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
~FileNExporter()247 FileNExporter::~FileNExporter() {}
248 } // namespace ModuleFileIO
249 } // namespace FileManagement
250 } // namespace OHOS