• 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 "common_func.h"
17 
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <sstream>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <vector>
25 
26 #include "class_stat/stat_entity.h"
27 #include "class_stat/stat_n_exporter.h"
28 #ifndef WIN_PLATFORM
29 #include "class_file/file_entity.h"
30 #include "class_file/file_n_exporter.h"
31 #include "class_stream/stream_entity.h"
32 #include "class_stream/stream_n_exporter.h"
33 #endif
34 #include "filemgmt_libhilog.h"
35 #include "filemgmt_libn.h"
36 #include "file_utils.h"
37 
38 namespace OHOS {
39 namespace FileManagement {
40 namespace ModuleFileIO {
41 using namespace std;
42 using namespace OHOS::FileManagement::LibN;
43 
44 namespace {
45     const std::vector<std::string> PUBLIC_DIR_PATHS = {
46         "/Documents"
47     };
48 }
49 
InitOpenMode(napi_env env,napi_value exports)50 void InitOpenMode(napi_env env, napi_value exports)
51 {
52     char propertyName[] = "OpenMode";
53     napi_property_descriptor desc[] = {
54         DECLARE_NAPI_STATIC_PROPERTY("READ_ONLY", NVal::CreateInt32(env, USR_READ_ONLY).val_),
55         DECLARE_NAPI_STATIC_PROPERTY("WRITE_ONLY", NVal::CreateInt32(env, USR_WRITE_ONLY).val_),
56         DECLARE_NAPI_STATIC_PROPERTY("READ_WRITE", NVal::CreateInt32(env, USR_RDWR).val_),
57         DECLARE_NAPI_STATIC_PROPERTY("CREATE", NVal::CreateInt32(env, USR_CREATE).val_),
58         DECLARE_NAPI_STATIC_PROPERTY("TRUNC", NVal::CreateInt32(env, USR_TRUNC).val_),
59         DECLARE_NAPI_STATIC_PROPERTY("APPEND", NVal::CreateInt32(env, USR_APPEND).val_),
60         DECLARE_NAPI_STATIC_PROPERTY("NONBLOCK", NVal::CreateInt32(env, USR_NONBLOCK).val_),
61         DECLARE_NAPI_STATIC_PROPERTY("DIR", NVal::CreateInt32(env, USR_DIRECTORY).val_),
62         DECLARE_NAPI_STATIC_PROPERTY("NOFOLLOW", NVal::CreateInt32(env, USR_NOFOLLOW).val_),
63         DECLARE_NAPI_STATIC_PROPERTY("SYNC", NVal::CreateInt32(env, USR_SYNC).val_),
64     };
65     napi_value obj = nullptr;
66     napi_status status = napi_create_object(env, &obj);
67     if (status != napi_ok) {
68         HILOGE("Failed to create object at initializing openMode");
69         return;
70     }
71     status = napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
72     if (status != napi_ok) {
73         HILOGE("Failed to set properties of character at initializing openMode");
74         return;
75     }
76     status = napi_set_named_property(env, exports, propertyName, obj);
77     if (status != napi_ok) {
78         HILOGE("Failed to set direction property at initializing openMode");
79         return;
80     }
81 }
82 
InitWhenceType(napi_env env,napi_value exports)83 void InitWhenceType(napi_env env, napi_value exports)
84 {
85     char propertyName[] = "WhenceType";
86     napi_property_descriptor desc[] = {
87         DECLARE_NAPI_STATIC_PROPERTY("SEEK_SET", NVal::CreateInt32(env, SEEK_SET).val_),
88         DECLARE_NAPI_STATIC_PROPERTY("SEEK_CUR", NVal::CreateInt32(env, SEEK_CUR).val_),
89         DECLARE_NAPI_STATIC_PROPERTY("SEEK_END", NVal::CreateInt32(env, SEEK_END).val_),
90     };
91     napi_value obj = nullptr;
92     napi_status status = napi_create_object(env, &obj);
93     if (status != napi_ok) {
94         HILOGE("Failed to create object at initializing whenceType");
95         return;
96     }
97     status = napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
98     if (status != napi_ok) {
99         HILOGE("Failed to set properties of character at initializing whenceType");
100         return;
101     }
102     status = napi_set_named_property(env, exports, propertyName, obj);
103     if (status != napi_ok) {
104         HILOGE("Failed to set direction property at initializing whenceType");
105         return;
106     }
107 }
108 
GetActualLen(napi_env env,size_t bufLen,size_t bufOff,NVal op)109 static tuple<bool, size_t> GetActualLen(napi_env env, size_t bufLen, size_t bufOff, NVal op)
110 {
111     bool succ = false;
112     size_t retLen = bufLen - bufOff;
113 
114     if (op.HasProp("length")) {
115         int64_t opLength = 0;
116 #ifdef WIN_PLATFORM
117         tie(succ, opLength) = op.GetPropValue("length").ToInt64(static_cast<int64_t>(retLen));
118 #else
119         tie(succ, opLength) = op.GetProp("length").ToInt64(static_cast<int64_t>(retLen));
120 #endif
121         if (!succ || opLength < 0 || static_cast<size_t>(opLength) > retLen) {
122             HILOGE("Invalid option.length");
123             NError(EINVAL).ThrowErr(env);
124             return { false, 0 };
125         }
126         retLen = static_cast<size_t>(opLength);
127     }
128     return { true, retLen };
129 }
130 
ConvertJsFlags(unsigned int & flags)131 unsigned int CommonFunc::ConvertJsFlags(unsigned int &flags)
132 {
133     // default value is usrReadOnly 00
134     unsigned int flagsABI = 0;
135     flagsABI |= ((flags & USR_WRITE_ONLY) == USR_WRITE_ONLY) ? WRONLY : 0;
136     flagsABI |= ((flags & USR_RDWR) == USR_RDWR) ? RDWR : 0;
137     flagsABI |= ((flags & USR_CREATE) == USR_CREATE) ? CREATE : 0;
138     flagsABI |= ((flags & USR_TRUNC) == USR_TRUNC) ? TRUNC : 0;
139     flagsABI |= ((flags & USR_APPEND) == USR_APPEND) ? APPEND : 0;
140     flagsABI |= ((flags & USR_NONBLOCK) == USR_NONBLOCK) ? NONBLOCK : 0;
141     flagsABI |= ((flags & USR_DIRECTORY) == USR_DIRECTORY) ? DIRECTORY : 0;
142     flagsABI |= ((flags & USR_NOFOLLOW) == USR_NOFOLLOW) ? NOFOLLOW : 0;
143     flagsABI |= ((flags & USR_SYNC) == USR_SYNC) ? SYNC : 0;
144     flags = flagsABI;
145     return flagsABI;
146 }
147 
148 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
InstantiateStat(napi_env env,const uv_stat_t & buf,shared_ptr<FileInfo> fileInfo)149 NVal CommonFunc::InstantiateStat(napi_env env, const uv_stat_t &buf, shared_ptr<FileInfo> fileInfo)
150 {
151     napi_value objStat = NClass::InstantiateClass(env, StatNExporter::className_, {});
152     if (!objStat) {
153         HILOGE("Failed to instantiate stat class");
154         NError(EIO).ThrowErr(env);
155         return NVal();
156     }
157 
158     auto statEntity = NClass::GetEntityOf<StatEntity>(env, objStat);
159     if (!statEntity) {
160         HILOGE("Failed to get stat entity");
161         NError(EIO).ThrowErr(env);
162         return NVal();
163     }
164 
165     statEntity->stat_ = buf;
166     statEntity->fileInfo_ = fileInfo;
167     return { env, objStat };
168 }
169 #endif
170 
InstantiateStat(napi_env env,const uv_stat_t & buf)171 NVal CommonFunc::InstantiateStat(napi_env env, const uv_stat_t &buf)
172 {
173     napi_value objStat = NClass::InstantiateClass(env, StatNExporter::className_, {});
174     if (!objStat) {
175         HILOGE("Failed to instantiate stat class");
176         NError(EIO).ThrowErr(env);
177         return NVal();
178     }
179 
180     auto statEntity = NClass::GetEntityOf<StatEntity>(env, objStat);
181     if (!statEntity) {
182         HILOGE("Failed to get stat entity");
183         NError(EIO).ThrowErr(env);
184         return NVal();
185     }
186 
187     statEntity->stat_ = buf;
188     return { env, objStat };
189 }
190 
191 #ifndef WIN_PLATFORM
InstantiateFile(napi_env env,int fd,const string & pathOrUri,bool isUri)192 NVal CommonFunc::InstantiateFile(napi_env env, int fd, const string &pathOrUri, bool isUri)
193 {
194     napi_value objFile = NClass::InstantiateClass(env, FileNExporter::className_, {});
195     if (!objFile) {
196         HILOGE("Failed to instantiate class");
197         NError(EIO).ThrowErr(env);
198         close(fd);
199         return NVal();
200     }
201 
202     auto fileEntity = NClass::GetEntityOf<FileEntity>(env, objFile);
203     if (!fileEntity) {
204         HILOGE("Failed to get fileEntity");
205         NError(EIO).ThrowErr(env);
206         close(fd);
207         return NVal();
208     }
209     auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(fd, false);
210     if (fdg == nullptr) {
211         HILOGE("Failed to request heap memory.");
212         NError(ENOMEM).ThrowErr(env);
213         return NVal();
214     }
215     fileEntity->fd_.swap(fdg);
216     if (isUri) {
217         fileEntity->path_ = "";
218         fileEntity->uri_ = pathOrUri;
219     } else {
220         fileEntity->path_ = pathOrUri;
221         fileEntity->uri_ = "";
222     }
223     return { env, objFile };
224 }
225 
InstantiateStream(napi_env env,unique_ptr<FILE,decltype(& fclose) > fp)226 NVal CommonFunc::InstantiateStream(napi_env env, unique_ptr<FILE, decltype(&fclose)> fp)
227 {
228     napi_value objStream = NClass::InstantiateClass(env, StreamNExporter::className_, {});
229     if (!objStream) {
230         HILOGE("INNER BUG. Cannot instantiate stream");
231         NError(EIO).ThrowErr(env);
232         return NVal();
233     }
234 
235     auto streamEntity = NClass::GetEntityOf<StreamEntity>(env, objStream);
236     if (!streamEntity) {
237         HILOGE("Cannot instantiate stream because of void entity");
238         NError(EIO).ThrowErr(env);
239         return NVal();
240     }
241 
242     streamEntity->fp.swap(fp);
243     return { env, objStream };
244 }
245 #endif
246 
fs_req_cleanup(uv_fs_t * req)247 void CommonFunc::fs_req_cleanup(uv_fs_t* req)
248 {
249     uv_fs_req_cleanup(req);
250     if (req) {
251         delete req;
252         req = nullptr;
253     }
254 }
255 
GetModeFromFlags(unsigned int flags)256 string CommonFunc::GetModeFromFlags(unsigned int flags)
257 {
258     const string readMode = "r";
259     const string writeMode = "w";
260     const string appendMode = "a";
261     const string truncMode = "t";
262     string mode = readMode;
263     mode += (((flags & O_RDWR) == O_RDWR) ? writeMode : "");
264     mode = (((flags & O_WRONLY) == O_WRONLY) ? writeMode : mode);
265     if (mode != readMode) {
266         mode += ((flags & O_TRUNC) ? truncMode : "");
267         mode += ((flags & O_APPEND) ? appendMode : "");
268     }
269     return mode;
270 }
271 
CheckPublicDirPath(const std::string & sandboxPath)272 bool CommonFunc::CheckPublicDirPath(const std::string &sandboxPath)
273 {
274     for (const std::string &path : PUBLIC_DIR_PATHS) {
275         if (sandboxPath.find(path) == 0) {
276             return true;
277         }
278     }
279     return false;
280 }
281 
Decode(const std::string & uri)282 string CommonFunc::Decode(const std::string &uri)
283 {
284     std::ostringstream outPutStream;
285     const int32_t encodeLen = 2;
286     size_t index = 0;
287     while (index < uri.length()) {
288         if (uri[index] == '%') {
289             int hex = 0;
290             std::istringstream inputStream(uri.substr(index + 1, encodeLen));
291             inputStream >> std::hex >> hex;
292             outPutStream << static_cast<char>(hex);
293             index += encodeLen + 1;
294         } else {
295             outPutStream << uri[index];
296             index++;
297         }
298     }
299 
300     return outPutStream.str();
301 }
302 
GetCopyPathArg(napi_env env,napi_value srcPath,napi_value dstPath)303 tuple<bool, unique_ptr<char[]>, unique_ptr<char[]>> CommonFunc::GetCopyPathArg(napi_env env,
304                                                                                napi_value srcPath,
305                                                                                napi_value dstPath)
306 {
307     bool succ = false;
308     unique_ptr<char[]> src = nullptr;
309     tie(succ, src, ignore) = NVal(env, srcPath).ToUTF8String();
310     if (!succ) {
311         HILOGE("Failed to convert the src path to UTF-8 string");
312         return { false, nullptr, nullptr };
313     }
314 
315     unique_ptr<char[]> dest = nullptr;
316     tie(succ, dest, ignore) = NVal(env, dstPath).ToUTF8String();
317     if (!succ) {
318         HILOGE("Failed to convert the dest path to UTF-8 string");
319         return { false, nullptr, nullptr };
320     }
321     return make_tuple(true, move(src), move(dest));
322 }
323 
DecodeString(napi_env env,NVal jsStr,NVal encoding)324 static tuple<bool, unique_ptr<char[]>, size_t> DecodeString(napi_env env, NVal jsStr, NVal encoding)
325 {
326     if (!jsStr.TypeIs(napi_string)) {
327         return { false, nullptr, 0 };
328     }
329     if (!encoding) {
330         return jsStr.ToUTF8String();
331     }
332 
333     bool succ = false;
334     unique_ptr<char[]> encodingBuf = nullptr;
335     tie(succ, encodingBuf, ignore) = encoding.ToUTF8String("utf-8");
336     if (!succ) {
337         HILOGE("Failed to convert encoding to UTF8");
338         return { false, nullptr, 0 };
339     }
340 
341     string_view encodingStr(encodingBuf.get());
342     if (encodingStr == "utf-8") {
343         return jsStr.ToUTF8String();
344     } else if (encodingStr == "utf-16") {
345         return jsStr.ToUTF16String();
346     } else {
347         HILOGE("Failed to recognize the str type");
348         return { false, nullptr, 0 };
349     }
350 }
351 
GetReadArg(napi_env env,napi_value readBuf,napi_value option)352 tuple<bool, void *, size_t, int64_t> CommonFunc::GetReadArg(napi_env env,
353     napi_value readBuf, napi_value option)
354 {
355     size_t retLen = 0;
356     int64_t offset = -1;
357     bool succ = false;
358 
359     NVal txt(env, readBuf);
360     void *buf = nullptr;
361     size_t bufLen = 0;
362     tie(succ, buf, bufLen) = txt.ToArraybuffer();
363     if (!succ || bufLen > UINT_MAX) {
364         HILOGE("Invalid arraybuffer");
365         NError(EINVAL).ThrowErr(env);
366         return { false, nullptr, retLen, offset };
367     }
368     NVal op = NVal(env, option);
369     tie(succ, retLen) = GetActualLen(env, bufLen, 0, op);
370     if (!succ) {
371         HILOGE("Failed to get actual length");
372         return { false, nullptr, retLen, offset };
373     }
374 #ifdef WIN_PLATFORM
375     if (op.HasProp("offset") && !op.GetPropValue("offset").TypeIs(napi_undefined)) {
376         tie(succ, offset) = op.GetPropValue("offset").ToInt64();
377 #else
378     if (op.HasProp("offset") && !op.GetProp("offset").TypeIs(napi_undefined)) {
379         tie(succ, offset) = op.GetProp("offset").ToInt64();
380 #endif
381         if (!succ || offset < 0) {
382             HILOGE("option.offset shall be positive number");
383             NError(EINVAL).ThrowErr(env);
384             return { false, nullptr, retLen, offset };
385         }
386     }
387     return { true, buf, retLen, offset };
388 }
389 
390 tuple<bool, unique_ptr<char[]>, void *, size_t, int64_t> CommonFunc::GetWriteArg(napi_env env,
391     napi_value argWBuf, napi_value argOption)
392 {
393     size_t bufLen = 0;
394     int64_t offset = -1;
395     bool succ = false;
396     void *buf = nullptr;
397     NVal op(env, argOption);
398     NVal jsBuffer(env, argWBuf);
399     unique_ptr<char[]> bufferGuard = nullptr;
400 #ifdef WIN_PLATFORM
401     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetPropValue("encoding"));
402 #else
403     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetProp("encoding"));
404 #endif
405     if (!succ) {
406         tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer();
407         if (!succ) {
408             HILOGE("Illegal write buffer or encoding");
409             NError(EINVAL).ThrowErr(env);
410             return { false, nullptr, nullptr, 0, offset };
411         }
412     } else {
413         buf = bufferGuard.get();
414     }
415     if (bufLen > UINT_MAX) {
416         HILOGE("The Size of buffer is too large");
417         NError(EINVAL).ThrowErr(env);
418         return { false, nullptr, nullptr, 0, offset } ;
419     }
420     size_t retLen = 0;
421     tie(succ, retLen) = GetActualLen(env, bufLen, 0, op);
422     if (!succ) {
423         HILOGE("Failed to get actual length");
424         return { false, nullptr, nullptr, 0, offset };
425     }
426 
427 #ifdef WIN_PLATFORM
428     if (op.HasProp("offset") && !op.GetPropValue("offset").TypeIs(napi_undefined)) {
429         tie(succ, offset) = op.GetPropValue("offset").ToInt64();
430 #else
431     if (op.HasProp("offset") && !op.GetProp("offset").TypeIs(napi_undefined)) {
432         tie(succ, offset) = op.GetProp("offset").ToInt64();
433 #endif
434         if (!succ || offset < 0) {
435             HILOGE("option.offset shall be positive number");
436             NError(EINVAL).ThrowErr(env);
437             return { false, nullptr, nullptr, 0, offset };
438         }
439     }
440     return { true, move(bufferGuard), buf, retLen, offset };
441 }
442 } // namespace ModuleFileIO
443 } // namespace FileManagement
444 } // namespace OHOS
445