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#ifndef OHOS_FILE_FS_COPY_H 17#define OHOS_FILE_FS_COPY_H 18 19#include <chrono> 20#include <cstring> 21#include <map> 22#include <memory> 23#include <mutex> 24#include <set> 25#include <sys/inotify.h> 26#include <thread> 27#include "utils.h" 28#include "cj_lambda.h" 29#include "ffi_remote_data.h" 30#include "macro.h" 31#include "task_signal.h" 32#include "task_signal_impl.h" 33#include "uni_error.h" 34 35extern "C" { 36struct CProgress { 37 uint64_t processedSize; 38 uint64_t totalSize; 39}; 40} 41 42namespace OHOS { 43namespace CJSystemapi { 44const uint64_t MAX_VALUE = 0x7FFFFFFFFFFFFFFF; 45struct ReceiveInfo { 46 std::string path; 47 std::map<std::string, uint64_t> fileList; 48}; 49 50struct CjCallbackObject { 51 int64_t callbackId = 0; 52 int32_t notifyFd = -1; 53 int32_t eventFd = -1; 54 std::function<void(CProgress)> callback; 55 std::vector<std::pair<int, std::shared_ptr<ReceiveInfo>>> wds; 56 uint64_t totalSize = 0; 57 uint64_t progressSize = 0; 58 uint64_t maxProgressSize = 0; 59 int32_t errorCode = 0; 60 std::thread notifyHandler; 61 explicit CjCallbackObject(int64_t id) : callbackId(id) 62 { 63 if (callbackId == 0) { 64 callback = nullptr; 65 return; 66 } 67 callback = CJLambda::Create(reinterpret_cast<void(*)(CProgress)>(callbackId)); 68 } 69 void CloseFd() 70 { 71 if (eventFd != -1) { 72 close(eventFd); 73 eventFd = -1; 74 } 75 if (notifyFd == -1) { 76 return; 77 } 78 for (auto item : wds) { 79 inotify_rm_watch(notifyFd, item.first); 80 } 81 close(notifyFd); 82 notifyFd = -1; 83 } 84 ~CjCallbackObject() 85 { 86 CloseFd(); 87 } 88}; 89 90struct FileInfos { 91 std::string srcUri; 92 std::string destUri; 93 std::string srcPath; 94 std::string destPath; 95 std::chrono::steady_clock::time_point notifyTime; 96 int32_t notifyFd = -1; 97 int32_t eventFd = -1; 98 bool run = true; 99 bool hasListener = false; 100 int64_t listenerId = 0; 101 int64_t copySignalId = 0; 102 int64_t exceptionCode = FileFs::ERRNO_NOERR; 103 std::shared_ptr<DistributedFS::ModuleTaskSignal::TaskSignal> taskSignal = nullptr; 104 std::set<std::string> filePaths; 105 bool operator==(const FileInfos &infos) const 106 { 107 return (srcUri == infos.srcUri && destUri == infos.destUri); 108 } 109 bool operator<(const FileInfos &infos) const 110 { 111 if (srcUri == infos.srcUri) { 112 return destUri < infos.destUri; 113 } 114 return srcUri < infos.srcUri; 115 } 116}; 117 118class CopyInfo : public OHOS::FFI::FFIData { 119 friend class CopyImpl; 120public: 121 CopyInfo(int64_t listener, int64_t signal) : listenerId(listener), signalId(signal) {} 122 ~CopyInfo(); 123private: 124 int64_t listenerId = 0; 125 int64_t signalId = 0; 126}; 127 128class CopyImpl final { 129public: 130 static std::map<FileInfos, std::shared_ptr<CjCallbackObject>> cjCbMap_; 131 static std::recursive_mutex mutex_; 132 static void UnregisterListener(std::shared_ptr<FileInfos> fileInfos); 133 static void Copy(const char* srcUri, const char* destUri, sptr<CopyInfo> info); 134private: 135 static int UpdateProgressSize(const std::string &filePath, 136 std::shared_ptr<ReceiveInfo> receivedInfo, 137 std::shared_ptr<CjCallbackObject> callback); 138 static void StartNotify(std::shared_ptr<FileInfos> infos, std::shared_ptr<CjCallbackObject> callback); 139 static bool IsRemoteUri(const std::string& uri); 140 static int64_t DoCopy(std::shared_ptr<FileInfos> infos, std::shared_ptr<CjCallbackObject> callback); 141 static int64_t ExecLocal(std::shared_ptr<FileInfos>& infos, std::shared_ptr<CjCallbackObject>& callback); 142 static void CloseNotifyFd(std::shared_ptr<FileInfos>& infos, std::shared_ptr<CjCallbackObject>& callback); 143 static void WaitNotifyFinished(std::shared_ptr<CjCallbackObject>& callback); 144 static void CopyComplete(std::shared_ptr<FileInfos>& infos, std::shared_ptr<CjCallbackObject>& callback); 145 static std::shared_ptr<FileInfos> InitCjFileInfo( 146 const std::string& srcUri, const std::string& destUri, sptr<CopyInfo> info); 147 static std::shared_ptr<CjCallbackObject> RegisterListener(std::shared_ptr<FileInfos>& infos); 148 static bool IsFile(const std::string &path); 149 static void CheckOrCreatePath(const std::string &destPath); 150 static int64_t SubscribeLocalListener(std::shared_ptr<FileInfos>& infos, 151 std::shared_ptr<CjCallbackObject>& callback); 152 static int ExecCopy(std::shared_ptr<FileInfos> infos); 153 static int CopyFile(const std::string &src, const std::string &dest, std::shared_ptr<FileInfos> infos); 154 static bool IsDirectory(const std::string &path); 155 static std::tuple<int, uint64_t> GetFileSize(const std::string &path); 156 static int MakeDir(const std::string &path); 157 static int CopySubDir(const std::string &srcPath, const std::string &destPath, std::shared_ptr<FileInfos> infos); 158 static int CopyDirFunc(const std::string &src, const std::string &dest, std::shared_ptr<FileInfos> infos); 159 static uint64_t GetDirSize(std::shared_ptr<FileInfos> infos, std::string path); 160 static int RecurCopyDir(const std::string &srcPath, const std::string &destPath, std::shared_ptr<FileInfos> infos); 161 static void GetNotifyEvent(std::shared_ptr<FileInfos> infos); 162 static bool CheckFileValid(const std::string &filePath, std::shared_ptr<FileInfos> infos); 163 static void OnFileReceive(std::shared_ptr<FileInfos> infos); 164 static std::shared_ptr<CjCallbackObject> GetRegisteredListener(std::shared_ptr<FileInfos> infos); 165 static std::shared_ptr<ReceiveInfo> GetReceivedInfo(int wd, std::shared_ptr<CjCallbackObject> callback); 166 static void ReadNotifyEvent(std::shared_ptr<FileInfos> infos); 167 static std::string GetRealPath(const std::string& path); 168 static std::tuple<bool, int, bool> HandleProgress(inotify_event *event, 169 std::shared_ptr<FileInfos> infos, 170 std::shared_ptr<CjCallbackObject> callback); 171 static void ReceiveComplete(CProgress data, 172 std::shared_ptr<FileInfos> infos, 173 std::shared_ptr<CjCallbackObject> callback); 174}; 175} 176} 177 178#endif // OHOS_FILE_FS_COPY_H 179