1 /*
2 * Copyright (c) 2024-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 "file_fs_impl.h"
17
18 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
19 #include <sys/xattr.h>
20
21 #include "bundle_mgr_proxy.h"
22 #include "ipc_skeleton.h"
23 #include "iservice_registry.h"
24 #include "system_ability_definition.h"
25 #endif
26
27 using namespace OHOS;
28 using namespace OHOS::FFI;
29 using namespace OHOS::FileManagement;
30 using namespace OHOS::CJSystemapi;
31 using namespace OHOS::CJSystemapi::FileFs;
32
33 namespace {
34
35 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
36 const std::string CLOUDDISK_FILE_PREFIX = "/data/storage/el2/cloud";
37 const std::string DISTRIBUTED_FILE_PREFIX = "/data/storage/el2/distributedfiles";
38 const std::string PACKAGE_NAME_FLAG = "<PackageName>";
39 const std::string USER_ID_FLAG = "<currentUserId>";
40 const std::string PHYSICAL_PATH_PREFIX = "/mnt/hmdfs/<currentUserId>/account/device_view/local/data/<PackageName>";
41 const std::string CLOUD_FILE_LOCATION = "user.cloud.location";
42 const char POSITION_LOCAL = '1';
43 const char POSITION_BOTH = '3';
44 const int BASE_USER_RANGE = 200000;
45 #endif
46
ParseFile(int32_t file)47 std::tuple<int, FileInfo> ParseFile(int32_t file)
48 {
49 if (file < 0) {
50 LOGE("Invalid fd");
51 return { EINVAL, FileInfo { false, {}, {} } };
52 }
53 auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(file, false);
54 if (fdg == nullptr) {
55 LOGE("Failed to request heap memory.");
56 return { ENOMEM, FileInfo { false, {}, {} } };
57 }
58 return { SUCCESS_CODE, FileInfo { false, {}, move(fdg) } };
59 };
60
ParseFile(std::string file)61 std::tuple<int, FileInfo> ParseFile(std::string file)
62 {
63 std::unique_ptr<char[]> filePath = std::make_unique<char[]>(file.length() + 1);
64 if (!filePath) {
65 return { ENOMEM, FileInfo { true, nullptr, {} } };
66 }
67 for (size_t i = 0; i < file.length(); i++) {
68 filePath[i] = file[i];
69 }
70
71 return { SUCCESS_CODE, FileInfo { true, move(filePath), {} } };
72 };
73
CheckFsStat(const FileInfo & fileInfo,uv_fs_t * req)74 int CheckFsStat(const FileInfo &fileInfo, uv_fs_t* req)
75 {
76 if (fileInfo.isPath) {
77 int ret = uv_fs_stat(nullptr, req, fileInfo.path.get(), nullptr);
78 if (ret < 0) {
79 LOGE("Failed to stat file with path");
80 return ret;
81 }
82 } else {
83 int ret = uv_fs_fstat(nullptr, req, fileInfo.fdg->GetFD(), nullptr);
84 if (ret < 0) {
85 LOGE("Failed to stat file with fd");
86 return ret;
87 }
88 }
89 return SUCCESS_CODE;
90 }
91
GetUvStat(const FileInfo & fileInfo)92 std::tuple<int, uv_stat_t*> GetUvStat(const FileInfo& fileInfo)
93 {
94 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> stat_req = {
95 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
96 if (!stat_req) {
97 LOGE("Failed to request heap memory.");
98 return {ENOMEM, nullptr};
99 }
100 auto state = CheckFsStat(fileInfo, stat_req.get());
101 if (state != SUCCESS_CODE) {
102 return { state, nullptr };
103 }
104 uv_stat_t* tempBuf = new (std::nothrow) uv_stat_t(stat_req->statbuf);
105 if (!tempBuf) {
106 return {ENOMEM, nullptr};
107 }
108 return {SUCCESS_CODE, tempBuf};
109 }
110
ParseRandomFile(std::string file)111 std::tuple<bool, FileInfo, int> ParseRandomFile(std::string file)
112 {
113 LOGI("FS_TEST:: RandomAccessFileImpl::ParseRandomFile");
114 std::unique_ptr<char[]> filePath = std::make_unique<char[]>(file.length() + 1);
115 if (!filePath) {
116 return { false, FileInfo { true, nullptr, {} }, ENOMEM };
117 }
118 for (size_t i = 0; i < file.length(); i++) {
119 filePath[i] = file[i];
120 }
121 OHOS::DistributedFS::FDGuard sfd;
122 auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(sfd, false);
123 if (fdg == nullptr) {
124 return { false, FileInfo { false, nullptr, nullptr }, ENOMEM };
125 }
126 LOGI("FS_TEST:: RandomAccessFileImpl::ParseRandomFile success");
127 return { true, FileInfo { true, move(filePath), move(fdg) }, ERRNO_NOERR };
128 }
129
UvAccess(const std::string & path,int mode)130 std::tuple<int32_t, bool> UvAccess(const std::string &path, int mode)
131 {
132 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> stat_req = {
133 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
134 if (!stat_req) {
135 LOGE("Failed to request heap memory.");
136 return {GetErrorCode(ENOMEM), false};
137 }
138 bool isAccess = false;
139 int ret = uv_fs_access(nullptr, stat_req.get(), path.c_str(), mode, nullptr);
140 if (ret < 0 && (std::string_view(uv_err_name(ret)) != "ENOENT")) {
141 LOGE("Failed to access file by path");
142 return {GetErrorCode(ret), false};
143 }
144 if (ret == 0) {
145 isAccess = true;
146 }
147 return {SUCCESS_CODE, isAccess};
148 }
149
150 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
IsCloudOrDistributedFilePath(const std::string & path)151 bool IsCloudOrDistributedFilePath(const std::string &path)
152 {
153 return path.find(CLOUDDISK_FILE_PREFIX) == 0 || path.find(DISTRIBUTED_FILE_PREFIX) == 0;
154 }
155
GetCurrentUserId()156 int GetCurrentUserId()
157 {
158 int uid = IPCSkeleton::GetCallingUid();
159 int userId = uid / BASE_USER_RANGE;
160 return userId;
161 }
162
GetBundleMgrProxy()163 sptr<OHOS::AppExecFwk::BundleMgrProxy> GetBundleMgrProxy()
164 {
165 sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
166 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
167 if (!systemAbilityManager) {
168 LOGE("Fail to get system ability mgr");
169 return nullptr;
170 }
171 sptr<OHOS::IRemoteObject> remoteObject =
172 systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
173 if (!remoteObject) {
174 LOGE("Fail to get bundle manager proxy");
175 return nullptr;
176 }
177 return iface_cast<OHOS::AppExecFwk::BundleMgrProxy>(remoteObject);
178 }
179
GetSelfBundleName()180 std::string GetSelfBundleName()
181 {
182 sptr<OHOS::AppExecFwk::BundleMgrProxy> bundleMgrProxy = GetBundleMgrProxy();
183 if (!bundleMgrProxy) {
184 LOGE("BundleMgrProxy is nullptr");
185 return "";
186 }
187 OHOS::AppExecFwk::BundleInfo bundleInfo;
188 auto ret = bundleMgrProxy->GetBundleInfoForSelf(0, bundleInfo);
189 if (ret != 0) {
190 LOGE("BundleName get fail");
191 return "";
192 }
193 return bundleInfo.name;
194 }
195
HandleLocalCheck(const std::string & path,int mode)196 std::tuple<int32_t, bool> HandleLocalCheck(const std::string &path, int mode)
197 {
198 // check if the file of /data/storage/el2/cloud is on the local
199 if (path.find(CLOUDDISK_FILE_PREFIX) == 0) {
200 char val[2] = {'\0'};
201 if (getxattr(path.c_str(), CLOUD_FILE_LOCATION.c_str(), val, sizeof(val)) < 0) {
202 LOGE("Get cloud file location fail, err: %{public}d", errno);
203 return {GetErrorCode(errno), false};
204 }
205 if (val[0] == POSITION_LOCAL || val[0] == POSITION_BOTH) {
206 return {SUCCESS_CODE, true};
207 }
208 return {GetErrorCode(ENOENT), false};
209 }
210 // check if the distributed file of /data/storage/el2/distributedfiles is on the local,
211 // convert into physical path(/mnt/hmdfs/<currentUserId>/account/device_view/local/data/<PackageName>) and check
212 if (path.find(DISTRIBUTED_FILE_PREFIX) == 0) {
213 int userId = GetCurrentUserId();
214 std::string bundleName = GetSelfBundleName();
215 std::string relativePath = path.substr(DISTRIBUTED_FILE_PREFIX.length());
216 std::string physicalPath = PHYSICAL_PATH_PREFIX + relativePath;
217 physicalPath.replace(physicalPath.find(USER_ID_FLAG), USER_ID_FLAG.length(), std::to_string(userId));
218 physicalPath.replace(physicalPath.find(PACKAGE_NAME_FLAG), PACKAGE_NAME_FLAG.length(), bundleName);
219 return UvAccess(physicalPath, mode);
220 }
221 return {GetErrorCode(ENOENT), false};
222 }
223 #endif
224 }
225
226 namespace OHOS {
227 namespace CJSystemapi {
228 using namespace std;
Stat(int32_t file)229 std::tuple<int, sptr<StatImpl>> FileFsImpl::Stat(int32_t file)
230 {
231 auto [fileState, fileInfo] = ParseFile(file);
232
233 if (fileState != SUCCESS_CODE) {
234 return {GetErrorCode(fileState), nullptr};
235 }
236 auto [statState, stat] = GetUvStat(fileInfo);
237 if (statState != SUCCESS_CODE) {
238 return {GetErrorCode(statState), nullptr};
239 }
240 auto nativeStat = FFIData::Create<StatImpl>(*stat);
241 delete(stat);
242 stat = nullptr;
243 if (!nativeStat) {
244 return {GetErrorCode(ENOMEM), nullptr};
245 }
246 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
247 auto fileInfoPtr = std::make_shared<FileInfo>(std::move(fileInfo));
248 nativeStat->SetFileInfo(fileInfoPtr);
249 #endif
250 return {SUCCESS_CODE, nativeStat};
251 }
252
Stat(std::string file)253 std::tuple<int32_t, sptr<StatImpl>> FileFsImpl::Stat(std::string file)
254 {
255 auto [fileState, fileInfo] = ParseFile(file);
256
257 if (fileState != SUCCESS_CODE) {
258 LOGE("ParseFile false, please check the file path!");
259 return {GetErrorCode(fileState), nullptr};
260 }
261 auto [statState, stat] = GetUvStat(fileInfo);
262 if (statState != SUCCESS_CODE) {
263 LOGE("Failed to getUvStat file by fileInfo");
264 return {GetErrorCode(statState), nullptr};
265 }
266 auto nativeStat = FFIData::Create<StatImpl>(*stat);
267 delete(stat);
268 stat = nullptr;
269 if (!nativeStat) {
270 return {GetErrorCode(ENOMEM), nullptr};
271 }
272 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
273 auto fileInfoPtr = std::make_shared<FileInfo>(std::move(fileInfo));
274 nativeStat->SetFileInfo(fileInfoPtr);
275 #endif
276 return {SUCCESS_CODE, nativeStat};
277 }
278
CreateStream(std::string path,std::string mode)279 std::tuple<int32_t, sptr<StreamImpl>> FileFsImpl::CreateStream(std::string path, std::string mode)
280 {
281 std::unique_ptr<FILE, decltype(&fclose)> fp = { fopen(path.c_str(), mode.c_str()), fclose };
282 if (!fp) {
283 LOGE("Failed to fdopen file by path");
284 return {GetErrorCode(errno), nullptr};
285 }
286 auto nativeStream = FFIData::Create<StreamImpl>(std::move(fp));
287 if (!nativeStream) {
288 return {GetErrorCode(ENOMEM), nullptr};
289 }
290 return {SUCCESS_CODE, nativeStream};
291 }
292
FdopenStream(int32_t fd,std::string mode)293 std::tuple<int32_t, sptr<StreamImpl>> FileFsImpl::FdopenStream(int32_t fd, std::string mode)
294 {
295 LOGI("FS_TEST::FileFsImpl::FdopenStream start");
296 if (fd < 0) {
297 LOGE("Invalid fd");
298 return {GetErrorCode(EINVAL), nullptr};
299 }
300 unique_ptr<FILE, decltype(&fclose)> fp = { fdopen(fd, mode.c_str()), fclose };
301 if (!fp) {
302 LOGE("Failed to fdopen file by fd:%{public}d", fd);
303 return {GetErrorCode(errno), nullptr};
304 }
305 auto nativeStream = FFIData::Create<StreamImpl>(std::move(fp));
306 if (!nativeStream) {
307 return {GetErrorCode(ENOMEM), nullptr};
308 }
309 return {SUCCESS_CODE, nativeStream};
310 }
311
Lstat(std::string path)312 std::tuple<int32_t, sptr<StatImpl>> FileFsImpl::Lstat(std::string path)
313 {
314 LOGI("FS_TEST::FileFsImpl::Lstat start");
315
316 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> lstat_req = {
317 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
318 if (!lstat_req) {
319 LOGE("Failed to request heap memory.");
320 return {GetErrorCode(ENOMEM), nullptr};
321 }
322 int ret = uv_fs_lstat(nullptr, lstat_req.get(), path.c_str(), nullptr);
323 if (ret < 0) {
324 LOGE("Failed to get stat of file, ret: %{public}d", ret);
325 return {GetErrorCode(ret), nullptr};
326 }
327 auto nativeStat = FFIData::Create<StatImpl>(lstat_req->statbuf);
328 if (!nativeStat) {
329 return {GetErrorCode(ENOMEM), nullptr};
330 }
331 return {SUCCESS_CODE, nativeStat};
332 }
333
CreateRandomAccessFileSync(std::string file,unsigned int mode)334 std::tuple<int32_t, sptr<RandomAccessFileImpl>> FileFsImpl::CreateRandomAccessFileSync(std::string file,
335 unsigned int mode)
336 {
337 auto [succ, fileInfo, err] = ParseRandomFile(file);
338 if (!succ) {
339 LOGE("Error because %{public}d", err);
340 return {GetErrorCode(err), nullptr};
341 }
342
343 if (fileInfo.isPath) {
344 if (mode < 0) {
345 LOGE("Invalid flags");
346 return {GetErrorCode(EINVAL), nullptr};
347 }
348 unsigned int flags = static_cast<unsigned int>(mode);
349 CommonFunc::ConvertCjFlags(flags);
350 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> open_req = {
351 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
352 if (!open_req) {
353 LOGE("Failed to request heap memory.");
354 return {GetErrorCode(ENOMEM), nullptr};
355 }
356
357 int ret = uv_fs_open(nullptr, open_req.get(), fileInfo.path.get(), flags, S_IRUSR |
358 S_IWUSR | S_IRGRP | S_IWGRP, NULL);
359 if (ret < 0) {
360 LOGE("Faile in fs_open %{public}d", ret);
361 return {GetErrorCode(ret), nullptr};
362 }
363 fileInfo.fdg->SetFD(open_req.get()->result, false);
364 }
365 std::shared_ptr<OHOS::FileManagement::ModuleFileIO::RandomAccessFileEntity> ptr =
366 std::make_shared<OHOS::FileManagement::ModuleFileIO::RandomAccessFileEntity>();
367 ptr->fd.swap(fileInfo.fdg);
368 ptr->filePointer = 0;
369 auto randomAccessFileImpl = FFIData::Create<RandomAccessFileImpl>(std::move(ptr));
370 if (!randomAccessFileImpl) {
371 return {GetErrorCode(ENOMEM), nullptr};
372 }
373 return {SUCCESS_CODE, randomAccessFileImpl};
374 }
375
CreateRandomAccessFileSync(sptr<FileEntity> entity,unsigned int mode)376 std::tuple<int32_t, sptr<RandomAccessFileImpl>> FileFsImpl::CreateRandomAccessFileSync(sptr<FileEntity> entity,
377 unsigned int mode)
378 {
379 auto fd = entity->fd_.get()->GetFD();
380 FileInfo fileInfo;
381 if (fd < 0) {
382 HILOGE("Invalid fd");
383 return { GetErrorCode(EINVAL), nullptr };
384 }
385 auto dupFd = dup(fd);
386 if (dupFd < 0) {
387 HILOGE("Failed to get valid fd, fail reason: %{public}s, fd: %{public}d", strerror(errno), fd);
388 return { GetErrorCode(EINVAL), nullptr};
389 }
390 auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(dupFd, false);
391 if (fdg == nullptr) {
392 HILOGE("Failed to request heap memory.");
393 close(dupFd);
394 return { GetErrorCode(ENOMEM), nullptr};
395 }
396 fileInfo = FileInfo { false, nullptr, move(fdg) };
397 std::shared_ptr<OHOS::FileManagement::ModuleFileIO::RandomAccessFileEntity> ptr =
398 std::make_shared<OHOS::FileManagement::ModuleFileIO::RandomAccessFileEntity>();
399 ptr->fd.swap(fileInfo.fdg);
400 ptr->filePointer = 0;
401 auto randomAccessFileImpl = FFIData::Create<RandomAccessFileImpl>(std::move(ptr));
402 if (!randomAccessFileImpl) {
403 close(dupFd);
404 return {GetErrorCode(ENOMEM), nullptr};
405 }
406 return {SUCCESS_CODE, randomAccessFileImpl};
407 }
408
Mkdir(std::string path,bool recursion,bool isTwoArgs)409 int FileFsImpl::Mkdir(std::string path, bool recursion, bool isTwoArgs)
410 {
411 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
412 if (isTwoArgs) {
413 MakeDirectionMode recursionMode = SINGLE;
414 recursionMode = static_cast<MakeDirectionMode>(recursion);
415 if (::Mkdirs(path.c_str(), recursionMode) < 0) {
416 HILOGE("Failed to create directories, error: %{public}d", errno);
417 return GetErrorCode(errno);
418 }
419 return SUCCESS_CODE;
420 }
421 #endif
422 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> mkdir_req = {
423 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
424 if (!mkdir_req) {
425 HILOGE("Failed to request heap memory.");
426 return GetErrorCode(ENOMEM);
427 }
428 int ret = uv_fs_mkdir(nullptr, mkdir_req.get(), path.c_str(), DIR_DEFAULT_PERM, nullptr);
429 if (ret) {
430 HILOGE("Failed to create directory");
431 return GetErrorCode(ret);
432 }
433 return SUCCESS_CODE;
434 }
435
Rmdir(std::string path)436 int FileFsImpl::Rmdir(std::string path)
437 {
438 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> scandir_req = {
439 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
440 if (!scandir_req) {
441 return GetErrorCode(ENOMEM);
442 }
443 int ret = 0;
444 ret = uv_fs_scandir(nullptr, scandir_req.get(), path.c_str(), 0, nullptr);
445 if (ret < 0) {
446 HILOGE("Failed to scandir, ret: %{public}d", ret);
447 return GetErrorCode(ret);
448 }
449 uv_dirent_t dent;
450 while (uv_fs_scandir_next(scandir_req.get(), &dent) != UV_EOF) {
451 string filePath = path + "/" + string(dent.name);
452 if (dent.type == UV_DIRENT_FILE) {
453 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> unlink_req = {
454 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
455 if (!unlink_req) {
456 HILOGE("Failed to request heap memory.");
457 return GetErrorCode(ENOMEM);
458 }
459 ret = uv_fs_unlink(nullptr, unlink_req.get(), filePath.c_str(), nullptr);
460 if (ret < 0) {
461 HILOGE("Failed to unlink file, ret: %{public}d", ret);
462 return GetErrorCode(ret);
463 }
464 } else if (dent.type == UV_DIRENT_DIR) {
465 auto rmDirentRes = Rmdir(filePath);
466 if (rmDirentRes) {
467 return rmDirentRes;
468 }
469 }
470 }
471 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> rmdir_req = {
472 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
473 if (!rmdir_req) {
474 LOGE("Failed to request heap memory.");
475 return GetErrorCode(ENOMEM);
476 }
477 ret = uv_fs_rmdir(nullptr, rmdir_req.get(), path.c_str(), nullptr);
478 if (ret < 0) {
479 LOGE("Failed to rmdir empty dir, ret: %{public}d", ret);
480 return GetErrorCode(ret);
481 }
482 return SUCCESS_CODE;
483 }
484
Rename(std::string oldPath,std::string newPath)485 int FileFsImpl::Rename(std::string oldPath, std::string newPath)
486 {
487 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> rename_req = {
488 new uv_fs_t, CommonFunc::FsReqCleanup };
489 if (!rename_req) {
490 HILOGE("Failed to request heap memory.");
491 return GetErrorCode(ENOMEM);
492 }
493 int ret = uv_fs_rename(nullptr, rename_req.get(), oldPath.c_str(), newPath.c_str(), nullptr);
494 if (ret < 0) {
495 LOGE("Failed to rename file with path");
496 return GetErrorCode(ret);
497 }
498 return SUCCESS_CODE;
499 }
500
Unlink(std::string path)501 int FileFsImpl::Unlink(std::string path)
502 {
503 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> unlink_req = {
504 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
505 if (!unlink_req) {
506 HILOGE("Failed to request heap memory.");
507 return GetErrorCode(ENOMEM);
508 }
509 int ret = uv_fs_unlink(nullptr, unlink_req.get(), path.c_str(), nullptr);
510 if (ret < 0) {
511 HILOGE("Failed to unlink with path");
512 return GetErrorCode(ret);
513 }
514 return SUCCESS_CODE;
515 }
516
517 static int RecurMoveDir(const string &srcPath, const string &destPath, const int mode,
518 deque<struct ConflictFiles> &errfiles);
519
JudgeExistAndEmpty(const string & path)520 static tuple<bool, bool> JudgeExistAndEmpty(const string &path)
521 {
522 filesystem::path pathName(path);
523 if (filesystem::exists(pathName)) {
524 if (filesystem::is_empty(pathName)) {
525 return { true, true };
526 }
527 return { true, false };
528 }
529 return { false, false };
530 }
531
RmDirectory(const string & path)532 static int RmDirectory(const string &path)
533 {
534 filesystem::path pathName(path);
535 if (filesystem::exists(pathName)) {
536 std::error_code errCode;
537 (void)filesystem::remove_all(pathName, errCode);
538 if (errCode.value() != 0) {
539 LOGE("Failed to remove directory, error code: %{public}d", errCode.value());
540 return errCode.value();
541 }
542 }
543 return ERRNO_NOERR;
544 }
545
RestoreTime(const string & srcPath,const string & destPath)546 static int RestoreTime(const string &srcPath, const string &destPath)
547 {
548 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> stat_req = {
549 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
550 if (!stat_req) {
551 HILOGE("Failed to request heap memory.");
552 return ENOMEM;
553 }
554 int ret = uv_fs_stat(nullptr, stat_req.get(), srcPath.c_str(), nullptr);
555 if (ret < 0) {
556 HILOGE("Failed to stat srcPath");
557 return ret;
558 }
559 double atime = static_cast<double>(stat_req->statbuf.st_atim.tv_sec) +
560 static_cast<double>(stat_req->statbuf.st_atim.tv_nsec) / NS;
561 double mtime = static_cast<double>(stat_req->statbuf.st_mtim.tv_sec) +
562 static_cast<double>(stat_req->statbuf.st_mtim.tv_nsec) / NS;
563 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> utime_req = {
564 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
565 if (!utime_req) {
566 HILOGE("Failed to request heap memory.");
567 return ENOMEM;
568 }
569 ret = uv_fs_utime(nullptr, utime_req.get(), destPath.c_str(), atime, mtime, nullptr);
570 if (ret < 0) {
571 HILOGE("Failed to utime %s, error code: %d", destPath.c_str(), ret);
572 return ret;
573 }
574 return ERRNO_NOERR;
575 }
576
577 struct NameListArg {
578 struct dirent** namelist;
579 int num;
580 };
581
Deleter(struct NameListArg * arg)582 static void Deleter(struct NameListArg *arg)
583 {
584 for (int i = 0; i < arg->num; i++) {
585 free((arg->namelist)[i]);
586 (arg->namelist)[i] = nullptr;
587 }
588 free(arg->namelist);
589 arg->namelist = nullptr;
590 delete arg;
591 arg = nullptr;
592 }
593
FilterFunc(const struct dirent * filename)594 static int32_t FilterFunc(const struct dirent *filename)
595 {
596 if (string_view(filename->d_name) == "." || string_view(filename->d_name) == "..") {
597 return FILE_DISMATCH;
598 }
599 return FILE_MATCH;
600 }
601
RemovePath(const string & pathStr)602 static int RemovePath(const string& pathStr)
603 {
604 filesystem::path pathTarget(pathStr);
605 std::error_code errCode;
606 if (!filesystem::remove(pathTarget, errCode)) {
607 HILOGE("Failed to remove file or directory, error code: %{public}d", errCode.value());
608 return errCode.value();
609 }
610 return ERRNO_NOERR;
611 }
612
613
RenameDir(const string & src,const string & dest,const int mode,deque<struct ConflictFiles> & errfiles)614 static int RenameDir(const string &src, const string &dest, const int mode, deque<struct ConflictFiles> &errfiles)
615 {
616 filesystem::path destPath(dest);
617 if (filesystem::exists(destPath)) {
618 return RecurMoveDir(src, dest, mode, errfiles);
619 }
620 filesystem::path srcPath(src);
621 std::error_code errCode;
622 filesystem::rename(srcPath, destPath, errCode);
623 if (errCode.value() == EXDEV) {
624 HILOGE("Failed to rename file due to EXDEV");
625 if (!filesystem::create_directory(destPath, errCode)) {
626 HILOGE("Failed to create directory, error code: %{public}d", errCode.value());
627 return errCode.value();
628 }
629 int ret = RestoreTime(srcPath, destPath);
630 if (ret) {
631 HILOGE("Failed to utime dstPath");
632 return ret;
633 }
634 return RecurMoveDir(src, dest, mode, errfiles);
635 }
636 if (errCode.value() != 0) {
637 HILOGE("Failed to rename file, error code: %{public}d", errCode.value());
638 return errCode.value();
639 }
640 return ERRNO_NOERR;
641 }
642
CopyAndDeleteFile(const string & src,const string & dest)643 static int CopyAndDeleteFile(const string &src, const string &dest)
644 {
645 filesystem::path dstPath(dest);
646 if (filesystem::exists(dstPath)) {
647 int removeRes = RemovePath(dest);
648 if (removeRes != 0) {
649 HILOGE("Failed to remove dest file");
650 return removeRes;
651 }
652 }
653 filesystem::path srcPath(src);
654 std::error_code errCode;
655 if (!filesystem::copy_file(srcPath, dstPath, filesystem::copy_options::overwrite_existing, errCode)) {
656 HILOGE("Failed to copy file, error code: %{public}d", errCode.value());
657 return errCode.value();
658 }
659 int ret = RestoreTime(srcPath, dstPath);
660 if (ret) {
661 HILOGE("Failed to utime dstPath");
662 return ret;
663 }
664 return RemovePath(src);
665 }
666
RenameFile(const string & src,const string & dest,const int mode,deque<struct ConflictFiles> & errfiles)667 static int RenameFile(const string &src, const string &dest, const int mode, deque<struct ConflictFiles> &errfiles)
668 {
669 filesystem::path dstPath(dest);
670 if (filesystem::exists(dstPath)) {
671 if (filesystem::is_directory(dstPath)) {
672 errfiles.emplace_front(src, dest);
673 return ERRNO_NOERR;
674 }
675 if (mode == DIRMODE_FILE_THROW_ERR) {
676 errfiles.emplace_back(src, dest);
677 return ERRNO_NOERR;
678 }
679 }
680 filesystem::path srcPath(src);
681 std::error_code errCode;
682 filesystem::rename(srcPath, dstPath, errCode);
683 if (errCode.value() == EXDEV) {
684 HILOGE("Failed to rename file due to EXDEV");
685 return CopyAndDeleteFile(src, dest);
686 }
687 return errCode.value();
688 }
689
RecurMoveDir(const string & srcPath,const string & destPath,const int mode,deque<struct ConflictFiles> & errfiles)690 static int RecurMoveDir(const string &srcPath, const string &destPath, const int mode,
691 deque<struct ConflictFiles> &errfiles)
692 {
693 filesystem::path dpath(destPath);
694 if (!filesystem::is_directory(dpath)) {
695 errfiles.emplace_front(srcPath, destPath);
696 return ERRNO_NOERR;
697 }
698
699 unique_ptr<struct NameListArg, decltype(Deleter)*> ptr = {new struct NameListArg, Deleter};
700 if (!ptr) {
701 HILOGE("Failed to request heap memory.");
702 return ENOMEM;
703 }
704 int num = scandir(srcPath.c_str(), &(ptr->namelist), FilterFunc, alphasort);
705 ptr->num = num;
706
707 for (int i = 0; i < num; i++) {
708 if ((ptr->namelist[i])->d_type == DT_DIR) {
709 string srcTemp = srcPath + '/' + string((ptr->namelist[i])->d_name);
710 string destTemp = destPath + '/' + string((ptr->namelist[i])->d_name);
711 size_t size = errfiles.size();
712 int res = RenameDir(srcTemp, destTemp, mode, errfiles);
713 if (res != ERRNO_NOERR) {
714 return res;
715 }
716 if (size != errfiles.size()) {
717 continue;
718 }
719 res = RemovePath(srcTemp);
720 if (res) {
721 return res;
722 }
723 } else {
724 string src = srcPath + '/' + string((ptr->namelist[i])->d_name);
725 string dest = destPath + '/' + string((ptr->namelist[i])->d_name);
726 int res = RenameFile(src, dest, mode, errfiles);
727 if (res != ERRNO_NOERR) {
728 HILOGE("Failed to rename file for error %{public}d", res);
729 return res;
730 }
731 }
732 }
733 return ERRNO_NOERR;
734 }
735
MoveDirFunc(const string & src,const string & dest,const int mode,std::deque<struct ConflictFiles> & errfiles)736 static int MoveDirFunc(const string &src, const string &dest, const int mode,
737 std::deque<struct ConflictFiles> &errfiles)
738 {
739 size_t found = string(src).rfind('/');
740 if (found == std::string::npos) {
741 return EINVAL;
742 }
743 if (access(src.c_str(), W_OK) != 0) {
744 LOGE("Failed to move src directory due to doesn't exist or hasn't write permission");
745 return errno;
746 }
747 string dirName = string(src).substr(found);
748 string destStr = dest + dirName;
749 auto [destStrExist, destStrEmpty] = JudgeExistAndEmpty(destStr);
750 if (destStrExist && !destStrEmpty) {
751 if (mode == DIRMODE_DIRECTORY_REPLACE) {
752 int removeRes = RmDirectory(destStr);
753 if (removeRes) {
754 HILOGE("Failed to remove dest directory in DIRMODE_DIRECTORY_REPLACE");
755 return removeRes;
756 }
757 }
758 if (mode == DIRMODE_DIRECTORY_THROW_ERR) {
759 HILOGE("Failed to move directory in DIRMODE_DIRECTORY_THROW_ERR");
760 return ENOTEMPTY;
761 }
762 }
763 int res = RenameDir(src, destStr, mode, errfiles);
764 if (res == ERRNO_NOERR) {
765 if (!errfiles.empty()) {
766 HILOGE("Failed to movedir with some conflicted files");
767 return EEXIST;
768 }
769 int removeRes = RmDirectory(src);
770 if (removeRes) {
771 HILOGE("Failed to remove src directory");
772 return removeRes;
773 }
774 }
775 return res;
776 }
777
DequeToCConflict(std::deque<struct ConflictFiles> errfiles)778 static CConflictFiles* DequeToCConflict(std::deque<struct ConflictFiles> errfiles)
779 {
780 CConflictFiles* result = new(std::nothrow) CConflictFiles[errfiles.size()];
781 if (result == nullptr) {
782 return nullptr;
783 }
784 size_t temp = 0;
785 for (size_t i = 0; i < errfiles.size(); i++) {
786 size_t srcFilesLen = errfiles[i].srcFiles.length() + 1;
787 result[i].srcFiles = static_cast<char*>(malloc(srcFilesLen));
788 if (result[i].srcFiles == nullptr) {
789 break;
790 }
791 if (strcpy_s(result[i].srcFiles, srcFilesLen, errfiles[i].srcFiles.c_str()) != 0) {
792 free(result[i].srcFiles);
793 result[i].srcFiles = nullptr;
794 break;
795 }
796 size_t destFilesLen = errfiles[i].destFiles.length() + 1;
797 result[i].destFiles = static_cast<char*>(malloc(destFilesLen));
798 if (result[i].destFiles == nullptr) {
799 free(result[i].srcFiles);
800 result[i].srcFiles = nullptr;
801 break;
802 }
803 if (strcpy_s(result[i].destFiles, destFilesLen, errfiles[i].destFiles.c_str()) != 0) {
804 free(result[i].srcFiles);
805 free(result[i].destFiles);
806
807 result[i].srcFiles = nullptr;
808 result[i].destFiles = nullptr;
809 break;
810 }
811 temp++;
812 }
813 if (temp != errfiles.size()) {
814 for (size_t j = temp; j > 0; j--) {
815 free(result[j - 1].srcFiles);
816 free(result[j - 1].destFiles);
817
818 result[j - 1].srcFiles = nullptr;
819 result[j - 1].destFiles = nullptr;
820 }
821 delete[] result;
822 result = nullptr;
823 return nullptr;
824 }
825 return result;
826 }
827
MoveDir(string src,string dest,int32_t mode)828 RetDataCArrConflictFiles FileFsImpl::MoveDir(string src, string dest, int32_t mode)
829 {
830 RetDataCArrConflictFiles ret = { .code = EINVAL, .data = { .head = nullptr, .size = 0 } };
831 if (!filesystem::is_directory(filesystem::status(src))) {
832 HILOGE("Invalid src");
833 ret.code = GetErrorCode(EINVAL);
834 return ret;
835 }
836 if (!filesystem::is_directory(filesystem::status(dest))) {
837 HILOGE("Invalid dest");
838 ret.code = GetErrorCode(EINVAL);
839 return ret;
840 }
841 if (mode < DIRMODE_MIN || mode > DIRMODE_MAX) {
842 HILOGE("Invalid mode");
843 ret.code = GetErrorCode(EINVAL);
844 return ret;
845 }
846 std::deque<struct ConflictFiles> errfiles = {};
847 int code = MoveDirFunc(src, dest, mode, errfiles);
848 if (code != SUCCESS_CODE) {
849 ret.code = GetErrorCode(code);
850 } else {
851 ret.code = SUCCESS_CODE;
852 }
853 ret.data.size = (int64_t)errfiles.size();
854 ret.data.head = DequeToCConflict(errfiles);
855 return ret;
856 }
857
CheckReadArgs(int32_t fd,const char * buf,int64_t bufLen,size_t length,int64_t offset)858 static bool CheckReadArgs(int32_t fd, const char* buf, int64_t bufLen, size_t length, int64_t offset)
859 {
860 if (fd < 0) {
861 LOGE("Invalid fd");
862 return false;
863 }
864 if (buf == nullptr) {
865 LOGE("malloc fail");
866 return false;
867 }
868 if (bufLen > UINT_MAX) {
869 LOGE("Invalid arraybuffer");
870 return false;
871 }
872 if (length > UINT_MAX) {
873 LOGE("Invalid arraybuffer");
874 return false;
875 }
876 if (offset < 0) {
877 LOGE("option.offset shall be positive number");
878 return false;
879 }
880 return true;
881 }
882
Read(int32_t fd,char * buf,int64_t bufLen,size_t length,int64_t offset)883 RetDataI64 FileFsImpl::Read(int32_t fd, char* buf, int64_t bufLen, size_t length, int64_t offset)
884 {
885 LOGI("FS_TEST::FileFsImpl::Read start");
886 RetDataI64 ret = { .code = EINVAL, .data = 0 };
887
888 if (!CheckReadArgs(fd, buf, bufLen, length, offset)) {
889 return ret;
890 }
891
892 auto [state, buff, len, offsetResult] = GetReadArg(static_cast<size_t>(bufLen), length, offset);
893 if (state != SUCCESS_CODE) {
894 LOGE("Failed to resolve buf and options");
895 return {GetErrorCode(state), 0};
896 }
897
898 uv_buf_t buffer = uv_buf_init(static_cast<char *>(buf), static_cast<unsigned int>(len));
899
900 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> read_req = {
901 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
902 if (!read_req) {
903 LOGE("Failed to request heap memory.");
904 ret.code = ENOMEM;
905 return ret;
906 }
907 int readCode = uv_fs_read(nullptr, read_req.get(), fd, &buffer, 1, offset, nullptr);
908 if (readCode < 0) {
909 LOGE("Failed to read file for %{public}d", readCode);
910 ret.code = readCode;
911 return ret;
912 }
913 ret.code = SUCCESS_CODE;
914 ret.data = static_cast<int64_t>(readCode);
915 return ret;
916 }
917
ReadCur(int32_t fd,char * buf,int64_t bufLen,size_t length)918 RetDataI64 FileFsImpl::ReadCur(int32_t fd, char* buf, int64_t bufLen, size_t length)
919 {
920 LOGI("FS_TEST::FileFsImpl::Read start");
921 RetDataI64 ret = { .code = EINVAL, .data = 0 };
922
923 if (!CheckReadArgs(fd, buf, bufLen, length, 0)) {
924 return ret;
925 }
926
927 auto [state, buff, len, offsetResult] = GetReadArg(static_cast<size_t>(bufLen), length, 0);
928 if (state != SUCCESS_CODE) {
929 LOGE("Failed to resolve buf and options");
930 return {GetErrorCode(state), 0};
931 }
932
933 uv_buf_t buffer = uv_buf_init(static_cast<char *>(buf), static_cast<unsigned int>(len));
934
935 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> read_req = {
936 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
937 if (!read_req) {
938 LOGE("Failed to request heap memory.");
939 ret.code = ENOMEM;
940 return ret;
941 }
942 int readCode = uv_fs_read(nullptr, read_req.get(), fd, &buffer, 1, -1, nullptr);
943 if (readCode < 0) {
944 LOGE("Failed to read file for %{public}d", readCode);
945 ret.code = readCode;
946 return ret;
947 }
948
949 ret.code = SUCCESS_CODE;
950 ret.data = static_cast<int64_t>(readCode);
951 return ret;
952 }
953
Write(int32_t fd,void * buf,size_t length,int64_t offset,std::string encode)954 RetDataI64 FileFsImpl::Write(int32_t fd, void* buf, size_t length, int64_t offset, std::string encode)
955 {
956 LOGI("FS_TEST::FileFsImpl::Write start");
957 RetDataI64 ret = { .code = EINVAL, .data = 0 };
958 if (fd < 0) {
959 LOGE("Invalid fd");
960 return ret;
961 }
962
963 auto [state, buff, len, offsetResult] =
964 CommonFunc::GetWriteArg(buf, length, offset, encode);
965 if (state != SUCCESS_CODE) {
966 LOGE("Failed to resolve buf and options");
967 return {state, 0};
968 }
969
970 uv_buf_t buffer = uv_buf_init(static_cast<char *>(buff), static_cast<unsigned int>(len));
971 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> write_req = {
972 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
973 if (!write_req) {
974 LOGE("Failed to request heap memory.");
975 ret.code = ENOMEM;
976 return ret;
977 }
978 int writeCode = uv_fs_write(nullptr, write_req.get(), fd, &buffer, 1, offset, nullptr);
979 if (writeCode < 0) {
980 LOGE("Failed to write file for %{public}d", writeCode);
981 ret.code = writeCode;
982 return ret;
983 }
984 ret.code = SUCCESS_CODE;
985 ret.data = static_cast<int64_t>(writeCode);
986 return ret;
987 }
988
WriteCur(int32_t fd,void * buf,size_t length,std::string encode)989 RetDataI64 FileFsImpl::WriteCur(int32_t fd, void* buf, size_t length, std::string encode)
990 {
991 LOGI("FS_TEST::FileFsImpl::Write start");
992 RetDataI64 ret = { .code = EINVAL, .data = 0 };
993 if (fd < 0) {
994 LOGE("Invalid fd");
995 return ret;
996 }
997
998 auto [state, buff, len, offsetResult] =
999 CommonFunc::GetWriteArg(buf, length, 0, encode);
1000 if (state != SUCCESS_CODE) {
1001 LOGE("Failed to resolve buf and options");
1002 return {state, 0};
1003 }
1004
1005 uv_buf_t buffer = uv_buf_init(static_cast<char *>(buff), static_cast<unsigned int>(len));
1006 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> write_req = {
1007 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
1008 if (!write_req) {
1009 LOGE("Failed to request heap memory.");
1010 ret.code = ENOMEM;
1011 return ret;
1012 }
1013 int writeCode = uv_fs_write(nullptr, write_req.get(), fd, &buffer, 1, -1, nullptr);
1014 if (writeCode < 0) {
1015 LOGE("Failed to write file for %{public}d", writeCode);
1016 ret.code = writeCode;
1017 return ret;
1018 }
1019 ret.code = SUCCESS_CODE;
1020 ret.data = static_cast<int64_t>(writeCode);
1021 return ret;
1022 }
1023
Access(std::string path,int32_t mode,int32_t flag)1024 std::tuple<int32_t, bool> FileFsImpl::Access(std::string path, int32_t mode, int32_t flag)
1025 {
1026 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
1027 if (flag == LOCAL_FLAG && IsCloudOrDistributedFilePath(path)) {
1028 return HandleLocalCheck(path, mode);
1029 }
1030 #endif
1031 return UvAccess(path, mode);
1032 }
1033
Truncate(std::string file,int64_t len)1034 int FileFsImpl::Truncate(std::string file, int64_t len)
1035 {
1036 auto [fileState, fileInfo] = ParseFile(file);
1037 if (fileState != SUCCESS_CODE) {
1038 return GetErrorCode(EINVAL);
1039 }
1040 if (len < 0) {
1041 return GetErrorCode(EINVAL);
1042 }
1043 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> open_req = {
1044 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
1045 if (!open_req) {
1046 HILOGE("Failed to request heap memory.");
1047 return GetErrorCode(ENOMEM);
1048 }
1049 int ret = uv_fs_open(nullptr, open_req.get(), fileInfo.path.get(), O_RDWR,
1050 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, nullptr);
1051 if (ret < 0) {
1052 return GetErrorCode(ret);
1053 }
1054 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> ftruncate_req = {
1055 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
1056 if (!ftruncate_req) {
1057 HILOGE("Failed to request heap memory.");
1058 return GetErrorCode(ENOMEM);
1059 }
1060 ret = uv_fs_ftruncate(nullptr, ftruncate_req.get(), ret, len, nullptr);
1061 if (ret < 0) {
1062 HILOGE("Failed to truncate file by path");
1063 return GetErrorCode(ret);
1064 }
1065 return SUCCESS_CODE;
1066 }
1067
Truncate(int32_t fd,int64_t len)1068 int FileFsImpl::Truncate(int32_t fd, int64_t len)
1069 {
1070 auto [fileState, fileInfo] = ParseFile(fd);
1071 if (fileState != SUCCESS_CODE) {
1072 return GetErrorCode(fileState);
1073 }
1074 if (len < 0) {
1075 return GetErrorCode(EINVAL);
1076 }
1077 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> ftruncate_req = {
1078 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
1079 if (!ftruncate_req) {
1080 HILOGE("Failed to request heap memory.");
1081 return GetErrorCode(ENOMEM);
1082 }
1083 int ret = uv_fs_ftruncate(nullptr, ftruncate_req.get(), fileInfo.fdg->GetFD(), len, nullptr);
1084 if (ret < 0) {
1085 HILOGE("Failed to truncate file by fd for libuv error %{public}d", ret);
1086 return GetErrorCode(ret);
1087 }
1088 return SUCCESS_CODE;
1089 }
1090
CloseFd(int fd)1091 static int CloseFd(int fd)
1092 {
1093 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> close_req = {
1094 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
1095 if (!close_req) {
1096 HILOGE("Failed to request heap memory.");
1097 return ENOMEM;
1098 }
1099 int ret = uv_fs_close(nullptr, close_req.get(), fd, nullptr);
1100 if (ret < 0) {
1101 HILOGE("Failed to close file with ret: %{public}d", ret);
1102 return ret;
1103 }
1104 return SUCCESS_CODE;
1105 }
1106
CloseCore(FileStruct fileStruct)1107 static int CloseCore(FileStruct fileStruct)
1108 {
1109 if (fileStruct.isFd) {
1110 auto err = CloseFd(fileStruct.fd);
1111 if (err) {
1112 return GetErrorCode(err);
1113 }
1114 } else {
1115 auto err = CloseFd(fileStruct.fileEntity->fd_->GetFD());
1116 if (err) {
1117 return GetErrorCode(err);
1118 }
1119 }
1120 return SUCCESS_CODE;
1121 }
1122
Close(int32_t file)1123 int FileFsImpl::Close(int32_t file)
1124 {
1125 FileStruct fileStruct;
1126 if (file >= 0) {
1127 fileStruct = FileStruct { true, file, nullptr };
1128 } else {
1129 return GetErrorCode(EINVAL);
1130 }
1131
1132 return CloseCore(fileStruct);
1133 }
1134
Close(sptr<OHOS::CJSystemapi::FileFs::FileEntity> file)1135 int FileFsImpl::Close(sptr<OHOS::CJSystemapi::FileFs::FileEntity> file)
1136 {
1137 FileStruct fileStruct = FileStruct { false, -1, file };
1138 return CloseCore(fileStruct);
1139 }
1140
GetFileSize(const string & path,int64_t & offset)1141 static int GetFileSize(const string &path, int64_t &offset)
1142 {
1143 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> stat_req = {
1144 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
1145 if (!stat_req) {
1146 HILOGE("Failed to request heap memory.");
1147 return ENOMEM;
1148 }
1149
1150 int ret = uv_fs_stat(nullptr, stat_req.get(), path.c_str(), nullptr);
1151 if (ret < 0) {
1152 HILOGE("Failed to get file stat by path");
1153 return ret;
1154 }
1155
1156 offset = static_cast<int64_t>(stat_req->statbuf.st_size);
1157 return ERRNO_NOERR;
1158 }
1159
ReadLines(char * file,std::string encoding)1160 std::tuple<int32_t, sptr<ReadIteratorImpl>> FileFsImpl::ReadLines(char* file, std::string encoding)
1161 {
1162 if (encoding != "utf-8") {
1163 return { GetErrorCode(EINVAL), nullptr};
1164 }
1165 auto iterator = ::ReaderIterator(file);
1166 if (iterator == nullptr) {
1167 HILOGE("Failed to read lines of the file, error: %{public}d", errno);
1168 return { GetErrorCode(errno), nullptr};
1169 }
1170 int64_t offset = 0;
1171 int ret = GetFileSize(file, offset);
1172 if (ret != 0) {
1173 HILOGE("Failed to get size of the file");
1174 return { GetErrorCode(ret), nullptr};
1175 }
1176 std::shared_ptr<OHOS::FileManagement::ModuleFileIO::ReaderIteratorEntity> ptr =
1177 std::make_shared<OHOS::FileManagement::ModuleFileIO::ReaderIteratorEntity>();
1178 ptr->iterator = iterator;
1179 ptr->offset = offset;
1180 auto readIteratorImpl = FFIData::Create<ReadIteratorImpl>(std::move(ptr));
1181 if (!readIteratorImpl) {
1182 return {GetErrorCode(ENOMEM), nullptr};
1183 }
1184 return {SUCCESS_CODE, readIteratorImpl};
1185 }
1186
ReadTextCheckArgs(int64_t offset,int64_t len,char * encoding)1187 static int ReadTextCheckArgs(int64_t offset, int64_t len, char* encoding)
1188 {
1189 if (offset < 0) {
1190 HILOGE("Illegal option.offset parameter");
1191 return GetErrorCode(EINVAL);
1192 }
1193 if (len < 0 || len > UINT_MAX) {
1194 HILOGE("Illegal option.length parameter");
1195 return GetErrorCode(EINVAL);
1196 }
1197 if (string(encoding) != "utf-8") {
1198 HILOGE("Illegal option.encoding parameter");
1199 return GetErrorCode(EINVAL);
1200 }
1201 return SUCCESS_CODE;
1202 }
1203
ReadTextOpenFile(const std::string & path)1204 static int ReadTextOpenFile(const std::string& path)
1205 {
1206 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> open_req = {
1207 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup
1208 };
1209 if (open_req == nullptr) {
1210 HILOGE("Failed to request heap memory.");
1211 return -ENOMEM;
1212 }
1213
1214 return uv_fs_open(nullptr, open_req.get(), path.c_str(), O_RDONLY,
1215 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, nullptr);
1216 }
1217
ReadFromFile(int fd,int64_t offset,string & buffer)1218 static int ReadFromFile(int fd, int64_t offset, string& buffer)
1219 {
1220 uv_buf_t readbuf = uv_buf_init(const_cast<char *>(buffer.c_str()), static_cast<unsigned int>(buffer.size()));
1221 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> read_req = {
1222 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
1223 if (read_req == nullptr) {
1224 HILOGE("Failed to request heap memory.");
1225 return -ENOMEM;
1226 }
1227 return uv_fs_read(nullptr, read_req.get(), fd, &readbuf, 1, offset, nullptr);
1228 }
1229
ReadText(char * path,int64_t offset,bool hasLen,int64_t len,char * encoding)1230 RetDataCString FileFsImpl::ReadText(char* path, int64_t offset, bool hasLen, int64_t len, char* encoding)
1231 {
1232 RetDataCString retData = { .code = ERR_INVALID_INSTANCE_CODE, .data = nullptr };
1233 int code = ReadTextCheckArgs(offset, len, encoding);
1234 if (code != SUCCESS_CODE) {
1235 retData.code = code;
1236 return retData;
1237 }
1238
1239 DistributedFS::FDGuard sfd;
1240 int fd = ReadTextOpenFile(path);
1241 if (fd < 0) {
1242 HILOGE("Failed to open file by ret: %{public}d", fd);
1243 retData.code = GetErrorCode(errno);
1244 return retData;
1245 }
1246 sfd.SetFD(fd);
1247 struct stat statbf;
1248 if ((!sfd) || (fstat(sfd.GetFD(), &statbf) < 0)) {
1249 HILOGE("Failed to get stat of file by fd: %{public}d", sfd.GetFD());
1250 retData.code = GetErrorCode(errno);
1251 return retData;
1252 }
1253
1254 if (offset > statbf.st_size) {
1255 HILOGE("Invalid offset: %{public}" PRIu64, offset);
1256 retData.code = GetErrorCode(EINVAL);
1257 return retData;
1258 }
1259
1260 len = (!hasLen || len > statbf.st_size) ? statbf.st_size : len;
1261 string buffer(len, '\0');
1262 int readRet = ReadFromFile(sfd.GetFD(), offset, buffer);
1263 if (readRet < 0) {
1264 HILOGE("Failed to read file by fd: %{public}d", sfd.GetFD());
1265 retData.code = GetErrorCode(errno);
1266 return retData;
1267 }
1268 char *value = static_cast<char*>(malloc((len + 1) * sizeof(char)));
1269 if (value == nullptr) {
1270 return retData;
1271 }
1272 std::char_traits<char>::copy(value, buffer.c_str(), len + 1);
1273 retData.code = SUCCESS_CODE;
1274 retData.data = value;
1275 return retData;
1276 }
1277
Utimes(std::string path,double mtime)1278 int FileFsImpl::Utimes(std::string path, double mtime)
1279 {
1280 if (mtime < 0) {
1281 HILOGE("Invalid mtime from JS second argument");
1282 return GetErrorCode(EINVAL);
1283 }
1284
1285 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> stat_req = {
1286 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
1287 if (!stat_req) {
1288 HILOGE("Failed to request heap memory.");
1289 return GetErrorCode(ENOMEM);
1290 }
1291
1292 int ret = uv_fs_stat(nullptr, stat_req.get(), path.c_str(), nullptr);
1293 if (ret < 0) {
1294 HILOGE("Failed to get stat of the file by path");
1295 return GetErrorCode(ret);
1296 }
1297
1298 std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> utimes_req = {
1299 new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
1300 if (!utimes_req) {
1301 HILOGE("Failed to request heap memory.");
1302 return GetErrorCode(ENOMEM);
1303 }
1304
1305 double atime = static_cast<double>(stat_req->statbuf.st_atim.tv_sec) +
1306 static_cast<double>(stat_req->statbuf.st_atim.tv_nsec) / NS;
1307 ret = uv_fs_utime(nullptr, utimes_req.get(), path.c_str(), atime, mtime / MS, nullptr);
1308 if (ret < 0) {
1309 HILOGE("Failed to chang mtime of the file for %{public}d", ret);
1310 return GetErrorCode(ret);
1311 }
1312 return SUCCESS_CODE;
1313 }
1314
CreateWatcher(std::string path,uint32_t events,void (* callback)(CWatchEvent))1315 std::tuple<int32_t, sptr<WatcherImpl>> FileFsImpl::CreateWatcher(std::string path, uint32_t events,
1316 void (*callback)(CWatchEvent))
1317 {
1318 std::shared_ptr<WatcherInfoArg> infoArg = std::make_shared<WatcherInfoArg>(callback);
1319 if (!FileWatcherManager::GetInstance().CheckEventValid(events)) {
1320 return { GetErrorCode(EINVAL), nullptr };
1321 }
1322 infoArg->events = events;
1323 infoArg->fileName = path;
1324
1325 auto watcherImpl = FFIData::Create<WatcherImpl>();
1326 if (!watcherImpl) {
1327 return {GetErrorCode(ENOMEM), nullptr};
1328 }
1329 watcherImpl->data_ = infoArg;
1330
1331 if (FileWatcherManager::GetInstance().GetNotifyId() < 0 &&
1332 !FileWatcherManager::GetInstance().InitNotify()) {
1333 HILOGE("Failed to get notifyId or initnotify fail");
1334 return { GetErrorCode(errno), nullptr };
1335 }
1336
1337 bool ret = FileWatcherManager::GetInstance().AddWatcherInfo(infoArg->fileName, infoArg);
1338 if (!ret) {
1339 HILOGE("Failed to add watcher info.");
1340 return {GetErrorCode(EINVAL), nullptr};
1341 }
1342 return {SUCCESS_CODE, watcherImpl};
1343 }
1344
1345 } // CJSystemapi
1346 } // namespace OHOS