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