/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FILEMANAGEMENT_FILE_API_COPY_H #define FILEMANAGEMENT_FILE_API_COPY_H #include #include #include #include #include "bundle_mgr_client_impl.h" #include "common_func.h" #include "filemgmt_libn.h" #include "n_async/n_ref.h" #include "task_signal.h" #include "class_tasksignal/task_signal_entity.h" namespace OHOS { namespace FileManagement { namespace ModuleFileIO { using namespace std; using namespace OHOS::FileManagement::LibN; using namespace OHOS::AppExecFwk; using namespace DistributedFS::ModuleTaskSignal; const uint64_t MAX_VALUE = 0x7FFFFFFFFFFFFFFF; struct ReceiveInfo { std::string path; // dir name std::map fileList; // filename, proceededSize }; struct JsCallbackObject { napi_env env = nullptr; LibN::NRef nRef; int32_t notifyFd = -1; int32_t eventFd = -1; std::vector>> wds; uint64_t totalSize = 0; uint64_t progressSize = 0; uint64_t maxProgressSize = 0; int32_t errorCode = 0; std::thread notifyHandler; explicit JsCallbackObject(napi_env env, LibN::NVal jsVal) : env(env), nRef(jsVal) {} void CloseFd() { if (eventFd != -1) { close(eventFd); eventFd = -1; } if (notifyFd == -1) { return; } for (auto item : wds) { inotify_rm_watch(notifyFd, item.first); } close(notifyFd); notifyFd = -1; } ~JsCallbackObject() { CloseFd(); } }; struct FileInfos { std::string srcUri; std::string destUri; std::string srcPath; std::string destPath; bool isFile = false; std::chrono::steady_clock::time_point notifyTime; int32_t notifyFd = -1; int32_t eventFd = -1; bool run = true; bool hasListener = false; napi_env env; NVal listener; NVal copySignal; std::shared_ptr taskSignal = nullptr; std::set filePaths; int exceptionCode = ERRNO_NOERR; // notify copy thread or listener thread has exceptions. bool operator==(const FileInfos &infos) const { return (srcUri == infos.srcUri && destUri == infos.destUri); } bool operator<(const FileInfos &infos) const { if (srcUri == infos.srcUri) { return destUri < infos.destUri; } return srcUri < infos.srcUri; } }; struct UvEntry { std::shared_ptr callback; std::shared_ptr fileInfos; uint64_t progressSize = 0; uint64_t totalSize = 0; UvEntry(const std::shared_ptr &cb, std::shared_ptr fileInfos) : callback(cb), fileInfos(fileInfos) { } explicit UvEntry(const std::shared_ptr &cb) : callback(cb) {} }; class Copy final { public: static napi_value Async(napi_env env, napi_callback_info info); static std::map> jsCbMap_; static void UnregisterListener(std::shared_ptr fileInfos); static std::recursive_mutex mutex_; private: // operator of napi static tuple ParseJsOperand(napi_env env, NVal pathOrFdFromJsArg); static tuple GetListenerFromOptionArg(napi_env env, const NFuncArg &funcArg); static tuple GetCopySignalFromOptionArg(napi_env env, const NFuncArg &funcArg); static int CheckOrCreatePath(const std::string &destPath); static int ParseJsParam(napi_env env, NFuncArg &funcArg, std::shared_ptr &fileInfos); // operator of local listener static int ExecLocal(std::shared_ptr infos, std::shared_ptr callback); static void CopyComplete(std::shared_ptr infos, std::shared_ptr callback); static void WaitNotifyFinished(std::shared_ptr callback); static void ReadNotifyEvent(std::shared_ptr infos); static int SubscribeLocalListener(std::shared_ptr infos, std::shared_ptr callback); static std::shared_ptr RegisterListener(napi_env env, const std::shared_ptr &infos); static void OnFileReceive(std::shared_ptr infos); static void GetNotifyEvent(std::shared_ptr infos); static void StartNotify(std::shared_ptr infos, std::shared_ptr callback); static uv_work_t *GetUVwork(std::shared_ptr infos); static void ReceiveComplete(uv_work_t *work, int stat); static std::shared_ptr GetRegisteredListener(std::shared_ptr infos); static void CloseNotifyFd(std::shared_ptr infos, std::shared_ptr callback); // operator of file static int RecurCopyDir(const string &srcPath, const string &destPath, std::shared_ptr infos); static tuple GetFileSize(const std::string &path); static uint64_t GetDirSize(std::shared_ptr infos, std::string path); static int CopyFile(const string &src, const string &dest, std::shared_ptr infos); static int MakeDir(const string &path); static int CopySubDir(const string &srcPath, const string &destPath, std::shared_ptr infos); static int CopyDirFunc(const string &src, const string &dest, std::shared_ptr infos); static tuple> CreateFileInfos( const std::string &srcUri, const std::string &destUri, NVal &listener, NVal copySignal); static int ExecCopy(std::shared_ptr infos); // operator of file size static int UpdateProgressSize(const std::string &filePath, std::shared_ptr receivedInfo, std::shared_ptr callback); static tuple HandleProgress( inotify_event *event, std::shared_ptr infos, std::shared_ptr callback); static std::shared_ptr GetReceivedInfo(int wd, std::shared_ptr callback); static bool CheckFileValid(const std::string &filePath, std::shared_ptr infos); // operator of uri or path static bool IsValidUri(const std::string &uri); static bool IsRemoteUri(const std::string &uri); static bool IsDirectory(const std::string &path); static bool IsFile(const std::string &path); static bool IsMediaUri(const std::string &uriPath); static std::string ConvertUriToPath(const std::string &uri); static std::string GetRealPath(const std::string& path); }; } // namespace ModuleFileIO } // namespace FileManagement } // namespace OHOS #endif // FILEMANAGEMENT_FILE_API_COPY_H