1 /* 2 * Copyright (c) 2023 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 FILEMANAGEMENT_FILE_API_COPY_H 17 #define FILEMANAGEMENT_FILE_API_COPY_H 18 19 #include <chrono> 20 #include <condition_variable> 21 #include <set> 22 #include <sys/inotify.h> 23 #include <thread> 24 25 #include "bundle_mgr_client_impl.h" 26 #include "common_func.h" 27 #include "filemgmt_libn.h" 28 #include "n_async/n_ref.h" 29 #include "task_signal.h" 30 #include "class_tasksignal/task_signal_entity.h" 31 32 namespace OHOS { 33 namespace FileManagement { 34 namespace ModuleFileIO { 35 using namespace std; 36 using namespace OHOS::FileManagement::LibN; 37 using namespace OHOS::AppExecFwk; 38 using namespace DistributedFS::ModuleTaskSignal; 39 const uint64_t MAX_VALUE = 0x7FFFFFFFFFFFFFFF; 40 41 struct ReceiveInfo { 42 std::string path; // dir name 43 std::map<std::string, uint64_t> fileList; // filename, proceededSize 44 }; 45 struct JsCallbackObject { 46 napi_env env = nullptr; 47 LibN::NRef nRef; 48 int32_t notifyFd = -1; 49 int32_t eventFd = -1; 50 std::vector<std::pair<int, std::shared_ptr<ReceiveInfo>>> wds; 51 uint64_t totalSize = 0; 52 uint64_t progressSize = 0; 53 uint64_t maxProgressSize = 0; 54 int32_t errorCode = 0; 55 std::thread notifyHandler; 56 std::mutex readMutex; 57 std::condition_variable cv; 58 std::mutex cvLock; 59 bool reading = false; 60 bool closed = false; JsCallbackObjectJsCallbackObject61 explicit JsCallbackObject(napi_env env, LibN::NVal jsVal) : env(env), nRef(jsVal) {} 62 CloseFdJsCallbackObject63 void CloseFd() 64 { 65 if (eventFd != -1) { 66 close(eventFd); 67 eventFd = -1; 68 } 69 if (notifyFd == -1) { 70 return; 71 } 72 for (auto item : wds) { 73 inotify_rm_watch(notifyFd, item.first); 74 } 75 close(notifyFd); 76 notifyFd = -1; 77 } 78 ~JsCallbackObjectJsCallbackObject79 ~JsCallbackObject() 80 { 81 CloseFd(); 82 } 83 }; 84 85 struct FileInfos { 86 std::string srcUri; 87 std::string destUri; 88 std::string srcPath; 89 std::string destPath; 90 bool isFile = false; 91 std::chrono::steady_clock::time_point notifyTime; 92 int32_t notifyFd = -1; 93 int32_t eventFd = -1; 94 bool run = true; 95 bool hasListener = false; 96 napi_env env; 97 NVal listener; 98 NVal copySignal; 99 std::shared_ptr<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 FileInfos &infos) const 103 { 104 return (srcUri == infos.srcUri && destUri == infos.destUri); 105 } 106 bool operator<(const FileInfos &infos) const 107 { 108 if (srcUri == infos.srcUri) { 109 return destUri < infos.destUri; 110 } 111 return srcUri < infos.srcUri; 112 } 113 }; 114 115 struct UvEntry { 116 std::shared_ptr<JsCallbackObject> callback; 117 std::shared_ptr<FileInfos> fileInfos; 118 uint64_t progressSize = 0; 119 uint64_t totalSize = 0; UvEntryUvEntry120 UvEntry(const std::shared_ptr<JsCallbackObject> &cb, std::shared_ptr<FileInfos> fileInfos) 121 : callback(cb), fileInfos(fileInfos) 122 { 123 } UvEntryUvEntry124 explicit UvEntry(const std::shared_ptr<JsCallbackObject> &cb) : callback(cb) {} 125 }; 126 127 class Copy final { 128 public: 129 static napi_value Async(napi_env env, napi_callback_info info); 130 static std::map<FileInfos, std::shared_ptr<JsCallbackObject>> jsCbMap_; 131 static void UnregisterListener(std::shared_ptr<FileInfos> fileInfos); 132 static std::recursive_mutex mutex_; 133 134 private: 135 // operator of napi 136 static tuple<bool, std::string> ParseJsOperand(napi_env env, NVal pathOrFdFromJsArg); 137 static tuple<bool, NVal> GetListenerFromOptionArg(napi_env env, const NFuncArg &funcArg); 138 static tuple<bool, NVal> GetCopySignalFromOptionArg(napi_env env, const NFuncArg &funcArg); 139 static int CheckOrCreatePath(const std::string &destPath); 140 static int ParseJsParam(napi_env env, NFuncArg &funcArg, std::shared_ptr<FileInfos> &fileInfos); 141 142 // operator of local listener 143 static int ExecLocal(std::shared_ptr<FileInfos> infos, std::shared_ptr<JsCallbackObject> callback); 144 static void CopyComplete(std::shared_ptr<FileInfos> infos, std::shared_ptr<JsCallbackObject> callback); 145 static void WaitNotifyFinished(std::shared_ptr<JsCallbackObject> callback); 146 static void ReadNotifyEvent(std::shared_ptr<FileInfos> infos); 147 static void ReadNotifyEventLocked(std::shared_ptr<FileInfos> infos, std::shared_ptr<JsCallbackObject> callback); 148 static int SubscribeLocalListener(std::shared_ptr<FileInfos> infos, std::shared_ptr<JsCallbackObject> callback); 149 static std::shared_ptr<JsCallbackObject> RegisterListener(napi_env env, const std::shared_ptr<FileInfos> &infos); 150 static void OnFileReceive(std::shared_ptr<FileInfos> infos); 151 static void GetNotifyEvent(std::shared_ptr<FileInfos> infos); 152 static void StartNotify(std::shared_ptr<FileInfos> infos, std::shared_ptr<JsCallbackObject> callback); 153 static UvEntry *GetUVwork(std::shared_ptr<FileInfos> infos); 154 static void ReceiveComplete(std::shared_ptr<UvEntry> entry); 155 static std::shared_ptr<JsCallbackObject> GetRegisteredListener(std::shared_ptr<FileInfos> infos); 156 static void CloseNotifyFd(std::shared_ptr<FileInfos> infos, std::shared_ptr<JsCallbackObject> callback); 157 static void CloseNotifyFdLocked(std::shared_ptr<FileInfos> infos, std::shared_ptr<JsCallbackObject> callback); 158 159 // operator of file 160 static int RecurCopyDir(const string &srcPath, const string &destPath, std::shared_ptr<FileInfos> infos); 161 static tuple<int, uint64_t> GetFileSize(const std::string &path); 162 static uint64_t GetDirSize(std::shared_ptr<FileInfos> infos, std::string path); 163 static int CopyFile(const string &src, const string &dest, std::shared_ptr<FileInfos> infos); 164 static int MakeDir(const string &path); 165 static int CopySubDir(const string &srcPath, const string &destPath, std::shared_ptr<FileInfos> infos); 166 static int CopyDirFunc(const string &src, const string &dest, std::shared_ptr<FileInfos> infos); 167 static tuple<int, std::shared_ptr<FileInfos>> CreateFileInfos( 168 const std::string &srcUri, const std::string &destUri, NVal &listener, NVal copySignal); 169 static int ExecCopy(std::shared_ptr<FileInfos> infos); 170 171 // operator of file size 172 static int UpdateProgressSize(const std::string &filePath, 173 std::shared_ptr<ReceiveInfo> receivedInfo, 174 std::shared_ptr<JsCallbackObject> callback); 175 static tuple<bool, int, bool> HandleProgress( 176 inotify_event *event, std::shared_ptr<FileInfos> infos, std::shared_ptr<JsCallbackObject> callback); 177 static std::shared_ptr<ReceiveInfo> GetReceivedInfo(int wd, std::shared_ptr<JsCallbackObject> callback); 178 static bool CheckFileValid(const std::string &filePath, std::shared_ptr<FileInfos> infos); 179 180 // operator of uri or path 181 static bool IsValidUri(const std::string &uri); 182 static bool IsRemoteUri(const std::string &uri); 183 static bool IsDirectory(const std::string &path); 184 static bool IsFile(const std::string &path); 185 static bool IsMediaUri(const std::string &uriPath); 186 static std::string ConvertUriToPath(const std::string &uri); 187 static std::string GetRealPath(const std::string& path); 188 }; 189 } // namespace ModuleFileIO 190 } // namespace FileManagement 191 } // namespace OHOS 192 193 #endif // FILEMANAGEMENT_FILE_API_COPY_H