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