• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "common_func.h"
17 
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 
24 #include "class_stat/stat_entity.h"
25 #include "class_stat/stat_n_exporter.h"
26 #include "class_stream/stream_entity.h"
27 #include "class_stream/stream_n_exporter.h"
28 #include "filemgmt_libhilog.h"
29 #include "filemgmt_libn.h"
30 
31 namespace OHOS {
32 namespace FileManagement {
33 namespace ModuleFileIO {
34 using namespace std;
35 using namespace OHOS::FileManagement::LibN;
36 
InitOpenMode(napi_env env,napi_value exports)37 void InitOpenMode(napi_env env, napi_value exports)
38 {
39     char propertyName[] = "OpenMode";
40     napi_property_descriptor desc[] = {
41         DECLARE_NAPI_STATIC_PROPERTY("READ_ONLY", NVal::CreateInt32(env, RDONLY).val_),
42         DECLARE_NAPI_STATIC_PROPERTY("WRITE_ONLY", NVal::CreateInt32(env, WRONLY).val_),
43         DECLARE_NAPI_STATIC_PROPERTY("READ_WRITE", NVal::CreateInt32(env, RDWR).val_),
44         DECLARE_NAPI_STATIC_PROPERTY("CREATE", NVal::CreateInt32(env, CREATE).val_),
45         DECLARE_NAPI_STATIC_PROPERTY("TRUNC", NVal::CreateInt32(env, TRUNC).val_),
46         DECLARE_NAPI_STATIC_PROPERTY("APPEND", NVal::CreateInt32(env, APPEND).val_),
47         DECLARE_NAPI_STATIC_PROPERTY("NONBLOCK", NVal::CreateInt32(env, NONBLOCK).val_),
48         DECLARE_NAPI_STATIC_PROPERTY("DIR", NVal::CreateInt32(env, DIRECTORY).val_),
49         DECLARE_NAPI_STATIC_PROPERTY("NOFOLLOW", NVal::CreateInt32(env, NOFOLLOW).val_),
50         DECLARE_NAPI_STATIC_PROPERTY("SYNC", NVal::CreateInt32(env, SYNC).val_),
51     };
52     napi_value obj = nullptr;
53     napi_status status = napi_create_object(env, &obj);
54     if (status != napi_ok) {
55         HILOGE("Failed to create object at initializing openMode");
56         return;
57     }
58     status = napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
59     if (status != napi_ok) {
60         HILOGE("Failed to set properties of character at initializing openMode");
61         return;
62     }
63     status = napi_set_named_property(env, exports, propertyName, obj);
64     if (status != napi_ok) {
65         HILOGE("Failed to set direction property at initializing openMode");
66         return;
67     }
68 }
69 
GetActualLen(napi_env env,size_t bufLen,size_t bufOff,NVal op)70 static tuple<bool, size_t> GetActualLen(napi_env env, size_t bufLen, size_t bufOff, NVal op)
71 {
72     bool succ = false;
73     size_t retLen = 0;
74 
75     if (op.HasProp("length")) {
76         int64_t opLength = 0;
77         tie(succ, opLength) = op.GetProp("length").ToInt64();
78         if (!succ) {
79             HILOGE("Invalid option.length, expect integer");
80             NError(EINVAL).ThrowErr(env);
81             return { false, 0 };
82         }
83         if (opLength < 0) {
84             retLen = bufLen - bufOff;
85         } else if (static_cast<size_t>(opLength) > bufLen - bufOff) {
86             HILOGE("Invalid option.length, buffer limit exceeded");
87             NError(EINVAL).ThrowErr(env);
88             return { false, 0 };
89         } else {
90             retLen = static_cast<size_t>(opLength);
91         }
92     } else {
93         retLen = bufLen - bufOff;
94     }
95 
96     return { true, retLen };
97 }
98 
ConvertJsFlags(unsigned int & flags)99 unsigned int CommonFunc::ConvertJsFlags(unsigned int &flags)
100 {
101     static constexpr unsigned int usrReadOnly = 00;
102     static constexpr unsigned int usrWriteOnly = 01;
103     static constexpr unsigned int usrReadWrite = 02;
104     static constexpr unsigned int usrCreate = 0100;
105     static constexpr unsigned int usrExecuteLock = 0200;
106     static constexpr unsigned int usrTruncate = 01000;
107     static constexpr unsigned int usrAppend = 02000;
108     static constexpr unsigned int usrNoneBlock = 04000;
109     static constexpr unsigned int usrDirectory = 0200000;
110     static constexpr unsigned int usrNoFollowed = 0400000;
111     static constexpr unsigned int usrSynchronous = 04010000;
112 
113     unsigned int flagsABI = 0;
114     flagsABI |= ((flags & usrReadOnly) == usrReadOnly) ? O_RDONLY : 0;
115     flagsABI |= ((flags & usrWriteOnly) == usrWriteOnly) ? O_WRONLY : 0;
116     flagsABI |= ((flags & usrReadWrite) == usrReadWrite) ? O_RDWR : 0;
117     flagsABI |= ((flags & usrCreate) == usrCreate) ? O_CREAT : 0;
118     flagsABI |= ((flags & usrExecuteLock) == usrExecuteLock) ? O_EXCL : 0;
119     flagsABI |= ((flags & usrTruncate) == usrTruncate) ? O_TRUNC : 0;
120     flagsABI |= ((flags & usrAppend) == usrAppend) ? O_APPEND : 0;
121     flagsABI |= ((flags & usrNoneBlock) == usrNoneBlock) ? O_NONBLOCK : 0;
122     flagsABI |= ((flags & usrDirectory) == usrDirectory) ? O_DIRECTORY : 0;
123     flagsABI |= ((flags & usrNoFollowed) == usrNoFollowed) ? O_NOFOLLOW : 0;
124     flagsABI |= ((flags & usrSynchronous) == usrSynchronous) ? O_SYNC : 0;
125     flags = flagsABI;
126     return flagsABI;
127 }
128 
InstantiateStat(napi_env env,struct stat & buf)129 NVal CommonFunc::InstantiateStat(napi_env env, struct stat &buf)
130 {
131     napi_value objStat = NClass::InstantiateClass(env, StatNExporter::className_, {});
132     if (!objStat) {
133         HILOGE("Failed to instantiate stat class");
134         NError(EIO).ThrowErr(env);
135         return NVal();
136     }
137 
138     auto statEntity = NClass::GetEntityOf<StatEntity>(env, objStat);
139     if (!statEntity) {
140         HILOGE("Failed to get stat entity");
141         NError(EIO).ThrowErr(env);
142         return NVal();
143     }
144 
145     statEntity->stat_ = buf;
146     return { env, objStat };
147 }
148 
InstantiateStream(napi_env env,unique_ptr<FILE,decltype(& fclose) > fp)149 NVal CommonFunc::InstantiateStream(napi_env env, unique_ptr<FILE, decltype(&fclose)> fp)
150 {
151     napi_value objStream = NClass::InstantiateClass(env, StreamNExporter::className_, {});
152     if (!objStream) {
153         HILOGE("INNER BUG. Cannot instantiate stream");
154         NError(EIO).ThrowErr(env);
155         return NVal();
156     }
157 
158     auto streamEntity = NClass::GetEntityOf<StreamEntity>(env, objStream);
159     if (!streamEntity) {
160         HILOGE("Cannot instantiate stream because of void entity");
161         NError(EIO).ThrowErr(env);
162         return NVal();
163     }
164 
165     streamEntity->fp.swap(fp);
166     return { env, objStream };
167 }
168 
fs_req_cleanup(uv_fs_t * req)169 void CommonFunc::fs_req_cleanup(uv_fs_t* req)
170 {
171     uv_fs_req_cleanup(req);
172     if (req) {
173         delete req;
174         req = nullptr;
175     }
176 }
177 
GetModeFromFlags(unsigned int flags)178 string CommonFunc::GetModeFromFlags(unsigned int flags)
179 {
180     const string RDONLY = "r";
181     const string WRONLY = "w";
182     const string APPEND = "a";
183     const string TRUNC = "t";
184     string mode = RDONLY;
185     mode += (((flags & O_RDWR) == O_RDWR) ? WRONLY : "");
186     mode = (((flags & O_WRONLY) == O_WRONLY) ? WRONLY : mode);
187     if (mode != RDONLY) {
188         mode += ((flags & O_TRUNC) ? TRUNC : "");
189         mode += ((flags & O_APPEND) ? APPEND : "");
190     }
191     return mode;
192 }
193 
GetCopyPathArg(napi_env env,napi_value srcPath,napi_value dstPath)194 tuple<bool, unique_ptr<char[]>, unique_ptr<char[]>> CommonFunc::GetCopyPathArg(napi_env env,
195                                                                                napi_value srcPath,
196                                                                                napi_value dstPath)
197 {
198     bool succ = false;
199     unique_ptr<char[]> src = nullptr;
200     tie(succ, src, ignore) = NVal(env, srcPath).ToUTF8String();
201     if (!succ) {
202         HILOGE("Failed to convert the src path to UTF-8 string");
203         return { false, nullptr, nullptr };
204     }
205 
206     unique_ptr<char[]> dest = nullptr;
207     tie(succ, dest, ignore) = NVal(env, dstPath).ToUTF8String();
208     if (!succ) {
209         HILOGE("Failed to convert the dest path to UTF-8 string");
210         return { false, nullptr, nullptr };
211     }
212     return make_tuple(true, move(src), move(dest));
213 }
214 
DecodeString(napi_env env,NVal jsStr,NVal encoding)215 static tuple<bool, unique_ptr<char[]>, size_t> DecodeString(napi_env env, NVal jsStr, NVal encoding)
216 {
217     if (!jsStr.TypeIs(napi_string)) {
218         return { false, nullptr, 0 };
219     }
220 
221     bool succ = false;
222     if (!encoding) {
223         return jsStr.ToUTF8String();
224     }
225 
226     unique_ptr<char[]> encodingBuf = nullptr;
227     tie(succ, encodingBuf, ignore) = encoding.ToUTF8String();
228     if (!succ) {
229         return { false, nullptr, 0 };
230     }
231     string_view encodingStr(encodingBuf.release());
232     if (encodingStr == "utf-8") {
233         return jsStr.ToUTF8String();
234     } else if (encodingStr == "utf-16") {
235         return jsStr.ToUTF16String();
236     } else {
237         HILOGE("Failed to recognize the str type");
238         return { false, nullptr, 0 };
239     }
240 }
241 
GetReadArg(napi_env env,napi_value readBuf,napi_value option)242 tuple<bool, void *, size_t, bool, int64_t> CommonFunc::GetReadArg(napi_env env,
243     napi_value readBuf, napi_value option)
244 {
245     size_t retLen = 0;
246     int64_t position = 0;
247     bool succ = false;
248     bool posAssigned = false;
249 
250     NVal txt(env, readBuf);
251     void *buf = nullptr;
252     size_t bufLen = 0;
253     tie(succ, buf, bufLen) = txt.ToArraybuffer();
254     if (!succ || bufLen > UINT_MAX) {
255         HILOGE("Invalid arraybuffer");
256         NError(EINVAL).ThrowErr(env);
257         return { false, nullptr, 0, posAssigned, position };
258     }
259     NVal op = NVal(env, option);
260     tie(succ, retLen) = GetActualLen(env, bufLen, 0, op);
261     if (!succ) {
262         HILOGE("Failed to get actual length");
263         return { false, nullptr, 0, posAssigned, position };
264     }
265 
266     if (op.HasProp("offset")) {
267         tie(succ, position) = op.GetProp("offset").ToInt64();
268         if (succ && position >= 0) {
269             posAssigned = true;
270         } else {
271             HILOGE("option.offset shall be positive number");
272             NError(EINVAL).ThrowErr(env);
273             return { false, nullptr, 0, posAssigned, position };
274         }
275     }
276 
277     return { true, buf, retLen, posAssigned, position };
278 }
279 
GetWriteArg(napi_env env,napi_value argWBuf,napi_value argOption)280 tuple<bool, unique_ptr<char[]>, void *, size_t, bool, int64_t> CommonFunc::GetWriteArg(napi_env env,
281     napi_value argWBuf, napi_value argOption)
282 {
283     int64_t retPos = 0;
284     size_t bufLen = 0;
285     bool hasPos = false;
286     bool succ = false;
287     void *buf = nullptr;
288     NVal op(env, argOption);
289     NVal jsBuffer(env, argWBuf);
290     unique_ptr<char[]> bufferGuard = nullptr;
291     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetProp("encoding"));
292     if (!succ) {
293         tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer();
294         if (!succ) {
295             HILOGE("Illegal write buffer or encoding");
296             NError(EINVAL).ThrowErr(env);
297             return { false, nullptr, nullptr, 0, hasPos, retPos };
298         }
299     } else {
300         buf = bufferGuard.get();
301     }
302     if (bufLen > UINT_MAX) {
303         HILOGE("The Size of buffer is too large");
304         NError(EINVAL).ThrowErr(env);
305         return { false, nullptr, nullptr, 0, hasPos, retPos} ;
306     }
307     size_t retLen = 0;
308     tie(succ, retLen) = GetActualLen(env, bufLen, 0, op);
309     if (!succ) {
310         HILOGE("Failed to get actual length");
311         return { false, nullptr, nullptr, 0, hasPos, retPos };
312     }
313 
314     if (op.HasProp("offset")) {
315         int64_t position = 0;
316         tie(succ, position) = op.GetProp("offset").ToInt64();
317         if (!succ || position < 0) {
318             HILOGE("option.offset shall be positive number");
319             NError(EINVAL).ThrowErr(env);
320             return { false, nullptr, nullptr, 0, hasPos, retPos };
321         }
322         hasPos = true;
323         retPos = position;
324     } else {
325         retPos = INVALID_POSITION;
326     }
327     return { true, move(bufferGuard), buf, retLen, hasPos, retPos };
328 }
329 } // namespace ModuleFileIO
330 } // namespace FileManagement
331 } // namespace OHOS
332