From c3648761767be0e0c7e105ad720ebd70e01a78f5 Mon Sep 17 00:00:00 2001 From: caochuan Date: Thu, 2 Feb 2023 17:28:26 +0800 Subject: [PATCH] feat: add copy interface for faf Signed-off-by: caochuan --- filemanagement_aafwk.gni | 6 + .../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 | 48 ++++ .../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 | 65 ++++++ .../file_access/src/file_access_ext_stub.cpp | 56 +++++ .../src/file_access_ext_stub_impl.cpp | 18 ++ .../file_access/src/file_access_helper.cpp | 104 ++++++++- .../file_access/test/unittest/BUILD.gn | 1 + .../medialibrary_file_access_test.cpp | 217 +++++++++++++++++- .../napi_fileaccess_helper.cpp | 118 +++++++++- .../napi_fileaccess_helper.h | 1 + utils/file_access_framework_errno.h | 48 ++++ 18 files changed, 691 insertions(+), 4 deletions(-) diff --git a/filemanagement_aafwk.gni b/filemanagement_aafwk.gni index 67a8ad86..8524a526 100644 --- a/filemanagement_aafwk.gni +++ b/filemanagement_aafwk.gni @@ -17,3 +17,9 @@ 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/include/file_access_ext_ability.h b/frameworks/innerkits/file_access/include/file_access_ext_ability.h index 158b6895..f5cb7b8b 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 8c079705..1e6d067d 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 3c42652f..180daf87 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 281c2542..44a7cc30 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 d1bfd225..613313b4 100644 --- a/frameworks/innerkits/file_access/include/file_access_extension_info.h +++ b/frameworks/innerkits/file_access/include/file_access_extension_info.h @@ -169,6 +169,54 @@ 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 30af9962..cd24d2cb 100644 --- a/frameworks/innerkits/file_access/include/file_access_helper.h +++ b/frameworks/innerkits/file_access/include/file_access_helper.h @@ -75,6 +75,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 7b17c163..3698ac28 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, @@ -57,6 +58,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 5c6fedc4..dfe8bcc3 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 EPERM; } +int FileAccessExtAbility::Copy(const std::vector &srcUriVect, const Uri &destUri, std::vector &result) +{ + HILOG_ERROR("FileAccessExtAbility::Copy Undefined operation"); + return EPERM; +} + 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 04caffb0..7f739c86 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,71 @@ 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 E_IPCS; + } + + if (!data.WriteInt32(srcUriVect.size())) { + HILOG_ERROR("fail to WriteParcelable size of srcUriVect"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return E_IPCS; + } + + for (auto &uri: srcUriVect) { + if (!data.WriteParcelable(&uri)) { + HILOG_ERROR("fail to WriteParcelable uri"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return E_IPCS; + } + } + + if (!data.WriteParcelable(&destUri)) { + HILOG_ERROR("fail to WriteParcelable targetParent"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return E_IPCS; + } + + 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 = E_IPCS; + if (!reply.ReadInt32(copyRet)) { // Copy 返回值 + HILOG_ERROR("fail to ReadInt32 ret"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return E_IPCS; + } + + int count = 0; + if (!reply.ReadInt32(count)) { // vector元素个数 + HILOG_ERROR("Copy operation failed to Read count"); + return E_IPCS; + } + + result.clear(); + for (int i = 0; i < count; i++) { // read CopyResult + std::unique_ptr copyResultPtr(reply.ReadParcelable()); + if (copyResultPtr != nullptr) { + 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 a5ba5dcf..d01fe10b 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; @@ -270,6 +271,61 @@ 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 E_IPCS; + } + + 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 E_IPCS; + } + 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 E_IPCS; + } + + if (!reply.WriteInt32(result.size())) { + HILOG_ERROR("fail to WriteParcelable size of result"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return E_IPCS; + } + + for (auto &res: result) { + if (!reply.WriteParcelable(&res)) { + HILOG_ERROR("fail to WriteParcelable uri"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return E_IPCS; + } + HILOG_ERROR("result.uri: %{public}s", res.uri.c_str()); + HILOG_ERROR("result.errCode: %{public}d", res.errCode); + HILOG_ERROR("result.errMsg: %{public}s", res.errMsg.c_str()); + } + + 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 355ac1b7..ea8eef90 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,24 @@ 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 E_IPCS; + } + int ret = extension_->Copy(srcUriVect, destUri, result); + for (auto &res: result) { + HILOG_ERROR("result.uri: %{public}s", res.uri.c_str()); + HILOG_ERROR("result.errCode: %{public}d", res.errCode); + HILOG_ERROR("result.errMsg: %{public}s", res.errMsg.c_str()); + } + 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 117c3882..88cdacf9 100644 --- a/frameworks/innerkits/file_access/src/file_access_helper.cpp +++ b/frameworks/innerkits/file_access/src/file_access_helper.cpp @@ -61,8 +61,11 @@ static bool GetBundleNameFromPath(const std::string &path, std::string &bundleNa static bool CheckUri(Uri &uri) { - HILOG_DEBUG("Uri : %{public}s.", uri.ToString().c_str()); + //HILOG_DEBUG("Uri : %{public}s.", uri.ToString().c_str()); + //std::string schemeStr = std::string(uri.GetScheme()); + HILOG_INFO("Uri : %{public}s.", uri.ToString().c_str()); // TODO: delete 3 lines std::string schemeStr = std::string(uri.GetScheme()); + HILOG_INFO("schemeStr : %{public}s.", schemeStr.c_str()); if (schemeStr.compare(SCHEME_NAME) != 0) { HILOG_ERROR("Uri scheme error."); return false; @@ -593,6 +596,105 @@ int FileAccessHelper::Move(Uri &sourceFile, Uri &targetParent, Uri &newFile) return ERR_OK; } +bool IsMediaUri(Uri &uri) +{ + HILOG_ERROR("IsMediaUri uri: %{public}s", uri.ToString().c_str()); + string path = uri.GetPath(); + HILOG_ERROR("IsMediaUri path: %{public}s", path.c_str()); + std::size_t len = MEDIA_BNUDLE_NAME_ALIAS.length(); + if (path.length() > len) { + string media = path.substr(1, 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; + } + + HILOG_INFO("destUri: %{public}s", destUri.ToString().c_str()); + if (!CheckUri(destUri)) { + HILOG_ERROR("destUri(%{public}s) format check error.", destUri.ToString().c_str()); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return E_URIS; + } + + std::vector srcExternalUri, srcMediaUri; + for (auto &uri : srcUriVect) { + if (!CheckUri(uri)) { + HILOG_ERROR("srcUriVect(%{public}s) format check error.", uri.ToString().c_str()); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return E_URIS; + } + + if (IsMediaUri(uri)) { + srcMediaUri.push_back(uri); + } else { //else if (IsExternalUri(uri)) { + srcExternalUri.push_back(uri); + } + HILOG_INFO("srcUriVect: %{public}s", uri.ToString().c_str()); + } + + HILOG_INFO("FileAccessHelper::Copy"); + + if (IsMediaUri(destUri)) { + HILOG_INFO("FileAccessHelper::Copy"); + sptr mediaFileExtProxy = GetProxyByUri(destUri); + if (mediaFileExtProxy == nullptr) { + HILOG_ERROR("failed with invalid fileAccessExtProxy"); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return E_IPCS; + } + HILOG_INFO("FileAccessHelper::Copy"); + + if (!srcMediaUri.empty()) { + int ret = mediaFileExtProxy->Copy(srcMediaUri, destUri, result); + if (ret != ERR_OK) { + HILOG_ERROR("Copy error, code:%{public}d", ret); + FinishTrace(HITRACE_TAG_FILEMANAGEMENT); + return ret; + } + + for (auto &res: result) { + HILOG_ERROR("result.uri: %{public}s", res.uri.c_str()); + HILOG_ERROR("result.errCode: %{public}d", res.errCode); + HILOG_ERROR("result.errMsg: %{public}s", res.errMsg.c_str()); + } + } + HILOG_INFO("FileAccessHelper::Copy"); + 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; + } + */ + } + }// 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/BUILD.gn b/frameworks/innerkits/file_access/test/unittest/BUILD.gn index 3d03347d..b19af97d 100644 --- a/frameworks/innerkits/file_access/test/unittest/BUILD.gn +++ b/frameworks/innerkits/file_access/test/unittest/BUILD.gn @@ -49,6 +49,7 @@ ohos_unittest("medialibrary_file_access_test") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", "ipc:ipc_core", "ipc_js:rpc", "samgr:samgr_proxy", 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 c33661e8..357edb71 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 @@ -1259,7 +1259,7 @@ HWTEST_F(FileAccessHelperTest, medialibrary_file_access_Move_0009, testing::ext: result = g_fah->Mkdir(g_newDirUri, "test2", newDirUriTest2); EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); Uri testUri(""); - size_t fileNumbers = 2000; + size_t fileNumbers = 2; for (size_t i = 0; i < fileNumbers; i++) { string fileName = "test" + ToString(i) + ".txt"; result = g_fah->CreateFile(newDirUriTest1, fileName, testUri); @@ -1373,6 +1373,219 @@ 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{"datashare:///media/file/6"}; + Uri testDirUri{""}; + int result = g_fah->Mkdir(g_newDirUri, "Copy_0000", testDirUri); // g_newDirUri对应开发板目录: /storage/media/100/local/files/Download/ + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + GTEST_LOG_(INFO) << "test dir path" << testDirUri.ToString(); + Uri aUri{""}; + result = g_fah->CreateFile(testDirUri, "a.txt", aUri); + GTEST_LOG_(INFO) << "Copy_0000 CreateFile result:" << result << endl; + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + int fd; + result = g_fah->OpenFile(aUri, WRITE_READ, fd); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + std::string aBuff = "Copy test content for a.txt"; + ssize_t aSize = write(fd, aBuff.c_str(), aBuff.size()); + EXPECT_EQ(aSize, aBuff.size()); + close(fd); + + Uri bUri{""}; + result = g_fah->CreateFile(testDirUri, "b.txt", bUri); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + GTEST_LOG_(INFO) << "Copy_0000 CreateFile result:" << result << endl; + result = g_fah->OpenFile(bUri, WRITE_READ, fd); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + std::string bBuff = "Copy test content for b.txt"; + ssize_t bSize = write(fd, bBuff.c_str(), bBuff.size()); + EXPECT_EQ(bSize, bBuff.size()); + close(fd); + + Uri copyTestDirUri(""); + result = g_fah->Mkdir(testDirUri, "copy_test_0000", copyTestDirUri); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + GTEST_LOG_(INFO) << "Copy_0000 Mkdir result:" << result << endl; + + vector uriVect {aUri, bUri}; + vector resultVect; + result = g_fah->Copy(uriVect, copyTestDirUri, resultVect); + GTEST_LOG_(INFO) << "Copy_0000 Copy result:" << result << endl; + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + + char buff[aSize+bSize+2]; + result = g_fah->OpenFile(aUri, READ, fd); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + EXPECT_EQ(read(fd, buff, sizeof(buff)), aSize); + close(fd); + result = g_fah->OpenFile(bUri, READ, fd); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + EXPECT_EQ(read(fd, buff, sizeof(buff)), bSize); + result = g_fah->Delete(testDirUri); + GTEST_LOG_(INFO) << "Copy_0000 Delete result:" << result << endl; + 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_Copy_0001 + * @tc.name: medialibrary_file_access_Copy_0001 + * @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_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FileAccessHelperTest-begin medialibrary_file_access_Copy_0001"; + try { + //Uri parentUri{"datashare:///media/file/6"}; + Uri testDirUri{""}; + int result = g_fah->Mkdir(g_newDirUri, "Copy_0001", testDirUri); // g_newDirUri对应开发板目录: /storage/media/100/local/files/Download/ + HILOG_ERROR("Mkdir : %{public}s", testDirUri.ToString().c_str()); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + Uri aUri{""}; + result = g_fah->CreateFile(testDirUri, "a.txt", aUri); + GTEST_LOG_(INFO) << "Copy_0001 CreateFile result:" << result << endl; + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + int fd; + result = g_fah->OpenFile(aUri, WRITE_READ, fd); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + std::string aBuff = "Copy test content for a.txt"; + ssize_t aSize = write(fd, aBuff.c_str(), aBuff.size()); + EXPECT_EQ(aSize, aBuff.size()); + close(fd); + + Uri bUri{""}; + result = g_fah->CreateFile(testDirUri, "b.txt", bUri); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + GTEST_LOG_(INFO) << "Copy_0001 CreateFile result:" << result << endl; + result = g_fah->OpenFile(bUri, WRITE_READ, fd); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + std::string bBuff = "Copy test content for b.txt"; + ssize_t bSize = write(fd, bBuff.c_str(), bBuff.size()); + EXPECT_EQ(bSize, bBuff.size()); + close(fd); + + Uri copyTestDirUri(""); + result = g_fah->Mkdir(testDirUri, "copy_test_0001", copyTestDirUri); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + GTEST_LOG_(INFO) << "Copy_0001 Mkdir result:" << result << endl; + + vector uriVect {aUri, bUri}; + vector resultVect; + result = g_fah->Delete(bUri); + EXPECT_GE(result, OHOS::FileAccessFwk::ERR_OK); // delete one of file + result = g_fah->Copy(uriVect, copyTestDirUri, resultVect); + GTEST_LOG_(INFO) << "Copy_0001 Copy result:" << result << endl; + EXPECT_NE(result, OHOS::FileAccessFwk::ERR_OK); + + char buff[aSize+bSize+2]; + result = g_fah->OpenFile(aUri, READ, fd); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + EXPECT_EQ(read(fd, buff, sizeof(buff)), aSize); + close(fd); + //result = g_fah->OpenFile(bUri, READ, fd); + //EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + //EXPECT_EQ(read(fd, buff, sizeof(buff)), bSize); + //close(fd); + result = g_fah->Delete(testDirUri); + GTEST_LOG_(INFO) << "Copy_0001 Delete result:" << result << endl; + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + } catch (...) { + GTEST_LOG_(ERROR) << "medialibrary_file_access_Copy_0001 occurs an exception."; + } + GTEST_LOG_(INFO) << "FileAccessHelperTest-end medialibrary_file_access_Copy_0001"; +} + +/** + * @tc.number: user_file_service_medialibrary_file_access_Copy_0002 + * @tc.name: medialibrary_file_access_Copy_0002 + * @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_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FileAccessHelperTest-begin medialibrary_file_access_Copy_0002"; + try { + //Uri parentUri{"datashare:///media/file/6"}; + Uri testDirUri{""}; + int result = g_fah->Mkdir(g_newDirUri, "copy_0002", testDirUri); // g_newDirUri对应开发板目录: /storage/media/100/local/files/Download/ + HILOG_ERROR("Mkdir : %{public}s", testDirUri.ToString().c_str()); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + Uri copySrcDirUri(""); + result = g_fah->Mkdir(testDirUri, "copy_src_0002", copySrcDirUri); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + GTEST_LOG_(INFO) << "copy_src_0002 Mkdir result:" << result << endl; + + Uri aUri{""}; + result = g_fah->CreateFile(copySrcDirUri, "a.txt", aUri); + GTEST_LOG_(INFO) << "Copy_0002 CreateFile result:" << result << endl; + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + int fd; + result = g_fah->OpenFile(aUri, WRITE_READ, fd); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + std::string aBuff = "Copy test content for a.txt"; + ssize_t aSize = write(fd, aBuff.c_str(), aBuff.size()); + EXPECT_EQ(aSize, aBuff.size()); + close(fd); + + Uri bUri{""}; + result = g_fah->CreateFile(testDirUri, "b.txt", bUri); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + GTEST_LOG_(INFO) << "Copy_0002 CreateFile result:" << result << endl; + result = g_fah->OpenFile(bUri, WRITE_READ, fd); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + std::string bBuff = "Copy test content for b.txt"; + ssize_t bSize = write(fd, bBuff.c_str(), bBuff.size()); + EXPECT_EQ(bSize, bBuff.size()); + close(fd); + + Uri copyDestUri(""); + result = g_fah->Mkdir(testDirUri, "copy_dest_0002", copyDestUri); + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + GTEST_LOG_(INFO) << "Copy_0002 Mkdir result:" << result << endl; + + vector uriVect {copySrcDirUri, bUri}; + vector resultVect; + result = g_fah->Copy(uriVect, copyDestUri, resultVect); + GTEST_LOG_(INFO) << "Copy_0002 Copy result:" << result << endl; + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + + char buff[aSize+bSize+2]; + Uri bDestUri(resultVect.at(1).uri); + result = g_fah->OpenFile(bDestUri, READ, fd); // open b.txt + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + EXPECT_EQ(read(fd, buff, sizeof(buff)), bSize); + close(fd); + result = g_fah->Delete(testDirUri); + GTEST_LOG_(INFO) << "Copy_0002 Delete result:" << result << endl; + EXPECT_EQ(result, OHOS::FileAccessFwk::ERR_OK); + } catch (...) { + GTEST_LOG_(ERROR) << "medialibrary_file_access_Copy_0002 occurs an exception."; + } + GTEST_LOG_(INFO) << "FileAccessHelperTest-end medialibrary_file_access_Copy_0002"; +} + /** * @tc.number: user_file_service_medialibrary_file_access_Rename_0000 * @tc.name: medialibrary_file_access_Rename_0000 @@ -2529,4 +2742,4 @@ HWTEST_F(FileAccessHelperTest, medialibrary_file_access_GetFileInfoFromRelativeP } GTEST_LOG_(INFO) << "FileAccessHelperTest-end medialibrary_file_access_GetFileInfoFromRelativePath_0004"; } -} // 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 152c66d2..886f0a93 100644 --- a/interfaces/kits/napi/file_access_module/napi_fileaccess_helper.cpp +++ b/interfaces/kits/napi/file_access_module/napi_fileaccess_helper.cpp @@ -228,6 +228,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), @@ -602,6 +603,121 @@ 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) +{ + HILOG_INFO("CreateObjectArray() Enter"); + 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); + HILOG_INFO("NAPI_COPY: cr.uri: %{public}s", cr.uri.c_str()); + HILOG_INFO("NAPI_COPY: cr.errCode: %{public}d", cr.errCode); + HILOG_INFO("NAPI_COPY: cr.errMsg: %{public}s", cr.errMsg.c_str()); + + napi_value crVal; + 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; + } + } + HILOG_INFO("CreateObjectArray() Exit"); + return copyResultArray; +} + +napi_value NAPI_Copy(napi_env env, napi_callback_info info) +{ + HILOG_INFO("NAPI_COPY Enter"); + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) { + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + HILOG_INFO("NAPI_COPY -------------------->"); + bool retStatus = false; + auto strVect = std::make_shared>(); + if (strVect == nullptr) { + NError(E_GETRESULT).ThrowErr(env); + return nullptr; + } + std::tie(retStatus, *strVect, std::ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToStringArray(); + if (!retStatus) { + NError(EINVAL).ThrowErr(env); + } + + HILOG_INFO("NAPI_COPY -------------------->"); + std::unique_ptr destChar; + std::tie(retStatus, destChar, std::ignore) = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String(); + if (!retStatus) { + NError(EINVAL).ThrowErr(env); + } + std::string destStr (destChar.get()); + HILOG_INFO("NAPI_COPY: destStr: %{public}s", destStr.c_str()); + + HILOG_INFO("NAPI_COPY -------------------->"); + FileAccessHelper *fileAccessHelper = GetFileAccessHelper(env, funcArg.GetThisVar()); + if (fileAccessHelper == nullptr) { + return nullptr; + } + + HILOG_INFO("NAPI_COPY -------------------->"); + auto result = std::make_shared>(); + if (result == nullptr) { + NError(E_GETRESULT).ThrowErr(env); + return nullptr; + } + + HILOG_INFO("NAPI_COPY -------------------->"); + auto cbExec = [strVect, destStr, result, fileAccessHelper]() -> NError { + std::vector srcUriVect; // translate string to Uri + HILOG_INFO("NAPI_COPY -------------------->"); + for (auto &str: *strVect) { + OHOS::Uri tmpUri(str); + srcUriVect.push_back(std::move(tmpUri)); + HILOG_INFO("NAPI_COPY: srcUriVect: %{public}s", srcUriVect.at(srcUriVect.size()-1).ToString().c_str()); + } + OHOS::Uri destUri(destStr); + HILOG_INFO("NAPI_COPY cpExec: destUri: %{public}s", destUri.ToString().c_str()); + int retVal = fileAccessHelper->Copy(srcUriVect, destUri, *result); + return NError(retVal); + }; + auto cbComplete = [result](napi_env env, NError err) -> NVal { + HILOG_INFO("NAPI_COPY -------------------->"); + if (err) { + NError(ERR_FAF_FAIL).ThrowErr(env, FAFErrCodeTable.at(ERR_FAF_FAIL)); + // return { env, CreateObjectArray(env, result) }; + } + return { env, CreateObjectArray(env, *result) }; + }; + + HILOG_INFO("NAPI_COPY -------------------->"); + 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)) { + NError(EINVAL).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); @@ -986,4 +1102,4 @@ napi_value NAPI_Off(napi_env env, napi_callback_info info) return NVal::CreateUndefined(env).val_; } } // namespace FileAccessFwk -} // namespace OHOS \ No newline at end of file +} // namespace OHOS 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 e29f3d39..e027e9bc 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 e3d79285..bd8f9a56 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 { @@ -36,6 +38,52 @@ enum { E_PERMISSION = 201, // Permission verification failed E_PERMISSION_SYS // 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 -- Gitee