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