From 301a23eefb46eb7f78ed9d4a23cb4a33eeffdb32 Mon Sep 17 00:00:00 2001 From: caochuan Date: Thu, 12 Jan 2023 12:21:02 +0800 Subject: [PATCH] feat: add copy interface for faf Signed-off-by: caochuan --- filemanagement_aafwk.gni | 5 ++ frameworks/innerkits/file_access/BUILD.gn | 2 + .../include/file_access_ext_ability.h | 1 + .../include/file_access_ext_proxy.h | 1 + .../include/file_access_ext_stub.h | 1 + .../include/file_access_ext_stub_impl.h | 1 + .../include/file_access_extension_info.h | 49 ++++++++++ .../file_access/include/file_access_helper.h | 1 + .../include/ifile_access_ext_base.h | 2 + .../src/file_access_ext_ability.cpp | 6 ++ .../file_access/src/file_access_ext_proxy.cpp | 66 ++++++++++++++ .../file_access/src/file_access_ext_stub.cpp | 53 +++++++++++ .../src/file_access_ext_stub_impl.cpp | 13 +++ .../file_access/src/file_access_helper.cpp | 86 ++++++++++++++++++ .../medialibrary_file_access_test.cpp | 41 ++++++++- .../napi_fileaccess_helper.cpp | 90 +++++++++++++++++++ .../napi_fileaccess_helper.h | 1 + utils/file_access_framework_errno.h | 50 ++++++++++- utils/napi_error.h | 12 +++ 19 files changed, 479 insertions(+), 2 deletions(-) diff --git a/filemanagement_aafwk.gni b/filemanagement_aafwk.gni index 67a8ad86..a165e465 100644 --- a/filemanagement_aafwk.gni +++ b/filemanagement_aafwk.gni @@ -17,3 +17,8 @@ ability_runtime_kits_path = "${ability_runtime_path}/frameworks/kits" ability_runtime_services_path = "${ability_runtime_path}/services" ability_runtime_napi_path = "${ability_runtime_path}/frameworks/js/napi" access_token_path = "//base/security/access_token" +foundation_f = "/f" +foundation_oundation = "oundation" +filemanagement = "filemanagement" +file_api = "file_api" +file_api_path = "/${foundation_f}${foundation_oundation}/${filemanagement}/${file_api}" diff --git a/frameworks/innerkits/file_access/BUILD.gn b/frameworks/innerkits/file_access/BUILD.gn index a470e321..409f4b0b 100644 --- a/frameworks/innerkits/file_access/BUILD.gn +++ b/frameworks/innerkits/file_access/BUILD.gn @@ -31,6 +31,7 @@ config("ability_config") { "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", "//foundation/bundlemanager/bundle_framework/interfaces/inner_api/appexecfwk_base/include", "//foundation/distributeddatamgr/distributedfile/interfaces/kits/js/src/common", + "${file_api_path}/interfaces/kits/native/remote_uri", ] cflags = [] @@ -81,6 +82,7 @@ ohos_shared_library("file_access_extension_ability_kit") { "${ability_runtime_path}/frameworks/native/ability/native:abilitykit_native", "${ability_runtime_path}/frameworks/native/appkit:app_context", "${access_token_path}/interfaces/innerkits/accesstoken:libtokenid_sdk", + "${file_api_path}/interfaces/kits/native:remote_uri_native", ] external_deps = [ diff --git a/frameworks/innerkits/file_access/include/file_access_ext_ability.h b/frameworks/innerkits/file_access/include/file_access_ext_ability.h index 22e4194d..d6cc2d42 100644 --- a/frameworks/innerkits/file_access/include/file_access_ext_ability.h +++ b/frameworks/innerkits/file_access/include/file_access_ext_ability.h @@ -47,6 +47,7 @@ public: virtual int Mkdir(const Uri &parent, const std::string &displayName, Uri &newFile); virtual int Delete(const Uri &sourceFile); virtual int Move(const Uri &sourceFile, const Uri &targetParent, Uri &newFile); + virtual int Copy(const std::vector &srcUriVect, const Uri &destUri, std::vector &result); virtual int Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile); virtual int ListFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount, const FileFilter &filter, std::vector &fileInfoVec); diff --git a/frameworks/innerkits/file_access/include/file_access_ext_proxy.h b/frameworks/innerkits/file_access/include/file_access_ext_proxy.h index 0b125108..dccb4725 100644 --- a/frameworks/innerkits/file_access/include/file_access_ext_proxy.h +++ b/frameworks/innerkits/file_access/include/file_access_ext_proxy.h @@ -41,6 +41,7 @@ public: virtual int Mkdir(const Uri &parent, const std::string &displayName, Uri &newFile) override; virtual int Delete(const Uri &sourceFile) override; virtual int Move(const Uri &sourceFile, const Uri &targetParent, Uri &newFile) override; + virtual int Copy(const std::vector &srcUriVect, const Uri &destUri, std::vector &result) override; virtual int Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile) override; virtual int ListFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount, const FileFilter &filter, std::vector &fileInfoVec) override; diff --git a/frameworks/innerkits/file_access/include/file_access_ext_stub.h b/frameworks/innerkits/file_access/include/file_access_ext_stub.h index 7d966173..fb179f75 100644 --- a/frameworks/innerkits/file_access/include/file_access_ext_stub.h +++ b/frameworks/innerkits/file_access/include/file_access_ext_stub.h @@ -40,6 +40,7 @@ private: ErrCode CmdMkdir(MessageParcel &data, MessageParcel &reply); ErrCode CmdDelete(MessageParcel &data, MessageParcel &reply); ErrCode CmdMove(MessageParcel &data, MessageParcel &reply); + ErrCode CmdCopy(MessageParcel &data, MessageParcel &reply); ErrCode CmdRename(MessageParcel &data, MessageParcel &reply); ErrCode CmdListFile(MessageParcel &data, MessageParcel &reply); ErrCode CmdScanFile(MessageParcel &data, MessageParcel &reply); diff --git a/frameworks/innerkits/file_access/include/file_access_ext_stub_impl.h b/frameworks/innerkits/file_access/include/file_access_ext_stub_impl.h index 5a9fa8a2..d8352e82 100644 --- a/frameworks/innerkits/file_access/include/file_access_ext_stub_impl.h +++ b/frameworks/innerkits/file_access/include/file_access_ext_stub_impl.h @@ -39,6 +39,7 @@ public: int Mkdir(const Uri &parent, const std::string &displayName, Uri &newFile) override; int Delete(const Uri &sourceFile) override; int Move(const Uri &sourceFile, const Uri &targetParent, Uri &newFile) override; + int Copy(const std::vector &srcUriVect, const Uri &destUri, std::vector &result) override; int Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile) override; int ListFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount, const FileFilter &filter, std::vector &fileInfoVec) override; diff --git a/frameworks/innerkits/file_access/include/file_access_extension_info.h b/frameworks/innerkits/file_access/include/file_access_extension_info.h index ea6a4106..6036292f 100644 --- a/frameworks/innerkits/file_access/include/file_access_extension_info.h +++ b/frameworks/innerkits/file_access/include/file_access_extension_info.h @@ -159,6 +159,55 @@ public: return info; } }; + +struct CopyResult : public virtual OHOS::Parcelable { +public: + std::string uri { "" }; + int32_t errCode { 0 }; + std::string errMsg { "" }; + + CopyResult() = default; + CopyResult(std::string uri, int32_t errCode, std::string errMsg) + : uri(uri), errCode(errCode), errMsg(errMsg) + {} + + bool ReadFromParcel(Parcel &parcel) + { + uri = parcel.ReadString(); + errCode = parcel.ReadInt32(); + errMsg = parcel.ReadString(); + return true; + } + + virtual bool Marshalling(Parcel &parcel) const override + { + if (!parcel.WriteString(uri)) { + return false; + } + if (!parcel.WriteInt32(errCode)) { + return false; + } + if (!parcel.WriteString(errMsg)) { + return false; + } + return true; + } + + static CopyResult *Unmarshalling(Parcel &parcel) + { + CopyResult *result = new (std::nothrow)CopyResult(); + if (result == nullptr) { + return nullptr; + } + + if (!result->ReadFromParcel(parcel)) { + delete result; + result = nullptr; + } + return result; + } +}; + } // namespace FileAccessFwk } // namespace OHOS #endif // FILE_ACCESS_EXTENSION_INFO_H \ No newline at end of file diff --git a/frameworks/innerkits/file_access/include/file_access_helper.h b/frameworks/innerkits/file_access/include/file_access_helper.h index 4a602e62..d18ade14 100644 --- a/frameworks/innerkits/file_access/include/file_access_helper.h +++ b/frameworks/innerkits/file_access/include/file_access_helper.h @@ -73,6 +73,7 @@ public: int Mkdir(Uri &parent, const std::string &displayName, Uri &newDir); int Delete(Uri &selectFile); int Move(Uri &sourceFile, Uri &targetParent, Uri &newFile); + int Copy(std::vector &srcUriVect, Uri &destUri, std::vector &result); int Rename(Uri &sourceFile, const std::string &displayName, Uri &newFile); int ListFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount, const FileFilter &filter, std::vector &fileInfoVec); diff --git a/frameworks/innerkits/file_access/include/ifile_access_ext_base.h b/frameworks/innerkits/file_access/include/ifile_access_ext_base.h index cffceff0..63745f79 100644 --- a/frameworks/innerkits/file_access/include/ifile_access_ext_base.h +++ b/frameworks/innerkits/file_access/include/ifile_access_ext_base.h @@ -41,6 +41,7 @@ public: CMD_MKDIR, CMD_DELETE, CMD_MOVE, + CMD_COPY, CMD_RENAME, CMD_LIST_FILE, CMD_SCAN_FILE, @@ -56,6 +57,7 @@ public: virtual int Mkdir(const Uri &parent, const std::string &displayName, Uri &newFile) = 0; virtual int Delete(const Uri &sourceFile) = 0; virtual int Move(const Uri &sourceFile, const Uri &targetParent, Uri &newFile) = 0; + virtual int Copy(const std::vector &srcUriVect, const Uri &destUri, std::vector &result) = 0; virtual int Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile) = 0; virtual int ListFile(const FileInfo &fileInfo, const int64_t offset, const int64_t maxCount, const FileFilter &filter, std::vector &fileInfoVec) = 0; diff --git a/frameworks/innerkits/file_access/src/file_access_ext_ability.cpp b/frameworks/innerkits/file_access/src/file_access_ext_ability.cpp index 9856ec8a..e0960f60 100644 --- a/frameworks/innerkits/file_access/src/file_access_ext_ability.cpp +++ b/frameworks/innerkits/file_access/src/file_access_ext_ability.cpp @@ -91,6 +91,12 @@ int FileAccessExtAbility::Move(const Uri &sourceFile, const Uri &targetParent, U return ERR_OPERATION_NOT_SUPPORT; } +int FileAccessExtAbility::Copy(const std::vector &srcUriVect, const Uri &destUri, std::vector &result) +{ + HILOG_ERROR("FileAccessExtAbility::Copy Undefined operation"); + return ERR_OPERATION_NOT_SUPPORT; +} + int FileAccessExtAbility::Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile) { HILOG_ERROR("FileAccessExtAbility::Rename Undefined operation"); diff --git a/frameworks/innerkits/file_access/src/file_access_ext_proxy.cpp b/frameworks/innerkits/file_access/src/file_access_ext_proxy.cpp index 867f04b4..4f2af618 100644 --- a/frameworks/innerkits/file_access/src/file_access_ext_proxy.cpp +++ b/frameworks/innerkits/file_access/src/file_access_ext_proxy.cpp @@ -307,6 +307,72 @@ int FileAccessExtProxy::Move(const Uri &sourceFile, const Uri &targetParent, Uri return ERR_OK; } +int FileAccessExtProxy::Copy(const std::vector &srcUriVect, const Uri &destUri, std::vector &result) +{ + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Copy"); + MessageParcel data; + if (!data.WriteInterfaceToken(FileAccessExtProxy::GetDescriptor())) { + HILOG_ERROR("WriteInterfaceToken failed"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_PARCEL_FAIL; + } + + if (!data.WriteInt32(srcUriVect.size())) { + HILOG_ERROR("fail to WriteParcelable size of srcUriVect"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_PARCEL_FAIL; + } + + for (auto &uri: srcUriVect) { + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_PARCEL_FAIL; + } + } + + if (!data.WriteParcelable(&destUri)) { + HILOG_ERROR("fail to WriteParcelable targetParent"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_PARCEL_FAIL; + } + + MessageParcel reply; + MessageOption option; + int err = Remote()->SendRequest(CMD_COPY, data, reply, option); + if (err != ERR_OK) { + HILOG_ERROR("fail to SendRequest. err: %{public}d", err); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return err; + } + + int copyRet = ERR_PARCEL_FAIL; + if (!reply.ReadInt32(copyRet)) { // 成功失败 + HILOG_ERROR("fail to ReadInt32 ret"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_PARCEL_FAIL; + } + + int count = 0; + if (!reply.ReadInt32(count)) { // vector元素个数 + HILOG_ERROR("Copy operation failed to Read count"); + return ERR_INVALID_RESULT; + } + + result.clear(); + for (int i = 0; i < count; i++) { // read CopyResult + std::unique_ptr copyResultPtr(reply.ReadParcelable()); + if (copyResultPtr != nullptr) { + // FIXME: 转换成通用错误码和错误msg, 应该在媒体库zuo + result.push_back(std::move(*copyResultPtr)); + } + } + + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return copyRet; + +} + int FileAccessExtProxy::Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile) { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Rename"); diff --git a/frameworks/innerkits/file_access/src/file_access_ext_stub.cpp b/frameworks/innerkits/file_access/src/file_access_ext_stub.cpp index e99785d2..840882d5 100644 --- a/frameworks/innerkits/file_access/src/file_access_ext_stub.cpp +++ b/frameworks/innerkits/file_access/src/file_access_ext_stub.cpp @@ -45,6 +45,7 @@ FileAccessExtStub::FileAccessExtStub() stubFuncMap_[CMD_MKDIR] = &FileAccessExtStub::CmdMkdir; stubFuncMap_[CMD_DELETE] = &FileAccessExtStub::CmdDelete; stubFuncMap_[CMD_MOVE] = &FileAccessExtStub::CmdMove; + stubFuncMap_[CMD_COPY] = &FileAccessExtStub::CmdCopy; stubFuncMap_[CMD_RENAME] = &FileAccessExtStub::CmdRename; stubFuncMap_[CMD_LIST_FILE] = &FileAccessExtStub::CmdListFile; stubFuncMap_[CMD_SCAN_FILE] = &FileAccessExtStub::CmdScanFile; @@ -269,6 +270,58 @@ ErrCode FileAccessExtStub::CmdMove(MessageParcel &data, MessageParcel &reply) return ERR_OK; } +ErrCode FileAccessExtStub::CmdCopy(MessageParcel &data, MessageParcel &reply) +{ + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "CmdCopy"); + int count = 0; + if (!data.ReadInt32(count)) { + HILOG_ERROR("parameter Copy fail to read size of srcUriVect"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_PARCEL_FAIL; + } + + std::vector srcUriVect; + for (int i = 0; i < count; i++) { + std::unique_ptr uriPtr(data.ReadParcelable()); + if (uriPtr != nullptr) { + srcUriVect.push_back(std::move(*uriPtr)); + } + } + + std::unique_ptr uriPtr(data.ReadParcelable()); + if (uriPtr == nullptr) { + HILOG_ERROR("Parameter Copy fail to ReadParcelable destDir"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_PARCEL_FAIL; + } + Uri destUri (*uriPtr); + + std::vector result; + int ret = Copy(srcUriVect, destUri, result); + if (!reply.WriteInt32(ret)) { + HILOG_ERROR("Parameter Copy fail to WriteInt32 ret"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_PARCEL_FAIL; + } + + if (!reply.WriteInt32(result.size())) { + HILOG_ERROR("fail to WriteParcelable size of result"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_PARCEL_FAIL; + } + + for (auto &r: result) { + if (!reply.WriteParcelable(&r)) { + HILOG_ERROR("fail to WriteParcelable uri"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_PARCEL_FAIL; + } + } + + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_OK; +} + ErrCode FileAccessExtStub::CmdRename(MessageParcel &data, MessageParcel &reply) { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "CmdRename"); diff --git a/frameworks/innerkits/file_access/src/file_access_ext_stub_impl.cpp b/frameworks/innerkits/file_access/src/file_access_ext_stub_impl.cpp index 5686bcaf..3dc5b226 100644 --- a/frameworks/innerkits/file_access/src/file_access_ext_stub_impl.cpp +++ b/frameworks/innerkits/file_access/src/file_access_ext_stub_impl.cpp @@ -98,6 +98,19 @@ int FileAccessExtStubImpl::Move(const Uri &sourceFile, const Uri &targetParent, return ret; } +int FileAccessExtStubImpl::Copy(const std::vector &srcUriVect, const Uri &destUri, std::vector &result) +{ + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Copy"); + if (extension_ == nullptr) { + HILOG_ERROR("Copy get extension failed."); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_IPC_ERROR; + } + int ret = extension_->Copy(srcUriVect, destUri, result); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ret; +} + int FileAccessExtStubImpl::Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile) { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Rename"); diff --git a/frameworks/innerkits/file_access/src/file_access_helper.cpp b/frameworks/innerkits/file_access/src/file_access_helper.cpp index a1471d7b..cefedc64 100644 --- a/frameworks/innerkits/file_access/src/file_access_helper.cpp +++ b/frameworks/innerkits/file_access/src/file_access_helper.cpp @@ -26,6 +26,7 @@ #include "iservice_registry.h" #include "system_ability_definition.h" #include "tokenid_kit.h" +#include "remote_uri.h" namespace OHOS { namespace FileAccessFwk { @@ -588,6 +589,91 @@ int FileAccessHelper::Move(Uri &sourceFile, Uri &targetParent, Uri &newFile) return ERR_OK; } +bool IsMediaUri(Uri &uri) +{ + string path = uri.GetPath(); + std::size_t len = MEDIA_BNUDLE_NAME_ALIAS.length(); + if (path.length() > len) { + string media = path.substr(0, len); + return (media == MEDIA_BNUDLE_NAME_ALIAS); + } + return false; +} +/* +bool IsMediaUri(Uri &uri) +{ + std::string bundleName; + if (!GetBundleNameFromPath(uri.GetPath(), bundleName)) { + HILOG_ERROR("Get BundleName failed."); + return nullptr; + } + return (bundleName.compare(MEDIA_BNUDLE_NAME) == 0); +} +*/ + +int FileAccessHelper::Copy(std::vector &srcUriVect, Uri &destUri, std::vector &result) +{ + StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Copy"); + if (!IsSystemApp()) { + HILOG_ERROR("FileAccessHelper::Copy check IsSystemAppByFullTokenID failed"); + return E_PERMISSION_SYS; + } + + if (!CheckUri(destUri)) { + HILOG_ERROR("destUri format check error."); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_INVALID_URI; + } + + std::vector srcExternalUri, srcMediaUri; + for (auto &uri : srcUriVect) { + if (!CheckUri(uri)) { + HILOG_ERROR("srcUriVect format check error."); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_INVALID_URI; + } + + if (IsMediaUri(uri)) { + srcMediaUri.push_back(uri); + } else { //else if (IsExternalUri(uri)) { + srcExternalUri.push_back(uri); + } + } + + if (IsMediaUri(destUri)) { + sptr mediaFileExtProxy = GetProxyByUri(destUri); + if (mediaFileExtProxy == nullptr) { + HILOG_ERROR("failed with invalid fileAccessExtProxy"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_IPC_ERROR; + } + + if (!srcMediaUri.empty()) { + int ret = mediaFileExtProxy->Copy(srcMediaUri, destUri, result); + if (ret != ERR_OK) { + HILOG_ERROR("Copy get result error, code:%{public}d", ret); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ret; + } + } + if (!srcExternalUri.empty()) { + /* + externalFileExtProxy = GetProxyByUri(srcExternalUri.at(0)); + if (externalFileExtProxy == nullptr) { + HILOG_ERROR("failed with invalid fileAccessExtProxy"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_IPC_ERROR; + } + */ + // srcExternalUri的proxy调用read,媒体库的调用write,大文件可能有性能问题 + } + }// else if (OHOS::DistributedFS::ModuleRemoteUri::RemoteUri::IsRemoteUri(destUri)) {} + + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ERR_OK; + +} + int FileAccessHelper::Rename(Uri &sourceFile, const std::string &displayName, Uri &newFile) { StartTrace(HITRACE_TAG_FILEMANAGEMENT, "Rename"); diff --git a/frameworks/innerkits/file_access/test/unittest/medialibrary_file_access_test.cpp b/frameworks/innerkits/file_access/test/unittest/medialibrary_file_access_test.cpp index 600329bd..ba77842f 100644 --- a/frameworks/innerkits/file_access/test/unittest/medialibrary_file_access_test.cpp +++ b/frameworks/innerkits/file_access/test/unittest/medialibrary_file_access_test.cpp @@ -1372,6 +1372,45 @@ HWTEST_F(FileAccessHelperTest, medialibrary_file_access_Move_0011, testing::ext: GTEST_LOG_(INFO) << "FileAccessHelperTest-end medialibrary_file_access_Move_0011"; } +/** + * @tc.number: user_file_service_medialibrary_file_access_Copy_0000 + * @tc.name: medialibrary_file_access_Copy_0000 + * @tc.desc: Test function of Copy interface + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: SR000H0386 + */ +HWTEST_F(FileAccessHelperTest, medialibrary_file_access_Copy_0000, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FileAccessHelperTest-begin medialibrary_file_access_Copy_0000"; + try { + Uri parentUri = GetParentUri(); + Uri aUri{""}; + std::string displayName = "a.txt"; + int result = g_fah->CreateFile(parentUri, displayName, aUri); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + Uri bUri{""}; + displayName = "b.txt"; + result = g_fah->CreateFile(parentUri, displayName, bUri); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + + Uri copyTestDirUri(""); + result = g_fah->Mkdir(parentUri, "copy_test", copyTestDirUri); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + + vector uriVect {aUri, bUri}; + vector resultVect; + result = g_fah->Copy(uriVect, copyTestDirUri, resultVect); + + result = g_fah->Delete(copyTestDirUri); + EXPECT_GE(result, OHOS::FileAccessFwk::ERR_OK); + } catch (...) { + GTEST_LOG_(ERROR) << "medialibrary_file_access_Copy_0000 occurs an exception."; + } + GTEST_LOG_(INFO) << "FileAccessHelperTest-end medialibrary_file_access_Copy_0000"; +} + /** * @tc.number: user_file_service_medialibrary_file_access_Rename_0000 * @tc.name: medialibrary_file_access_Rename_0000 @@ -2139,4 +2178,4 @@ HWTEST_F(FileAccessHelperTest, medialibrary_file_access_GetRoots_0000, testing:: } GTEST_LOG_(INFO) << "FileAccessHelperTest-end medialibrary_file_access_GetRoots_0000"; } -} // namespace \ No newline at end of file +} // namespace diff --git a/interfaces/kits/napi/file_access_module/napi_fileaccess_helper.cpp b/interfaces/kits/napi/file_access_module/napi_fileaccess_helper.cpp index 59b4fc4d..1eedb7d2 100644 --- a/interfaces/kits/napi/file_access_module/napi_fileaccess_helper.cpp +++ b/interfaces/kits/napi/file_access_module/napi_fileaccess_helper.cpp @@ -224,6 +224,7 @@ napi_value FileAccessHelperInit(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("createFile", NAPI_CreateFile), DECLARE_NAPI_FUNCTION("delete", NAPI_Delete), DECLARE_NAPI_FUNCTION("move", NAPI_Move), + DECLARE_NAPI_FUNCTION("copy", NAPI_Copy), DECLARE_NAPI_FUNCTION("rename", NAPI_Rename), DECLARE_NAPI_FUNCTION("getRoots", NAPI_GetRoots), DECLARE_NAPI_FUNCTION("access", NAPI_Access), @@ -597,6 +598,95 @@ napi_value NAPI_Move(napi_env env, napi_callback_info info) return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_; } +napi_value CreateObjectArray(napi_env env, std::vector result) +{ + uint32_t status = napi_ok; + napi_value copyResultArray = nullptr; + status = napi_create_array_with_length(env, result.size(), ©ResultArray); + if (status != napi_ok) { + return nullptr; + } + + for (size_t i = 0; i < result.size(); i++) { + CopyResult &cr = result.at(i); + napi_value crVal= nullptr; + status |= napi_create_object(env, &crVal); + napi_value tmpVal; + status |= napi_create_string_utf8(env, cr.uri.c_str(), cr.uri.length(), &tmpVal); + status |= napi_set_named_property(env, crVal, "uri", tmpVal); + status |= napi_create_int32(env, cr.errCode, &tmpVal); + status |= napi_set_named_property(env, crVal, "errCode", tmpVal); + status |= napi_create_string_utf8(env, cr.errMsg.c_str(), cr.errMsg.length(), &tmpVal); + status |= napi_set_named_property(env, crVal, "errMsg", tmpVal); + status |= napi_set_element(env, copyResultArray, i, crVal); + if (status != napi_ok) { + return nullptr; + } + } + return copyResultArray; +} + +napi_value NAPI_Copy(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) { + NapiError(ERR_PARAM_NUMBER).ThrowErr(env); + return nullptr; + } + + bool retStatus = false; + std::vector strVect; + std::tie(retStatus, strVect, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToStringArray(); + if (!retStatus) { + NapiError(ERR_INVALID_PARAM).ThrowErr(env); + } + std::vector srcUriVect; // translate string to Uri + for (auto &str: strVect) { + OHOS::Uri tmpUri(str); + srcUriVect.push_back(std::move(tmpUri)); + } + + std::unique_ptr destStr; + std::tie(retStatus, destStr, std::ignore) = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String(); + if (!retStatus) { + NapiError(ERR_INVALID_PARAM).ThrowErr(env); + } + std::string destString (destStr.get()); + OHOS::Uri destUri(destString); + + FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar()); + if (fileAccessHelper == nullptr) { + return nullptr; + } + + std::vector result; + auto cbExec = [&srcUriVect, &destUri, &result, fileAccessHelper]() -> NError { + int retVal = fileAccessHelper->Copy(srcUriVect, destUri, result); + return NError(retVal); + }; + auto cbComplete = [&result](napi_env env, NError err) -> NVal { + if (err) { + // FIXME: 抛异常 + NapiError(ERR_FAF_FAIL).ThrowErr(env, FAFErrCodeTable.at(ERR_FAF_FAIL)); + // return { env, CreateObjectArray(env, result) }; + } + return { env, CreateObjectArray(env, result) }; + }; + + const std::string procedureName = "copy"; + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::TWO) { + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_; + } + + NVal cb(env, funcArg[NARG_POS::THIRD]); + if (!cb.TypeIs(napi_function)) { + NapiError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_; +} + napi_value NAPI_Rename(napi_env env, napi_callback_info info) { NFuncArg funcArg(env, info); diff --git a/interfaces/kits/napi/file_access_module/napi_fileaccess_helper.h b/interfaces/kits/napi/file_access_module/napi_fileaccess_helper.h index 26069715..c6766ed9 100644 --- a/interfaces/kits/napi/file_access_module/napi_fileaccess_helper.h +++ b/interfaces/kits/napi/file_access_module/napi_fileaccess_helper.h @@ -29,6 +29,7 @@ namespace FileAccessFwk { napi_value NAPI_Mkdir(napi_env env, napi_callback_info info); napi_value NAPI_Delete(napi_env env, napi_callback_info info); napi_value NAPI_Move(napi_env env, napi_callback_info info); + napi_value NAPI_Copy(napi_env env, napi_callback_info info); napi_value NAPI_Rename(napi_env env, napi_callback_info info); napi_value NAPI_GetRoots(napi_env env, napi_callback_info info); napi_value NAPI_Access(napi_env env, napi_callback_info info); diff --git a/utils/file_access_framework_errno.h b/utils/file_access_framework_errno.h index f78026a0..1fc03e77 100644 --- a/utils/file_access_framework_errno.h +++ b/utils/file_access_framework_errno.h @@ -16,6 +16,8 @@ #ifndef FILE_ACCESS_FRAMEWORK_ERRNO_H #define FILE_ACCESS_FRAMEWORK_ERRNO_H +#include +#include #include "errors.h" namespace OHOS { @@ -45,6 +47,52 @@ enum { ERR_NULL_POINTER, // get value is nullptr E_PERMISSION_SYS = 202 // is not system app }; + +// General error code for FAF +enum { + ERR_FAF_SUCCESS = 0, + ERR_FAF_FAIL, + ERR_FAF_PERM, + ERR_FAF_NOENT, + ERR_FAF_INTR, + ERR_FAF_IO, + ERR_FAF_NXIO, + ERR_FAF_2BIG, + ERR_FAF_NOMEM, + ERR_FAF_ACCES, + ERR_FAF_FAULT, + ERR_FAF_BUSY, + ERR_FAF_EXIST, + ERR_FAF_NOTDIR, + ERR_FAF_INVAL, + ERR_FAF_FBIG, + ERR_FAF_NOSPC, + ERR_FAF_ROFS, + ERR_FAF_NAMETOOLONG, +}; + +// {FAF error code, error message} +const std::unordered_map FAFErrCodeTable = { + { ERR_FAF_SUCCESS, "Execute succeed" }, + { ERR_FAF_FAIL, "Execute failed" }, + { ERR_FAF_PERM, "Operation not permitted" }, + { ERR_FAF_NOENT, "No such file or directory" }, + { ERR_FAF_INTR, "Interrupted system call" }, + { ERR_FAF_IO, "I/O error" }, + { ERR_FAF_NXIO, "No such device or address" }, + { ERR_FAF_2BIG, "Arg list too long" }, + { ERR_FAF_NOMEM, "Out of memory" }, + { ERR_FAF_ACCES, "Permission denied" }, + { ERR_FAF_FAULT, "Bad address" }, + { ERR_FAF_BUSY, "Device or resource busy" }, + { ERR_FAF_EXIST, "File exists" }, + { ERR_FAF_NOTDIR, "Not a directory" }, + { ERR_FAF_INVAL, "Invalid argument" }, + { ERR_FAF_FBIG, "File too large" }, + { ERR_FAF_NOSPC, "No space left on device" }, + { ERR_FAF_ROFS, "Read-only file system" }, + { ERR_FAF_NAMETOOLONG, "File name too long" } +}; } // namespace FileAccessFwk } // namespace OHOS -#endif // FILE_ACCESS_FRAMEWORK_ERRNO_H \ No newline at end of file +#endif // FILE_ACCESS_FRAMEWORK_ERRNO_H diff --git a/utils/napi_error.h b/utils/napi_error.h index 9d81b6a3..880fbaf0 100644 --- a/utils/napi_error.h +++ b/utils/napi_error.h @@ -41,6 +41,18 @@ public: throwStatus, std::to_string(errno_).c_str()); } } + + void ThrowErr(napi_env env, std::string errMsg) + { + napi_value tmp = nullptr; + napi_get_and_clear_last_exception(env, &tmp); + // Note that ace engine cannot thow errors created by napi_create_error so far + napi_status throwStatus = napi_throw_error(env, std::to_string(errno_).c_str(), errMsg.c_str()); + if (throwStatus != napi_ok) { + HILOG_WARN("Failed to throw an exception, %{public}d, code = %{public}s", + throwStatus, std::to_string(errno_).c_str()); + } + } private: int errno_ = ERRNO_NOERR; }; -- Gitee