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}