• 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 
GetActualLen(napi_env env,size_t bufLen,size_t bufOff,NVal op)83 static tuple<bool, size_t> GetActualLen(napi_env env, size_t bufLen, size_t bufOff, NVal op)
84 {
85     bool succ = false;
86     size_t retLen = bufLen - bufOff;
87 
88     if (op.HasProp("length")) {
89         int64_t opLength = 0;
90 #ifdef WIN_PLATFORM
91         tie(succ, opLength) = op.GetPropValue("length").ToInt64(static_cast<int64_t>(retLen));
92 #else
93         tie(succ, opLength) = op.GetProp("length").ToInt64(static_cast<int64_t>(retLen));
94 #endif
95         if (!succ || opLength < 0 || static_cast<size_t>(opLength) > retLen) {
96             HILOGE("Invalid option.length");
97             NError(EINVAL).ThrowErr(env);
98             return { false, 0 };
99         }
100         retLen = static_cast<size_t>(opLength);
101     }
102     return { true, retLen };
103 }
104 
ConvertJsFlags(unsigned int & flags)105 unsigned int CommonFunc::ConvertJsFlags(unsigned int &flags)
106 {
107     // default value is usrReadOnly 00
108     unsigned int flagsABI = 0;
109     flagsABI |= ((flags & USR_WRITE_ONLY) == USR_WRITE_ONLY) ? WRONLY : 0;
110     flagsABI |= ((flags & USR_RDWR) == USR_RDWR) ? RDWR : 0;
111     flagsABI |= ((flags & USR_CREATE) == USR_CREATE) ? CREATE : 0;
112     flagsABI |= ((flags & USR_TRUNC) == USR_TRUNC) ? TRUNC : 0;
113     flagsABI |= ((flags & USR_APPEND) == USR_APPEND) ? APPEND : 0;
114     flagsABI |= ((flags & USR_NONBLOCK) == USR_NONBLOCK) ? NONBLOCK : 0;
115     flagsABI |= ((flags & USR_DIRECTORY) == USR_DIRECTORY) ? DIRECTORY : 0;
116     flagsABI |= ((flags & USR_NOFOLLOW) == USR_NOFOLLOW) ? NOFOLLOW : 0;
117     flagsABI |= ((flags & USR_SYNC) == USR_SYNC) ? SYNC : 0;
118     flags = flagsABI;
119     return flagsABI;
120 }
121 
InstantiateStat(napi_env env,const uv_stat_t & buf)122 NVal CommonFunc::InstantiateStat(napi_env env, const uv_stat_t &buf)
123 {
124     napi_value objStat = NClass::InstantiateClass(env, StatNExporter::className_, {});
125     if (!objStat) {
126         HILOGE("Failed to instantiate stat class");
127         NError(EIO).ThrowErr(env);
128         return NVal();
129     }
130 
131     auto statEntity = NClass::GetEntityOf<StatEntity>(env, objStat);
132     if (!statEntity) {
133         HILOGE("Failed to get stat entity");
134         NError(EIO).ThrowErr(env);
135         return NVal();
136     }
137 
138     statEntity->stat_ = buf;
139     return { env, objStat };
140 }
141 
142 #ifndef WIN_PLATFORM
InstantiateFile(napi_env env,int fd,string pathOrUri,bool isUri)143 NVal CommonFunc::InstantiateFile(napi_env env, int fd, string pathOrUri, bool isUri)
144 {
145     napi_value objFile = NClass::InstantiateClass(env, FileNExporter::className_, {});
146     if (!objFile) {
147         HILOGE("Failed to instantiate class");
148         NError(EIO).ThrowErr(env);
149         close(fd);
150         return NVal();
151     }
152 
153     auto fileEntity = NClass::GetEntityOf<FileEntity>(env, objFile);
154     if (!fileEntity) {
155         HILOGE("Failed to get fileEntity");
156         NError(EIO).ThrowErr(env);
157         close(fd);
158         return NVal();
159     }
160     auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(fd, false);
161     if (fdg == nullptr) {
162         HILOGE("Failed to request heap memory.");
163         NError(ENOMEM).ThrowErr(env);
164         return NVal();
165     }
166     fileEntity->fd_.swap(fdg);
167     if (isUri) {
168         fileEntity->path_ = "";
169         fileEntity->uri_ = pathOrUri;
170     } else {
171         fileEntity->path_ = pathOrUri;
172         fileEntity->uri_ = "";
173     }
174     return { env, objFile };
175 }
176 
InstantiateStream(napi_env env,unique_ptr<FILE,decltype(& fclose) > fp)177 NVal CommonFunc::InstantiateStream(napi_env env, unique_ptr<FILE, decltype(&fclose)> fp)
178 {
179     napi_value objStream = NClass::InstantiateClass(env, StreamNExporter::className_, {});
180     if (!objStream) {
181         HILOGE("INNER BUG. Cannot instantiate stream");
182         NError(EIO).ThrowErr(env);
183         return NVal();
184     }
185 
186     auto streamEntity = NClass::GetEntityOf<StreamEntity>(env, objStream);
187     if (!streamEntity) {
188         HILOGE("Cannot instantiate stream because of void entity");
189         NError(EIO).ThrowErr(env);
190         return NVal();
191     }
192 
193     streamEntity->fp.swap(fp);
194     return { env, objStream };
195 }
196 #endif
197 
fs_req_cleanup(uv_fs_t * req)198 void CommonFunc::fs_req_cleanup(uv_fs_t* req)
199 {
200     uv_fs_req_cleanup(req);
201     if (req) {
202         delete req;
203         req = nullptr;
204     }
205 }
206 
GetModeFromFlags(unsigned int flags)207 string CommonFunc::GetModeFromFlags(unsigned int flags)
208 {
209     const string readMode = "r";
210     const string writeMode = "w";
211     const string appendMode = "a";
212     const string truncMode = "t";
213     string mode = readMode;
214     mode += (((flags & O_RDWR) == O_RDWR) ? writeMode : "");
215     mode = (((flags & O_WRONLY) == O_WRONLY) ? writeMode : mode);
216     if (mode != readMode) {
217         mode += ((flags & O_TRUNC) ? truncMode : "");
218         mode += ((flags & O_APPEND) ? appendMode : "");
219     }
220     return mode;
221 }
222 
CheckPublicDirPath(const std::string & sandboxPath)223 bool CommonFunc::CheckPublicDirPath(const std::string &sandboxPath)
224 {
225     for (const std::string &path : PUBLIC_DIR_PATHS) {
226         if (sandboxPath.find(path) == 0) {
227             return true;
228         }
229     }
230     return false;
231 }
232 
Decode(const std::string & uri)233 string CommonFunc::Decode(const std::string &uri)
234 {
235     std::ostringstream outPutStream;
236     const int32_t encodeLen = 2;
237     size_t index = 0;
238     while (index < uri.length()) {
239         if (uri[index] == '%') {
240             int hex = 0;
241             std::istringstream inputStream(uri.substr(index + 1, encodeLen));
242             inputStream >> std::hex >> hex;
243             outPutStream << static_cast<char>(hex);
244             index += encodeLen + 1;
245         } else {
246             outPutStream << uri[index];
247             index++;
248         }
249     }
250 
251     return outPutStream.str();
252 }
253 
GetCopyPathArg(napi_env env,napi_value srcPath,napi_value dstPath)254 tuple<bool, unique_ptr<char[]>, unique_ptr<char[]>> CommonFunc::GetCopyPathArg(napi_env env,
255                                                                                napi_value srcPath,
256                                                                                napi_value dstPath)
257 {
258     bool succ = false;
259     unique_ptr<char[]> src = nullptr;
260     tie(succ, src, ignore) = NVal(env, srcPath).ToUTF8String();
261     if (!succ) {
262         HILOGE("Failed to convert the src path to UTF-8 string");
263         return { false, nullptr, nullptr };
264     }
265 
266     unique_ptr<char[]> dest = nullptr;
267     tie(succ, dest, ignore) = NVal(env, dstPath).ToUTF8String();
268     if (!succ) {
269         HILOGE("Failed to convert the dest path to UTF-8 string");
270         return { false, nullptr, nullptr };
271     }
272     return make_tuple(true, move(src), move(dest));
273 }
274 
DecodeString(napi_env env,NVal jsStr,NVal encoding)275 static tuple<bool, unique_ptr<char[]>, size_t> DecodeString(napi_env env, NVal jsStr, NVal encoding)
276 {
277     if (!jsStr.TypeIs(napi_string)) {
278         return { false, nullptr, 0 };
279     }
280     if (!encoding) {
281         return jsStr.ToUTF8String();
282     }
283 
284     bool succ = false;
285     unique_ptr<char[]> encodingBuf = nullptr;
286     tie(succ, encodingBuf, ignore) = encoding.ToUTF8String("utf-8");
287     if (!succ) {
288         HILOGE("Failed to convert encoding to UTF8");
289         return { false, nullptr, 0 };
290     }
291 
292     string_view encodingStr(encodingBuf.get());
293     if (encodingStr == "utf-8") {
294         return jsStr.ToUTF8String();
295     } else if (encodingStr == "utf-16") {
296         return jsStr.ToUTF16String();
297     } else {
298         HILOGE("Failed to recognize the str type");
299         return { false, nullptr, 0 };
300     }
301 }
302 
GetReadArg(napi_env env,napi_value readBuf,napi_value option)303 tuple<bool, void *, size_t, int64_t> CommonFunc::GetReadArg(napi_env env,
304     napi_value readBuf, napi_value option)
305 {
306     size_t retLen = 0;
307     int64_t offset = -1;
308     bool succ = false;
309 
310     NVal txt(env, readBuf);
311     void *buf = nullptr;
312     size_t bufLen = 0;
313     tie(succ, buf, bufLen) = txt.ToArraybuffer();
314     if (!succ || bufLen > UINT_MAX) {
315         HILOGE("Invalid arraybuffer");
316         NError(EINVAL).ThrowErr(env);
317         return { false, nullptr, retLen, offset };
318     }
319     NVal op = NVal(env, option);
320     tie(succ, retLen) = GetActualLen(env, bufLen, 0, op);
321     if (!succ) {
322         HILOGE("Failed to get actual length");
323         return { false, nullptr, retLen, offset };
324     }
325 #ifdef WIN_PLATFORM
326     if (op.HasProp("offset") && !op.GetPropValue("offset").TypeIs(napi_undefined)) {
327         tie(succ, offset) = op.GetPropValue("offset").ToInt64();
328 #else
329     if (op.HasProp("offset") && !op.GetProp("offset").TypeIs(napi_undefined)) {
330         tie(succ, offset) = op.GetProp("offset").ToInt64();
331 #endif
332         if (!succ || offset < 0) {
333             HILOGE("option.offset shall be positive number");
334             NError(EINVAL).ThrowErr(env);
335             return { false, nullptr, retLen, offset };
336         }
337     }
338     return { true, buf, retLen, offset };
339 }
340 
341 tuple<bool, unique_ptr<char[]>, void *, size_t, int64_t> CommonFunc::GetWriteArg(napi_env env,
342     napi_value argWBuf, napi_value argOption)
343 {
344     size_t bufLen = 0;
345     int64_t offset = -1;
346     bool succ = false;
347     void *buf = nullptr;
348     NVal op(env, argOption);
349     NVal jsBuffer(env, argWBuf);
350     unique_ptr<char[]> bufferGuard = nullptr;
351 #ifdef WIN_PLATFORM
352     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetPropValue("encoding"));
353 #else
354     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetProp("encoding"));
355 #endif
356     if (!succ) {
357         tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer();
358         if (!succ) {
359             HILOGE("Illegal write buffer or encoding");
360             NError(EINVAL).ThrowErr(env);
361             return { false, nullptr, nullptr, 0, offset };
362         }
363     } else {
364         buf = bufferGuard.get();
365     }
366     if (bufLen > UINT_MAX) {
367         HILOGE("The Size of buffer is too large");
368         NError(EINVAL).ThrowErr(env);
369         return { false, nullptr, nullptr, 0, offset } ;
370     }
371     size_t retLen = 0;
372     tie(succ, retLen) = GetActualLen(env, bufLen, 0, op);
373     if (!succ) {
374         HILOGE("Failed to get actual length");
375         return { false, nullptr, nullptr, 0, offset };
376     }
377 
378 #ifdef WIN_PLATFORM
379     if (op.HasProp("offset") && !op.GetPropValue("offset").TypeIs(napi_undefined)) {
380         tie(succ, offset) = op.GetPropValue("offset").ToInt64();
381 #else
382     if (op.HasProp("offset") && !op.GetProp("offset").TypeIs(napi_undefined)) {
383         tie(succ, offset) = op.GetProp("offset").ToInt64();
384 #endif
385         if (!succ || offset < 0) {
386             HILOGE("option.offset shall be positive number");
387             NError(EINVAL).ThrowErr(env);
388             return { false, nullptr, nullptr, 0, offset };
389         }
390     }
391     return { true, move(bufferGuard), buf, retLen, offset };
392 }
393 } // namespace ModuleFileIO
394 } // namespace FileManagement
395 } // namespace OHOS
396