diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..22c002243e45cb58b9dac253eec37acbc6d7feca --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 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. + */ + +#include "dup_ani.h" + +#include "ani_helper.h" +#include "dup_core.h" +#include "error_handler.h" +#include "file_wrapper.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace OHOS::FileManagement::ModuleFileIO; + +ani_object DupAni::Dup(ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd) +{ + FsResult ret = DupCore::DoDup(static_cast(fd)); + if (!ret.IsSuccess()) { + HILOGE("Dup file failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + const FsFile *file = ret.GetData().value(); + auto result = FileWrapper::Wrap(env, move(file)); + if (result == nullptr) { + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..8f943ddb2f4cb475f5e4b85bbd33dc3cf158e801 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 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 INTERFACES_KITS_JS_SRC_MOD_FS_DUP_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_DUP_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class DupAni final { +public: + static ani_object Dup(ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_DUP_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/dup_core.cpp b/interfaces/kits/js/src/mod_fs/properties/dup_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddb5d4eb18b6a4e141b16cffe3bc31ece2f9d7ed --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/dup_core.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 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. + */ + +#include "dup_core.h" + +#include +#include +#include +#include + +#include "file_entity.h" +#include "file_instantiator.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_utils.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +static bool ValidFd(const int32_t &fd) +{ + if (fd < 0) { + HILOGE("Invalid fd"); + return false; + } + return true; +} + +FsResult DupCore::DoDup(const int32_t &fd) +{ + if (!ValidFd(fd)) { + return FsResult::Error(EINVAL); + } + int dstFd = dup(fd); + if (dstFd < 0) { + HILOGE("Failed to dup fd, errno: %{public}d", errno); + return FsResult::Error(errno); + } + + unique_ptr readLinkReq = { + new (std::nothrow) uv_fs_t, FsUtils::FsReqCleanup }; + if (!readLinkReq) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + string path = "/proc/self/fd/" + to_string(dstFd); + int ret = uv_fs_readlink(nullptr, readLinkReq.get(), path.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to readlink fd, ret: %{public}d", ret); + return FsResult::Error(ret); + } + return FileInstantiator::InstantiateFile(dstFd, string(static_cast(readLinkReq->ptr)), false); +} +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/dup_core.h b/interfaces/kits/js/src/mod_fs/properties/dup_core.h new file mode 100644 index 0000000000000000000000000000000000000000..074d07a8e2e400e969d8503377eda9d78823316d --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/dup_core.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 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 INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_DUP_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_DUP_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_file.h" + +namespace OHOS::FileManagement::ModuleFileIO { +class DupCore final { +public: + static FsResult DoDup(const int32_t &fd); +}; + +} // namespace OHOS::FileManagement::ModuleFileIO + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_DUP_CORE_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/dup_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/dup_core_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..283a64bc75c28ba989c6e078c8cb34978143f5dd --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/dup_core_mock_test.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2025 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. + */ + +#include "dup_core.h" +#include "uv_fs_mock.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class DupCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +void DupCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + uvMock = make_shared(); + Uvfs::ins = uvMock; +} + +void DupCoreMockTest::TearDownTestCase(void) +{ + Uvfs::ins = nullptr; + uvMock = nullptr; + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void DupCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void DupCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: DupCoreMockTest_DoDup_001 + * @tc.desc: Test function of DupCore::DoDup interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(DupCoreMockTest, DupCoreMockTest_DoDup_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "DupCoreMockTest-begin DupCoreMockTest_DoDup_001"; + + int32_t fd = 1; + + EXPECT_CALL(*uvMock, uv_fs_readlink(_, _, _, _)).WillOnce(Return(-1)); + auto res = DupCore::DoDup(fd); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "DupCoreMockTest-end DupCoreMockTest_DoDup_001"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/dup_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/dup_core_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c78be7c3a2fe76e5bfb46d4897fc5043ff8e9547 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/dup_core_test.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2025 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. + */ + +#include "dup_core.h" + +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class DupCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DupCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void DupCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void DupCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void DupCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: DupCoreTest_DoDup_001 + * @tc.desc: Test function of DupCore::DoDup interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(DupCoreTest, DupCoreTest_DoDup_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin DupCoreTest_DoDup_001"; + int32_t fd = -1; + auto res = DupCore::DoDup(fd); + + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "NClassTest-end DupCoreTest_DoDup_001"; +} + +/** + * @tc.name: DupCoreTest_DoDup_002 + * @tc.desc: Test function of DupCore::DoDup interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(DupCoreTest, DupCoreTest_DoDup_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin DupCoreTest_DoDup_002"; + int32_t fd = open("temp_file.txt", O_CREAT | O_RDWR, 0666); + ASSERT_NE(fd, -1); + close(fd); + + auto res = DupCore::DoDup(fd); + + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "NClassTest-end DupCoreTest_DoDup_002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file