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