• 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 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) && !defined(CROSS_PLATFORM)
38 #include "ipc_skeleton.h"
39 #include "tokenid_kit.h"
40 #endif
41 
42 namespace OHOS {
43 namespace FileManagement {
44 namespace ModuleFileIO {
45 using namespace std;
46 using namespace OHOS::FileManagement::LibN;
47 
48 namespace {
49     const std::vector<std::string> PUBLIC_DIR_PATHS = {
50         "/Documents"
51     };
52 }
53 
InitAccessModeType(napi_env env,napi_value exports)54 void InitAccessModeType(napi_env env, napi_value exports)
55 {
56     char propertyName[] = "AccessModeType";
57     napi_property_descriptor desc[] = {
58         DECLARE_NAPI_STATIC_PROPERTY("EXIST", NVal::CreateInt32(env, MODE_EXIST).val_),
59         DECLARE_NAPI_STATIC_PROPERTY("WRITE", NVal::CreateInt32(env, MODE_WRITE).val_),
60         DECLARE_NAPI_STATIC_PROPERTY("READ", NVal::CreateInt32(env, MODE_READ).val_),
61         DECLARE_NAPI_STATIC_PROPERTY("READ_WRITE", NVal::CreateInt32(env, MODE_READ_WRITE).val_),
62     };
63     napi_value obj = nullptr;
64     napi_status status = napi_create_object(env, &obj);
65     if (status != napi_ok) {
66         HILOGE("Failed to create object at initializing openMode");
67         return;
68     }
69     status = napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
70     if (status != napi_ok) {
71         HILOGE("Failed to set properties of character at initializing openMode");
72         return;
73     }
74     status = napi_set_named_property(env, exports, propertyName, obj);
75     if (status != napi_ok) {
76         HILOGE("Failed to set direction property at initializing openMode");
77         return;
78     }
79 }
80 
InitAccessFlagType(napi_env env,napi_value exports)81 void InitAccessFlagType(napi_env env, napi_value exports)
82 {
83     char propertyName[] = "AccessFlagType";
84     napi_property_descriptor desc[] = {
85         DECLARE_NAPI_STATIC_PROPERTY("LOCAL", NVal::CreateInt32(env, MODE_LOCAL).val_),
86     };
87     napi_value obj = nullptr;
88     napi_status status = napi_create_object(env, &obj);
89     if (status != napi_ok) {
90         HILOGE("Failed to create object at initializing AccessFlagType");
91         return;
92     }
93     status = napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
94     if (status != napi_ok) {
95         HILOGE("Failed to set properties of character at initializing AccessFlagType");
96         return;
97     }
98     status = napi_set_named_property(env, exports, propertyName, obj);
99     if (status != napi_ok) {
100         HILOGE("Failed to set direction property at initializing AccessFlagType");
101         return;
102     }
103 }
104 
InitLocationType(napi_env env,napi_value exports)105 void InitLocationType(napi_env env, napi_value exports)
106 {
107     char propertyName[] = "LocationType";
108     napi_property_descriptor desc[] = {
109         DECLARE_NAPI_STATIC_PROPERTY("LOCAl", NVal::CreateInt32(env, MODE_LOCATION_LOCAL).val_),
110         DECLARE_NAPI_STATIC_PROPERTY("CLOUD", NVal::CreateInt32(env, MODE_LOCATION_CLOUD).val_),
111     };
112     napi_value obj = nullptr;
113     napi_status status = napi_create_object(env, &obj);
114     if (status != napi_ok) {
115         HILOGE("Failed to create object at initializing LocationType");
116         return;
117     }
118     status = napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
119     if (status != napi_ok) {
120         HILOGE("Failed to set properties of character at initializing LocationType");
121         return;
122     }
123     status = napi_set_named_property(env, exports, propertyName, obj);
124     if (status != napi_ok) {
125         HILOGE("Failed to set direction property at initializing LocationType");
126         return;
127     }
128 }
129 
InitOpenMode(napi_env env,napi_value exports)130 void InitOpenMode(napi_env env, napi_value exports)
131 {
132     char propertyName[] = "OpenMode";
133     napi_property_descriptor desc[] = {
134         DECLARE_NAPI_STATIC_PROPERTY("READ_ONLY", NVal::CreateInt32(env, USR_READ_ONLY).val_),
135         DECLARE_NAPI_STATIC_PROPERTY("WRITE_ONLY", NVal::CreateInt32(env, USR_WRITE_ONLY).val_),
136         DECLARE_NAPI_STATIC_PROPERTY("READ_WRITE", NVal::CreateInt32(env, USR_RDWR).val_),
137         DECLARE_NAPI_STATIC_PROPERTY("CREATE", NVal::CreateInt32(env, USR_CREATE).val_),
138         DECLARE_NAPI_STATIC_PROPERTY("TRUNC", NVal::CreateInt32(env, USR_TRUNC).val_),
139         DECLARE_NAPI_STATIC_PROPERTY("APPEND", NVal::CreateInt32(env, USR_APPEND).val_),
140         DECLARE_NAPI_STATIC_PROPERTY("NONBLOCK", NVal::CreateInt32(env, USR_NONBLOCK).val_),
141         DECLARE_NAPI_STATIC_PROPERTY("DIR", NVal::CreateInt32(env, USR_DIRECTORY).val_),
142         DECLARE_NAPI_STATIC_PROPERTY("NOFOLLOW", NVal::CreateInt32(env, USR_NOFOLLOW).val_),
143         DECLARE_NAPI_STATIC_PROPERTY("SYNC", NVal::CreateInt32(env, USR_SYNC).val_),
144     };
145     napi_value obj = nullptr;
146     napi_status status = napi_create_object(env, &obj);
147     if (status != napi_ok) {
148         HILOGE("Failed to create object at initializing openMode");
149         return;
150     }
151     status = napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
152     if (status != napi_ok) {
153         HILOGE("Failed to set properties of character at initializing openMode");
154         return;
155     }
156     status = napi_set_named_property(env, exports, propertyName, obj);
157     if (status != napi_ok) {
158         HILOGE("Failed to set direction property at initializing openMode");
159         return;
160     }
161 }
162 
InitWhenceType(napi_env env,napi_value exports)163 void InitWhenceType(napi_env env, napi_value exports)
164 {
165     char propertyName[] = "WhenceType";
166     napi_property_descriptor desc[] = {
167         DECLARE_NAPI_STATIC_PROPERTY("SEEK_SET", NVal::CreateInt32(env, SEEK_SET).val_),
168         DECLARE_NAPI_STATIC_PROPERTY("SEEK_CUR", NVal::CreateInt32(env, SEEK_CUR).val_),
169         DECLARE_NAPI_STATIC_PROPERTY("SEEK_END", NVal::CreateInt32(env, SEEK_END).val_),
170     };
171     napi_value obj = nullptr;
172     napi_status status = napi_create_object(env, &obj);
173     if (status != napi_ok) {
174         HILOGE("Failed to create object at initializing whenceType");
175         return;
176     }
177     status = napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
178     if (status != napi_ok) {
179         HILOGE("Failed to set properties of character at initializing whenceType");
180         return;
181     }
182     status = napi_set_named_property(env, exports, propertyName, obj);
183     if (status != napi_ok) {
184         HILOGE("Failed to set direction property at initializing whenceType");
185         return;
186     }
187 }
188 
GetActualLen(napi_env env,size_t bufLen,size_t bufOff,NVal op)189 static tuple<bool, size_t> GetActualLen(napi_env env, size_t bufLen, size_t bufOff, NVal op)
190 {
191     bool succ = false;
192     size_t retLen = bufLen - bufOff;
193 
194     if (op.HasProp("length")) {
195         int64_t opLength = 0;
196 #ifdef WIN_PLATFORM
197         tie(succ, opLength) = op.GetPropValue("length").ToInt64(static_cast<int64_t>(retLen));
198 #else
199         tie(succ, opLength) = op.GetProp("length").ToInt64(static_cast<int64_t>(retLen));
200 #endif
201         if (!succ || opLength < 0 || static_cast<size_t>(opLength) > retLen) {
202             HILOGE("Invalid option.length");
203             NError(EINVAL).ThrowErr(env);
204             return { false, 0 };
205         }
206         retLen = static_cast<size_t>(opLength);
207     }
208     return { true, retLen };
209 }
210 
ConvertJsFlags(unsigned int & flags)211 unsigned int CommonFunc::ConvertJsFlags(unsigned int &flags)
212 {
213     // default value is usrReadOnly 00
214     unsigned int flagsABI = 0;
215     flagsABI |= ((flags & USR_WRITE_ONLY) == USR_WRITE_ONLY) ? WRONLY : 0;
216     flagsABI |= ((flags & USR_RDWR) == USR_RDWR) ? RDWR : 0;
217     flagsABI |= ((flags & USR_CREATE) == USR_CREATE) ? CREATE : 0;
218     flagsABI |= ((flags & USR_TRUNC) == USR_TRUNC) ? TRUNC : 0;
219     flagsABI |= ((flags & USR_APPEND) == USR_APPEND) ? APPEND : 0;
220     flagsABI |= ((flags & USR_NONBLOCK) == USR_NONBLOCK) ? NONBLOCK : 0;
221     flagsABI |= ((flags & USR_DIRECTORY) == USR_DIRECTORY) ? DIRECTORY : 0;
222     flagsABI |= ((flags & USR_NOFOLLOW) == USR_NOFOLLOW) ? NOFOLLOW : 0;
223     flagsABI |= ((flags & USR_SYNC) == USR_SYNC) ? SYNC : 0;
224     flags = flagsABI;
225     return flagsABI;
226 }
227 
228 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
InstantiateStat(napi_env env,const uv_stat_t & buf,shared_ptr<FileInfo> fileInfo,bool async)229 NVal CommonFunc::InstantiateStat(napi_env env, const uv_stat_t &buf, shared_ptr<FileInfo> fileInfo, bool async)
230 {
231     napi_value objStat = NClass::InstantiateClass(env, StatNExporter::className_, {});
232     if (!objStat) {
233         HILOGE("Failed to instantiate stat class");
234         if (async) {
235             return {env, NError(EIO).GetNapiErr(env)};
236         }
237         NError(EIO).ThrowErr(env);
238         return NVal();
239     }
240 
241     auto statEntity = NClass::GetEntityOf<StatEntity>(env, objStat);
242     if (!statEntity) {
243         HILOGE("Failed to get stat entity");
244         if (async) {
245             return {env, NError(EIO).GetNapiErr(env)};
246         }
247         NError(EIO).ThrowErr(env);
248         return NVal();
249     }
250 
251     statEntity->stat_ = buf;
252     statEntity->fileInfo_ = fileInfo;
253     return { env, objStat };
254 }
255 #endif
256 
InstantiateStat(napi_env env,const uv_stat_t & buf,bool async)257 NVal CommonFunc::InstantiateStat(napi_env env, const uv_stat_t &buf, bool async)
258 {
259     napi_value objStat = NClass::InstantiateClass(env, StatNExporter::className_, {});
260     if (!objStat) {
261         HILOGE("Failed to instantiate stat class");
262         if (async) {
263             return {env, NError(EIO).GetNapiErr(env)};
264         }
265         NError(EIO).ThrowErr(env);
266         return NVal();
267     }
268 
269     auto statEntity = NClass::GetEntityOf<StatEntity>(env, objStat);
270     if (!statEntity) {
271         HILOGE("Failed to get stat entity");
272         if (async) {
273             return {env, NError(EIO).GetNapiErr(env)};
274         }
275         NError(EIO).ThrowErr(env);
276         return NVal();
277     }
278 
279     statEntity->stat_ = buf;
280     return { env, objStat };
281 }
282 
283 #ifndef WIN_PLATFORM
InstantiateFile(napi_env env,int fd,const string & pathOrUri,bool isUri)284 NVal CommonFunc::InstantiateFile(napi_env env, int fd, const string &pathOrUri, bool isUri)
285 {
286     napi_value objFile = NClass::InstantiateClass(env, FileNExporter::className_, {});
287     if (!objFile) {
288         HILOGE("Failed to instantiate class");
289         NError(EIO).ThrowErr(env);
290         close(fd);
291         return NVal();
292     }
293 
294     auto fileEntity = NClass::GetEntityOf<FileEntity>(env, objFile);
295     if (!fileEntity) {
296         HILOGE("Failed to get fileEntity");
297         NError(EIO).ThrowErr(env);
298         close(fd);
299         return NVal();
300     }
301     auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(fd, false);
302     if (fdg == nullptr) {
303         HILOGE("Failed to request heap memory.");
304         close(fd);
305         NError(ENOMEM).ThrowErr(env);
306         return NVal();
307     }
308     fileEntity->fd_.swap(fdg);
309     if (isUri) {
310         fileEntity->path_ = "";
311         fileEntity->uri_ = pathOrUri;
312     } else {
313         fileEntity->path_ = pathOrUri;
314         fileEntity->uri_ = "";
315     }
316     return { env, objFile };
317 }
318 
InstantiateStream(napi_env env,shared_ptr<FILE> fp,bool async)319 NVal CommonFunc::InstantiateStream(napi_env env, shared_ptr<FILE> fp, bool async)
320 {
321     napi_value objStream = NClass::InstantiateClass(env, StreamNExporter::className_, {});
322     if (!objStream) {
323         HILOGE("INNER BUG. Cannot instantiate stream");
324         if (async) {
325             return {env, NError(EIO).GetNapiErr(env)};
326         }
327         NError(EIO).ThrowErr(env);
328         return NVal();
329     }
330 
331     auto streamEntity = NClass::GetEntityOf<StreamEntity>(env, objStream);
332     if (!streamEntity) {
333         HILOGE("Cannot instantiate stream because of void entity");
334         if (async) {
335             return {env, NError(EIO).GetNapiErr(env)};
336         }
337         NError(EIO).ThrowErr(env);
338         return NVal();
339     }
340     streamEntity->fp.swap(fp);
341     return { env, objStream };
342 }
343 #endif
344 
fs_req_cleanup(uv_fs_t * req)345 void CommonFunc::fs_req_cleanup(uv_fs_t* req)
346 {
347     uv_fs_req_cleanup(req);
348     if (req) {
349         delete req;
350         req = nullptr;
351     }
352 }
353 
GetModeFromFlags(unsigned int flags)354 string CommonFunc::GetModeFromFlags(unsigned int flags)
355 {
356     const string readMode = "r";
357     const string writeMode = "w";
358     const string appendMode = "a";
359     const string truncMode = "t";
360     string mode = readMode;
361     mode += (((flags & O_RDWR) == O_RDWR) ? writeMode : "");
362     mode = (((flags & O_WRONLY) == O_WRONLY) ? writeMode : mode);
363     if (mode != readMode) {
364         mode += ((flags & O_TRUNC) ? truncMode : "");
365         mode += ((flags & O_APPEND) ? appendMode : "");
366     }
367     return mode;
368 }
369 
CheckPublicDirPath(const std::string & sandboxPath)370 bool CommonFunc::CheckPublicDirPath(const std::string &sandboxPath)
371 {
372     for (const std::string &path : PUBLIC_DIR_PATHS) {
373         if (sandboxPath.find(path) == 0) {
374             return true;
375         }
376     }
377     return false;
378 }
379 
Decode(const std::string & uri)380 string CommonFunc::Decode(const std::string &uri)
381 {
382     std::ostringstream outPutStream;
383     const int32_t encodeLen = 2;
384     size_t index = 0;
385     while (index < uri.length()) {
386         if (uri[index] == '%') {
387             int hex = 0;
388             std::istringstream inputStream(uri.substr(index + 1, encodeLen));
389             inputStream >> std::hex >> hex;
390             outPutStream << static_cast<char>(hex);
391             index += encodeLen + 1;
392         } else {
393             outPutStream << uri[index];
394             index++;
395         }
396     }
397 
398     return outPutStream.str();
399 }
400 
401 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) && !defined(CROSS_PLATFORM)
IsNumeric(const string & str)402 bool IsNumeric(const string &str)
403 {
404     if (str.empty()) {
405         return false;
406     }
407     for (char const &c : str) {
408         if (!isdigit(c)) {
409             return false;
410         }
411     }
412     return true;
413 }
414 
SetQueryMap(Uri * uri,std::unordered_map<std::string,std::string> & queryMap)415 void SetQueryMap(Uri* uri, std::unordered_map<std::string,
416       std::string> &queryMap)
417 {
418     // file://media/image/12?networkid=xxxx&api_version=xxxx?times=xxx&user=101
419     string query = uri->GetQuery();
420     string pairString;
421     stringstream queryStream(query);
422 
423     while (getline(queryStream, pairString, '&')) {
424         size_t splitIndex = pairString.find('=');
425         if (splitIndex == string::npos || splitIndex == (pairString.length() - 1)) {
426             HILOGE("failed to parse query, query field is %{private}s!", pairString.c_str());
427             continue;
428         }
429         queryMap[pairString.substr(0, splitIndex)] = pairString.substr(splitIndex + 1);
430     }
431     return;
432 }
433 
GetAndCheckUserId(Uri * uri,string & userId)434 bool CommonFunc::GetAndCheckUserId(Uri* uri, string &userId)
435 {
436     if (uri->ToString().find("user=") == string::npos) {
437         return false;
438     }
439 
440     std::unordered_map<std::string, std::string> queryMap;
441     SetQueryMap(uri, queryMap);
442     auto it = queryMap.find("user");
443     if (it != queryMap.end()) {
444         userId = it->second;
445         if (!IsNumeric(userId)) {
446             HILOGE("IsNumeric check fail");
447             return false;
448         }
449         return true;
450     } else {
451         HILOGE("GetAndCheckUserId no match userId");
452     }
453     return false;
454 }
455 
456 /*
457  * For compatibility considerations, filtering system applications require non permission verification
458 */
IsSystemApp()459 bool CommonFunc::IsSystemApp()
460 {
461     uint64_t fullTokenId = OHOS::IPCSkeleton::GetSelfTokenID();
462     return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
463 }
464 #endif
465 
GetCopyPathArg(napi_env env,napi_value srcPath,napi_value dstPath)466 tuple<bool, unique_ptr<char[]>, unique_ptr<char[]>> CommonFunc::GetCopyPathArg(napi_env env,
467                                                                                napi_value srcPath,
468                                                                                napi_value dstPath)
469 {
470     bool succ = false;
471     unique_ptr<char[]> src = nullptr;
472     tie(succ, src, ignore) = NVal(env, srcPath).ToUTF8StringPath();
473     if (!succ) {
474         HILOGE("Failed to convert the src path to UTF-8 string");
475         return { false, nullptr, nullptr };
476     }
477 
478     unique_ptr<char[]> dest = nullptr;
479     tie(succ, dest, ignore) = NVal(env, dstPath).ToUTF8StringPath();
480     if (!succ) {
481         HILOGE("Failed to convert the dest path to UTF-8 string");
482         return { false, nullptr, nullptr };
483     }
484     return make_tuple(true, move(src), move(dest));
485 }
486 
DecodeString(napi_env env,NVal jsStr,NVal encoding)487 static tuple<bool, unique_ptr<char[]>, size_t> DecodeString(napi_env env, NVal jsStr, NVal encoding)
488 {
489     if (!jsStr.TypeIs(napi_string)) {
490         return { false, nullptr, 0 };
491     }
492     if (!encoding) {
493         return jsStr.ToUTF8String();
494     }
495 
496     bool succ = false;
497     unique_ptr<char[]> encodingBuf = nullptr;
498     tie(succ, encodingBuf, ignore) = encoding.ToUTF8String("utf-8");
499     if (!succ) {
500         HILOGE("Failed to convert encoding to UTF8");
501         return { false, nullptr, 0 };
502     }
503 
504     string_view encodingStr(encodingBuf.get());
505     if (encodingStr == "utf-8") {
506         return jsStr.ToUTF8String();
507     } else if (encodingStr == "utf-16") {
508         return jsStr.ToUTF16String();
509     } else {
510         HILOGE("Failed to recognize the str type");
511         return { false, nullptr, 0 };
512     }
513 }
514 
GetReadArg(napi_env env,napi_value readBuf,napi_value option)515 tuple<bool, void *, size_t, int64_t> CommonFunc::GetReadArg(napi_env env,
516     napi_value readBuf, napi_value option)
517 {
518     size_t retLen = 0;
519     int64_t offset = -1;
520     bool succ = false;
521 
522     NVal txt(env, readBuf);
523     void *buf = nullptr;
524     size_t bufLen = 0;
525     tie(succ, buf, bufLen) = txt.ToArraybuffer();
526     if (!succ || bufLen > UINT_MAX) {
527         HILOGE("Invalid arraybuffer");
528         NError(EINVAL).ThrowErr(env);
529         return { false, nullptr, retLen, offset };
530     }
531     NVal op = NVal(env, option);
532     tie(succ, retLen) = GetActualLen(env, bufLen, 0, op);
533     if (!succ) {
534         HILOGE("Failed to get actual length");
535         return { false, nullptr, retLen, offset };
536     }
537 #ifdef WIN_PLATFORM
538     if (op.HasProp("offset") && !op.GetPropValue("offset").TypeIs(napi_undefined)) {
539         tie(succ, offset) = op.GetPropValue("offset").ToInt64();
540 #else
541     if (op.HasProp("offset") && !op.GetProp("offset").TypeIs(napi_undefined)) {
542         tie(succ, offset) = op.GetProp("offset").ToInt64();
543 #endif
544         if (!succ || offset < 0) {
545             HILOGE("option.offset shall be positive number");
546             NError(EINVAL).ThrowErr(env);
547             return { false, nullptr, retLen, offset };
548         }
549     }
550     return { true, buf, retLen, offset };
551 }
552 
553 tuple<bool, unique_ptr<char[]>, void *, size_t, int64_t> CommonFunc::GetWriteArg(napi_env env,
554     napi_value argWBuf, napi_value argOption)
555 {
556     size_t bufLen = 0;
557     int64_t offset = -1;
558     bool succ = false;
559     void *buf = nullptr;
560     NVal op(env, argOption);
561     NVal jsBuffer(env, argWBuf);
562     unique_ptr<char[]> bufferGuard = nullptr;
563 #ifdef WIN_PLATFORM
564     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetPropValue("encoding"));
565 #else
566     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetProp("encoding"));
567 #endif
568     if (!succ) {
569         tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer();
570         if (!succ) {
571             HILOGE("Illegal write buffer or encoding");
572             NError(EINVAL).ThrowErr(env);
573             return { false, nullptr, nullptr, 0, offset };
574         }
575     } else {
576         buf = bufferGuard.get();
577     }
578     if (bufLen > UINT_MAX) {
579         HILOGE("The Size of buffer is too large");
580         NError(EINVAL).ThrowErr(env);
581         return { false, nullptr, nullptr, 0, offset } ;
582     }
583     size_t retLen = 0;
584     tie(succ, retLen) = GetActualLen(env, bufLen, 0, op);
585     if (!succ) {
586         HILOGE("Failed to get actual length");
587         return { false, nullptr, nullptr, 0, offset };
588     }
589 
590 #ifdef WIN_PLATFORM
591     if (op.HasProp("offset") && !op.GetPropValue("offset").TypeIs(napi_undefined)) {
592         tie(succ, offset) = op.GetPropValue("offset").ToInt64();
593 #else
594     if (op.HasProp("offset") && !op.GetProp("offset").TypeIs(napi_undefined)) {
595         tie(succ, offset) = op.GetProp("offset").ToInt64();
596 #endif
597         if (!succ || offset < 0) {
598             HILOGE("option.offset shall be positive number");
599             NError(EINVAL).ThrowErr(env);
600             return { false, nullptr, nullptr, 0, offset };
601         }
602     }
603     return { true, move(bufferGuard), buf, retLen, offset };
604 }
605 } // namespace ModuleFileIO
606 } // namespace FileManagement
607 } // namespace OHOS
608