1 /* 2 * Copyright (c) 2025 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 INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_CORE_H 17 #define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_CORE_H 18 19 #include <chrono> 20 #include <condition_variable> 21 #include <set> 22 #include <thread> 23 #include <sys/inotify.h> 24 25 #include "bundle_mgr_client_impl.h" 26 #include "filemgmt_libfs.h" 27 #include "filemgmt_libhilog.h" 28 #include "fs_task_signal.h" 29 #include "i_progress_listener.h" 30 31 namespace OHOS { 32 namespace FileManagement { 33 namespace ModuleFileIO { 34 using namespace std; 35 using namespace OHOS::AppExecFwk; 36 using namespace DistributedFS::ModuleTaskSignal; 37 38 struct CopyOptions { 39 shared_ptr<IProgressListener> progressListener; 40 FsTaskSignal* copySignal = nullptr; 41 }; 42 43 struct ReceiveInfo { 44 std::string path; // dir name 45 std::map<std::string, uint64_t> fileList; // filename, proceededSize 46 }; 47 48 struct FsCallbackObject { 49 std::shared_ptr<IProgressListener> listener = nullptr; 50 int32_t notifyFd = -1; 51 int32_t eventFd = -1; 52 std::vector<std::pair<int, std::shared_ptr<ReceiveInfo>>> wds; 53 uint64_t totalSize = 0; 54 uint64_t progressSize = 0; 55 uint64_t maxProgressSize = 0; 56 int32_t errorCode = 0; 57 std::thread notifyHandler; 58 std::mutex readMutex; 59 std::condition_variable cv; 60 std::mutex cvLock; 61 bool reading = false; 62 bool closed = false; FsCallbackObjectFsCallbackObject63 explicit FsCallbackObject(std::shared_ptr<IProgressListener> listener) : listener(listener) {} 64 CloseFdFsCallbackObject65 void CloseFd() 66 { 67 if (eventFd != -1) { 68 close(eventFd); 69 eventFd = -1; 70 } 71 if (notifyFd == -1) { 72 return; 73 } 74 for (auto item : wds) { 75 inotify_rm_watch(notifyFd, item.first); 76 } 77 close(notifyFd); 78 notifyFd = -1; 79 } 80 ~FsCallbackObjectFsCallbackObject81 ~FsCallbackObject() 82 { 83 CloseFd(); 84 } 85 }; 86 87 struct FsFileInfos { 88 std::string srcUri; 89 std::string destUri; 90 std::string srcPath; 91 std::string destPath; 92 bool isFile = false; 93 std::chrono::steady_clock::time_point notifyTime; 94 int32_t notifyFd = -1; 95 int32_t eventFd = -1; 96 bool run = true; 97 bool hasListener = false; 98 std::shared_ptr<IProgressListener> listener = nullptr; 99 TaskSignal* taskSignal = nullptr; 100 std::set<std::string> filePaths; 101 int exceptionCode = ERRNO_NOERR; // notify copy thread or listener thread has exceptions. 102 bool operator==(const FsFileInfos &infos) const 103 { 104 return (srcUri == infos.srcUri && destUri == infos.destUri); 105 } 106 bool operator<(const FsFileInfos &infos) const 107 { 108 if (srcUri == infos.srcUri) { 109 return destUri < infos.destUri; 110 } 111 return srcUri < infos.srcUri; 112 } 113 }; 114 115 struct FsUvEntry { 116 std::shared_ptr<FsCallbackObject> callback; 117 std::shared_ptr<FsFileInfos> fileInfos; 118 uint64_t progressSize = 0; 119 uint64_t totalSize = 0; FsUvEntryFsUvEntry120 FsUvEntry(const std::shared_ptr<FsCallbackObject> &cb, std::shared_ptr<FsFileInfos> fileInfos) 121 : callback(cb), fileInfos(fileInfos) {} 122 FsUvEntryFsUvEntry123 explicit FsUvEntry(const std::shared_ptr<FsCallbackObject> &cb) : callback(cb) {} 124 }; 125 126 class CopyCore final { 127 public: 128 static FsResult<void> DoCopy(const string &src, const string &dest, std::optional<CopyOptions> &options); 129 130 private: 131 // operator of params 132 static bool ValidOperand(std::string uriStr); 133 static int CheckOrCreatePath(const std::string &destPath); 134 static bool ValidParams(const string &src, const string &dest); 135 136 // operator of local listener 137 static std::shared_ptr<FsCallbackObject> RegisterListener(const std::shared_ptr<FsFileInfos> &infos); 138 static std::shared_ptr<FsCallbackObject> GetRegisteredListener(std::shared_ptr<FsFileInfos> infos); 139 static void UnregisterListener(std::shared_ptr<FsFileInfos> fileInfos); 140 static int ExecLocal(std::shared_ptr<FsFileInfos> infos, std::shared_ptr<FsCallbackObject> callback); 141 static void CopyComplete(std::shared_ptr<FsFileInfos> infos, std::shared_ptr<FsCallbackObject> callback); 142 static void WaitNotifyFinished(std::shared_ptr<FsCallbackObject> callback); 143 static void ReadNotifyEvent(std::shared_ptr<FsFileInfos> infos); 144 static void ReadNotifyEventLocked(std::shared_ptr<FsFileInfos> infos, std::shared_ptr<FsCallbackObject> callback); 145 static int SubscribeLocalListener(std::shared_ptr<FsFileInfos> infos, std::shared_ptr<FsCallbackObject> callback); 146 static void OnFileReceive(std::shared_ptr<FsFileInfos> infos); 147 static void GetNotifyEvent(std::shared_ptr<FsFileInfos> infos); 148 static void StartNotify(std::shared_ptr<FsFileInfos> infos, std::shared_ptr<FsCallbackObject> callback); 149 static FsUvEntry *GetUVEntry(std::shared_ptr<FsFileInfos> infos); 150 static void ReceiveComplete(std::shared_ptr<FsUvEntry> entry); 151 static void CloseNotifyFd(std::shared_ptr<FsFileInfos> infos, std::shared_ptr<FsCallbackObject> callback); 152 static void CloseNotifyFdLocked(std::shared_ptr<FsFileInfos> infos, std::shared_ptr<FsCallbackObject> callback); 153 154 // operator of file 155 static int RecurCopyDir(const string &srcPath, const string &destPath, std::shared_ptr<FsFileInfos> infos); 156 static tuple<int, uint64_t> GetFileSize(const std::string &path); 157 static uint64_t GetDirSize(std::shared_ptr<FsFileInfos> infos, std::string path); 158 static int CopyFile(const string &src, const string &dest, std::shared_ptr<FsFileInfos> infos); 159 static int MakeDir(const string &path); 160 static int CopySubDir(const string &srcPath, const string &destPath, std::shared_ptr<FsFileInfos> infos); 161 static int CopyDirFunc(const string &src, const string &dest, std::shared_ptr<FsFileInfos> infos); 162 static tuple<int, std::shared_ptr<FsFileInfos>> CreateFileInfos( 163 const std::string &srcUri, const std::string &destUri, const std::optional<CopyOptions> &options); 164 static int ExecCopy(std::shared_ptr<FsFileInfos> infos); 165 166 // operator of file size 167 static int UpdateProgressSize(const std::string &filePath, std::shared_ptr<ReceiveInfo> receivedInfo, 168 std::shared_ptr<FsCallbackObject> callback); 169 static tuple<bool, int, bool> HandleProgress( 170 inotify_event *event, std::shared_ptr<FsFileInfos> infos, std::shared_ptr<FsCallbackObject> callback); 171 static std::shared_ptr<ReceiveInfo> GetReceivedInfo(int wd, std::shared_ptr<FsCallbackObject> callback); 172 static bool CheckFileValid(const std::string &filePath, std::shared_ptr<FsFileInfos> infos); 173 174 // operator of uri or path 175 static bool IsValidUri(const std::string &uri); 176 static bool IsRemoteUri(const std::string &uri); 177 static bool IsDirectory(const std::string &path); 178 static bool IsFile(const std::string &path); 179 static bool IsMediaUri(const std::string &uriPath); 180 static std::string ConvertUriToPath(const std::string &uri); 181 static std::string GetRealPath(const std::string &path); 182 183 static std::recursive_mutex mutex_; 184 static std::map<FsFileInfos, std::shared_ptr<FsCallbackObject>> callbackMap_; 185 }; 186 } // namespace ModuleFileIO 187 } // namespace FileManagement 188 } // namespace OHOS 189 190 #endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_CORE_H