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