15bebb993Sopenharmony_ci/*
25bebb993Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
35bebb993Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
45bebb993Sopenharmony_ci * you may not use this file except in compliance with the License.
55bebb993Sopenharmony_ci * You may obtain a copy of the License at
65bebb993Sopenharmony_ci *
75bebb993Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
85bebb993Sopenharmony_ci *
95bebb993Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
105bebb993Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
115bebb993Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125bebb993Sopenharmony_ci * See the License for the specific language governing permissions and
135bebb993Sopenharmony_ci * limitations under the License.
145bebb993Sopenharmony_ci */
155bebb993Sopenharmony_ci
165bebb993Sopenharmony_ci#include "copy.h"
175bebb993Sopenharmony_ci#include <fcntl.h>
185bebb993Sopenharmony_ci#include <filesystem>
195bebb993Sopenharmony_ci#include <poll.h>
205bebb993Sopenharmony_ci#include <sys/eventfd.h>
215bebb993Sopenharmony_ci#include <sys/inotify.h>
225bebb993Sopenharmony_ci#include <sys/prctl.h>
235bebb993Sopenharmony_ci#include <sys/stat.h>
245bebb993Sopenharmony_ci#include <sys/types.h>
255bebb993Sopenharmony_ci#include <thread>
265bebb993Sopenharmony_ci#include "datashare_helper.h"
275bebb993Sopenharmony_ci#include "file_uri.h"
285bebb993Sopenharmony_ci#include "file_utils.h"
295bebb993Sopenharmony_ci#include "iservice_registry.h"
305bebb993Sopenharmony_ci#include "translistener.h"
315bebb993Sopenharmony_ci
325bebb993Sopenharmony_cinamespace OHOS {
335bebb993Sopenharmony_cinamespace CJSystemapi {
345bebb993Sopenharmony_ciusing namespace FileFs;
355bebb993Sopenharmony_cinamespace fs = std::filesystem;
365bebb993Sopenharmony_ciconst std::string NETWORK_PARA = "?networkid=";
375bebb993Sopenharmony_ciconst std::string MEDIALIBRARY_DATA_URI = "datashare:///media";
385bebb993Sopenharmony_ciconstexpr int DISMATCH = 0;
395bebb993Sopenharmony_ciconstexpr int MATCH = 1;
405bebb993Sopenharmony_ciconstexpr int BUF_SIZE = 1024;
415bebb993Sopenharmony_ciconstexpr size_t MAX_SIZE = 1024 * 1024 * 128;
425bebb993Sopenharmony_ciconstexpr std::chrono::milliseconds NOTIFY_PROGRESS_DELAY(300);
435bebb993Sopenharmony_cistd::recursive_mutex CopyImpl::mutex_;
445bebb993Sopenharmony_cistd::map<FileInfos, std::shared_ptr<CjCallbackObject>> CopyImpl::cjCbMap_;
455bebb993Sopenharmony_ci
465bebb993Sopenharmony_cistatic int OpenSrcFile(const std::string &srcPth, std::shared_ptr<FileInfos> infos, int32_t &srcFd)
475bebb993Sopenharmony_ci{
485bebb993Sopenharmony_ci    Uri uri(infos->srcUri);
495bebb993Sopenharmony_ci    if (uri.GetAuthority() == "media") {
505bebb993Sopenharmony_ci        sptr<FileIoToken> remote = new (std::nothrow) IRemoteStub<FileIoToken>();
515bebb993Sopenharmony_ci        if (!remote) {
525bebb993Sopenharmony_ci            LOGE("Failed to get remote object");
535bebb993Sopenharmony_ci            return ENOMEM;
545bebb993Sopenharmony_ci        }
555bebb993Sopenharmony_ci        auto dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), MEDIALIBRARY_DATA_URI);
565bebb993Sopenharmony_ci        if (!dataShareHelper) {
575bebb993Sopenharmony_ci            LOGE("Failed to connect to datashare");
585bebb993Sopenharmony_ci            return E_PERMISSION;
595bebb993Sopenharmony_ci        }
605bebb993Sopenharmony_ci        srcFd = dataShareHelper->OpenFile(uri, CommonFunc::GetModeFromFlags(O_RDONLY));
615bebb993Sopenharmony_ci        if (srcFd < 0) {
625bebb993Sopenharmony_ci            LOGE("Open media uri by data share fail. ret = %{public}d", srcFd);
635bebb993Sopenharmony_ci            return EPERM;
645bebb993Sopenharmony_ci        }
655bebb993Sopenharmony_ci    } else {
665bebb993Sopenharmony_ci        srcFd = open(srcPth.c_str(), O_RDONLY);
675bebb993Sopenharmony_ci        if (srcFd < 0) {
685bebb993Sopenharmony_ci            LOGE("Error opening src file descriptor. errno = %{public}d", errno);
695bebb993Sopenharmony_ci            return errno;
705bebb993Sopenharmony_ci        }
715bebb993Sopenharmony_ci    }
725bebb993Sopenharmony_ci    return ERRNO_NOERR;
735bebb993Sopenharmony_ci}
745bebb993Sopenharmony_ci
755bebb993Sopenharmony_cistatic int SendFileCore(std::unique_ptr<DistributedFS::FDGuard> srcFdg,
765bebb993Sopenharmony_ci                        std::unique_ptr<DistributedFS::FDGuard> destFdg,
775bebb993Sopenharmony_ci                        std::shared_ptr<FileInfos> infos)
785bebb993Sopenharmony_ci{
795bebb993Sopenharmony_ci    std::unique_ptr<uv_fs_t, decltype(CommonFunc::FsReqCleanup)*> sendFileReq = {
805bebb993Sopenharmony_ci        new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup };
815bebb993Sopenharmony_ci    if (sendFileReq == nullptr) {
825bebb993Sopenharmony_ci        LOGE("Failed to request heap memory.");
835bebb993Sopenharmony_ci        return ENOMEM;
845bebb993Sopenharmony_ci    }
855bebb993Sopenharmony_ci    int64_t offset = 0;
865bebb993Sopenharmony_ci    struct stat srcStat{};
875bebb993Sopenharmony_ci    if (fstat(srcFdg->GetFD(), &srcStat) < 0) {
885bebb993Sopenharmony_ci        LOGE("Failed to get stat of file by fd: %{public}d ,errno = %{public}d", srcFdg->GetFD(), errno);
895bebb993Sopenharmony_ci        return errno;
905bebb993Sopenharmony_ci    }
915bebb993Sopenharmony_ci    int32_t ret = 0;
925bebb993Sopenharmony_ci    int64_t size = static_cast<int64_t>(srcStat.st_size);
935bebb993Sopenharmony_ci    while (size >= 0) {
945bebb993Sopenharmony_ci        ret = uv_fs_sendfile(nullptr, sendFileReq.get(), destFdg->GetFD(), srcFdg->GetFD(),
955bebb993Sopenharmony_ci            offset, MAX_SIZE, nullptr);
965bebb993Sopenharmony_ci        if (ret < 0) {
975bebb993Sopenharmony_ci            LOGE("Failed to sendfile by errno : %{public}d", errno);
985bebb993Sopenharmony_ci            return errno;
995bebb993Sopenharmony_ci        }
1005bebb993Sopenharmony_ci        if (infos != nullptr && infos->taskSignal != nullptr) {
1015bebb993Sopenharmony_ci            if (infos->taskSignal->CheckCancelIfNeed(infos->srcPath)) {
1025bebb993Sopenharmony_ci                return ECANCELED;
1035bebb993Sopenharmony_ci            }
1045bebb993Sopenharmony_ci        }
1055bebb993Sopenharmony_ci        offset += static_cast<int64_t>(ret);
1065bebb993Sopenharmony_ci        size -= static_cast<int64_t>(ret);
1075bebb993Sopenharmony_ci        if (ret == 0) {
1085bebb993Sopenharmony_ci            break;
1095bebb993Sopenharmony_ci        }
1105bebb993Sopenharmony_ci    }
1115bebb993Sopenharmony_ci    if (size != 0) {
1125bebb993Sopenharmony_ci        LOGE("The execution of the sendfile task was terminated, remaining file size %{public}" PRIu64, size);
1135bebb993Sopenharmony_ci        return EIO;
1145bebb993Sopenharmony_ci    }
1155bebb993Sopenharmony_ci    return ERRNO_NOERR;
1165bebb993Sopenharmony_ci}
1175bebb993Sopenharmony_ci
1185bebb993Sopenharmony_cistatic int FilterFunc(const struct dirent *filename)
1195bebb993Sopenharmony_ci{
1205bebb993Sopenharmony_ci    if (std::string_view(filename->d_name) == "." || std::string_view(filename->d_name) == "..") {
1215bebb993Sopenharmony_ci        return DISMATCH;
1225bebb993Sopenharmony_ci    }
1235bebb993Sopenharmony_ci    return MATCH;
1245bebb993Sopenharmony_ci}
1255bebb993Sopenharmony_ci
1265bebb993Sopenharmony_cistruct NameList {
1275bebb993Sopenharmony_ci    struct dirent **namelist = { nullptr };
1285bebb993Sopenharmony_ci    int direntNum = 0;
1295bebb993Sopenharmony_ci};
1305bebb993Sopenharmony_ci
1315bebb993Sopenharmony_cistatic void Deleter(struct NameList *arg)
1325bebb993Sopenharmony_ci{
1335bebb993Sopenharmony_ci    for (int i = 0; i < arg->direntNum; i++) {
1345bebb993Sopenharmony_ci        free((arg->namelist)[i]);
1355bebb993Sopenharmony_ci        (arg->namelist)[i] = nullptr;
1365bebb993Sopenharmony_ci    }
1375bebb993Sopenharmony_ci    free(arg->namelist);
1385bebb993Sopenharmony_ci}
1395bebb993Sopenharmony_ci
1405bebb993Sopenharmony_cistd::string CopyImpl::GetRealPath(const std::string& path)
1415bebb993Sopenharmony_ci{
1425bebb993Sopenharmony_ci    fs::path tempPath(path);
1435bebb993Sopenharmony_ci    fs::path realPath{};
1445bebb993Sopenharmony_ci    for (const auto& component : tempPath) {
1455bebb993Sopenharmony_ci        if (component == ".") {
1465bebb993Sopenharmony_ci            continue;
1475bebb993Sopenharmony_ci        } else if (component == "..") {
1485bebb993Sopenharmony_ci            realPath = realPath.parent_path();
1495bebb993Sopenharmony_ci        } else {
1505bebb993Sopenharmony_ci            realPath /= component;
1515bebb993Sopenharmony_ci        }
1525bebb993Sopenharmony_ci    }
1535bebb993Sopenharmony_ci    return realPath.string();
1545bebb993Sopenharmony_ci}
1555bebb993Sopenharmony_ci
1565bebb993Sopenharmony_cibool CopyImpl::IsFile(const std::string &path)
1575bebb993Sopenharmony_ci{
1585bebb993Sopenharmony_ci    struct stat buf {};
1595bebb993Sopenharmony_ci    int ret = stat(path.c_str(), &buf);
1605bebb993Sopenharmony_ci    if (ret == -1) {
1615bebb993Sopenharmony_ci        LOGI("stat failed, errno is %{public}d, ", errno);
1625bebb993Sopenharmony_ci        return false;
1635bebb993Sopenharmony_ci    }
1645bebb993Sopenharmony_ci    return (buf.st_mode & S_IFMT) == S_IFREG;
1655bebb993Sopenharmony_ci}
1665bebb993Sopenharmony_ci
1675bebb993Sopenharmony_cistd::tuple<int, uint64_t> CopyImpl::GetFileSize(const std::string &path)
1685bebb993Sopenharmony_ci{
1695bebb993Sopenharmony_ci    struct stat buf {};
1705bebb993Sopenharmony_ci    int ret = stat(path.c_str(), &buf);
1715bebb993Sopenharmony_ci    if (ret == -1) {
1725bebb993Sopenharmony_ci        LOGI("Stat failed.");
1735bebb993Sopenharmony_ci        return { errno, 0 };
1745bebb993Sopenharmony_ci    }
1755bebb993Sopenharmony_ci    return { ERRNO_NOERR, buf.st_size };
1765bebb993Sopenharmony_ci}
1775bebb993Sopenharmony_ci
1785bebb993Sopenharmony_cibool CopyImpl::CheckFileValid(const std::string &filePath, std::shared_ptr<FileInfos> infos)
1795bebb993Sopenharmony_ci{
1805bebb993Sopenharmony_ci    return infos->filePaths.count(filePath) != 0;
1815bebb993Sopenharmony_ci}
1825bebb993Sopenharmony_ci
1835bebb993Sopenharmony_ciint CopyImpl::UpdateProgressSize(const std::string &filePath,
1845bebb993Sopenharmony_ci    std::shared_ptr<ReceiveInfo> receivedInfo, std::shared_ptr<CjCallbackObject> callback)
1855bebb993Sopenharmony_ci{
1865bebb993Sopenharmony_ci    auto [err, fileSize] = GetFileSize(filePath);
1875bebb993Sopenharmony_ci    if (err != ERRNO_NOERR) {
1885bebb993Sopenharmony_ci        LOGE("GetFileSize failed, err: %{public}d.", err);
1895bebb993Sopenharmony_ci        return err;
1905bebb993Sopenharmony_ci    }
1915bebb993Sopenharmony_ci    auto size = fileSize;
1925bebb993Sopenharmony_ci    auto iter = receivedInfo->fileList.find(filePath);
1935bebb993Sopenharmony_ci    if (iter == receivedInfo->fileList.end()) {
1945bebb993Sopenharmony_ci        receivedInfo->fileList.insert({ filePath, size });
1955bebb993Sopenharmony_ci        callback->progressSize += size;
1965bebb993Sopenharmony_ci    } else { // file
1975bebb993Sopenharmony_ci        if (size > iter->second) {
1985bebb993Sopenharmony_ci            callback->progressSize += (size - iter->second);
1995bebb993Sopenharmony_ci            iter->second = size;
2005bebb993Sopenharmony_ci        }
2015bebb993Sopenharmony_ci    }
2025bebb993Sopenharmony_ci    return ERRNO_NOERR;
2035bebb993Sopenharmony_ci}
2045bebb993Sopenharmony_ci
2055bebb993Sopenharmony_civoid CopyImpl::CheckOrCreatePath(const std::string &destPath)
2065bebb993Sopenharmony_ci{
2075bebb993Sopenharmony_ci    if (!std::filesystem::exists(destPath)) {
2085bebb993Sopenharmony_ci        LOGI("destPath not exist, destPath = %{public}s", destPath.c_str());
2095bebb993Sopenharmony_ci        auto file = open(destPath.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
2105bebb993Sopenharmony_ci        if (file < 0) {
2115bebb993Sopenharmony_ci            LOGE("Error opening file descriptor. errno = %{public}d", errno);
2125bebb993Sopenharmony_ci        }
2135bebb993Sopenharmony_ci        close(file);
2145bebb993Sopenharmony_ci    }
2155bebb993Sopenharmony_ci}
2165bebb993Sopenharmony_ci
2175bebb993Sopenharmony_ciint CopyImpl::MakeDir(const std::string &path)
2185bebb993Sopenharmony_ci{
2195bebb993Sopenharmony_ci    std::filesystem::path destDir(path);
2205bebb993Sopenharmony_ci    std::error_code errCode;
2215bebb993Sopenharmony_ci    if (!std::filesystem::create_directory(destDir, errCode)) {
2225bebb993Sopenharmony_ci        LOGE("Failed to create directory, error code: %{public}d", errCode.value());
2235bebb993Sopenharmony_ci        return errCode.value();
2245bebb993Sopenharmony_ci    }
2255bebb993Sopenharmony_ci    return ERRNO_NOERR;
2265bebb993Sopenharmony_ci}
2275bebb993Sopenharmony_ci
2285bebb993Sopenharmony_ciint CopyImpl::CopySubDir(const std::string &srcPath, const std::string &destPath, std::shared_ptr<FileInfos> infos)
2295bebb993Sopenharmony_ci{
2305bebb993Sopenharmony_ci    if (!std::filesystem::exists(destPath)) {
2315bebb993Sopenharmony_ci        int res = MakeDir(destPath);
2325bebb993Sopenharmony_ci        if (res != ERRNO_NOERR) {
2335bebb993Sopenharmony_ci            LOGE("Failed to mkdir");
2345bebb993Sopenharmony_ci            return res;
2355bebb993Sopenharmony_ci        }
2365bebb993Sopenharmony_ci    }
2375bebb993Sopenharmony_ci    uint32_t watchEvents = IN_MODIFY;
2385bebb993Sopenharmony_ci    if (infos->notifyFd >= 0) {
2395bebb993Sopenharmony_ci        int newWd = inotify_add_watch(infos->notifyFd, destPath.c_str(), watchEvents);
2405bebb993Sopenharmony_ci        if (newWd < 0) {
2415bebb993Sopenharmony_ci            LOGE("inotify_add_watch, newWd is unvaild, newWd = %{public}d", newWd);
2425bebb993Sopenharmony_ci            return errno;
2435bebb993Sopenharmony_ci        }
2445bebb993Sopenharmony_ci        {
2455bebb993Sopenharmony_ci            std::lock_guard<std::recursive_mutex> lock(CopyImpl::mutex_);
2465bebb993Sopenharmony_ci            auto iter = CopyImpl::cjCbMap_.find(*infos);
2475bebb993Sopenharmony_ci            auto receiveInfo = FileManagement::CreateSharedPtr<ReceiveInfo>();
2485bebb993Sopenharmony_ci            if (receiveInfo == nullptr) {
2495bebb993Sopenharmony_ci                LOGE("Failed to request heap memory.");
2505bebb993Sopenharmony_ci                return ENOMEM;
2515bebb993Sopenharmony_ci            }
2525bebb993Sopenharmony_ci            receiveInfo->path = destPath;
2535bebb993Sopenharmony_ci            if (iter == CopyImpl::cjCbMap_.end() || iter->second == nullptr) {
2545bebb993Sopenharmony_ci                LOGE("Failed to find infos, srcPath = %{public}s, destPath = %{public}s", infos->srcPath.c_str(),
2555bebb993Sopenharmony_ci                    infos->destPath.c_str());
2565bebb993Sopenharmony_ci                return UNKNOWN_ERR;
2575bebb993Sopenharmony_ci            }
2585bebb993Sopenharmony_ci            iter->second->wds.push_back({ newWd, receiveInfo });
2595bebb993Sopenharmony_ci        }
2605bebb993Sopenharmony_ci    }
2615bebb993Sopenharmony_ci    return RecurCopyDir(srcPath, destPath, infos);
2625bebb993Sopenharmony_ci}
2635bebb993Sopenharmony_ci
2645bebb993Sopenharmony_ciint CopyImpl::RecurCopyDir(const std::string &srcPath, const std::string &destPath, std::shared_ptr<FileInfos> infos)
2655bebb993Sopenharmony_ci{
2665bebb993Sopenharmony_ci    std::unique_ptr<struct NameList, decltype(Deleter) *> pNameList = { new (std::nothrow) struct NameList, Deleter };
2675bebb993Sopenharmony_ci    if (pNameList == nullptr) {
2685bebb993Sopenharmony_ci        LOGE("Failed to request heap memory.");
2695bebb993Sopenharmony_ci        return ENOMEM;
2705bebb993Sopenharmony_ci    }
2715bebb993Sopenharmony_ci    int num = scandir(srcPath.c_str(), &(pNameList->namelist), FilterFunc, alphasort);
2725bebb993Sopenharmony_ci    pNameList->direntNum = num;
2735bebb993Sopenharmony_ci
2745bebb993Sopenharmony_ci    for (int i = 0; i < num; i++) {
2755bebb993Sopenharmony_ci        std::string src = srcPath + '/' + std::string((pNameList->namelist[i])->d_name);
2765bebb993Sopenharmony_ci        std::string dest = destPath + '/' + std::string((pNameList->namelist[i])->d_name);
2775bebb993Sopenharmony_ci        if ((pNameList->namelist[i])->d_type == DT_LNK) {
2785bebb993Sopenharmony_ci            continue;
2795bebb993Sopenharmony_ci        }
2805bebb993Sopenharmony_ci        int ret = ERRNO_NOERR;
2815bebb993Sopenharmony_ci        if ((pNameList->namelist[i])->d_type == DT_DIR) {
2825bebb993Sopenharmony_ci            ret = CopySubDir(src, dest, infos);
2835bebb993Sopenharmony_ci        } else {
2845bebb993Sopenharmony_ci            infos->filePaths.insert(dest);
2855bebb993Sopenharmony_ci            ret = CopyFile(src, dest, infos);
2865bebb993Sopenharmony_ci        }
2875bebb993Sopenharmony_ci        if (ret != ERRNO_NOERR) {
2885bebb993Sopenharmony_ci            return ret;
2895bebb993Sopenharmony_ci        }
2905bebb993Sopenharmony_ci    }
2915bebb993Sopenharmony_ci    return ERRNO_NOERR;
2925bebb993Sopenharmony_ci}
2935bebb993Sopenharmony_ci
2945bebb993Sopenharmony_cibool CopyImpl::IsDirectory(const std::string &path)
2955bebb993Sopenharmony_ci{
2965bebb993Sopenharmony_ci    struct stat buf {};
2975bebb993Sopenharmony_ci    int ret = stat(path.c_str(), &buf);
2985bebb993Sopenharmony_ci    if (ret == -1) {
2995bebb993Sopenharmony_ci        LOGE("stat failed, errno is %{public}d, path is %{public}s", errno, path.c_str());
3005bebb993Sopenharmony_ci        return false;
3015bebb993Sopenharmony_ci    }
3025bebb993Sopenharmony_ci    return (buf.st_mode & S_IFMT) == S_IFDIR;
3035bebb993Sopenharmony_ci}
3045bebb993Sopenharmony_ci
3055bebb993Sopenharmony_ciint CopyImpl::CopyDirFunc(const std::string &src, const std::string &dest, std::shared_ptr<FileInfos> infos)
3065bebb993Sopenharmony_ci{
3075bebb993Sopenharmony_ci    LOGI("CopyDirFunc in, src = %{public}s, dest = %{public}s", src.c_str(), dest.c_str());
3085bebb993Sopenharmony_ci    size_t found = dest.find(src);
3095bebb993Sopenharmony_ci    if (found != std::string::npos && found == 0) {
3105bebb993Sopenharmony_ci        return EINVAL;
3115bebb993Sopenharmony_ci    }
3125bebb993Sopenharmony_ci    fs::path srcPath = fs::u8path(src);
3135bebb993Sopenharmony_ci    std::string dirName;
3145bebb993Sopenharmony_ci    if (srcPath.has_parent_path()) {
3155bebb993Sopenharmony_ci        dirName = srcPath.parent_path().filename();
3165bebb993Sopenharmony_ci    }
3175bebb993Sopenharmony_ci    std::string destStr = dest + "/" + dirName;
3185bebb993Sopenharmony_ci    return CopySubDir(src, destStr, infos);
3195bebb993Sopenharmony_ci}
3205bebb993Sopenharmony_ci
3215bebb993Sopenharmony_ciuint64_t CopyImpl::GetDirSize(std::shared_ptr<FileInfos> infos, std::string path)
3225bebb993Sopenharmony_ci{
3235bebb993Sopenharmony_ci    std::unique_ptr<struct NameList, decltype(Deleter) *> pNameList = { new (std::nothrow) struct NameList, Deleter };
3245bebb993Sopenharmony_ci    if (pNameList == nullptr) {
3255bebb993Sopenharmony_ci        LOGE("Failed to request heap memory.");
3265bebb993Sopenharmony_ci        return ENOMEM;
3275bebb993Sopenharmony_ci    }
3285bebb993Sopenharmony_ci    int num = scandir(path.c_str(), &(pNameList->namelist), FilterFunc, alphasort);
3295bebb993Sopenharmony_ci    pNameList->direntNum = num;
3305bebb993Sopenharmony_ci
3315bebb993Sopenharmony_ci    long int size = 0;
3325bebb993Sopenharmony_ci    for (int i = 0; i < num; i++) {
3335bebb993Sopenharmony_ci        std::string dest = path + '/' + std::string((pNameList->namelist[i])->d_name);
3345bebb993Sopenharmony_ci        if ((pNameList->namelist[i])->d_type == DT_LNK) {
3355bebb993Sopenharmony_ci            continue;
3365bebb993Sopenharmony_ci        }
3375bebb993Sopenharmony_ci        if ((pNameList->namelist[i])->d_type == DT_DIR) {
3385bebb993Sopenharmony_ci            size += static_cast<int64_t>(GetDirSize(infos, dest));
3395bebb993Sopenharmony_ci        } else {
3405bebb993Sopenharmony_ci            struct stat st {};
3415bebb993Sopenharmony_ci            if (stat(dest.c_str(), &st) == -1) {
3425bebb993Sopenharmony_ci                return size;
3435bebb993Sopenharmony_ci            }
3445bebb993Sopenharmony_ci            size += st.st_size;
3455bebb993Sopenharmony_ci        }
3465bebb993Sopenharmony_ci    }
3475bebb993Sopenharmony_ci    return size;
3485bebb993Sopenharmony_ci}
3495bebb993Sopenharmony_ci
3505bebb993Sopenharmony_cistd::shared_ptr<FileInfos> CopyImpl::InitCjFileInfo(
3515bebb993Sopenharmony_ci    const std::string& srcUri, const std::string& destUri, sptr<CopyInfo> info)
3525bebb993Sopenharmony_ci{
3535bebb993Sopenharmony_ci    auto infos = FileManagement::CreateSharedPtr<FileInfos>();
3545bebb993Sopenharmony_ci    if (infos == nullptr) {
3555bebb993Sopenharmony_ci        LOGE("Failed to request heap memory by create FileInfos struct.");
3565bebb993Sopenharmony_ci        return nullptr;
3575bebb993Sopenharmony_ci    }
3585bebb993Sopenharmony_ci    infos->srcUri = srcUri;
3595bebb993Sopenharmony_ci    infos->destUri = destUri;
3605bebb993Sopenharmony_ci    infos->listenerId = info->listenerId;
3615bebb993Sopenharmony_ci    infos->copySignalId = info->signalId;
3625bebb993Sopenharmony_ci    AppFileService::ModuleFileUri::FileUri srcFileUri(srcUri);
3635bebb993Sopenharmony_ci    AppFileService::ModuleFileUri::FileUri destFileUri(destUri);
3645bebb993Sopenharmony_ci    infos->srcPath = srcFileUri.GetRealPath();
3655bebb993Sopenharmony_ci    infos->destPath = destFileUri.GetPath();
3665bebb993Sopenharmony_ci    infos->srcPath = GetRealPath(infos->srcPath);
3675bebb993Sopenharmony_ci    infos->destPath = GetRealPath(infos->destPath);
3685bebb993Sopenharmony_ci    infos->notifyTime = std::chrono::steady_clock::now() + NOTIFY_PROGRESS_DELAY;
3695bebb993Sopenharmony_ci    if (info->listenerId > 0) {
3705bebb993Sopenharmony_ci        infos->hasListener = true;
3715bebb993Sopenharmony_ci    }
3725bebb993Sopenharmony_ci    auto signal = FFI::FFIData::GetData<TaskSignalImpl>(infos->copySignalId);
3735bebb993Sopenharmony_ci    if (signal != nullptr && signal->signalEntity != nullptr) {
3745bebb993Sopenharmony_ci        infos->taskSignal = signal->signalEntity->taskSignal_;
3755bebb993Sopenharmony_ci    }
3765bebb993Sopenharmony_ci    return infos;
3775bebb993Sopenharmony_ci}
3785bebb993Sopenharmony_ci
3795bebb993Sopenharmony_civoid CopyImpl::ReceiveComplete(CProgress data,
3805bebb993Sopenharmony_ci    std::shared_ptr<FileInfos> infos, std::shared_ptr<CjCallbackObject> callback)
3815bebb993Sopenharmony_ci{
3825bebb993Sopenharmony_ci    if (callback == nullptr) {
3835bebb993Sopenharmony_ci        LOGE("callback pointer is nullptr.");
3845bebb993Sopenharmony_ci        return;
3855bebb993Sopenharmony_ci    }
3865bebb993Sopenharmony_ci    auto processedSize = data.processedSize;
3875bebb993Sopenharmony_ci    if (processedSize < callback->maxProgressSize) {
3885bebb993Sopenharmony_ci        return;
3895bebb993Sopenharmony_ci    }
3905bebb993Sopenharmony_ci    callback->maxProgressSize = processedSize;
3915bebb993Sopenharmony_ci
3925bebb993Sopenharmony_ci    if (callback->callback == nullptr) {
3935bebb993Sopenharmony_ci        LOGI("Empty callback.");
3945bebb993Sopenharmony_ci        return;
3955bebb993Sopenharmony_ci    }
3965bebb993Sopenharmony_ci    callback->callback(data);
3975bebb993Sopenharmony_ci}
3985bebb993Sopenharmony_ci
3995bebb993Sopenharmony_civoid CopyImpl::OnFileReceive(std::shared_ptr<FileInfos> infos)
4005bebb993Sopenharmony_ci{
4015bebb993Sopenharmony_ci    auto callback = GetRegisteredListener(infos);
4025bebb993Sopenharmony_ci    if (callback == nullptr) {
4035bebb993Sopenharmony_ci        LOGE("failed to get listener progress");
4045bebb993Sopenharmony_ci        return;
4055bebb993Sopenharmony_ci    }
4065bebb993Sopenharmony_ci    CProgress data = {.processedSize = callback->progressSize,
4075bebb993Sopenharmony_ci                      .totalSize = callback->totalSize};
4085bebb993Sopenharmony_ci    ReceiveComplete(data, infos, callback);
4095bebb993Sopenharmony_ci}
4105bebb993Sopenharmony_ci
4115bebb993Sopenharmony_cistd::shared_ptr<ReceiveInfo> CopyImpl::GetReceivedInfo(int wd, std::shared_ptr<CjCallbackObject> callback)
4125bebb993Sopenharmony_ci{
4135bebb993Sopenharmony_ci    auto it = find_if(callback->wds.begin(), callback->wds.end(), [wd](const auto& item) {
4145bebb993Sopenharmony_ci        return item.first == wd;
4155bebb993Sopenharmony_ci    });
4165bebb993Sopenharmony_ci    if (it != callback->wds.end()) {
4175bebb993Sopenharmony_ci        return it->second;
4185bebb993Sopenharmony_ci    }
4195bebb993Sopenharmony_ci    return nullptr;
4205bebb993Sopenharmony_ci}
4215bebb993Sopenharmony_ci
4225bebb993Sopenharmony_ciint CopyImpl::CopyFile(const std::string &src, const std::string &dest, std::shared_ptr<FileInfos> infos)
4235bebb993Sopenharmony_ci{
4245bebb993Sopenharmony_ci    LOGI("src = %{public}s, dest = %{public}s", src.c_str(), dest.c_str());
4255bebb993Sopenharmony_ci    int32_t srcFd = -1;
4265bebb993Sopenharmony_ci    int32_t ret = OpenSrcFile(src, infos, srcFd);
4275bebb993Sopenharmony_ci    if (srcFd < 0) {
4285bebb993Sopenharmony_ci        return ret;
4295bebb993Sopenharmony_ci    }
4305bebb993Sopenharmony_ci    auto destFd = open(dest.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
4315bebb993Sopenharmony_ci    if (destFd < 0) {
4325bebb993Sopenharmony_ci        LOGE("Error opening dest file descriptor. errno = %{public}d", errno);
4335bebb993Sopenharmony_ci        close(srcFd);
4345bebb993Sopenharmony_ci        return errno;
4355bebb993Sopenharmony_ci    }
4365bebb993Sopenharmony_ci    auto srcFdg = FileManagement::CreateUniquePtr<DistributedFS::FDGuard>(srcFd, true);
4375bebb993Sopenharmony_ci    auto destFdg = FileManagement::CreateUniquePtr<DistributedFS::FDGuard>(destFd, true);
4385bebb993Sopenharmony_ci    if (srcFdg == nullptr || destFdg == nullptr) {
4395bebb993Sopenharmony_ci        LOGE("Failed to request heap memory.");
4405bebb993Sopenharmony_ci        close(srcFd);
4415bebb993Sopenharmony_ci        close(destFd);
4425bebb993Sopenharmony_ci        return ENOMEM;
4435bebb993Sopenharmony_ci    }
4445bebb993Sopenharmony_ci    return SendFileCore(move(srcFdg), move(destFdg), infos);
4455bebb993Sopenharmony_ci}
4465bebb993Sopenharmony_ci
4475bebb993Sopenharmony_cistd::shared_ptr<CjCallbackObject> CopyImpl::GetRegisteredListener(std::shared_ptr<FileInfos> infos)
4485bebb993Sopenharmony_ci{
4495bebb993Sopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
4505bebb993Sopenharmony_ci    auto iter = cjCbMap_.find(*infos);
4515bebb993Sopenharmony_ci    if (iter == cjCbMap_.end()) {
4525bebb993Sopenharmony_ci        LOGE("It is not registered.");
4535bebb993Sopenharmony_ci        return nullptr;
4545bebb993Sopenharmony_ci    }
4555bebb993Sopenharmony_ci    return iter->second;
4565bebb993Sopenharmony_ci}
4575bebb993Sopenharmony_ci
4585bebb993Sopenharmony_cistd::tuple<bool, int, bool> CopyImpl::HandleProgress(
4595bebb993Sopenharmony_ci    inotify_event *event, std::shared_ptr<FileInfos> infos, std::shared_ptr<CjCallbackObject> callback)
4605bebb993Sopenharmony_ci{
4615bebb993Sopenharmony_ci    if (callback == nullptr) {
4625bebb993Sopenharmony_ci        return { true, EINVAL, false };
4635bebb993Sopenharmony_ci    }
4645bebb993Sopenharmony_ci    auto receivedInfo = GetReceivedInfo(event->wd, callback);
4655bebb993Sopenharmony_ci    if (receivedInfo == nullptr) {
4665bebb993Sopenharmony_ci        return { true, EINVAL, false };
4675bebb993Sopenharmony_ci    }
4685bebb993Sopenharmony_ci    std::string fileName = receivedInfo->path;
4695bebb993Sopenharmony_ci    if (event->len > 0) { // files under subdir
4705bebb993Sopenharmony_ci        fileName += "/" + std::string(event->name);
4715bebb993Sopenharmony_ci        if (!CheckFileValid(fileName, infos)) {
4725bebb993Sopenharmony_ci            return { true, EINVAL, false };
4735bebb993Sopenharmony_ci        }
4745bebb993Sopenharmony_ci        auto err = UpdateProgressSize(fileName, receivedInfo, callback);
4755bebb993Sopenharmony_ci        if (err != ERRNO_NOERR) {
4765bebb993Sopenharmony_ci            return { false, err, false };
4775bebb993Sopenharmony_ci        }
4785bebb993Sopenharmony_ci    } else {
4795bebb993Sopenharmony_ci        auto [err, fileSize] = GetFileSize(fileName);
4805bebb993Sopenharmony_ci        if (err != ERRNO_NOERR) {
4815bebb993Sopenharmony_ci            return { false, err, false };
4825bebb993Sopenharmony_ci        }
4835bebb993Sopenharmony_ci        callback->progressSize = fileSize;
4845bebb993Sopenharmony_ci    }
4855bebb993Sopenharmony_ci    return { true, callback->errorCode, true };
4865bebb993Sopenharmony_ci}
4875bebb993Sopenharmony_ci
4885bebb993Sopenharmony_civoid CopyImpl::ReadNotifyEvent(std::shared_ptr<FileInfos> infos)
4895bebb993Sopenharmony_ci{
4905bebb993Sopenharmony_ci    char buf[BUF_SIZE] = { 0 };
4915bebb993Sopenharmony_ci    struct inotify_event *event = nullptr;
4925bebb993Sopenharmony_ci    int len = 0;
4935bebb993Sopenharmony_ci    int64_t index = 0;
4945bebb993Sopenharmony_ci    auto callback = GetRegisteredListener(infos);
4955bebb993Sopenharmony_ci    while (((len = read(infos->notifyFd, &buf, sizeof(buf))) < 0) && (errno == EINTR)) {}
4965bebb993Sopenharmony_ci    while (infos->run && index < len) {
4975bebb993Sopenharmony_ci        event = reinterpret_cast<inotify_event *>(buf + index);
4985bebb993Sopenharmony_ci        auto [needContinue, errCode, needSend] = HandleProgress(event, infos, callback);
4995bebb993Sopenharmony_ci        if (!needContinue) {
5005bebb993Sopenharmony_ci            infos->exceptionCode = errCode;
5015bebb993Sopenharmony_ci            return;
5025bebb993Sopenharmony_ci        }
5035bebb993Sopenharmony_ci        if (needContinue && !needSend) {
5045bebb993Sopenharmony_ci            index += static_cast<int64_t>(sizeof(struct inotify_event) + event->len);
5055bebb993Sopenharmony_ci            continue;
5065bebb993Sopenharmony_ci        }
5075bebb993Sopenharmony_ci        if (callback->progressSize == callback->totalSize) {
5085bebb993Sopenharmony_ci            infos->run = false;
5095bebb993Sopenharmony_ci            return;
5105bebb993Sopenharmony_ci        }
5115bebb993Sopenharmony_ci        auto currentTime = std::chrono::steady_clock::now();
5125bebb993Sopenharmony_ci        if (currentTime >= infos->notifyTime) {
5135bebb993Sopenharmony_ci            OnFileReceive(infos);
5145bebb993Sopenharmony_ci            infos->notifyTime = currentTime + NOTIFY_PROGRESS_DELAY;
5155bebb993Sopenharmony_ci        }
5165bebb993Sopenharmony_ci        index += static_cast<int64_t>(sizeof(struct inotify_event) + event->len);
5175bebb993Sopenharmony_ci    }
5185bebb993Sopenharmony_ci}
5195bebb993Sopenharmony_ci
5205bebb993Sopenharmony_civoid CopyImpl::GetNotifyEvent(std::shared_ptr<FileInfos> infos)
5215bebb993Sopenharmony_ci{
5225bebb993Sopenharmony_ci    auto callback = GetRegisteredListener(infos);
5235bebb993Sopenharmony_ci    if (callback == nullptr) {
5245bebb993Sopenharmony_ci        infos->exceptionCode = EINVAL;
5255bebb993Sopenharmony_ci        return;
5265bebb993Sopenharmony_ci    }
5275bebb993Sopenharmony_ci    prctl(PR_SET_NAME, "NotifyThread");
5285bebb993Sopenharmony_ci    nfds_t nfds = 2;
5295bebb993Sopenharmony_ci    struct pollfd fds[2];
5305bebb993Sopenharmony_ci    fds[0].events = 0;
5315bebb993Sopenharmony_ci    fds[1].events = POLLIN;
5325bebb993Sopenharmony_ci    fds[0].fd = infos->eventFd;
5335bebb993Sopenharmony_ci    fds[1].fd = infos->notifyFd;
5345bebb993Sopenharmony_ci    while (infos->run && infos->exceptionCode == ERRNO_NOERR && infos->eventFd != -1 && infos->notifyFd != -1) {
5355bebb993Sopenharmony_ci        auto ret = poll(fds, nfds, -1);
5365bebb993Sopenharmony_ci        if (ret > 0) {
5375bebb993Sopenharmony_ci            if (static_cast<unsigned short>(fds[0].revents) & POLLNVAL) {
5385bebb993Sopenharmony_ci                infos->run = false;
5395bebb993Sopenharmony_ci                return;
5405bebb993Sopenharmony_ci            }
5415bebb993Sopenharmony_ci            if (static_cast<unsigned short>(fds[1].revents) & POLLIN) {
5425bebb993Sopenharmony_ci                ReadNotifyEvent(infos);
5435bebb993Sopenharmony_ci            }
5445bebb993Sopenharmony_ci        } else if (ret < 0 && errno == EINTR) {
5455bebb993Sopenharmony_ci            continue;
5465bebb993Sopenharmony_ci        } else {
5475bebb993Sopenharmony_ci            infos->exceptionCode = errno;
5485bebb993Sopenharmony_ci            return;
5495bebb993Sopenharmony_ci        }
5505bebb993Sopenharmony_ci    }
5515bebb993Sopenharmony_ci}
5525bebb993Sopenharmony_ci
5535bebb993Sopenharmony_civoid CopyImpl::StartNotify(std::shared_ptr<FileInfos> infos, std::shared_ptr<CjCallbackObject> callback)
5545bebb993Sopenharmony_ci{
5555bebb993Sopenharmony_ci    if (infos->hasListener && callback != nullptr) {
5565bebb993Sopenharmony_ci        callback->notifyHandler = std::thread([infos] {
5575bebb993Sopenharmony_ci            GetNotifyEvent(infos);
5585bebb993Sopenharmony_ci            });
5595bebb993Sopenharmony_ci    }
5605bebb993Sopenharmony_ci}
5615bebb993Sopenharmony_ci
5625bebb993Sopenharmony_ciint CopyImpl::ExecCopy(std::shared_ptr<FileInfos> infos)
5635bebb993Sopenharmony_ci{
5645bebb993Sopenharmony_ci    if (IsFile(infos->srcPath) && IsFile(infos->destPath)) {
5655bebb993Sopenharmony_ci        // copyFile
5665bebb993Sopenharmony_ci        return CopyFile(infos->srcPath.c_str(), infos->destPath.c_str(), infos);
5675bebb993Sopenharmony_ci    }
5685bebb993Sopenharmony_ci    if (IsDirectory(infos->srcPath) && IsDirectory(infos->destPath)) {
5695bebb993Sopenharmony_ci        if (infos->srcPath.back() != '/') {
5705bebb993Sopenharmony_ci            infos->srcPath += '/';
5715bebb993Sopenharmony_ci        }
5725bebb993Sopenharmony_ci        if (infos->destPath.back() != '/') {
5735bebb993Sopenharmony_ci            infos->destPath += '/';
5745bebb993Sopenharmony_ci        }
5755bebb993Sopenharmony_ci        // copyDir
5765bebb993Sopenharmony_ci        return CopyDirFunc(infos->srcPath.c_str(), infos->destPath.c_str(), infos);
5775bebb993Sopenharmony_ci    }
5785bebb993Sopenharmony_ci    return EINVAL;
5795bebb993Sopenharmony_ci}
5805bebb993Sopenharmony_ci
5815bebb993Sopenharmony_cistd::shared_ptr<CjCallbackObject> CopyImpl::RegisterListener(std::shared_ptr<FileInfos>& infos)
5825bebb993Sopenharmony_ci{
5835bebb993Sopenharmony_ci    auto callback = FileManagement::CreateSharedPtr<CjCallbackObject>(infos->listenerId);
5845bebb993Sopenharmony_ci    if (callback == nullptr) {
5855bebb993Sopenharmony_ci        LOGE("Failed to request heap memory by create callback object.");
5865bebb993Sopenharmony_ci        return nullptr;
5875bebb993Sopenharmony_ci    }
5885bebb993Sopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
5895bebb993Sopenharmony_ci    auto iter = cjCbMap_.find(*infos);
5905bebb993Sopenharmony_ci    if (iter != cjCbMap_.end()) {
5915bebb993Sopenharmony_ci        LOGE("Regist copy listener, already registered.")
5925bebb993Sopenharmony_ci        return nullptr;
5935bebb993Sopenharmony_ci    }
5945bebb993Sopenharmony_ci    cjCbMap_.insert({*infos, callback});
5955bebb993Sopenharmony_ci    return callback;
5965bebb993Sopenharmony_ci}
5975bebb993Sopenharmony_ci
5985bebb993Sopenharmony_civoid CopyImpl::UnregisterListener(std::shared_ptr<FileInfos> infos)
5995bebb993Sopenharmony_ci{
6005bebb993Sopenharmony_ci    if (infos == nullptr) {
6015bebb993Sopenharmony_ci        LOGE("infos is nullptr");
6025bebb993Sopenharmony_ci        return;
6035bebb993Sopenharmony_ci    }
6045bebb993Sopenharmony_ci    std::lock_guard<std::recursive_mutex> lock(mutex_);
6055bebb993Sopenharmony_ci    auto iter = cjCbMap_.find(*infos);
6065bebb993Sopenharmony_ci    if (iter == cjCbMap_.end()) {
6075bebb993Sopenharmony_ci        LOGI("It is not be registered.");
6085bebb993Sopenharmony_ci        return;
6095bebb993Sopenharmony_ci    }
6105bebb993Sopenharmony_ci    cjCbMap_.erase(*infos);
6115bebb993Sopenharmony_ci}
6125bebb993Sopenharmony_ci
6135bebb993Sopenharmony_cibool CopyImpl::IsRemoteUri(const std::string& uri)
6145bebb993Sopenharmony_ci{
6155bebb993Sopenharmony_ci    return uri.find(NETWORK_PARA) != uri.npos;
6165bebb993Sopenharmony_ci}
6175bebb993Sopenharmony_ci
6185bebb993Sopenharmony_ciint64_t CopyImpl::DoCopy(std::shared_ptr<FileInfos> infos, std::shared_ptr<CjCallbackObject> callback)
6195bebb993Sopenharmony_ci{
6205bebb993Sopenharmony_ci    if (IsRemoteUri(infos->srcUri)) {
6215bebb993Sopenharmony_ci        if (infos->taskSignal != nullptr) {
6225bebb993Sopenharmony_ci            infos->taskSignal->MarkRemoteTask();
6235bebb993Sopenharmony_ci        }
6245bebb993Sopenharmony_ci        auto ret = TransListener::CopyFileFromSoftBus(
6255bebb993Sopenharmony_ci            infos->srcUri, infos->destUri, infos, std::move(callback));
6265bebb993Sopenharmony_ci        return ret;
6275bebb993Sopenharmony_ci    }
6285bebb993Sopenharmony_ci    auto result = ExecLocal(infos, callback);
6295bebb993Sopenharmony_ci    CloseNotifyFd(infos, callback);
6305bebb993Sopenharmony_ci    infos->run = false;
6315bebb993Sopenharmony_ci    WaitNotifyFinished(callback);
6325bebb993Sopenharmony_ci    if (result != ERRNO_NOERR) {
6335bebb993Sopenharmony_ci        infos->exceptionCode = result;
6345bebb993Sopenharmony_ci        return infos->exceptionCode;
6355bebb993Sopenharmony_ci    }
6365bebb993Sopenharmony_ci    CopyComplete(infos, callback);
6375bebb993Sopenharmony_ci    return infos->exceptionCode;
6385bebb993Sopenharmony_ci}
6395bebb993Sopenharmony_ci
6405bebb993Sopenharmony_ciint64_t CopyImpl::ExecLocal(std::shared_ptr<FileInfos>& infos, std::shared_ptr<CjCallbackObject>& callback)
6415bebb993Sopenharmony_ci{
6425bebb993Sopenharmony_ci    if (IsFile(infos->srcPath)) {
6435bebb993Sopenharmony_ci        if (infos->srcPath == infos->destPath) {
6445bebb993Sopenharmony_ci            LOGE("The src and dest is same, path = %{public}s", infos->srcPath.c_str());
6455bebb993Sopenharmony_ci            return EINVAL;
6465bebb993Sopenharmony_ci        }
6475bebb993Sopenharmony_ci        CheckOrCreatePath(infos->destPath);
6485bebb993Sopenharmony_ci    }
6495bebb993Sopenharmony_ci    if (!infos->hasListener) {
6505bebb993Sopenharmony_ci        return ExecCopy(infos);
6515bebb993Sopenharmony_ci    }
6525bebb993Sopenharmony_ci    auto ret = SubscribeLocalListener(infos, callback);
6535bebb993Sopenharmony_ci    if (ret != ERRNO_NOERR) {
6545bebb993Sopenharmony_ci        LOGE("Failed to subscribe local listener, errno = %{public}" PRIu64, ret);
6555bebb993Sopenharmony_ci        return ret;
6565bebb993Sopenharmony_ci    }
6575bebb993Sopenharmony_ci    StartNotify(infos, callback);
6585bebb993Sopenharmony_ci    return ExecCopy(infos);
6595bebb993Sopenharmony_ci}
6605bebb993Sopenharmony_ci
6615bebb993Sopenharmony_ciint64_t CopyImpl::SubscribeLocalListener(std::shared_ptr<FileInfos>& infos, std::shared_ptr<CjCallbackObject>& callback)
6625bebb993Sopenharmony_ci{
6635bebb993Sopenharmony_ci    infos->notifyFd = inotify_init();
6645bebb993Sopenharmony_ci    if (infos->notifyFd < 0) {
6655bebb993Sopenharmony_ci        LOGE("Failed to init inotify, errno:%{public}d", errno);
6665bebb993Sopenharmony_ci        return errno;
6675bebb993Sopenharmony_ci    }
6685bebb993Sopenharmony_ci    infos->eventFd = eventfd(0, EFD_CLOEXEC);
6695bebb993Sopenharmony_ci    if (infos->eventFd < 0) {
6705bebb993Sopenharmony_ci        LOGE("Failed to init eventFd, errno:%{public}d", errno);
6715bebb993Sopenharmony_ci        return errno;
6725bebb993Sopenharmony_ci    }
6735bebb993Sopenharmony_ci    callback->notifyFd = infos->notifyFd;
6745bebb993Sopenharmony_ci    callback->eventFd = infos->eventFd;
6755bebb993Sopenharmony_ci    int newWd = inotify_add_watch(infos->notifyFd, infos->destPath.c_str(), IN_MODIFY);
6765bebb993Sopenharmony_ci    if (newWd < 0) {
6775bebb993Sopenharmony_ci        LOGE("Failed to add watch, errno = %{public}d, notifyFd: %{public}d, destPath: %{public}s",
6785bebb993Sopenharmony_ci             errno, infos->notifyFd, infos->destPath.c_str());
6795bebb993Sopenharmony_ci        CloseNotifyFd(infos, callback);
6805bebb993Sopenharmony_ci        return errno;
6815bebb993Sopenharmony_ci    }
6825bebb993Sopenharmony_ci    auto receiveInfo = FileManagement::CreateSharedPtr<ReceiveInfo>();
6835bebb993Sopenharmony_ci    if (receiveInfo == nullptr) {
6845bebb993Sopenharmony_ci        LOGE("Failed to request heap memory.");
6855bebb993Sopenharmony_ci        inotify_rm_watch(infos->notifyFd, newWd);
6865bebb993Sopenharmony_ci        CloseNotifyFd(infos, callback);
6875bebb993Sopenharmony_ci        return ENOMEM;
6885bebb993Sopenharmony_ci    }
6895bebb993Sopenharmony_ci    receiveInfo->path = infos->destPath;
6905bebb993Sopenharmony_ci    callback->wds.push_back({ newWd, receiveInfo });
6915bebb993Sopenharmony_ci    if (IsDirectory(infos->srcPath)) {
6925bebb993Sopenharmony_ci        callback->totalSize = GetDirSize(infos, infos->srcPath);
6935bebb993Sopenharmony_ci        return ERRNO_NOERR;
6945bebb993Sopenharmony_ci    }
6955bebb993Sopenharmony_ci    auto [err, fileSize] = GetFileSize(infos->srcPath);
6965bebb993Sopenharmony_ci    if (err == ERRNO_NOERR) {
6975bebb993Sopenharmony_ci        callback->totalSize = fileSize;
6985bebb993Sopenharmony_ci    }
6995bebb993Sopenharmony_ci    return err;
7005bebb993Sopenharmony_ci}
7015bebb993Sopenharmony_ci
7025bebb993Sopenharmony_civoid CopyImpl::CloseNotifyFd(std::shared_ptr<FileInfos>& infos, std::shared_ptr<CjCallbackObject>& callback)
7035bebb993Sopenharmony_ci{
7045bebb993Sopenharmony_ci    callback->CloseFd();
7055bebb993Sopenharmony_ci    infos->eventFd = -1;
7065bebb993Sopenharmony_ci    infos->notifyFd = -1;
7075bebb993Sopenharmony_ci}
7085bebb993Sopenharmony_ci
7095bebb993Sopenharmony_civoid CopyImpl::WaitNotifyFinished(std::shared_ptr<CjCallbackObject>& callback)
7105bebb993Sopenharmony_ci{
7115bebb993Sopenharmony_ci    if (callback != nullptr) {
7125bebb993Sopenharmony_ci        if (callback->notifyHandler.joinable()) {
7135bebb993Sopenharmony_ci            callback->notifyHandler.join();
7145bebb993Sopenharmony_ci        }
7155bebb993Sopenharmony_ci    }
7165bebb993Sopenharmony_ci}
7175bebb993Sopenharmony_ci
7185bebb993Sopenharmony_civoid CopyImpl::CopyComplete(std::shared_ptr<FileInfos>& infos, std::shared_ptr<CjCallbackObject>& callback)
7195bebb993Sopenharmony_ci{
7205bebb993Sopenharmony_ci    if (callback != nullptr && infos->hasListener) {
7215bebb993Sopenharmony_ci        callback->progressSize = callback->totalSize;
7225bebb993Sopenharmony_ci        OnFileReceive(infos);
7235bebb993Sopenharmony_ci    }
7245bebb993Sopenharmony_ci}
7255bebb993Sopenharmony_ci
7265bebb993Sopenharmony_civoid CopyImpl::Copy(const char* srcUri, const char* destUri, sptr<CopyInfo> info)
7275bebb993Sopenharmony_ci{
7285bebb993Sopenharmony_ci    if (srcUri == nullptr || destUri == nullptr) {
7295bebb993Sopenharmony_ci        LOGE("Invalid input.");
7305bebb993Sopenharmony_ci        return;
7315bebb993Sopenharmony_ci    }
7325bebb993Sopenharmony_ci    std::string src(srcUri);
7335bebb993Sopenharmony_ci    std::string dest(destUri);
7345bebb993Sopenharmony_ci    std::shared_ptr<FileInfos> infos = InitCjFileInfo(src, dest, info);
7355bebb993Sopenharmony_ci    if (infos == nullptr) {
7365bebb993Sopenharmony_ci        return;
7375bebb993Sopenharmony_ci    }
7385bebb993Sopenharmony_ci    auto callback = RegisterListener(infos);
7395bebb993Sopenharmony_ci    if (callback == nullptr) {
7405bebb993Sopenharmony_ci        return;
7415bebb993Sopenharmony_ci    }
7425bebb993Sopenharmony_ci    DoCopy(infos, callback);
7435bebb993Sopenharmony_ci    UnregisterListener(infos);
7445bebb993Sopenharmony_ci}
7455bebb993Sopenharmony_ci
7465bebb993Sopenharmony_ciCopyInfo::~CopyInfo() {}
7475bebb993Sopenharmony_ci}
7485bebb993Sopenharmony_ci}