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