diff --git a/bundle.json b/bundle.json index 2edbfd663a7d9e4d1faf6169501620f2868c0bd5..eaabdd7f459e6f4a7fe9b89126662f1b9435b3d0 100644 --- a/bundle.json +++ b/bundle.json @@ -51,6 +51,7 @@ "node", "openssl", "os_account", + "runtime_core", "rust_libc", "samgr" ], @@ -114,6 +115,15 @@ "header_base": "//foundation/filemanagement/file_api/interfaces/kits/rust/include" } }, + { + "name": "//foundation/filemanagement/file_api/utils/filemgmt_libfs:filemgmt_libfs", + "header": { + "header_files": [ + "filemgmt_libfs.h" + ], + "header_base": "//foundation/filemanagement/file_api/utils/filemgmt_libfs/include" + } + }, { "name": "//foundation/filemanagement/file_api/utils/filemgmt_libn:filemgmt_libn", "header": { @@ -202,7 +212,7 @@ } ], "test": [ - "//foundation/filemanagement/file_api/interfaces/test/unittest:unittest" + "//foundation/filemanagement/file_api/interfaces/test/unittest:file_api_unittest" ] } } diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index 1fad4e0e9161834e3cb76c4bbe3db8b80ce6d624..f7ec898fef557facdd79b08cf116153ce080f07a 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -11,6 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import("//build/config/components/ets_frontend/ets2abc_config.gni") import("//build/ohos.gni") import("//foundation/filemanagement/file_api/file_api.gni") @@ -623,3 +624,249 @@ group("build_kits_js") { ":statvfs", ] } + + +group("ani_file_api") { + deps = [ + ":ani_file_fs", + ":ani_file_hash", + ":ani_file_securitylabel", + ] +} + +config("ani_config") { + include_dirs = [ + "./include", + "${file_api_path}/interfaces/kits/rust/include", + "${utils_path}/common/include", + "${utils_path}/filemgmt_libfs/include", + "${utils_path}/filemgmt_libhilog", + "src/common", + "src/common/ani_helper", + "src/common/file_helper", + "src/mod_fs", + ] + + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc = [ + "-std=c++17", + "-fvisibility-inlines-hidden", + "-Oz", + ] +} + +ohos_shared_library("ani_file_fs") { + public_configs = [ ":ani_config" ] + include_dirs = [ + "include/ipc", + "src/mod_fs/ani", + "src/mod_fs/properties", + "src/mod_fs/properties/ani", + ] + sources = [ + "src/common/ani_helper/ani_signature.cpp", + "src/common/ani_helper/error_handler.cpp", + "src/common/ani_helper/type_converter.cpp", + "src/common/file_helper/fd_guard.cpp", + "src/mod_fs/ani/bind_function_class.cpp", + "src/mod_fs/fs_utils.cpp", + "src/mod_fs/properties/ani/listfile_ani.cpp", + "src/mod_fs/properties/ani/mkdir_ani.cpp", + "src/mod_fs/properties/ani/read_text_ani.cpp", + "src/mod_fs/properties/ani/unlink_ani.cpp", + "src/mod_fs/properties/ani/write_ani.cpp", + "src/mod_fs/properties/listfile_core.cpp", + "src/mod_fs/properties/mkdir_core.cpp", + "src/mod_fs/properties/read_text_core.cpp", + "src/mod_fs/properties/unlink_core.cpp", + "src/mod_fs/properties/write_core.cpp", + ] + deps = [ + ":ohos_file_fs_abc_etc", + "${file_api_path}/interfaces/kits/native:remote_uri_native", + "${file_api_path}/interfaces/kits/native:task_signal_native", + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + use_exceptions = true + external_deps = [ + "ability_runtime:ability_manager", + "app_file_service:fileuri_native", + "bounds_checking_function:libsec_static", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "data_share:datashare_common", + "data_share:datashare_consumer", + "dfs_service:distributed_file_daemon_kit_inner", + "dfs_service:libdistributedfileutils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "libuv:uv", + "runtime_core:ani", + "runtime_core:ani_helpers", + "runtime_core:libarkruntime", + "samgr:samgr_proxy", + ] + + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + output_extension = "so" + subsystem_name = "filemanagement" + part_name = "file_api" +} + +generate_static_abc("ohos_file_fs_abc") { + base_url = "./src/mod_fs/ani/ets" + files = [ "./src/mod_fs/ani/ets/@ohos.file.fs.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ohos_file_fs_abc.abc" +} + +ohos_prebuilt_etc("ohos_file_fs_abc_etc") { + source = "$target_out_dir/ohos_file_fs_abc.abc" + module_install_dir = "framework" + subsystem_name = "filemanagement" + part_name = "file_api" + deps = [ ":ohos_file_fs_abc" ] +} + +ohos_shared_library("ani_file_hash") { + public_configs = [ ":ani_config" ] + include_dirs = [ + "src/mod_hash", + "src/mod_hash/ani", + ] + sources = [ + "src/common/ani_helper/ani_signature.cpp", + "src/common/ani_helper/error_handler.cpp", + "src/common/ani_helper/type_converter.cpp", + "src/common/file_helper/fd_guard.cpp", + "src/common/file_helper/hash_file.cpp", + "src/mod_fs/fs_utils.cpp", + "src/mod_hash/ani/bind_function_class.cpp", + "src/mod_hash/ani/hash_ani.cpp", + "src/mod_hash/hash_core.cpp", + ] + + deps = [ + ":ohos_file_hash_abc_etc", + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + "libuv:uv", + "openssl:libcrypto_shared", + "runtime_core:ani", + "runtime_core:ani_helpers", + "runtime_core:libarkruntime", + ] + use_exceptions = true + + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + output_extension = "so" + subsystem_name = "filemanagement" + part_name = "file_api" +} + +generate_static_abc("ohos_file_hash_abc") { + base_url = "./src/mod_hash/ani/ets" + files = [ "./src/mod_hash/ani/ets/@ohos.file.hash.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ohos_file_hash_abc.abc" +} + +ohos_prebuilt_etc("ohos_file_hash_abc_etc") { + source = "$target_out_dir/ohos_file_hash_abc.abc" + module_install_dir = "framework" + subsystem_name = "filemanagement" + part_name = "file_api" + deps = [ ":ohos_file_hash_abc" ] +} + +ohos_shared_library("ani_file_securitylabel") { + public_configs = [ ":ani_config" ] + include_dirs = [ + "src/mod_securitylabel/ani", + "src/mod_securitylabel", + ] + sources = [ + "src/common/ani_helper/ani_signature.cpp", + "src/common/ani_helper/error_handler.cpp", + "src/common/ani_helper/type_converter.cpp", + "src/common/file_helper/fd_guard.cpp", + "src/mod_fs/fs_utils.cpp", + "src/mod_securitylabel/ani/bind_function_class.cpp", + "src/mod_securitylabel/ani/securitylabel_ani.cpp", + "src/mod_securitylabel/securitylabel_core.cpp", + ] + + deps = [ + ":ohos_file_securityLabel_abc_etc", + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + "libuv:uv", + "runtime_core:ani", + "runtime_core:ani_helpers", + "runtime_core:libarkruntime", + ] + use_exceptions = true + + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + output_extension = "so" + subsystem_name = "filemanagement" + part_name = "file_api" +} + +generate_static_abc("ohos_file_securityLabel_abc") { + base_url = "./src/mod_securitylabel/ani/ets" + files = [ "./src/mod_securitylabel/ani/ets/@ohos.file.securityLabel.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ohos_file_securityLabel_abc.abc" +} + +ohos_prebuilt_etc("ohos_file_securityLabel_abc_etc") { + source = "$target_out_dir/ohos_file_securityLabel_abc.abc" + module_install_dir = "framework" + subsystem_name = "filemanagement" + part_name = "file_api" + deps = [ ":ohos_file_securityLabel_abc" ] +} \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/ani_helper.h b/interfaces/kits/js/src/common/ani_helper/ani_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..c1781d8299b454a85dd16b196509b9d305493cd5 --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/ani_helper.h @@ -0,0 +1,208 @@ +/* + * 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 FILEMANAGEMENT_ANI_ANI_HELPER_H +#define FILEMANAGEMENT_ANI_ANI_HELPER_H + +#include +#include +#include + +#include + +#include "ani_signature.h" +#include "event_handler.h" +#include "event_runner.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static thread_local shared_ptr mainHandler; + +class AniHelper { +public: + template + static ani_status SetFieldValue( + ani_env *env, const ani_class &cls, ani_object &obj, const char *fieldName, const T &value) + { + ani_field field; + auto status = env->Class_FindField(cls, fieldName, &field); + if (status != ANI_OK) { + return status; + } + if constexpr (is_same_v || is_same_v || is_same_v) { + status = env->Object_SetField_Int(obj, field, value); + } else if constexpr (is_same_v || is_same_v) { + status = env->Object_SetField_Long(obj, field, value); + } else if constexpr (is_same_v || is_same_v) { + status = env->Object_SetField_Double(obj, field, value); + } else if constexpr (is_same_v || is_same_v) { + status = env->Object_SetField_Boolean(obj, field, value); + } else if constexpr (is_same_v || is_same_v) { + auto [succ, aniStr] = TypeConverter::ToAniString(env, value); + if (!succ) { + return ANI_ERROR; + } + status = env->Object_SetField_Ref(obj, field, move(aniStr)); + } else if constexpr (is_base_of_v) { + status = env->Object_SetField_Ref(obj, field, value); + } else { + return ANI_INVALID_TYPE; + } + return status; + } + + template + static ani_status SetPropertyValue( + ani_env *env, const ani_class &cls, ani_object &obj, const string &property, const T &value) + { + ani_method method; + string setter = "" + property; + auto status = env->Class_FindMethod(cls, setter.c_str(), nullptr, &method); + if (status != ANI_OK) { + return status; + } + + if constexpr (is_same_v || is_same_v) { + auto [succ, aniStr] = TypeConverter::ToAniString(env, value); + if (!succ) { + return ANI_ERROR; + } + status = env->Object_CallMethod_Void(obj, method, move(aniStr)); + } else if constexpr (is_base_of_v || is_same_v || is_same_v || + is_same_v || is_same_v || is_same_v || + is_same_v || is_same_v || is_same_v || + is_same_v) { + status = env->Object_CallMethod_Void(obj, method, value); + } else { + return ANI_INVALID_TYPE; + } + return status; + } + + static tuple> ParseInt64Option(ani_env *env, ani_object obj, const string &tag) + { + ani_boolean isUndefined = true; + ani_ref property; + ani_status status = ANI_ERROR; + status = env->Object_GetPropertyByName_Ref(obj, tag.c_str(), &property); + if (status != ANI_OK) { + return { false, nullopt }; + } + env->Reference_IsUndefined(property, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + static const string longValueSig = Builder::BuildSignatureDescriptor({}, BasicTypes::longType); + ani_long value; + status = env->Object_CallMethodByName_Long( + static_cast(property), "toLong", longValueSig.c_str(), &value); + if (status != ANI_OK) { + return { false, nullopt }; + } + auto result = make_optional(static_cast(value)); + return { true, move(result) }; + } + + static tuple> ParseEncoding(ani_env *env, ani_object obj) + { + ani_boolean isUndefined; + ani_ref property; + if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, "encoding", &property)) { + return { false, nullopt }; + } + env->Reference_IsUndefined(property, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + auto [succ, encoding] = TypeConverter::ToUTF8String(env, (ani_string)property); + if (!succ) { + return { false, nullopt }; + } + return { true, make_optional(move(encoding)) }; + } + + static ani_env *&GetThreadEnvStorage() + { + static thread_local ani_env *env { nullptr }; + return env; + } + + static ani_env *GetThreadEnv(ani_vm *vm) + { + auto &env = GetThreadEnvStorage(); + if (env != nullptr) { + return env; + } + + ani_options aniArgs { 0, nullptr }; + auto status = vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env); + if (status != ANI_OK) { + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + HILOGE("vm GetEnv, err: %{private}d", status); + return nullptr; + } + } + return env; + } + + static void DetachThreadEnv(ani_vm *vm) + { + if (vm && GetThreadEnvStorage()) { + auto status = vm->DetachCurrentThread(); + if (status != ANI_OK) { + HILOGE("Detach thread env from vm failed! status: %{private}d", status); + return; + } + GetThreadEnvStorage() = nullptr; + } + } + + static bool SendEventToMainThread(const function &func) + { + if (func == nullptr) { + HILOGE("func is nullptr!"); + return false; + } + + if (mainHandler == nullptr) { + shared_ptr runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); + if (!runner) { + HILOGE("get main event runner failed!"); + return false; + } + mainHandler = CreateSharedPtr(runner); + if (mainHandler == nullptr) { + HILOGE("Failed to request heap memory."); + return false; + } + } + bool succ = mainHandler->PostTask(func, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {}); + if (!succ) { + HILOGE("Failed to post task to main thread."); + return false; + } + return true; + } +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI + +#endif // FILEMANAGEMENT_ANI_ANI_HELPER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp b/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a683a78389923e50500cae3dfe396b8b81857c8 --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp @@ -0,0 +1,137 @@ +/* + * 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 "ani_signature.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature { +// BasicTypes +const Type BasicTypes::undefinedType = Builder::BuildUndefined(); +const Type BasicTypes::nullType = Builder::BuildNull(); +const Type BasicTypes::booleanType = Builder::BuildBoolean(); +const Type BasicTypes::byteType = Builder::BuildByte(); +const Type BasicTypes::charType = Builder::BuildChar(); +const Type BasicTypes::shortType = Builder::BuildShort(); +const Type BasicTypes::intType = Builder::BuildInt(); +const Type BasicTypes::longType = Builder::BuildLong(); +const Type BasicTypes::floatType = Builder::BuildFloat(); +const Type BasicTypes::doubleType = Builder::BuildDouble(); +// BoxedTypes::Boolean +const Type BoxedTypes::Boolean::classType = Builder::BuildClass("std.core.Boolean"); +const string BoxedTypes::Boolean::classDesc = BoxedTypes::Double::classType.Descriptor(); +const string BoxedTypes::Boolean::unboxedDesc = "unboxed"; +const string BoxedTypes::Boolean::unboxedSig = Builder::BuildSignatureDescriptor({}, BasicTypes::booleanType); +// BoxedTypes::Int +const Type BoxedTypes::Int::classType = Builder::BuildClass("std.core.Int"); +const string BoxedTypes::Int::classDesc = BoxedTypes::Int::classType.Descriptor(); +// BoxedTypes::Double +const Type BoxedTypes::Double::classType = Builder::BuildClass("std.core.Double"); +const string BoxedTypes::Double::classDesc = BoxedTypes::Double::classType.Descriptor(); +// BaseType +const string BaseType::ctorDesc = Builder::BuildConstructorName(); +const string BaseType::ctorSig0 = Builder::BuildSignatureDescriptor({}); +// BuiltInTypes::Object +const Type BuiltInTypes::Object::classType = Builder::BuildClass("std.core.Object"); +const string BuiltInTypes::Object::classDesc = BuiltInTypes::Object::classType.Descriptor(); +// BuiltInTypes::String +const Type BuiltInTypes::String::classType = Builder::BuildClass("std.core.String"); +const string BuiltInTypes::String::classDesc = BuiltInTypes::String::classType.Descriptor(); +// BuiltInTypes::Array +const Type BuiltInTypes::Array::classType = Builder::BuildClass("escompat.Array"); +const string BuiltInTypes::Array::classDesc = BuiltInTypes::Array::classType.Descriptor(); +const string BuiltInTypes::Array::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::intType }); +const string BuiltInTypes::Array::getterDesc = "$_get"; +const string BuiltInTypes::Array::setterDesc = "$_set"; +const string BuiltInTypes::Array::objectGetterSig = + Builder::BuildSignatureDescriptor({ BasicTypes::intType }, BuiltInTypes::objectType); +const string BuiltInTypes::Array::objectSetterSig = + Builder::BuildSignatureDescriptor({ BasicTypes::intType, BuiltInTypes::objectType }); +// BuiltInTypes::ArrayBuffer +const Type BuiltInTypes::ArrayBuffer::classType = Builder::BuildClass("escompat.ArrayBuffer"); +const string BuiltInTypes::ArrayBuffer::classDesc = BuiltInTypes::ArrayBuffer::classType.Descriptor(); +// BuiltInTypes::BigInt +const Type BuiltInTypes::BigInt::classType = Builder::BuildClass("escompat.BigInt"); +const string BuiltInTypes::BigInt::classDesc = BuiltInTypes::BigInt::classType.Descriptor(); +const string BuiltInTypes::BigInt::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::doubleType }); +// BuiltInTypes::BusinessError +const Type BuiltInTypes::BusinessError::classType = Builder::BuildClass("@ohos.base.BusinessError"); +const string BuiltInTypes::BusinessError::classDesc = BuiltInTypes::BusinessError::classType.Descriptor(); +// FS::ConflictFilesInner +const Type FS::ConflictFilesInner::classType = Builder::BuildClass("@ohos.file.fs.ConflictFilesInner"); +const string FS::ConflictFilesInner::classDesc = FS::ConflictFilesInner::classType.Descriptor(); +const string FS::ConflictFilesInner::ctorSig = + Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType, BuiltInTypes::stringType }); +// FS::FileInner +const Type FS::FileInner::classType = Builder::BuildClass("@ohos.file.fs.fileIo.FileInner"); +const string FS::FileInner::classDesc = FS::FileInner::classType.Descriptor(); +const string FS::FileInner::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); +// FS::ProgressInner +const Type FS::ProgressInner::classType = Builder::BuildClass("@ohos.file.fs.fileIo.ProgressInner"); +const string FS::ProgressInner::classDesc = FS::ProgressInner::classType.Descriptor(); +const string FS::ProgressInner::ctorSig = + Builder::BuildSignatureDescriptor({ BasicTypes::doubleType, BasicTypes::doubleType }); +// FS::RandomAccessFileInner +const Type FS::RandomAccessFileInner::classType = Builder::BuildClass("@ohos.file.fs.fileIo.RandomAccessFileInner"); +const string FS::RandomAccessFileInner::classDesc = FS::RandomAccessFileInner::classType.Descriptor(); +const string FS::RandomAccessFileInner::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); +// FS::ReaderIteratorInner +const Type FS::ReaderIteratorInner::classType = Builder::BuildClass("@ohos.file.fs.fileIo.ReaderIteratorInner"); +const string FS::ReaderIteratorInner::classDesc = FS::ReaderIteratorInner::classType.Descriptor(); +const string FS::ReaderIteratorInner::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); +// FS::ReaderIteratorResultInner +const Type FS::ReaderIteratorResultInner::classType = + Builder::BuildClass("@ohos.file.fs.fileIo.ReaderIteratorResultInner"); +const string FS::ReaderIteratorResultInner::classDesc = FS::ReaderIteratorResultInner::classType.Descriptor(); +const string FS::ReaderIteratorResultInner::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); +// FS::StatInner +const Type FS::StatInner::classType = Builder::BuildClass("@ohos.file.fs.fileIo.StatInner"); +const string FS::StatInner::classDesc = FS::StatInner::classType.Descriptor(); +const string FS::StatInner::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); +// FS::StreamInner +const Type FS::StreamInner::classType = Builder::BuildClass("@ohos.file.fs.fileIo.StreamInner"); +const string FS::StreamInner::classDesc = FS::StreamInner::classType.Descriptor(); +const string FS::StreamInner::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); +// FS::TaskSignal +const Type FS::TaskSignal::classType = Builder::BuildClass("@ohos.file.fs.fileIo.TaskSignal"); +const string FS::TaskSignal::classDesc = FS::TaskSignal::classType.Descriptor(); +const string FS::TaskSignal::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); +// FS::WatcherInner +const Type FS::WatcherInner::classType = Builder::BuildClass("@ohos.file.fs.fileIo.WatcherInner"); +const string FS::WatcherInner::classDesc = FS::WatcherInner::classType.Descriptor(); +const string FS::WatcherInner::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); +// FS::WatchEventInner +const Type FS::WatchEventInner::classType = Builder::BuildClass("@ohos.file.fs.WatchEventInner"); +const string FS::WatchEventInner::classDesc = FS::WatchEventInner::classType.Descriptor(); +const string FS::WatchEventInner::ctorSig = + Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType, BasicTypes::doubleType, BasicTypes::doubleType }); +// FS::LocationType +const Type FS::LocationType::classType = Builder::BuildClass("@ohos.file.fs.fileIo.LocationType"); +const string FS::LocationType::classDesc = FS::LocationType::classType.Descriptor(); +// Impl::EnvironmentImpl +const Type Impl::EnvironmentImpl::classType = Builder::BuildClass("@ohos.file.environment.EnvironmentImpl"); +const string Impl::EnvironmentImpl::classDesc = Impl::EnvironmentImpl::classType.Descriptor(); +// Impl::FileIoImpl +const Type Impl::FileIoImpl::classType = Builder::BuildClass("@ohos.file.fs.FileIoImpl"); +const string Impl::FileIoImpl::classDesc = Impl::FileIoImpl::classType.Descriptor(); +// Impl::HashImpl +const Type Impl::HashImpl::classType = Builder::BuildClass("@ohos.file.hash.HashImpl"); +const string Impl::HashImpl::classDesc = Impl::HashImpl::classType.Descriptor(); +// Impl::SecurityLabelImpl +const Type Impl::SecurityLabelImpl::classType = Builder::BuildClass("@ohos.file.securityLabel.SecurityLabelImpl"); +const string Impl::SecurityLabelImpl::classDesc = Impl::SecurityLabelImpl::classType.Descriptor(); +// Impl::StatvfsImpl +const Type Impl::StatvfsImpl::classType = Builder::BuildClass("@ohos.file.statvfs.StatvfsImpl"); +const string Impl::StatvfsImpl::classDesc = Impl::StatvfsImpl::classType.Descriptor(); + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/ani_signature.h b/interfaces/kits/js/src/common/ani_helper/ani_signature.h new file mode 100644 index 0000000000000000000000000000000000000000..8b7e4328169b56ae56340086e9ef251da41e2c4c --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/ani_signature.h @@ -0,0 +1,217 @@ +/* + * 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_COMMON_ANI_HELPER_ANI_SIGNATURE_H +#define INTERFACES_KITS_JS_SRC_COMMON_ANI_HELPER_ANI_SIGNATURE_H + +#pragma once + +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature { +using namespace std; +using namespace arkts::ani_signature; + +struct BasicTypes { + static const Type undefinedType; + static const Type nullType; + static const Type booleanType; + static const Type byteType; + static const Type charType; + static const Type shortType; + static const Type intType; + static const Type longType; + static const Type floatType; + static const Type doubleType; +}; + +struct BaseType { + static const string ctorDesc; + static const string ctorSig0; +}; + +namespace BoxedTypes { + +struct Boolean : public BaseType { + static const Type classType; + static const string classDesc; + static const string unboxedDesc; + static const string unboxedSig; +}; + +struct Int : public BaseType { + static const Type classType; + static const string classDesc; +}; + +struct Double : public BaseType { + static const Type classType; + static const string classDesc; +}; + +} // namespace BoxedTypes + +namespace BuiltInTypes { + +struct Object : public BaseType { + static const Type classType; + static const string classDesc; +}; + +inline const Type &objectType = BuiltInTypes::Object::classType; + +struct String : public BaseType { + static const Type classType; + static const string classDesc; +}; + +inline const Type &stringType = BuiltInTypes::String::classType; + +struct Array : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; + static const string getterDesc; + static const string setterDesc; + static const string objectGetterSig; + static const string objectSetterSig; +}; + +struct ArrayBuffer : public BaseType { + static const Type classType; + static const string classDesc; +}; + +struct BigInt : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct BusinessError : public BaseType { + static const Type classType; + static const string classDesc; +}; + +}; // namespace BuiltInTypes + +namespace FS { + +struct ConflictFilesInner : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct FileInner : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct ProgressInner : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct RandomAccessFileInner : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct ReaderIteratorInner : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct ReaderIteratorResultInner : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct StatInner : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct StreamInner : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct TaskSignal : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct WatcherInner : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct WatchEventInner : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct LocationType : public BaseType { + static const Type classType; + static const string classDesc; +}; + +} // namespace FS + +namespace Impl { + +struct EnvironmentImpl : public BaseType { + static const Type classType; + static const string classDesc; +}; + +struct FileIoImpl : public BaseType { + static const Type classType; + static const string classDesc; +}; + +struct HashImpl : public BaseType { + static const Type classType; + static const string classDesc; +}; + +struct SecurityLabelImpl : public BaseType { + static const Type classType; + static const string classDesc; +}; + +struct StatvfsImpl : public BaseType { + static const Type classType; + static const string classDesc; +}; + +} // namespace Impl + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature + +#endif // INTERFACES_KITS_JS_SRC_COMMON_ANI_HELPER_ANI_SIGNATURE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/bind_function.h b/interfaces/kits/js/src/common/ani_helper/bind_function.h new file mode 100644 index 0000000000000000000000000000000000000000..3c951b25125364260b1879851df4f1b832e9b233 --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/bind_function.h @@ -0,0 +1,86 @@ +/* + * 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 FILEMANAGEMENT_ANI_BIND_FUNCTION_H +#define FILEMANAGEMENT_ANI_BIND_FUNCTION_H + +#include +#include +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +template +ANI_EXPORT ani_status BindClass(ani_env *env, const char *className, const std::array &methods) +{ + if (env == nullptr) { + HILOGE("Invalid parameter env"); + return ANI_INVALID_ARGS; + } + + if (className == nullptr) { + HILOGE("Invalid parameter className"); + return ANI_INVALID_ARGS; + } + + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Cannot find class '%{private}s'", className); + return ANI_NOT_FOUND; + } + + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + HILOGE("Cannot bind native methods to '%{private}s'", className); + return ANI_ERROR; + }; + return ANI_OK; +} + +template +ANI_EXPORT ani_status BindNamespace( + ani_env *env, const char *namespaceStr, const std::array &methods) +{ + if (env == nullptr) { + HILOGE("Invalid parameter env"); + return ANI_INVALID_ARGS; + } + + if (namespaceStr == nullptr) { + HILOGE("Invalid parameter namespaceStr"); + return ANI_INVALID_ARGS; + } + + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceStr, &ns)) { + HILOGE("Cannot find namespace '%{private}s'", namespaceStr); + return ANI_NOT_FOUND; + } + + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) { + HILOGE("Cannot bind native methods to '%{private}s'", namespaceStr); + return ANI_ERROR; + }; + return ANI_OK; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // FILEMANAGEMENT_ANI_BIND_FUNCTION_H \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/error_handler.cpp b/interfaces/kits/js/src/common/ani_helper/error_handler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c56a4dc0d26aaacdb2c42811d411d47d4341421d --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/error_handler.cpp @@ -0,0 +1,27 @@ +/* + * 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 "error_handler.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { + +ani_status ErrorHandler::Throw( + ani_env *env, int32_t code, const std::string &errMsg, const std::optional &errData) +{ + auto classDesc = BuiltInTypes::BusinessError::classDesc.c_str(); + return Throw(env, classDesc, code, errMsg, errData); +} + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/error_handler.h b/interfaces/kits/js/src/common/ani_helper/error_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..2138f075dbe1e380b84568929445c692e9b99298 --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/error_handler.h @@ -0,0 +1,144 @@ +/* + * 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 FILEMANAGEMENT_ANI_ERROR_HANDLER_H +#define FILEMANAGEMENT_ANI_ERROR_HANDLER_H + +#include +#include +#include +#include "ani_helper.h" +#include "ani_signature.h" +#include "filemgmt_libhilog.h" +#include "fs_error.h" +#include "type_converter.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +class ErrorHandler { +public: + static ani_status Throw( + ani_env *env, int32_t code, const std::string &errMsg, const std::optional &errData = std::nullopt); + + static ani_status Throw(ani_env *env, int32_t code, const std::optional &errData = std::nullopt) + { + if (env == nullptr) { + HILOGE("Invalid parameter env"); + return ANI_INVALID_ARGS; + } + FsError err(code); + return Throw(env, std::move(err), errData); + } + + static ani_status Throw(ani_env *env, const FsError &err, const std::optional &errData = std::nullopt) + { + if (env == nullptr) { + HILOGE("Invalid parameter env"); + return ANI_INVALID_ARGS; + } + auto code = err.GetErrNo(); + const auto &errMsg = err.GetErrMsg(); + return Throw(env, code, errMsg, errData); + } + +private: + static ani_status Throw(ani_env *env, const char *className, int32_t code, const std::string &errMsg, + const std::optional &errData = std::nullopt) + { + if (env == nullptr) { + HILOGE("Invalid parameter env"); + return ANI_INVALID_ARGS; + } + + if (className == nullptr) { + HILOGE("Invalid parameter className"); + return ANI_INVALID_ARGS; + } + + auto [status, err] = CreateErrorObj(env, className, code, errMsg, errData); + + if (status != ANI_OK) { + HILOGE("Create error object failed!"); + return status; + } + + status = env->ThrowError(err); + if (status != ANI_OK) { + HILOGE("Throw ani error object failed!"); + return status; + } + return ANI_OK; + } + + static std::tuple CreateErrorObj(ani_env *env, const char *className, int32_t code, + const std::string &errMsg, const std::optional &errData = std::nullopt) + { + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Cannot find class '%{private}s'", className); + return { ANI_NOT_FOUND, nullptr }; + } + + auto ctorDesc = BaseType::ctorDesc.c_str(); + auto ctorSig = BaseType::ctorSig0.c_str(); + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) { + HILOGE("Cannot find constructor for class '%{private}s'", className); + return { ANI_NOT_FOUND, nullptr }; + } + + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj)) { + HILOGE("Cannot create ani error object"); + return { ANI_ERROR, nullptr }; + } + + auto [succ, message] = TypeConverter::ToAniString(env, errMsg); + if (!succ) { + HILOGE("Convert errMsg to ani string failed"); + return { ANI_ERROR, nullptr }; + } + + ani_status status = ANI_ERROR; + + status = env->Object_SetPropertyByName_Ref(obj, "message", message); + if (status != ANI_OK) { + HILOGE("Set property 'message' value failed"); + return { status, nullptr }; + } + + status = env->Object_SetPropertyByName_Double(obj, "code", static_cast(code)); + if (status != ANI_OK) { + HILOGE("Set property 'code' value failed"); + return { status, nullptr }; + } + + if (errData.has_value()) { + status = env->Object_SetPropertyByName_Ref(obj, "data", errData.value()); + if (status != ANI_OK) { + HILOGE("Set property 'data' value failed"); + return { status, nullptr }; + } + } + + ani_error err = static_cast(obj); + return { ANI_OK, std::move(err) }; + } +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI + +#endif // FILEMANAGEMENT_ANI_ERROR_HANDLER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/type_converter.cpp b/interfaces/kits/js/src/common/ani_helper/type_converter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..564d7bc56e1baf1dd65cdcaa42f1521936887de3 --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/type_converter.cpp @@ -0,0 +1,297 @@ +/* + * 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 "type_converter.h" + +#include +#include +#include + +#include "ani_signature.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "securec.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +std::tuple TypeConverter::ToUTF8String(ani_env *env, const ani_string &path) +{ + if (env == nullptr) { + return { false, EMPTY_STRING }; + } + ani_size sz {}; + std::string result; + auto status = env->String_GetUTF8Size(path, &sz); + if (status != ANI_OK) { + return { false, EMPTY_STRING }; + } + result.resize(sz + 1); + status = env->String_GetUTF8SubString(path, 0, sz, result.data(), result.size(), &sz); + if (status != ANI_OK) { + return { false, EMPTY_STRING }; + } + result.resize(sz); + return { true, std::move(result) }; +} + +std::tuple> TypeConverter::ToOptionalInt32(ani_env *env, const ani_object &value) +{ + if (env == nullptr) { + return { false, {} }; + } + ani_boolean isUndefined; + env->Reference_IsUndefined(value, &isUndefined); + if (isUndefined) { + return { true, std::nullopt }; + } + + ani_int intValue; + if (ANI_OK == env->Object_CallMethodByName_Int(value, "toInt", nullptr, &intValue)) { + return { true, std::make_optional(intValue) }; + } + + return { false, {} }; +} + +std::tuple> TypeConverter::ToOptionalInt64(ani_env *env, const ani_object &value) +{ + if (env == nullptr) { + return { false, {} }; + } + + ani_boolean isUndefined; + env->Reference_IsUndefined(value, &isUndefined); + if (isUndefined) { + return { true, std::nullopt }; + } + + ani_long longValue; + if (ANI_OK == env->Object_CallMethodByName_Long(value, "toLong", nullptr, &longValue)) { + return { true, std::make_optional(longValue) }; + } + + return { false, {} }; +} + +std::tuple TypeConverter::ToAniString(ani_env *env, std::string str) +{ + if (env == nullptr) { + return { false, {} }; + } + + ani_string result; + if (ANI_OK != env->String_NewUTF8(str.c_str(), str.size(), &result)) { + return { false, {} }; + } + return { true, std::move(result) }; +} + +std::tuple TypeConverter::ToAniString(ani_env *env, std::string str, size_t size) +{ + if (env == nullptr) { + return { false, {} }; + } + + ani_string result; + if (ANI_OK != env->String_NewUTF8(str.c_str(), size, &result)) { + return { false, {} }; + } + return { true, std::move(result) }; +} + +std::tuple TypeConverter::ToAniString(ani_env *env, const char *str) +{ + if (env == nullptr) { + return { false, {} }; + } + + size_t length = std::strlen(str); + ani_string result; + if (ANI_OK != env->String_NewUTF8(str, length, &result)) { + return { false, {} }; + } + return { true, std::move(result) }; +} + +std::tuple> TypeConverter::EnumToInt32(ani_env *env, const ani_enum_item &enumOp) +{ + ani_boolean isUndefined; + env->Reference_IsUndefined(enumOp, &isUndefined); + if (isUndefined) { + return { true, std::nullopt }; + } + + ani_int result; + if (ANI_OK != env->EnumItem_GetValue_Int(enumOp, &result)) { + return { false, {} }; + } + + return { true, std::make_optional(result) }; +} + +static std::tuple ParseFd(ani_env *env, const ani_object &pathOrFd) +{ + ani_boolean isFd = false; + + auto intClassDesc = BoxedTypes::Int::classDesc.c_str(); + ani_class intClass; + env->FindClass(intClassDesc, &intClass); + env->Object_InstanceOf(pathOrFd, intClass, &isFd); + if (isFd) { + ani_int fd; + if (ANI_OK != env->Object_CallMethodByName_Int(pathOrFd, "toInt", nullptr, &fd)) { + HILOGE("Parse file path failed"); + return { false, 0 }; + } + return { true, fd }; + } + + return { false, 0 }; +} + +std::tuple TypeConverter::ToFileInfo(ani_env *env, const ani_object &pathOrFd) +{ + if (env == nullptr) { + HILOGE("Invalid parameter env"); + return { false, FileInfo { false, {}, {} } }; + } + + auto stringClassDesc = BuiltInTypes::String::classDesc.c_str(); + ani_class stringClass; + env->FindClass(stringClassDesc, &stringClass); + + ani_boolean isPath = false; + env->Object_InstanceOf(pathOrFd, stringClass, &isPath); + if (isPath) { + auto [succ, path] = TypeConverter::ToUTF8String(env, static_cast(pathOrFd)); + if (!succ) { + HILOGE("Parse file path failed"); + return { false, FileInfo { false, {}, {} } }; + } + size_t length = path.length() + 1; + auto chars = std::make_unique(length); + auto ret = strncpy_s(chars.get(), length, path.c_str(), length - 1); + if (ret != EOK) { + HILOGE("Copy file path failed!"); + return { false, FileInfo { false, {}, {} } }; + } + return { true, FileInfo { true, move(chars), {} } }; + } + + auto [isFd, fd] = ParseFd(env, pathOrFd); + if (isFd) { + auto fdg = CreateUniquePtr(fd, false); + if (fdg == nullptr) { + HILOGE("Failed to request heap memory."); + return { false, FileInfo { false, {}, {} } }; + } + return { true, FileInfo { false, {}, move(fdg) } }; + } + + return { false, FileInfo { false, {}, {} } }; +} + +std::tuple TypeConverter::ToArrayBuffer(ani_env *env, ani_arraybuffer &buffer) +{ + if (env == nullptr) { + return { false, ArrayBuffer { nullptr, 0 } }; + } + + void *buf = nullptr; + ani_size length = 0; + + if (ANI_OK != env->ArrayBuffer_GetInfo(buffer, &buf, &length)) { + return { false, ArrayBuffer { nullptr, 0 } }; + } + return { true, ArrayBuffer { std::move(buf), length } }; +} + +std::tuple TypeConverter::ToAniArrayBuffer(ani_env *env, void *buffer, size_t length) +{ + if (env == nullptr) { + return { false, nullptr }; + } + + static const char *className = "Lescompat/ArrayBuffer;"; + ani_status ret; + ani_class cls; + if ((ret = env->FindClass(className, &cls)) != ANI_OK) { + HILOGE("Not found %{private}s, err: %{private}d", className, ret); + return { false, nullptr }; + } + + ani_method ctor; + if ((ret = env->Class_FindMethod(cls, "", "I:V", &ctor)) != ANI_OK) { + HILOGE("Not found ctor, err: %{private}d", ret); + return { false, nullptr }; + } + + ani_object obj; + if ((ret = env->Object_New(cls, ctor, &obj, length)) != ANI_OK) { + HILOGE("New Uint8Array err: %{private}d", ret); + return { false, nullptr }; + } + + if (!buffer || !length) { + return { true, static_cast(obj) }; + } + + void *buf = nullptr; + ani_size len = 0; + + if ((ANI_OK != env->ArrayBuffer_GetInfo(static_cast(obj), &buf, &len)) && (!buf)) { + return { false, nullptr }; + } + + int res = memcpy_s(buf, length, buffer, length); + if (res != 0) { + return { false, nullptr }; + } + len = length; + + return { true, static_cast(obj) }; +} + +std::tuple TypeConverter::ToAniStringList( + ani_env *env, const std::string strList[], const uint32_t length) +{ + if (env == nullptr) { + return { false, nullptr }; + } + + auto classDesc = BuiltInTypes::String::classDesc.c_str(); + ani_array_ref result = nullptr; + ani_class cls = nullptr; + if (env->FindClass(classDesc, &cls) != ANI_OK) { + return { false, result }; + } + if (env->Array_New_Ref(cls, length, nullptr, &result) != ANI_OK) { + return { false, result }; + } + for (uint32_t i = 0; i < length; i++) { + auto [ret, item] = TypeConverter::ToAniString(env, strList[i]); + if (!ret) { + return { false, nullptr }; + } + + if (env->Array_Set_Ref(result, i, item) != ANI_OK) { + return { false, nullptr }; + } + } + return { true, result }; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/type_converter.h b/interfaces/kits/js/src/common/ani_helper/type_converter.h new file mode 100644 index 0000000000000000000000000000000000000000..bac25493fda5311c32340a5ce0371dd981a9af1d --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/type_converter.h @@ -0,0 +1,48 @@ +/* + * 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 FILEMANAGEMENT_ANI_TYPE_CONVERTER_H +#define FILEMANAGEMENT_ANI_TYPE_CONVERTER_H + +#include +#include + +#include + +#include "fs_array_buffer.h" +#include "fs_utils.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { +inline const std::string EMPTY_STRING = ""; + +class TypeConverter { +public: + static std::tuple ToUTF8String(ani_env *env, const ani_string &path); + static std::tuple> ToOptionalInt32(ani_env *env, const ani_object &value); + static std::tuple> ToOptionalInt64(ani_env *env, const ani_object &value); + static std::tuple ToAniArrayBuffer(ani_env *env, void *buffer, size_t length); + static std::tuple ToAniString(ani_env *env, std::string str); + static std::tuple ToAniString(ani_env *env, std::string str, size_t size); + static std::tuple ToAniString(ani_env *env, const char *str); + static std::tuple> EnumToInt32(ani_env *env, const ani_enum_item &enumOp); + static std::tuple ToFileInfo(ani_env *env, const ani_object &pathOrFd); + static std::tuple ToArrayBuffer(ani_env *env, ani_arraybuffer &buffer); + static std::tuple ToAniStringList( + ani_env *env, const std::string strList[], const uint32_t length); +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI + +#endif // FILEMANAGEMENT_ANI_TYPE_CONVERTER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/common/fs_file_filter.h b/interfaces/kits/js/src/common/fs_file_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..f16c178213255dd738a7c62d64419e0d7adf6271 --- /dev/null +++ b/interfaces/kits/js/src/common/fs_file_filter.h @@ -0,0 +1,117 @@ +/* + * 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 FS_FILE_FILTER_H +#define FS_FILE_FILTER_H + +#include +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +class FsFileFilter { +public: + FsFileFilter() = default; + ~FsFileFilter() = default; + + FsFileFilter(const FsFileFilter &filter) = default; + FsFileFilter &operator=(const FsFileFilter &filter) = default; + + void SetSuffix(const std::optional> &suffix) + { + suffix_ = std::move(suffix); + } + + const std::optional> &GetSuffix() const + { + return suffix_; + } + + void SetDisplayName(const std::optional> &displayName) + { + displayName_ = std::move(displayName); + } + + const std::optional> &GetDisplayName() const + { + return displayName_; + } + + void SetMimeType(const std::optional> &mimeType) + { + mimeType_ = std::move(mimeType); + } + + const std::optional> &GetMimeType() const + { + return mimeType_; + } + + void SetFileSizeOver(const std::optional &fileSizeOver) + { + fileSizeOver_ = std::move(fileSizeOver); + } + + const std::optional &GetFileSizeOver() const + { + return fileSizeOver_; + } + + void SetLastModifiedAfter(const std::optional &lastModifiedAfter) + { + lastModifiedAfter_ = std::move(lastModifiedAfter); + } + + const std::optional &GetLastModifiedAfter() const + { + return lastModifiedAfter_; + } + + void SetExcludeMedia(const bool &excludeMedia) + { + excludeMedia_ = excludeMedia; + } + + bool GetExcludeMedia() const + { + return excludeMedia_; + } + + void SetHasFilter(const bool &hasFilter) + { + hasFilter_ = hasFilter; + } + + bool GetHasFilter() const + { + return hasFilter_; + } + +private: + std::optional> suffix_ = std::nullopt; + std::optional> displayName_ = std::nullopt; + std::optional> mimeType_ = std::nullopt; + std::optional fileSizeOver_ = std::nullopt; + std::optional lastModifiedAfter_ = std::nullopt; + bool excludeMedia_ = false; + bool hasFilter_ = false; +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // FS_FILE_FILTER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp b/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6231b5093dcc80f5033d9f367f744c8ea68ea294 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp @@ -0,0 +1,87 @@ +/* + * 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 + +#include + +#include "ani_signature.h" +#include "bind_function.h" +#include "listfile_ani.h" +#include "mkdir_ani.h" +#include "read_text_ani.h" +#include "unlink_ani.h" +#include "write_ani.h" + +using namespace OHOS::FileManagement::ModuleFileIO::ANI; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +const static string mkdirCtorSig0 = Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType }); +const static string mkdirCtorSig1 = + Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType, BasicTypes::booleanType }); + +static ani_status BindStaticMethods(ani_env *env) +{ + auto classDesc = Impl::FileIoImpl::classDesc.c_str(); + + std::array methods = { + ani_native_function { "listFileSync", nullptr, reinterpret_cast(ListFileAni::ListFileSync) }, + ani_native_function { "mkdirSync", mkdirCtorSig0.c_str(), reinterpret_cast(MkdirkAni::MkdirSync0) }, + ani_native_function { "mkdirSync", mkdirCtorSig1.c_str(), reinterpret_cast(MkdirkAni::MkdirSync1) }, + ani_native_function { "readTextSync", nullptr, reinterpret_cast(ReadTextAni::ReadTextSync) }, + ani_native_function { "unlinkSync", nullptr, reinterpret_cast(UnlinkAni::UnlinkSync) }, + ani_native_function { "writeSync", nullptr, reinterpret_cast(WriteAni::WriteSync) }, + }; + return BindClass(env, classDesc, methods); +} + +static ani_status DoBindMethods(ani_env *env) +{ + ani_status status; + if ((status = BindStaticMethods(env)) != ANI_OK) { + HILOGE("Cannot bind native static methods for BindStaticMethods!"); + return status; + }; + + return ANI_OK; +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + if (vm == nullptr) { + HILOGE("Invalid parameter vm"); + return ANI_INVALID_ARGS; + } + + if (result == nullptr) { + HILOGE("Invalid parameter result"); + return ANI_INVALID_ARGS; + } + + ani_env *env; + ani_status status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + HILOGE("Invalid ani version!"); + return ANI_INVALID_VERSION; + } + + status = DoBindMethods(env); + if (status != ANI_OK) { + return status; + } + + *result = ANI_VERSION_1; + return ANI_OK; +} diff --git a/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets new file mode 100644 index 0000000000000000000000000000000000000000..5de05d13c16f74668df53433be2c1f8fdb6bccda --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets @@ -0,0 +1,2173 @@ +/* + * 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. + */ +import { BusinessError, AsyncCallback } from '@ohos.base'; +// import stream from '@ohos.util.stream'; + +const UNKNOWN_ERR: number = 13900042 +const UNKNOWN_MSG: string = "Unknown error" + +function createBusinessError(code: number, msg: string): BusinessError { + let err = new BusinessError(); + err.code = code; + err.message = msg; + return err; +} + +namespace fileIo { + export namespace OpenMode { + export const READ_ONLY = 0o0; + export const WRITE_ONLY = 0o1; + export const READ_WRITE = 0o2; + export const CREATE = 0o100; + export const TRUNC = 0o1000; + export const APPEND = 0o2000; + export const NONBLOCK = 0o4000; + export const DIR = 0o200000; + export const NOFOLLOW = 0o400000; + export const SYNC = 0o4010000; + } + +function access(path: string, mode?: AccessModeType): Promise { + return new Promise((resolve: (result: boolean) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: string, mode?: AccessModeType): boolean => { + return FileIoImpl.doAccessSync(path, mode); + }, path, mode); + promise.then((ret: NullishType): void => { + let result = ret as boolean; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function access(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): boolean => { + return FileIoImpl.doAccessSync(path); + }, path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as boolean; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, false); + }); +} + +function access(path: string, mode: AccessModeType, flag: AccessFlagType): Promise { + return new Promise((resolve: (result: boolean) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: string, mode: AccessModeType, flag: AccessFlagType): boolean => { + return FileIoImpl.doAccessSync(path, mode, flag); + }, path, mode, flag); + promise.then((ret: NullishType): void => { + let result = ret as boolean; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }) +} + +function accessSync(path: string, mode?: AccessModeType): boolean { + return FileIoImpl.doAccessSync(path, mode); +} + +function accessSync(path: string, mode: AccessModeType, flag: AccessFlagType): boolean { + return FileIoImpl.doAccessSync(path, mode, flag); +} + +function close(file: number | File): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((file: number | File): undefined => FileIoImpl.closeSync(file), file); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function close(file: number | File, callback: AsyncCallback): void { + let promise = taskpool.execute((file: number | File): undefined => FileIoImpl.closeSync(file), file); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function closeSync(file: number | File): void { + return FileIoImpl.closeSync(file) +} + +function connectDfs(networkId: string, listeners: DfsListeners): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((networkId: string, listeners: DfsListeners): void => + FileIoImpl.connectDfs(networkId, listeners), networkId, listeners); + promise.then((): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function disconnectDfs(networkId: string): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((networkId: string): void => FileIoImpl.disConnectDfs(networkId), networkId); + promise.then((): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function getxattrSync(path: string, key: string): string { + return FileIoImpl.getxattrSync(path, key) +} + +function getxattr(path: string, key: string): Promise { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string, key: string): string => { + return FileIoImpl.getxattrSync(path, key); + }, path, key); + promise.then((ret: NullishType): void => { + let result = ret as string; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function dup(fd: number): File { + return FileIoImpl.dup(fd); +} + +function copyDirSync(src: string, dest: string, mode?: number): void { + return FileIoImpl.copyDirSync(src, dest, mode); +} + +function copyDir(src: string, dest: string, mode?: number): Promise { + return new Promise((resolve: (result: undefined) => void, + reject: (e: BusinessError>) => void): void => { + let promise = taskpool.execute((src: string, dest: string, mode?: number): undefined => + FileIoImpl.copyDirSync(src, dest, mode), src, dest, mode); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError>): void => { + reject(e); + }); + }); +} + +function copyDir(src: string, dest: string, callback: AsyncCallback>): void { + let promise = taskpool.execute((src: string, dest: string): undefined => + FileIoImpl.copyDirSync(src, dest), src, dest); + promise.then((ret: NullishType): void => { + let e = new BusinessError>(); + e.code = 0; + e.data = new Array(0); + callback(e, undefined); + }).catch((e: BusinessError>): void => { + callback(e, undefined); + }); +} + +function copyDir(src: string, dest: string, mode: number, callback: AsyncCallback>): void { + let promise = taskpool.execute((src: string, dest: string, mode: number): undefined => + FileIoImpl.copyDirSync(src, dest, mode), src, dest, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError>(); + e.code = 0; + e.data = new Array(0); + callback(e, undefined); + }).catch((e: BusinessError>): void => { + callback(e, undefined); + }); +} + +function copyDir(arg0: Object, arg1: Object, arg2: NullishType, arg3: NullishType): void { + let src = arg0 as string; + let dest = arg1 as string; + if (typeof arg2 === 'number' && typeof arg3 === 'function') { + let mode: number = 0; + try { + mode = arg2 as number; + } catch (error) { + mode = (arg2 as int) + 0; + } + let callback = arg3 as AsyncCallback>; + copyDir(src, dest, mode, callback); + return; + } + if (typeof arg2 === 'function') { + let callback = arg2 as AsyncCallback>; + copyDir(src, dest, callback); + return; + } +} + +function mkdirSync(path: string): void { + return FileIoImpl.mkdirSync(path) +} + +function fdatasyncSync(fd: number): void { + return FileIoImpl.fdatasyncSync(fd) +} + +function fdatasync(fd: number): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((fd: number): undefined => FileIoImpl.fdatasyncSync(fd), fd); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e as BusinessError); + }); + }); +} + +function fdatasync(fd: number, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number): undefined => FileIoImpl.fdatasyncSync(fd), fd); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function mkdirSync(path: string, recursion: boolean): void { + return FileIoImpl.mkdirSync(path, recursion) +} + +function mkdirSync1(path: string): undefined { + FileIoImpl.mkdirSync(path); + return undefined; +} + +function mkdirSync2(path: string, recursion: boolean): undefined { + FileIoImpl.mkdirSync(path, recursion); + return undefined; +} + +function mkdir(path: string): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string): undefined => mkdirSync1(path), path); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e as BusinessError); + }); + }); +} + +function mkdir(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): undefined => mkdirSync1(path), path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function mkdir(path: string, recursion: boolean): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string, recursion: boolean): undefined => + mkdirSync2(path, recursion), path, recursion); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: NullishType): void => { + reject(e as BusinessError); + }); + }); +} + +function mkdir(path: string, recursion: boolean, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string, recursion: boolean): undefined => + mkdirSync2(path, recursion), path, recursion); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function moveDirSync(src: string, dest: string, mode?: number): void { + return FileIoImpl.movedirSync(src, dest, mode) +} + +function moveDir(src: string, dest: string, mode?: number): Promise { + return new Promise((resolve: (result: undefined) => void, + reject: (e: BusinessError>) => void): void => { + let promise = taskpool.execute((src: string, dest: string, mode?: number): undefined => { + return FileIoImpl.movedirSync(src, dest, mode); + }, src, dest, mode); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError>): void => { + reject(e); + }); + }) +} + +function moveDir(src: string, dest: string, callback: AsyncCallback>): void { + let promise = taskpool.execute((src: string, dest: string): undefined => { + return FileIoImpl.movedirSync(src, dest); + }, src, dest); + promise.then((ret: NullishType): void => { + let e = new BusinessError>(); + e.code = 0; + e.data = new Array(0); + callback(e, undefined); + }).catch((e: BusinessError>): void => { + callback(e, undefined); + }); +} + +function moveDir(src: string, dest: string, mode: number, callback: AsyncCallback>): void { + let promise = taskpool.execute((src: string, dest: string, mode: number): undefined => { + return FileIoImpl.movedirSync(src, dest, mode); + }, src, dest, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError>(); + e.code = 0; + e.data = new Array(0); + callback(e, undefined); + }).catch((e: BusinessError>): void => { + callback(e, undefined); + }); +} + +function moveDir(arg0: Object, arg1: Object, arg2: NullishType, arg3: NullishType): void { + let src = arg0 as string; + let dest = arg1 as string; + if (typeof arg2 === 'number' && typeof arg3 === 'function') { + let mode: number = 0; + try { + mode = arg2 as number; + } catch (error) { + mode = (arg2 as int) + 0; + } + let callback = arg3 as AsyncCallback>; + moveDir(src, dest, mode, callback); + return; + } + if (typeof arg2 === 'function') { + let callback = arg2 as AsyncCallback>; + moveDir(src, dest, callback); + return; + } +} + +function mkdtempSync(prefix: string): string { + return FileIoImpl.mkdtempSync(prefix); +} + +function mkdtemp(prefix: string): Promise { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((prefix: string): string => { + return FileIoImpl.mkdtempSync(prefix); + }, prefix); + promise.then((ret: NullishType): void => { + let result = ret as string; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function mkdtemp(prefix: string, callback: AsyncCallback): void { + let promise = taskpool.execute((prefix: string): string => { + return FileIoImpl.mkdtempSync(prefix); + }, prefix); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as string; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, ""); + }); +} + +function moveFileSync(src: string, dest: string, mode?: number): void { + return FileIoImpl.moveFileSync(src, dest, mode); +} + +function moveFile(src: string, dest: string, mode?: number): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((src: string, dest: string, mode?: number): undefined => { + return FileIoImpl.moveFileSync(src, dest, mode); + }, src, dest, mode); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function moveFile(src: string, dest: string, mode: number, callback: AsyncCallback): void { + let promise = taskpool.execute((src: string, dest: string, mode: number): undefined => { + return FileIoImpl.moveFileSync(src, dest, mode); + }, src, dest, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function moveFile(src: string, dest: string, callback: AsyncCallback): void { + let promise = taskpool.execute((src: string, dest: string): undefined => { + return FileIoImpl.moveFileSync(src, dest); + }, src, dest); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function openSync(path: string, mode?: number): File { + return FileIoImpl.openSync(path, mode); +} + +function open(path: String, mode?: number): Promise { + return new Promise((resolve: (result: File) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: String, mode?: number): File => { + return FileIoImpl.openSync(path, mode); + },path, mode); + promise.then((ret: NullishType): void => { + let file = ret as File; + resolve(file); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function open(path: String, mode: number, callback: AsyncCallback): void { + let promise = taskpool.execute((path: String, mode: number): File => { + return FileIoImpl.openSync(path, mode); + }, path, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let file = ret as File; + callback(e, file); + }).catch((e: BusinessError): void => { + let f: File = new FileInner(0); + callback(e, f); + }); +} + +function open(path: String, callback: AsyncCallback): void { + let promise = taskpool.execute((path: String): File => { + return FileIoImpl.openSync(path); + }, path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let file = ret as File; + callback(e, file); + }).catch((e: BusinessError): void => { + let f: File = new FileInner(0); + callback(e, f); + }); +} + +function writeSync(fd: number, buffer: string | ArrayBuffer, options?: WriteOptions): number { + return FileIoImpl.writeSync(fd, buffer, options); +} + +function write(fd: number, buffer: string | ArrayBuffer, options?: WriteOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((fd: number, buffer: string | ArrayBuffer, options?: WriteOptions): number => { + return FileIoImpl.writeSync(fd, buffer, options); + }, fd, buffer, options); + promise.then((ret: NullishType): void => { + let result = ret as number + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function write(fd: number, buffer: string | ArrayBuffer, options: WriteOptions, + callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number, buffer: string | ArrayBuffer, options: WriteOptions): number => { + return FileIoImpl.writeSync(fd, buffer, options); + }, fd, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); +} + +function write(fd: number, buffer: string | ArrayBuffer, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number, buffer: string | ArrayBuffer): number => { + return FileIoImpl.writeSync(fd, buffer); + }, fd, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); +} + +function readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number { + return FileIoImpl.readSync(fd, buffer, options) +} + +function read(fd: number, buffer: ArrayBuffer, options?: ReadOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((fd: number, buffer: ArrayBuffer, options?: ReadOptions): number => { + return FileIoImpl.readSync(fd, buffer, options) + }, fd, buffer, options); + promise.then((ret: NullishType) => { + let result = ret as number; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function read(fd: number, buffer: ArrayBuffer, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number, buffer: ArrayBuffer): number => { + return FileIoImpl.readSync(fd, buffer); + }, fd, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); +} + +function read(fd: number, buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number, buffer: ArrayBuffer, options: ReadOptions): number => { + return FileIoImpl.readSync(fd, buffer, options); + }, fd, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); +} + +function readLinesSync(filePath: string, options?: Options): ReaderIterator { + return FileIoImpl.readlinesSync(filePath, options) +} + +function readLines(filePath: string, options?: Options): Promise { + return new Promise((resolve: (result: ReaderIterator) => void, + reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((filePath: string, options?: Options): ReaderIterator => { + return FileIoImpl.readlinesSync(filePath, options); + }, filePath, options); + promise.then((ret: NullishType): void => { + let it = ret as ReaderIterator; + resolve(it); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function readLines(filePath: string, callback: AsyncCallback): void { + let promise = taskpool.execute((filePath: string): ReaderIterator => { + return FileIoImpl.readlinesSync(filePath); + }, filePath); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let it = ret as ReaderIterator; + callback(e, it); + }).catch((e: BusinessError): void => { + let r: ReaderIterator = new ReaderIteratorInner(0); + callback(e, r); + }); +} + +function readLines(filePath: string, options: Options, callback: AsyncCallback): void { + let promise = taskpool.execute((filePath: string, options: Options): ReaderIterator => { + return FileIoImpl.readlinesSync(filePath, options); + }, filePath, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let it = ret as ReaderIterator; + callback(e, it); + }).catch((e: BusinessError): void => { + let r: ReaderIterator = new ReaderIteratorInner(0); + callback(e, r); + }); +} + +function rmdirSync(path: string): void { + return FileIoImpl.rmdirSync(path) +} + +function rmdir(path: string): Promise { + return new Promise((resolve: (result: undefined) => void, + reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string): void => FileIoImpl.rmdirSync(path), path); + promise.then((ret: NullishType) => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function rmdir(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): void => FileIoImpl.rmdirSync(path), path); + promise.then((ret: NullishType) => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function truncateSync(file: string | number, len?: number): void { + return FileIoImpl.truncateSync(file, len) +} + +function truncate(file: string | number, len?: number): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((file: string | number, len?: number): undefined => { + return FileIoImpl.truncateSync(file, len); + }, file, len); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }) +} + +function truncate(file: string | number, callback: AsyncCallback): void { + let promise = taskpool.execute((file: string | number): undefined => { + return FileIoImpl.truncateSync(file); + }, file); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function truncate(file: string | number, len: number, callback: AsyncCallback): void { + let promise = taskpool.execute((file: string | number, len: number): undefined => { + return FileIoImpl.truncateSync(file, len); + }, file, len); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function unlinkSync(path: string): void { + return FileIoImpl.unlinkSync(path) +} + +function unlink(path: string): Promise { + return new Promise((resolve: (result: undefined) => void, + reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string): undefined => unlinkSync(path), path); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function unlink(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): undefined => unlinkSync(path), path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function readText(filePath: string, options?: ReadTextOptions): Promise { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((filePath: string, options?: ReadTextOptions): string => { + return FileIoImpl.readTextSync(filePath, options); + }, filePath, options); + promise.then((ret: NullishType): void => { + let r = ret as string; + resolve(r); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function readText(filePath: string, callback: AsyncCallback): void { + let promise = taskpool.execute((filePath: string): string => { + return FileIoImpl.readTextSync(filePath); + }, filePath); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as string; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, ""); + }); +} + +function readText(filePath: string, options: ReadTextOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((filePath: string, options: ReadTextOptions): string => { + return FileIoImpl.readTextSync(filePath, options); + }, filePath, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as string; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, ""); + }); +} + +function readTextSync(filePath: string, options?: ReadTextOptions): string { + return FileIoImpl.readTextSync(filePath, options); +} + +function listFile(path: string, options?: ListFileOptions): Promise { + return new Promise((resolve: (result: string[]) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: string, options?: ListFileOptions): string[] => { + return FileIoImpl.listFileSync(path, options); + }, path, options); + promise.then((ret: NullishType): void => { + let r = ret as string[]; + resolve(r); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function listFile(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): string[] => { + return FileIoImpl.listFileSync(path); + }, path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as string[]; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, []); + }); +} + +function listFile(path: string, options: ListFileOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string, options: ListFileOptions): string[] => { + return FileIoImpl.listFileSync(path, options); + }, path, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as string[]; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, []); + }); +} + +function listFileSync(path: string, options?: ListFileOptions): string[] { + return FileIoImpl.listFileSync(path, options); +} + +function copyFileSync(src: string | number, dest: string | number, mode?: number): void { + return FileIoImpl.copyFileSync(src, dest, mode) +} + +function statSync(file: string | number): Stat { + return FileIoImpl.statSync(file) +} + +function stat(file: string | number): Promise { + return new Promise((resolve: (result: Stat) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((file: string | number): Stat => { + return FileIoImpl.statSync(file); + }, file); + promise.then((ret: NullishType): void => { + let r = ret as Stat; + resolve(r); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function stat(file: string | number, callback: AsyncCallback): void { + let p = taskpool.execute((file: string | number): Stat => { + return FileIoImpl.statSync(file); + }, file); + p.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as Stat; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, new StatInner(0)); + }); +} + +function fsyncSync(fd: number): void { + return FileIoImpl.fsyncSync(fd); +} + +function fsync(fd: number): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((fd: number): undefined => { + return FileIoImpl.fsyncSync(fd); + }, fd); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function fsync(fd: number, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number): undefined => { + return FileIoImpl.fsyncSync(fd); + }, fd); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function symlinkSync(target: string, srcPath: string): void { + return FileIoImpl.symlinkSync(target, srcPath); +} + +function symlink(target: string, srcPath: string): Promise { + return new Promise((resolve: (result: undefined) => void, + reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((target: string, srcPath: string): undefined => { + return FileIoImpl.symlinkSync(target, srcPath); + }, target, srcPath); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} +function renameSync(oldPath: string, newPath: string): void { + return FileIoImpl.renameSync(oldPath, newPath); +} + +function rename(oldPath: string, newPath: string): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((oldPath: string, newPath: string): undefined => { + return FileIoImpl.renameSync(oldPath, newPath); + }, oldPath, newPath); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function rename(oldPath: string, newPath: string, callback: AsyncCallback): void { + let promise = taskpool.execute((oldPath: string, newPath: string): undefined => { + return FileIoImpl.renameSync(oldPath, newPath); + }, oldPath, newPath); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function createRandomAccessFileSync(file: string | File, mode?: number, + options?: RandomAccessFileOptions): RandomAccessFile { + return FileIoImpl.createRandomAccessFileSync(file, mode, options); +} + +function createRandomAccessFile(file: string | File, mode?: number, + options?: RandomAccessFileOptions): Promise { + return new Promise((resolve: (result: RandomAccessFile) => void, + reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((file: string | File, mode?: number, + options?: RandomAccessFileOptions): RandomAccessFile => { + return FileIoImpl.createRandomAccessFileSync(file, mode, options); + }, file, mode, options); + promise.then((ret: NullishType): void => { + let raffile = ret as RandomAccessFileInner; + resolve(raffile); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function fdopenStream(fd: number, mode: string): Promise { + return new Promise((resolve: (result: Stream) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((fd: number, mode: string): Stream => { + return FileIoImpl.fdopenStreamSync(fd, mode); + }, fd, mode); + promise.then((ret: NullishType): void => { + let stream = ret as Stream; + resolve(stream); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function setxattrSync(path: string, key: string, value: string): void { + return FileIoImpl.setxattrSync(path, key, value) +} + +function setxattr(path: string, key: string, value: string): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string, key: string, value: string): undefined => + FileIoImpl.setxattrSync(path, key, value), path, key, value); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e as BusinessError); + }); + }); +} + +function createRandomAccessFile(file: string | File, callback: AsyncCallback): void { + let promise = taskpool.execute((file: string | File): RandomAccessFile => { + return FileIoImpl.createRandomAccessFileSync(file); + }, file); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let raffile = ret as RandomAccessFile; + callback(e, raffile); + }).catch((e: BusinessError): void => { + let f: RandomAccessFile = new RandomAccessFileInner(0); + callback(e, f); + }); +} + +function createRandomAccessFile(file: string | File, mode: number, + callback: AsyncCallback): void { + let promise = taskpool.execute((file: string | File, mode: number): RandomAccessFile => { + return FileIoImpl.createRandomAccessFileSync(file, mode); + }, file, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let raffile = ret as RandomAccessFile; + callback(e, raffile); + }).catch((e: BusinessError): void => { + let f: RandomAccessFile = new RandomAccessFileInner(0); + callback(e, f); + }); +} + +function fdopenStream(fd: number, mode: string, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number, mode: string): Stream => { + return FileIoImpl.fdopenStreamSync(fd, mode); + }, fd, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let stream = ret as Stream; + callback(e, stream); + }).catch((e: BusinessError): void => { + let r: Stream = new StreamInner(0); + callback(e, r); + }); +} + +function fdopenStreamSync(fd: number, mode: string): Stream { + return FileIoImpl.fdopenStreamSync(fd, mode); +} + +function createStream(path: string, mode: string): Promise { + return new Promise((resolve: (result: Stream) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: string, mode: string): Stream => { + return FileIoImpl.createStreamSync(path, mode); + }, path, mode); + promise.then((ret: NullishType): void => { + let stream = ret as Stream; + resolve(stream); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function createStream(path: string, mode: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string, mode: string): Stream => { + return FileIoImpl.createStreamSync(path, mode); + }, path, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let stream = ret as Stream; + callback(e, stream); + }).catch((e: BusinessError): void => { + let r: Stream = new StreamInner(0); + callback(e, r); + }); +} + +function createStreamSync(path: string, mode: string): Stream { + return FileIoImpl.createStreamSync(path, mode); +} + +// function createReadStream(path: string, options?: ReadStreamOptions): ReadStream { +// return new ReadStream(path, options) +// } + +// function createWriteStream(path: string, options?: WriteStreamOptions): WriteStream { +// return new WriteStream(path, options); +// } + +function createWatcher(path: string, events: number, listener: WatchEventListener): Watcher { + return FileIoImpl.createWatcherSync(path, events, listener); +} + +function symlink(target: string, srcPath: string, callback: AsyncCallback): void { + let promise = taskpool.execute((target: string, srcPath: string): undefined => { + return FileIoImpl.symlinkSync(target, srcPath); + }, target, srcPath); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function utimes(path: string, mtime: number): void { + return FileIoImpl.utimes(path, mtime); +} + +function lstatSync(path: string): Stat { + return FileIoImpl.lstatSync(path) +} + +function lstat(path: string): Promise { + return new Promise((resolve: (result: Stat) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: string): Stat => { + return FileIoImpl.lstatSync(path); + }, path); + promise.then((ret: NullishType): void => { + if (ret === null || ret === undefined) { + let e = new BusinessError(); + e.code = -1; + reject(e); + } else { + let r = ret as Stat; + resolve(r); + } + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function lstat(path: string, callback: AsyncCallback): void { + let p = taskpool.execute((path: string): Stat => { + return FileIoImpl.lstatSync(path); + }, path); + p.then((ret: NullishType): void => { + let e = new BusinessError(); + if (ret === null || ret === undefined) { + e.code = -1; + let stat: Stat = new StatInner(0); + callback(e, stat); + } else { + e.code = 0; + let r = ret as Stat; + callback(e, r); + } + }).catch((e: BusinessError): void => { + callback(e, new StatInner(0)); + }); +} +function copyFile(src: string | number, dest: string | number, mode?: number): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((src: string | number, dest: string | number, mode?: number): undefined => + FileIoImpl.copyFileSync(src, dest, mode), src, dest, mode); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function copy(srcUri: string, destUri: string, options?: CopyOptions): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((srcUri: string, destUri: string, options?: CopyOptions): undefined => + FileIoImpl.copySync(srcUri, destUri, options), srcUri, destUri, options); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function copyFile(src: string | number, dest: string | number, mode: number, callback: AsyncCallback): void { + let promise = taskpool.execute((src: string | number, dest: string | number, mode: number): undefined => + FileIoImpl.copyFileSync(src, dest, mode), src, dest, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function copy(srcUri: string, destUri: string, options: CopyOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((srcUri: string, destUri: string, options: CopyOptions): undefined => + FileIoImpl.copySync(srcUri, destUri, options), srcUri, destUri, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function copyFile(src: string | number, dest: string | number, callback: AsyncCallback): void { + let promise = taskpool.execute((src: string | number, dest: string | number): undefined => + FileIoImpl.copyFileSync(src, dest), src, dest); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function copy(srcUri: string, destUri: string, callback: AsyncCallback): void { + let promise = taskpool.execute((srcUri: string, destUri: string): undefined => + FileIoImpl.copySync(srcUri, destUri), srcUri, destUri); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function lseek(fd: number, offset: number, whence?: WhenceType): number { + return FileIoImpl.lseekSync(fd, offset, whence); +} + +export interface Filter { + suffix?: Array; + displayName?: Array; + mimeType?: Array; + fileSizeOver?: number; + lastModifiedAfter?: number; + excludeMedia?: boolean; +} + +export interface Progress { + processedSize: number; + totalSize: number; +} + +export interface DfsListeners { + onStatus(networkId: string, status: number): void; +} + +export class ProgressInner implements Progress { + processedSize: number; + totalSize: number; + + constructor(pSize: number, tSize: number) { + this.processedSize = pSize; + this.totalSize = tSize; + } +} + +export type ProgressListener = (progress: Progress) => void; + +export class TaskSignal { + private nativeTaskSignal: long = 0; + private native onCancelNative(): void; + private onCancelResolve: (path: string) => void = (path: string): void => {}; + private onCancelCallback(path: string): void { + if (this.onCancelResolve) { + this.onCancelResolve(path); + } + } + native cancel(): void; + onCancel(): Promise { + return new Promise((resolve: (path: string) => void, reject: (e: BusinessError) => void): void => { + this.onCancelResolve = resolve; + this.onCancelNative(); + }); + } +} + +export interface CopyOptions { + progressListener?: ProgressListener; + copySignal?: TaskSignal; +} + +export enum AccessModeType { + EXIST = 0, + WRITE = 2, + READ = 4, + READ_WRITE = 6, +} + +export enum AccessFlagType { + LOCAL = 0, +} + +export interface RandomAccessFile { + fd: number; + filePointer: number; + + setFilePointer(filePointer: number): void; + close(): void; + write(buffer: ArrayBuffer | string, options?: WriteOptions): Promise; + write(buffer: ArrayBuffer | string, callback: AsyncCallback): void; + write(buffer: ArrayBuffer | string, options: WriteOptions, callback: AsyncCallback): void; + writeSync(buffer: ArrayBuffer | string, options?: WriteOptions): number; + read(buffer: ArrayBuffer, options?: ReadOptions): Promise; + read(buffer: ArrayBuffer, callback: AsyncCallback): void; + read(buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void; + readSync(buffer: ArrayBuffer, options?: ReadOptions): number; + // getReadStream(): ReadStream; + // getWriteStream(): WriteStream; +} + +export class RandomAccessFileInner implements RandomAccessFile { + fd: number = -1; + filePointer: number = -1; + + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + setFilePointer(filePointer: number): void { + this.setFilePointer0(filePointer); + this.filePointer = filePointer; + } + + native setFilePointer0(filePointer: number): void; + + native close(): void; + + writeSync(buffer: ArrayBuffer | string, options?: WriteOptions): number { + let length = options ? this.writeSync0(buffer, options) : this.writeSync0(buffer); + this.filePointer += (options?.offset?? 0) + length; + return length; + } + + native writeSync0(buffer: ArrayBuffer | string, options?: WriteOptions): number; + + write(buffer: ArrayBuffer | string, options?: WriteOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((buffer: ArrayBuffer | string, options?: WriteOptions): number => { + return this.writeSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let result = ret as number + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + write(buffer: ArrayBuffer | string, options: WriteOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer | string, options: WriteOptions): number => { + return this.writeSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + write(buffer: ArrayBuffer | string, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer | string): number => { + return this.writeSync(buffer); + }, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + readSync(buffer: ArrayBuffer, options?: ReadOptions): number { + const length = options ? this.readSync0(buffer, options) : this.readSync0(buffer); + this.filePointer += (options?.offset?? 0) + length; + return length; + } + + native readSync0(buffer: ArrayBuffer, options?: ReadOptions): number; + + read(buffer: ArrayBuffer, options?: ReadOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((buffer: ArrayBuffer, options?: ReadOptions): number => { + return this.readSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let result = ret as number; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + read(buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer, options: ReadOptions): number => { + return this.readSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + read(buffer: ArrayBuffer, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer): number => { + return this.readSync(buffer); + }, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + // native getReadStream(): ReadStream; + // native getWriteStream(): WriteStream; +} + +export interface File { + fd: number; + path: String; + name: String; + + getParent(): String; + lock(exclusive?: boolean): Promise; + lock(callback: AsyncCallback): void; + lock(exclusive: boolean, callback: AsyncCallback): void; + tryLock(exclusive?: boolean): void; + unlock(): void; +} + +export class FileInner implements File { + fd: number = -1; + path: String = ""; + name: String = ""; + + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + native getParent(): String; + native lockSync(exclusive?: boolean): void; + + lock(exclusive?: boolean): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((exclusive?: boolean): undefined => { + return this.lockSync(exclusive); + }, exclusive); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + lock(callback: AsyncCallback): void { + let promise = taskpool.execute((): undefined => { + return this.lockSync(); + }); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); + } + + lock(exclusive: boolean, callback: AsyncCallback): void { + let promise = taskpool.execute((exclusive: boolean): undefined => { + return this.lockSync(exclusive); + }, exclusive); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); + } + + native tryLock(exclusive?: boolean): void; + native unlock(): void; + +} + +export enum LocationType { + LOCAL = 1, + CLOUD = 2 +} + + +export class ReaderIteratorResultInner implements ReaderIteratorResult { + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + done: boolean = false; + value: string = ""; +} + +export interface ReaderIterator { + next(): ReaderIteratorResult; +} + +export class ReaderIteratorInner implements ReaderIterator { + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + native next(): ReaderIteratorResult; +} + +export interface Stat { + ino: bigint; + mode: number; + uid: number; + gid: number; + size: number; + atime: number; + mtime: number; + ctime: number; + atimeNs: bigint; + mtimeNs: bigint; + ctimeNs: bigint; + location: LocationType; + + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isDirectory(): boolean; + isFIFO(): boolean; + isFile(): boolean; + isSocket(): boolean; + isSymbolicLink(): boolean; +} + +export class StatInner implements Stat { + ino: bigint = 0n; + mode: number; + uid: number; + gid: number; + size: number; + atime: number; + mtime: number; + ctime: number; + atimeNs: bigint = 0n; + mtimeNs: bigint = 0n; + ctimeNs: bigint = 0n; + location: LocationType = LocationType.LOCAL; + + private nativeStat: long = 0; + + constructor(stat: long) { + if (this.nativeStat === 0) { + this.nativeStat = stat; + } + } + + native isBlockDevice(): boolean; + native isCharacterDevice(): boolean; + native isDirectory(): boolean; + native isFIFO(): boolean; + native isFile(): boolean; + native isSocket(): boolean; + native isSymbolicLink(): boolean; +} + +export interface Stream { + close(): Promise; + close(callback: AsyncCallback): void; + closeSync(): void; + flush(): Promise; + flush(callback: AsyncCallback): void; + flushSync(): void; + write(buffer: ArrayBuffer | string, options?: WriteOptions): Promise; + write(buffer: ArrayBuffer | string, callback: AsyncCallback): void; + write(buffer: ArrayBuffer | string, options: WriteOptions, callback: AsyncCallback): void; + writeSync(buffer: ArrayBuffer | string, options?: WriteOptions): number; + read(buffer: ArrayBuffer, options?: ReadOptions): Promise; + read(buffer: ArrayBuffer, callback: AsyncCallback): void; + read(buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void; + readSync(buffer: ArrayBuffer, options?: ReadOptions): number; + seek(offset: number, whence?: number): number; +} + +export class StreamInner implements Stream { + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + close(): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((): undefined => this.closeSync()); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + close(callback: AsyncCallback): void { + let promise = taskpool.execute((): undefined => this.closeSync()); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); + } + + native closeSync(): void; + + flush(): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((): undefined => this.flushSync()); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + flush(callback: AsyncCallback): void { + let promise = taskpool.execute((): undefined => this.flushSync()); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); + } + + native flushSync(): void; + + write(buffer: ArrayBuffer | string, options?: WriteOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((buffer: ArrayBuffer | string, options?: WriteOptions): number => { + return this.writeSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let result = ret as number + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + write(buffer: ArrayBuffer | string, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer | string): number => { + return this.writeSync(buffer); + }, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + write(buffer: ArrayBuffer | string, options: WriteOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer | string, options: WriteOptions): number => { + return this.writeSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + native writeSync(buffer: ArrayBuffer | string, options?: WriteOptions): number; + + read(buffer: ArrayBuffer, options?: ReadOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((buffer: ArrayBuffer, options?: ReadOptions): number => { + return this.readSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let result = ret as number + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + read(buffer: ArrayBuffer, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer): number => { + return this.readSync(buffer); + }, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + read(buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer, options: ReadOptions): number => { + return this.readSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + native readSync(buffer: ArrayBuffer, options?: ReadOptions): number; + native seek(offset: number, whence?: number): number; +} + +// export class ReadStream extends stream.Readable { +// path: string; +// bytesRead: number; +// private offset: number; +// private start?: number; +// private end?: number; +// private stream?: Stream; + +// constructor(path: string, options?: ReadStreamOptions) { +// super(); +// this.path = path; +// this.bytesRead = 0; +// this.start = options?.start; +// this.end = options?.end; +// this.stream = createStreamSync(this.path, 'r'); +// this.offset = this.start ?? 0; +// } + +// seek(offset: number, whence?: WhenceType): number { +// if (whence === undefined) { +// let off = this.stream?.seek(offset); +// if (off !== undefined) { +// this.offset = off +// } +// } else { +// let off = this.stream?.seek(offset, whence); +// if (off !== undefined) { +// this.offset = off +// } +// } +// return this.offset; +// } + +// close(): void { +// this.stream?.close(); +// } + +// doInitialize(callback: () => void): void { +// callback(); +// } + +// doRead(size: number): void { +// let readSize = size; +// let end = this.end +// if (end !== undefined) { +// if (this.offset > end) { +// this.push(null); +// return; +// } +// if (this.offset + readSize > end) { +// readSize = end - this.offset; +// } +// } +// let buffer = new ArrayBuffer(readSize); +// const off = this.offset; +// this.offset += readSize; +// this.stream?.read(buffer, { offset: off, length: readSize }) +// .then((readOut: number) => { +// if (readOut > 0) { +// this.bytesRead += readOut; +// this.push(new Uint8Array(buffer.slice(0, readOut))); +// } +// if (readOut !== readSize || readOut < size) { +// this.offset = this.offset - readSize + readOut; +// this.push(null); +// } +// }); +// } +// } + +// export class WriteStream extends stream.Writable { +// path: string; +// bytesWritten: number; +// private offset: number; +// private mode: string; +// private start?: number; +// private stream?: Stream; + +// constructor(path: string, options?: WriteStreamOptions) { +// super(); +// this.path = path; +// this.bytesWritten = 0; +// this.start = options?.start; +// this.mode = this.convertOpenMode(options?.mode); +// this.stream = createStreamSync(this.path, this.mode); +// this.offset = this.start ?? 0; +// } + +// seek(offset: number, whence?: WhenceType): number { +// if (whence === undefined) { +// let off = this.stream?.seek(offset); +// if (off !== undefined) { +// this.offset = off +// } +// } else { +// let off = this.stream?.seek(offset, whence); +// if (off !== undefined) { +// this.offset = off +// } +// } +// return this.offset; +// } + +// close(): void { +// this.stream?.close(); +// } + +// closeSync(): void { +// this.stream?.closeSync(); +// } + +// doInitialize(callback: () => void): void { +// callback(); +// } + +// doWrite(chunk: string | ArrayBuffer, encoding: string, callback: () => void): void { +// this.stream?.write(chunk, { offset: this.offset }) +// .then((writeIn: number) => { +// this.offset += writeIn; +// this.bytesWritten += writeIn; +// callback(); +// }) +// .finally(() => { +// this.stream?.flush(); +// }); +// } + +// convertOpenMode(mode?: number): string { +// let modeStr = 'w'; +// if (mode === undefined) { +// return modeStr; +// } +// if ((mode as number) & fileIo.OpenMode.WRITE_ONLY) { +// modeStr = 'w'; +// } +// if ((mode as number) & fileIo.OpenMode.READ_WRITE) { +// modeStr = 'w+'; +// } +// if (((mode as number) & fileIo.OpenMode.WRITE_ONLY) && ((mode as number) & fileIo.OpenMode.APPEND)) { +// modeStr = 'a'; +// } +// if (((mode as number) & fileIo.OpenMode.READ_WRITE) && ((mode as number) & fileIo.OpenMode.APPEND)) { +// modeStr = 'a+'; +// } +// return modeStr; +// } +// } + +export class AtomicFile { + static { + loadLibrary("ani_file_fs"); + } + + private nativePtr: long = 0; + private native getPath(): string; + // private writeStream: WriteStream | null = null; + + native constructor(path: string); + + native getBaseFile(): File; + + // native openRead(): ReadStream; + + native readFully(): ArrayBuffer; + + // native nativeStartWrite(): WriteStream; + // startWrite(): WriteStream { + // let ws = this.nativeStartWrite(); + // this.writeStream = ws; + // return ws; + // } + + // native nativeFinishWrite(): void; + // finishWrite(): void { + // if (!this.writeStream) { + // throw createBusinessError(UNKNOWN_ERR, UNKNOWN_MSG); + // } + // this.writeStream?.close(); + // this.nativeFinishWrite(); + // this.writeStream = null; + // }; + + // native nativeFailWrite(): void; + // failWrite(): void { + // if (!this.writeStream) { + // throw createBusinessError(UNKNOWN_ERR, UNKNOWN_MSG); + // } + // this.writeStream?.close(); + // this.nativeFailWrite(); + // this.writeStream = null; + // }; + + native delete(): void; +} + +export enum WhenceType { + SEEK_SET = 0, + SEEK_CUR = 1, + SEEK_END = 2 +} + +export interface Watcher { + start(): void; + stop(): void; +} + +class WatcherInner implements Watcher { + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + native start(): void; + + native stop(): void; +} + +} // namespace fileIo + +export interface ConflictFiles { + srcFile: string; + destFile: string; +} + +class ConflictFilesInner implements ConflictFiles { + srcFile: string = ""; + destFile: string = ""; + + constructor(src: string, dest: string) { + this.srcFile = src; + this.destFile = dest; + } +} + +export interface WatchEvent { + fileName: string; + event: number; + cookie: number; +} + +class WatchEventInner implements WatchEvent { + fileName: string = ''; + event: number; + cookie: number; + + constructor(fileName: string, event: number, cookie: number) { + this.fileName = fileName; + this.event = event; + this.cookie = cookie; + } + +} + +export type WatchEventListener = (event: WatchEvent) => void; + +export interface Options { + encoding?: string; +} + +export interface ReadOptions { + offset?: number; + length?: number; +} + +export interface ReadTextOptions extends ReadOptions { + encoding?: string; +} + +export interface WriteOptions extends Options { + offset?: number; + length?: number; +} + +export interface RandomAccessFileOptions { + start?: number; + end?: number; +} + +export interface ListFileOptions { + recursion?: boolean; + listNum?: number; + filter?: Filter; +} + +export interface WriteStreamOptions { + mode?: number; + start?: number; +} + +export interface ReadStreamOptions { + start?: number; + end?: number; +} + +export class ReadStreamOptionsInner implements ReadStreamOptions { + constructor() {} + start?: number; + end?: number; +} + +export class WriteStreamOptionsInner implements WriteStreamOptions { + constructor() {} + mode?: number; + start?: number; +} + +export interface ReaderIteratorResult { + done: boolean; + value: string; +} + +export interface Filter { + suffix?: Array; + displayName?: Array; + mimeType?: Array; + fileSizeOver?: number; + lastModifiedAfter?: number; + excludeMedia?: boolean; +} + +type TaskSignal = fileIo.TaskSignal; +type DfsListeners = fileIo.DfsListeners; + + +export class FileIoImpl { + + static { + loadLibrary("ani_file_fs"); + } + + static native doAccessSync(path: string, mode?: fileIo.AccessModeType, flag?: fileIo.AccessFlagType): boolean; + + static native closeSync(file: number | fileIo.File): void; + + static native copySync(srcUri: string, destUri: string, options?: fileIo.CopyOptions): void; + + static native connectDfs(networkId: string, listeners: DfsListeners): void; + + static native copyDirSync(src: string, dest: string, mode?: number): void; + + static native copyFileSync(src: string | number, dest: string | number, mode?: number): void; + + static native disConnectDfs(networkId: string): void; + + static native fdatasyncSync(fd: number): void; + + static native getxattrSync(path: string, key: string): string; + + static native createStreamSync(path: string, mode: string): fileIo.Stream; + + static native createWatcherSync(path: string, events: number, listener: WatchEventListener): fileIo.Watcher; + + static native fdopenStreamSync(fd: number, mode: string): fileIo.Stream; + + static native dup(fd: number): fileIo.File; + + static native listFileSync(path: string, options?: ListFileOptions): string[]; + + static native lstatSync(path: string): fileIo.Stat; + + static native lseekSync(fd: number, offset: number, whence?: fileIo.WhenceType): number; + + static native mkdirSync(path: string): void; + + static native mkdirSync(path: string, recursion: boolean): void; + + static native movedirSync(src: string, dest: string, mode?: number): void; + + static native mkdtempSync(prefix: string): string; + + static native moveFileSync(src: String, dest: String, mode?: number): void; + + static native openSync(path: String, mode?: number): fileIo.File; + + static native readlinesSync(filePath: string, options?: Options): fileIo.ReaderIterator; + + static native readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number; + + static native readTextSync(filePath: string, options?: ReadTextOptions): string; + + static native rmdirSync(path: string): void; + + static native setxattrSync(path: string, key: string, value: string): void; + + static native statSync(file: string | number): fileIo.Stat; + + static native truncateSync(file: string | number, len?: number): void; + + static native unlinkSync(path: string): void; + + static native writeSync(fd: number, buffer: string | ArrayBuffer, options?: WriteOptions): number; + + static native fsyncSync(fd: number): void; + + static native renameSync(oldPath: string, newPath: string): void; + + static native createRandomAccessFileSync(file: string | fileIo.File, mode?: number, + options?: RandomAccessFileOptions): fileIo.RandomAccessFile; + + static native symlinkSync(target: string, srcPath: string): void; + + static native utimes(path: string, mtime: number): void; +} diff --git a/interfaces/kits/js/src/mod_fs/fs_utils.cpp b/interfaces/kits/js/src/mod_fs/fs_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..94b7b81bd336cfecce0ba093bd48fa5c9d6fd4f2 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/fs_utils.cpp @@ -0,0 +1,113 @@ +/* + * 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 "fs_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +namespace { +const vector PUBLIC_DIR_PATHS = { "/Documents" }; +} + +tuple FsUtils::GetActualLen(size_t bufLen, size_t bufOff, const optional &length) +{ + size_t retLen = bufLen - bufOff; + + if (length.has_value()) { + int64_t opLength = length.value(); + if (opLength < 0 || static_cast(opLength) > retLen) { + HILOGE("Invalid option.length"); + return { false, 0 }; + } + retLen = static_cast(opLength); + } + return { true, retLen }; +} + +uint32_t FsUtils::ConvertFlags(const uint32_t &flags) +{ + // default value is usrReadOnly 00 + uint32_t flagsABI = 0; + flagsABI |= ((flags & USR_WRITE_ONLY) == USR_WRITE_ONLY) ? WRONLY : 0; + flagsABI |= ((flags & USR_RDWR) == USR_RDWR) ? RDWR : 0; + flagsABI |= ((flags & USR_CREATE) == USR_CREATE) ? CREATE : 0; + flagsABI |= ((flags & USR_TRUNC) == USR_TRUNC) ? TRUNC : 0; + flagsABI |= ((flags & USR_APPEND) == USR_APPEND) ? APPEND : 0; + flagsABI |= ((flags & USR_NONBLOCK) == USR_NONBLOCK) ? NONBLOCK : 0; + flagsABI |= ((flags & USR_DIRECTORY) == USR_DIRECTORY) ? DIRECTORY : 0; + flagsABI |= ((flags & USR_NOFOLLOW) == USR_NOFOLLOW) ? NOFOLLOW : 0; + flagsABI |= ((flags & USR_SYNC) == USR_SYNC) ? SYNC : 0; + return flagsABI; +} + +void FsUtils::FsReqCleanup(uv_fs_t *req) +{ + uv_fs_req_cleanup(req); + if (req) { + delete req; + req = nullptr; + } +} + +string FsUtils::GetModeFromFlags(const uint32_t &flags) +{ + const string readMode = "r"; + const string writeMode = "w"; + const string appendMode = "a"; + const string truncMode = "t"; + string mode = readMode; + mode += (((flags & O_RDWR) == O_RDWR) ? writeMode : ""); + mode = (((flags & O_WRONLY) == O_WRONLY) ? writeMode : mode); + if (mode != readMode) { + mode += ((flags & O_TRUNC) ? truncMode : ""); + mode += ((flags & O_APPEND) ? appendMode : ""); + } + return mode; +} + +bool FsUtils::CheckPublicDirPath(const string &sandboxPath) +{ + for (const string &path : PUBLIC_DIR_PATHS) { + if (sandboxPath.find(path) == 0) { + return true; + } + } + return false; +} + +string FsUtils::Decode(const string &uri) +{ + ostringstream outPutStream; + const int32_t encodeLen = 2; + size_t index = 0; + while (index < uri.length()) { + if (uri[index] == '%') { + int hex = 0; + istringstream inputStream(uri.substr(index + 1, encodeLen)); + inputStream >> hex >> hex; + outPutStream << static_cast(hex); + index += encodeLen + 1; + } else { + outPutStream << uri[index]; + index++; + } + } + + return outPutStream.str(); +} + +} // namespace OHOS::FileManagement::ModuleFileIO diff --git a/interfaces/kits/js/src/mod_fs/fs_utils.h b/interfaces/kits/js/src/mod_fs/fs_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..e75809ff245043e9ba71165decfb66689ce8113c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/fs_utils.h @@ -0,0 +1,99 @@ +/* + * 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 FILEMANAGEMENT_FS_UTILS_H +#define FILEMANAGEMENT_FS_UTILS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "fd_guard.h" +#include "uv.h" + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +#include "iremote_broker.h" +#endif + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +constexpr int32_t RDONLY = UV_FS_O_RDONLY; +constexpr int32_t WRONLY = UV_FS_O_WRONLY; +constexpr int32_t RDWR = UV_FS_O_RDWR; +constexpr int32_t CREATE = UV_FS_O_CREAT; +constexpr int32_t TRUNC = UV_FS_O_TRUNC; +constexpr int32_t APPEND = UV_FS_O_APPEND; +constexpr int32_t NONBLOCK = UV_FS_O_NONBLOCK; +constexpr int32_t DIRECTORY = UV_FS_O_DIRECTORY; +constexpr int32_t NOFOLLOW = UV_FS_O_NOFOLLOW; +constexpr int32_t SYNC = UV_FS_O_SYNC; + +constexpr uint32_t MODE_EXIST = 00; +constexpr uint32_t MODE_WRITE = 02; +constexpr uint32_t MODE_READ = 04; +constexpr uint32_t MODE_READ_WRITE = 06; + +constexpr uint32_t USR_READ_ONLY = 00; +constexpr uint32_t USR_WRITE_ONLY = 01; +constexpr uint32_t USR_RDWR = 02; +constexpr uint32_t USR_CREATE = 0100; +constexpr uint32_t USR_TRUNC = 01000; +constexpr uint32_t USR_APPEND = 02000; +constexpr uint32_t USR_NONBLOCK = 04000; +constexpr uint32_t USR_DIRECTORY = 0200000; +constexpr uint32_t USR_NOFOLLOW = 0400000; +constexpr uint32_t USR_SYNC = 04010000; + +const double NS = 1e9; +const double MS = 1e3; + +struct FileInfo { + bool isPath = false; + unique_ptr path = { nullptr }; + unique_ptr fdg = { nullptr }; +}; + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +class FileIoToken : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.fileio.open"); + + FileIoToken() = default; + virtual ~FileIoToken() noexcept = default; +}; +#endif + +class FsUtils { +public: + static tuple GetActualLen(size_t bufLen, size_t bufOff, const optional &length = nullopt); + static uint32_t ConvertFlags(const uint32_t &flags); + static void FsReqCleanup(uv_fs_t *req); + static string GetModeFromFlags(const uint32_t &flags); + static bool CheckPublicDirPath(const string &sandboxPath); + static string Decode(const string &uri); +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // FILEMANAGEMENT_FS_UTILS_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44b8faf6e3ac8aece21d13579e52bbd4f2a37655 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp @@ -0,0 +1,247 @@ +/* + * 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 "listfile_ani.h" + +#include "ani_signature.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "listfile_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +tuple ParseBooleanParam(ani_env *env, ani_object obj, string tag) +{ + ani_ref bool_ref; + ani_boolean isUndefined; + if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, tag.c_str(), &bool_ref)) { + return { false, false }; + } + env->Reference_IsUndefined(bool_ref, &isUndefined); + if (isUndefined) { + return { true, false }; + } + auto unboxedDesc = BoxedTypes::Boolean::unboxedDesc.c_str(); + auto unboxedSig = BoxedTypes::Boolean::unboxedSig.c_str(); + ani_boolean bool_ref_res; + if (ANI_OK != env->Object_CallMethodByName_Boolean( + static_cast(bool_ref), unboxedDesc, unboxedSig, &bool_ref_res)) { + return { false, false }; + } + return { true, static_cast(bool_ref_res) }; +} + +tuple ParseIntParam(ani_env *env, ani_object obj, string tag) +{ + int result = 0; + ani_boolean isUndefined; + ani_ref result_ref; + if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, tag.c_str(), &result_ref)) { + return { false, result }; + } + env->Reference_IsUndefined(result_ref, &isUndefined); + if (isUndefined) { + return { true, result }; + } + ani_int result_ref_res; + if (ANI_OK != env->Object_CallMethodByName_Int( + static_cast(result_ref), "toInt", nullptr, &result_ref_res)) { + result = -1; + return { false, result }; + } + result = static_cast(result_ref_res); + return { true, result }; +} + +tuple> ParseDoubleParam(ani_env *env, ani_object obj, string tag) +{ + ani_boolean isUndefined; + ani_ref result_ref; + if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, tag.c_str(), &result_ref)) { + return { false, nullopt }; + } + env->Reference_IsUndefined(result_ref, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + ani_double result_ref_res; + if (ANI_OK != env->Object_CallMethodByName_Double( + static_cast(result_ref), "toDouble", nullptr, &result_ref_res)) { + return { false, nullopt }; + } + double result = static_cast(result_ref_res); + return { true, make_optional(result) }; +} + +tuple>> ParseArrayString(ani_env *env, ani_object obj, string tag) +{ + ani_boolean isUndefined; + ani_ref result_ref; + vector strings; + if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, tag.c_str(), &result_ref)) { + return { false, nullopt }; + } + env->Reference_IsUndefined(result_ref, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + ani_double length; + if (ANI_OK != env->Object_GetPropertyByName_Double( + static_cast(result_ref), "length", &length) || length == 0) { + return { false, nullopt }; + } + auto getterDesc = BuiltInTypes::Array::getterDesc.c_str(); + auto getterSig = BuiltInTypes::Array::objectGetterSig.c_str(); + for (int i = 0; i < int(length); i++) { + ani_ref stringEntryRef; + if (ANI_OK != env->Object_CallMethodByName_Ref( + static_cast(result_ref), getterDesc, getterSig, &stringEntryRef, (ani_int)i)) { + return { false, nullopt }; + } + auto [succ, tmp] = TypeConverter::ToUTF8String(env, static_cast(stringEntryRef)); + if (!succ) { + return { false, nullopt }; + } + strings.emplace_back(tmp); + } + return { true, make_optional>(move(strings)) }; +} + +tuple> ParseFilter(ani_env *env, ani_object obj) +{ + FsFileFilter filter; + + auto [succfileSizeOver, fileSizeOver] = ParseIntParam(env, obj, "fileSizeOver"); + if (!succfileSizeOver) { + HILOGE("Illegal option.fileSizeOver parameter"); + return { false, move(filter) }; + } + filter.SetFileSizeOver(fileSizeOver); + + auto [succlastModifiedAfter, lastModifiedAfter] = ParseDoubleParam(env, obj, "lastModifiedAfter"); + if (!succlastModifiedAfter) { + HILOGE("Illegal option.lastModifiedAfter parameter"); + return { false, move(filter) }; + } + filter.SetLastModifiedAfter(lastModifiedAfter); + + auto [succSuffix, suffix] = ParseArrayString(env, obj, "suffix"); + if (!succSuffix) { + HILOGE("Illegal option.suffix parameter"); + return { false, move(filter) }; + } + filter.SetSuffix(move(suffix)); + + auto [succDisplayName, displayName] = ParseArrayString(env, obj, "displayName"); + if (!succDisplayName) { + HILOGE("Illegal option.displayName parameter"); + return { false, move(filter) }; + } + filter.SetDisplayName(move(displayName)); + + return { true, move(filter) }; +} + +tuple> ParseArgs(ani_env *env, ani_object obj) +{ + FsListFileOptions result; + ani_boolean isUndefined; + env->Reference_IsUndefined(obj, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + auto [succRecursion, recursion] = ParseBooleanParam(env, obj, "recursion"); + if (!succRecursion) { + HILOGE("Invalid recursion"); + return { false, nullopt }; + } + result.recursion = recursion; + + auto [succlistNum, listNumRes] = ParseIntParam(env, obj, "listNum"); + if (!succlistNum) { + HILOGE("Invalid listNum"); + return { false, nullopt }; + } + result.listNum = (int)listNumRes; + + ani_ref filter_ref; + if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, "filter", &filter_ref)) { + HILOGE("Invalid filter"); + return { false, nullopt }; + } + env->Reference_IsUndefined(filter_ref, &isUndefined); + if (isUndefined) { + return { true, make_optional(result) }; + } + auto [succFilter, filterFilterClass] = ParseFilter(env, static_cast(filter_ref)); + if (!succFilter) { + HILOGE("Invalid filter"); + return { false, nullopt }; + } + result.filter = move(filterFilterClass); + + return { true, make_optional(result) }; +} + +ani_array_ref ListFileAni::ListFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_object obj) +{ + auto [succPath, srcPath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto [succOpt, opt] = ParseArgs(env, obj); + if (!succOpt) { + HILOGE("Invalid options Arguments"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto ret = ListFileCore::DoListFile(srcPath, opt); + if (!ret.IsSuccess()) { + HILOGE("DoListFile failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + auto fileList = ret.GetData().value(); + const std::string *strArray = fileList.data(); + auto [succ, result] = TypeConverter::ToAniStringList(env, strArray, fileList.size()); + if (!succ) { + HILOGE("Convert list file result to ani string array failed"); + 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/listfile_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..63ff7731db00fd48fae52f975b7af4f6aa99f99d --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.h @@ -0,0 +1,36 @@ +/* + * 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_FILELIST_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FILELIST_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class ListFileAni final { +public: + static ani_array_ref ListFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_object obj); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FILELIST_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/mkdir_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/mkdir_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5cd88374fc3bf4e0af4e4eba32427439116a59f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/mkdir_ani.cpp @@ -0,0 +1,65 @@ +/* + * 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 "mkdir_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "mkdir_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +void MkdirkAni::MkdirSync0(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path) +{ + auto [succ, pathStr] = TypeConverter::ToUTF8String(env, path); + if (!succ) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return; + } + auto ret = MkdirCore::DoMkdir(pathStr); + if (!ret.IsSuccess()) { + HILOGE("Mkdir failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +void MkdirkAni::MkdirSync1(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_boolean recursion) +{ + auto [succ, pathStr] = ANI::TypeConverter::ToUTF8String(env, path); + if (!succ) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return; + } + auto ret = MkdirCore::DoMkdir(pathStr, recursion); + if (!ret.IsSuccess()) { + HILOGE("DoMkdir failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/mkdir_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/mkdir_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..8ed780e9619e99f3390c2db0493d9063a9b37e33 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/mkdir_ani.h @@ -0,0 +1,37 @@ +/* + * 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_MKDIR_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_MKDIR_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class MkdirkAni final { +public: + static void MkdirSync0(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path); + static void MkdirSync1(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_boolean recursion); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_MKDIR_ANI_H diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/read_text_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/read_text_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..05689d3d79dd010dc42ea4374d4648e08a78b358 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/read_text_ani.cpp @@ -0,0 +1,108 @@ +/* + * 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 "read_text_ani.h" + +#include +#include "ani_helper.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "read_text_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI; + +static tuple> ToReadTextOptions(ani_env *env, ani_object obj) +{ + ReadTextOptions options; + + ani_boolean isUndefined; + env->Reference_IsUndefined(obj, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + auto [succOffset, offset] = AniHelper::ParseInt64Option(env, obj, "offset"); + if (!succOffset) { + HILOGE("Illegal option.offset parameter"); + return { false, nullopt }; + } + options.offset = offset; + + auto [succLength, length] = AniHelper::ParseInt64Option(env, obj, "length"); + if (!succLength) { + HILOGE("Illegal option.length parameter"); + return { false, nullopt }; + } + options.length = length; + + auto [succEncoding, encoding] = AniHelper::ParseEncoding(env, obj); + if (!succEncoding) { + HILOGE("Illegal option.encoding parameter"); + return { false, nullopt }; + } + options.encoding = encoding; + + return { true, make_optional(move(options)) }; +} + +ani_string ReadTextAni::ReadTextSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string filePath, ani_object obj) +{ + auto [succOpt, options] = ToReadTextOptions(env, obj); + if (!succOpt) { + HILOGE("Invalid options"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto [succPath, path] = TypeConverter::ToUTF8String(env, filePath); + if (!succPath) { + HILOGE("Invalid Path"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto ret = ReadTextCore::DoReadText(path, options); + if (!ret.IsSuccess()) { + HILOGE("DoReadText failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + const auto &resText = ret.GetData().value(); + string res = std::get<0>(resText); // get buffer + size_t size = std::get<1>(resText); // get buffer length + auto [succ, result] = TypeConverter::ToAniString(env, res, size); + if (!succ) { + HILOGE("Convert result to ani string failed"); + 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/read_text_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/read_text_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..5d3bf6ad10e9152f9d72f2545e2cc499f1843081 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/read_text_ani.h @@ -0,0 +1,36 @@ +/* + * 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_READ_TEXT_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_TEXT_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class ReadTextAni final { +public: + static ani_string ReadTextSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string filePath, ani_object obj); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_TEXT_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/unlink_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/unlink_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..91a929d134e2b5443fe840fc16441cedf4e45f5e --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/unlink_ani.cpp @@ -0,0 +1,48 @@ +/* + * 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 "unlink_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" +#include "unlink_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +void UnlinkAni::UnlinkSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path) +{ + auto [succ, pathStr] = TypeConverter::ToUTF8String(env, path); + if (!succ) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return; + } + auto ret = UnlinkCore::DoUnlink(pathStr); + if (!ret.IsSuccess()) { + HILOGE("Unlink failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +} // 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/unlink_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/unlink_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..817b258000b9f13b5dbbc8f498b00cc74e7dc1e0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/unlink_ani.h @@ -0,0 +1,36 @@ +/* + * 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_UNLINK_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_UNLINK_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class UnlinkAni final { +public: + static void UnlinkSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_UNLINK_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/write_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/write_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f20a83917d86ca6b514c7b49fe818bd92c661ae4 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/write_ani.cpp @@ -0,0 +1,148 @@ +/* + * 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 "write_ani.h" + +#include +#include "ani_helper.h" +#include "ani_signature.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" +#include "write_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static tuple> ToWriteOptions(ani_env *env, ani_object obj) +{ + WriteOptions options; + ani_boolean isUndefined; + env->Reference_IsUndefined(obj, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + auto [succOffset, offset] = AniHelper::ParseInt64Option(env, obj, "offset"); + if (!succOffset) { + HILOGE("Illegal option.offset parameter"); + return { false, nullopt }; + } + options.offset = offset; + + auto [succLength, length] = AniHelper::ParseInt64Option(env, obj, "length"); + if (!succLength) { + HILOGE("Illegal option.length parameter"); + return { false, nullopt }; + } + options.length = length; + + auto [succEncoding, encoding] = AniHelper::ParseEncoding(env, obj); + if (!succEncoding) { + HILOGE("Illegal option.encoding parameter"); + return { false, nullopt }; + } + options.encoding = encoding; + return { true, make_optional(move(options)) }; +} + +static std::tuple ParseStringBuffer(ani_env *env, const ani_object &buf) +{ + auto classDesc = BuiltInTypes::String::classDesc.c_str(); + ani_class cls; + env->FindClass(classDesc, &cls); + + ani_boolean isString; + env->Object_InstanceOf(buf, cls, &isString); + if (!isString) { + return { false, {} }; + } + auto result = static_cast(buf); + return { true, std::move(result) }; +} + +static std::tuple ParseArrayBuffer(ani_env *env, const ani_object &buf) +{ + auto classDesc = BuiltInTypes::ArrayBuffer::classDesc.c_str(); + ani_class cls; + env->FindClass(classDesc, &cls); + + ani_boolean isArrayBuffer; + env->Object_InstanceOf(buf, cls, &isArrayBuffer); + if (!isArrayBuffer) { + return { false, {} }; + } + auto result = static_cast(buf); + return { true, std::move(result) }; +} + +ani_double WriteAni::WriteSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd, ani_object buf, ani_object options) +{ + auto [succOp, op] = ToWriteOptions(env, options); + if (!succOp) { + HILOGE("Failed to resolve options!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + + auto [isString, stringBuffer] = ParseStringBuffer(env, buf); + if (isString) { + auto [succBuf, buffer] = TypeConverter::ToUTF8String(env, stringBuffer); + if (!succBuf) { + HILOGE("Failed to resolve stringBuffer!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + auto ret = WriteCore::DoWrite(static_cast(fd), buffer, op); + if (!ret.IsSuccess()) { + HILOGE("write buffer failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return -1; + } + return static_cast(ret.GetData().value()); + } + + auto [isArrayBuffer, arrayBuffer] = ParseArrayBuffer(env, buf); + if (isArrayBuffer) { + auto [succBuf, buffer] = TypeConverter::ToArrayBuffer(env, arrayBuffer); + if (!succBuf) { + HILOGE("Failed to resolve arrayBuffer!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + auto ret = WriteCore::DoWrite(static_cast(fd), buffer, op); + if (!ret.IsSuccess()) { + HILOGE("write buffer failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return -1; + } + return static_cast(ret.GetData().value()); + } + HILOGE("Unsupported buffer type!"); + ErrorHandler::Throw(env, EINVAL); + return -1; +} +} // 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/write_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/write_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..aeb6e2c4c841a9b2cd5f95958fed92ac0c383c37 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/write_ani.h @@ -0,0 +1,36 @@ +/* + * 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_WRITE_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_WRITE_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class WriteAni final { +public: + static ani_double WriteSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd, ani_object buf, ani_object options); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_WRITE_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/listfile_core.cpp b/interfaces/kits/js/src/mod_fs/properties/listfile_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d334c8a47a11a6165ce4c65a41a78408f976d9f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/listfile_core.cpp @@ -0,0 +1,310 @@ +/* + * 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 "listfile_core.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +thread_local OptionArgs g_optionArgsCore; + +static bool CheckSuffix(const vector &suffixs) +{ + for (string suffix : suffixs) { + if (suffix.length() <= 1 || suffix.length() > MAX_SUFFIX_LENGTH) { + return false; + } + if (suffix[0] != '.') { + return false; + } + for (size_t i = 1; i < suffix.length(); i++) { + if (!isalnum(suffix[i])) { + return false; + } + } + } + return true; +} + +static bool ValidFileFilterParam(FsFileFilter &fsFilter, FileFilter *filter) +{ + auto suffixs = fsFilter.GetSuffix(); + if (fsFilter.GetSuffix().has_value()) { + vector suffixs = fsFilter.GetSuffix().value(); + if (!CheckSuffix(suffixs) || suffixs.size() == 0) { + HILOGE("Invalid suffix."); + return false; + } + filter->SetSuffix(suffixs); + } + + if (fsFilter.GetDisplayName().has_value()) { + vector displayNames = fsFilter.GetDisplayName().value(); + if (displayNames.size() == 0) { + HILOGE("Invalid displayName."); + return false; + } + filter->SetDisplayName(displayNames); + } + + if (fsFilter.GetFileSizeOver().has_value()) { + int64_t fileSizeOver = fsFilter.GetFileSizeOver().value(); + if (fileSizeOver < 0) { + HILOGE("Failed to get fileSizeOver prop."); + return false; + } + filter->SetFileSizeOver(fileSizeOver); + } + + if (fsFilter.GetLastModifiedAfter().has_value()) { + double lastModifiedAfter = fsFilter.GetLastModifiedAfter().value(); + if (lastModifiedAfter < 0) { + HILOGE("Failed to get lastModifiedAfter prop."); + return false; + } + filter->SetLastModifiedAfter(lastModifiedAfter); + } + + return true; +} + +static bool ValidOptionParam(const string &path, const optional &opt, OptionArgs &optionArgs) +{ + g_optionArgsCore.Clear(); + g_optionArgsCore.path = path; + + if (opt.has_value()) { + auto op = opt.value(); + if (op.listNum < 0) { + HILOGE("Failed to get listNum prop"); + return false; + } + + optionArgs.recursion = op.recursion; + optionArgs.listNum = op.listNum; + + if (op.filter.has_value()) { + bool ret = ValidFileFilterParam(op.filter.value(), &(optionArgs.filter)); + if (!ret) { + HILOGE("Failed to get filter prop."); + return false; + } + } + } + + return true; +} + +static bool FilterSuffix(const vector &suffixs, const struct dirent &filename) +{ + if (filename.d_type == DT_DIR) { + return true; + } + size_t found = string(filename.d_name).rfind('.'); + if (found == std::string::npos) { + return false; + } + string suffixStr = string(filename.d_name).substr(found); + for (const auto &iter : suffixs) { + if (iter == suffixStr) { + return true; + } + } + return false; +} + +static bool FilterDisplayname(const vector &displaynames, const struct dirent &filename) +{ + for (const auto &iter : displaynames) { + int ret = fnmatch(iter.c_str(), filename.d_name, FNM_PATHNAME | FNM_PERIOD); + if (ret == 0) { + return true; + } + } + return false; +} + +static bool FilterFilesizeOver(const int64_t fFileSizeOver, const struct dirent &filename) +{ + if (fFileSizeOver < 0) { + return true; + } + struct stat info; + string stPath = (g_optionArgsCore.path + '/' + string(filename.d_name)); + int32_t res = stat(stPath.c_str(), &info); + if (res != 0) { + HILOGE("Failed to stat file."); + return false; + } + if (info.st_size > fFileSizeOver) { + return true; + } + return false; +} + +static bool FilterLastModifyTime(const double lastModifiedAfter, const struct dirent &filename) +{ + if (lastModifiedAfter < 0) { + return true; + } + struct stat info; + string stPath = g_optionArgsCore.path + '/' + string(filename.d_name); + int32_t res = stat(stPath.c_str(), &info); + if (res != 0) { + HILOGE("Failed to stat file."); + return false; + } + if (static_cast(info.st_mtime) > lastModifiedAfter) { + return true; + } + return false; +} + +static bool FilterResult(const struct dirent &filename) +{ + vector fSuffixs = g_optionArgsCore.filter.GetSuffix(); + if (!FilterSuffix(fSuffixs, filename) && fSuffixs.size() > 0) { + return false; + } + vector fDisplaynames = g_optionArgsCore.filter.GetDisplayName(); + if (!FilterDisplayname(fDisplaynames, filename) && fDisplaynames.size() > 0) { + return false; + } + int64_t fFileSizeOver = g_optionArgsCore.filter.GetFileSizeOver(); + if (!FilterFilesizeOver(fFileSizeOver, filename)) { + return false; + } + double fLastModifiedAfter = g_optionArgsCore.filter.GetLastModifiedAfter(); + if (!FilterLastModifyTime(fLastModifiedAfter, filename)) { + return false; + } + g_optionArgsCore.countNum++; + return true; +} + +static int32_t FilterFunc(const struct dirent *filename) +{ + if (string_view(filename->d_name) == "." || string_view(filename->d_name) == "..") { + return FILTER_DISMATCH; + } + + if (g_optionArgsCore.countNum < g_optionArgsCore.listNum || g_optionArgsCore.listNum == 0) { + if ((filename->d_type == DT_DIR && g_optionArgsCore.recursion) || FilterResult(*filename)) { + return FILTER_MATCH; + } + } + return FILTER_DISMATCH; +} + +static void Deleter(struct NameListArg *arg) +{ + for (int i = 0; i < arg->direntNum; i++) { + free((arg->namelist)[i]); + (arg->namelist)[i] = nullptr; + } + free(arg->namelist); + arg->namelist = nullptr; + delete arg; + arg = nullptr; +} + +static int FilterFileRes(const string &path, vector &dirents) +{ + unique_ptr pNameList = { new (nothrow) struct NameListArg, Deleter }; + if (!pNameList) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int num = scandir(path.c_str(), &(pNameList->namelist), FilterFunc, nullptr); + if (num < 0) { + HILOGE("Failed to scan dir"); + return errno; + } + pNameList->direntNum = num; + for (int i = 0; i < num; i++) { + dirents.emplace_back(pNameList->namelist[i]->d_name); + } + return ERRNO_NOERR; +} + +static int RecursiveFunc(const string &path, vector &dirents) +{ + unique_ptr pNameList = { new (nothrow) struct NameListArg, Deleter }; + if (!pNameList) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int num = scandir(path.c_str(), &(pNameList->namelist), FilterFunc, nullptr); + if (num < 0) { + HILOGE("Failed to scan dir"); + return errno; + } + pNameList->direntNum = num; + for (int i = 0; i < num; i++) { + if ((*(pNameList->namelist[i])).d_type == DT_REG) { + dirents.emplace_back(path + '/' + pNameList->namelist[i]->d_name); + } else if ((*(pNameList->namelist[i])).d_type == DT_DIR) { + string pathTemp = g_optionArgsCore.path; + g_optionArgsCore.path += '/' + string((*(pNameList->namelist[i])).d_name); + int ret = RecursiveFunc(g_optionArgsCore.path, dirents); + if (ret != ERRNO_NOERR) { + return ret; + } + g_optionArgsCore.path = pathTemp; + } + } + return ERRNO_NOERR; +} + +static void DoListFileVector(const string &path, vector &dirents, bool recursion) +{ + if (recursion) { + for (size_t i = 0; i < dirents.size(); i++) { + dirents[i] = dirents[i].substr(path.length()); + } + } +} + +FsResult> ListFileCore::DoListFile(const string &path, const optional &opt) +{ + if (!ValidOptionParam(path, opt, g_optionArgsCore)) { + HILOGE("Invalid options"); + return FsResult>::Error(EINVAL); + } + + vector direntsRes; + int ret = 0; + ret = g_optionArgsCore.recursion ? RecursiveFunc(path, direntsRes) : FilterFileRes(path, direntsRes); + if (ret) { + return FsResult>::Error(ret); + } + DoListFileVector(path, direntsRes, g_optionArgsCore.recursion); + g_optionArgsCore.Clear(); + + return FsResult>::Success(direntsRes); +} + +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/listfile_core.h b/interfaces/kits/js/src/mod_fs/properties/listfile_core.h new file mode 100644 index 0000000000000000000000000000000000000000..5299762c9fceae2391df3bd306f244b3eecac15a --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/listfile_core.h @@ -0,0 +1,71 @@ +/* + * 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_LISTFILE_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_LISTFILE_CORE_H + +#include + +#include "file_filter.h" +#include "filemgmt_libfs.h" +#include "fs_file_filter.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +struct NameListArg { + struct dirent **namelist = { nullptr }; + int direntNum = 0; +}; + +constexpr int DEFAULT_SIZE = -1; +constexpr int DEFAULT_MODIFY_AFTER = -1; +struct OptionArgs { + FileFilter filter = + FileFilterBuilder().SetFileSizeOver(DEFAULT_SIZE).SetLastModifiedAfter(DEFAULT_MODIFY_AFTER).Build(); + int listNum = 0; + int countNum = 0; + bool recursion = false; + std::string path = ""; + void Clear() + { + filter.FilterClear(); + filter.SetFileSizeOver(DEFAULT_SIZE); + filter.SetLastModifiedAfter(DEFAULT_MODIFY_AFTER); + listNum = 0; + countNum = 0; + recursion = false; + path = ""; + } +}; + +struct FsListFileOptions { + bool recursion = false; + int64_t listNum = 0; + optional filter = nullopt; +}; + +class ListFileCore { +public: + static FsResult> DoListFile( + const std::string &path, const optional &opt = nullopt); +}; + +constexpr int FILTER_MATCH = 1; +constexpr int FILTER_DISMATCH = 0; +const int32_t MAX_SUFFIX_LENGTH = 256; +const std::string LIST_FILE_PRODUCE_NAME = "FileIOListFile"; +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_LISTFILE_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/mkdir_core.cpp b/interfaces/kits/js/src/mod_fs/properties/mkdir_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ae96ff21a7ef2e09a8dd11e0f4e26b654e4d8c9 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/mkdir_core.cpp @@ -0,0 +1,112 @@ +/* + * 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 "mkdir_core.h" + +#include +#include +#include +#include +#include +#include + +#include "filemgmt_libhilog.h" + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +#include "rust_file.h" +#endif + +#ifdef FILE_API_TRACE +#include "hitrace_meter.h" +#endif + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static int UvAccess(const string &path, int mode) +{ + std::unique_ptr access_req = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!access_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + return uv_fs_access(nullptr, access_req.get(), path.c_str(), mode, nullptr); +} + +static int MkdirCore(const string &path) +{ + std::unique_ptr mkdir_req = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!mkdir_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + return uv_fs_mkdir(nullptr, mkdir_req.get(), path.c_str(), DIR_DEFAULT_PERM, nullptr); +} + +static int32_t MkdirExec(const string &path, bool recursion, bool hasOption) +{ +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + if (hasOption) { + int ret = UvAccess(path, 0); + if (ret == ERRNO_NOERR) { + HILOGD("The path already exists"); + return EEXIST; + } + if (ret != -ENOENT) { + HILOGE("Failed to check for illegal path or request for heap memory"); + return ret; + } + if (::Mkdirs(path.c_str(), static_cast(recursion)) < 0) { + HILOGD("Failed to create directories, error: %{public}d", errno); + return errno; + } + ret = UvAccess(path, 0); + if (ret) { + HILOGE("Failed to verify the result of Mkdirs function"); + return ret; + } + return ERRNO_NOERR; + } +#endif + int ret = MkdirCore(path); + if (ret) { + HILOGD("Failed to create directory"); + return ret; + } + return ERRNO_NOERR; +} + +FsResult MkdirCore::DoMkdir(const std::string &path, std::optional recursion) +{ + bool hasOption = false; + bool mkdirRecursion = false; +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + hasOption = recursion.has_value(); + if (hasOption) { + mkdirRecursion = recursion.value(); + } +#endif + auto err = MkdirExec(path, mkdirRecursion, hasOption); + if (err) { + return FsResult::Error(err); + } + return FsResult::Success(); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/mkdir_core.h b/interfaces/kits/js/src/mod_fs/properties/mkdir_core.h new file mode 100644 index 0000000000000000000000000000000000000000..7b92bbde0e12e6a2538311e04f44018e78cecfa7 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/mkdir_core.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022-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 INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MKDIR_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MKDIR_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +class MkdirCore final { +public: + static FsResult DoMkdir(const std::string& path, std::optional recursion = std::nullopt); +}; +constexpr int DIR_DEFAULT_PERM = 0770; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MKDIR_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp b/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90b1b71095eca8e106dad4fa14cd74ac48a44d30 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp @@ -0,0 +1,138 @@ +/* + * 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 "read_text_core.h" + +#include +#include +#include +#include +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static tuple> ValidReadTextArg( + const std::optional &options) +{ + int64_t offset = -1; + int64_t len = 0; + bool hasLen = false; + unique_ptr encoding { new char[]{ "utf-8" } }; + + if (!options.has_value()) { + return { true, offset, hasLen, len, move(encoding) }; + } + + ReadTextOptions op = options.value(); + if (op.offset.has_value()) { + offset = op.offset.value(); + if (offset < 0) { + HILOGE("Illegal option.offset parameter"); + return { false, offset, hasLen, len, nullptr }; + } + } + + if (op.length.has_value()) { + len = op.length.value(); + if (len < 0 || len > UINT_MAX) { + HILOGE("Illegal option.length parameter"); + return { false, offset, hasLen, len, nullptr }; + } + hasLen = true; + } + + if (op.encoding.has_value()) { + auto encoding = op.encoding.value(); + if (encoding != "utf-8") { + HILOGE("Illegal option.encoding parameter"); + return { false, offset, hasLen, len, nullptr }; + } + } + + return { true, offset, hasLen, len, move(encoding) }; +} + +static int OpenFile(const std::string& path) +{ + std::unique_ptr openReq = { + new uv_fs_t, FsUtils::FsReqCleanup + }; + if (openReq == nullptr) { + HILOGE("Failed to request heap memory."); + return -ENOMEM; + } + + return uv_fs_open(nullptr, openReq.get(), path.c_str(), O_RDONLY, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, nullptr); +} + +static int ReadFromFile(int fd, int64_t offset, string& buffer) +{ + uv_buf_t readbuf = uv_buf_init(const_cast(buffer.c_str()), static_cast(buffer.size())); + std::unique_ptr readReq = { + new uv_fs_t, FsUtils::FsReqCleanup }; + if (readReq == nullptr) { + HILOGE("Failed to request heap memory."); + return -ENOMEM; + } + return uv_fs_read(nullptr, readReq.get(), fd, &readbuf, 1, offset, nullptr); +} + +FsResult> ReadTextCore::DoReadText(const std::string &path, + const std::optional &options) +{ + auto [resGetReadTextArg, offset, hasLen, len, encoding] = ValidReadTextArg(options); + if (!resGetReadTextArg) { + return FsResult>::Error(EINVAL); + } + + OHOS::DistributedFS::FDGuard sfd; + int fd = OpenFile(path); + if (fd < 0) { + HILOGD("Failed to open file by ret: %{public}d", fd); + return FsResult>::Error(fd); + } + sfd.SetFD(fd); + + struct stat statbf; + if ((!sfd) || (fstat(sfd.GetFD(), &statbf) < 0)) { + HILOGE("Failed to get stat of file by fd: %{public}d", sfd.GetFD()); + return FsResult>::Error(errno); + } + + if (offset > statbf.st_size) { + HILOGE("Invalid offset: %{public}" PRIu64, offset); + return FsResult>::Error(EINVAL); + } + + len = (!hasLen || len > statbf.st_size) ? statbf.st_size : len; + string buffer(len, '\0'); + int readRet = ReadFromFile(sfd.GetFD(), offset, buffer); + if (readRet < 0) { + HILOGE("Failed to read file by fd: %{public}d", fd); + return FsResult>::Error(readRet); + } + + return FsResult>::Success(make_tuple(move(buffer), readRet)); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/read_text_core.h b/interfaces/kits/js/src/mod_fs/properties/read_text_core.h new file mode 100644 index 0000000000000000000000000000000000000000..87e0a4300d0454472089ce84a70c46ea7573a011 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/read_text_core.h @@ -0,0 +1,43 @@ +/* + * 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_READ_TEXT_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_TEXT_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +struct ReadTextOptions final { + optional offset = nullopt; + optional length = nullopt; + optional encoding = nullopt; +}; + +class ReadTextCore final { +public: + static FsResult> DoReadText(const string &filePath, + const optional &options = nullopt); +}; + +const string PROCEDURE_READTEXT_NAME = "FileIOReadText"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_TEXT_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/unlink_core.cpp b/interfaces/kits/js/src/mod_fs/properties/unlink_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ecb92452e2eeb401b856238f52175487ae824523 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/unlink_core.cpp @@ -0,0 +1,48 @@ +/* + * 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 "unlink_core.h" + +#ifdef FILE_API_TRACE +#include "hitrace_meter.h" +#endif + +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +FsResult UnlinkCore::DoUnlink(const std::string &src) +{ + std::unique_ptr unlink_req = { + new uv_fs_t, FsUtils::FsReqCleanup }; + if (!unlink_req) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + int ret = uv_fs_unlink(nullptr, unlink_req.get(), src.c_str(), nullptr); + if (ret < 0) { + HILOGD("Failed to unlink with path"); + return FsResult::Error(ret); + } + + return FsResult::Success(); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/unlink_core.h b/interfaces/kits/js/src/mod_fs/properties/unlink_core.h new file mode 100644 index 0000000000000000000000000000000000000000..b2ea553f4b62130bc691bda5daca16dbe7bc28d4 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/unlink_core.h @@ -0,0 +1,34 @@ +/* + * 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_UNLINK_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_UNLINK_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +class UnlinkCore final { +public: + static FsResult DoUnlink(const std::string &src); +}; +const std::string PROCEDURE_READTEXT_NAME = "FileIOUnlink"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_UNLINK_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/write_core.cpp b/interfaces/kits/js/src/mod_fs/properties/write_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f282f9cf337afe5be1227b625a9c37dc6915645b --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/write_core.cpp @@ -0,0 +1,130 @@ +/* + * 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 "write_core.h" + +#include +#include +#include +#include +#include +#include + +#ifdef FILE_API_TRACE +#include "hitrace_meter.h" +#endif + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static tuple ValidWriteArg( + void *buffer, const size_t bufLen, const optional &options) +{ + size_t retLen = 0; + int64_t offset = -1; + bool succ = false; + + if (bufLen > UINT_MAX) { + HILOGE("The Size of buffer is too large"); + return { false, nullptr, 0, offset }; + } + + optional lengthOp = nullopt; + optional offsetOp = nullopt; + if (options.has_value()) { + WriteOptions op = options.value(); + lengthOp = op.length; + offsetOp = op.offset; + } + + tie(succ, retLen) = FsUtils::GetActualLen(bufLen, 0, lengthOp); + if (!succ) { + HILOGE("Failed to get actual length"); + return { false, nullptr, 0, offset }; + } + + if (offsetOp.has_value()) { + offset = offsetOp.value(); + if (offset < 0) { + HILOGE("option.offset shall be positive number"); + return { false, nullptr, 0, offset }; + } + } + return { true, buffer, retLen, offset }; +} + +FsResult WriteCore::DoWrite(const int32_t fd, const string &buffer, const optional &options) +{ + if (fd < 0) { + HILOGE("Invalid fd"); + return FsResult::Error(EINVAL); + } + + bool succ = false; + size_t len = 0; + int64_t offset = -1; + void *buf = const_cast(static_cast(buffer.c_str())); + size_t bufLen = static_cast(buffer.length()); + + tie(succ, buf, len, offset) = ValidWriteArg(buf, bufLen, options); + if (!succ) { + HILOGE("Failed to resolve buf and options"); + return FsResult::Error(EINVAL); + } + + return DoWrite(fd, buf, len, offset); +} + +FsResult WriteCore::DoWrite(const int32_t fd, const ArrayBuffer &buffer, const optional &options) +{ + if (fd < 0) { + HILOGE("Invalid fd"); + return FsResult::Error(EINVAL); + } + + bool succ = false; + size_t len = 0; + int64_t offset = -1; + void *buf = nullptr; + + tie(succ, buf, len, offset) = ValidWriteArg(buffer.buf, buffer.length, options); + if (!succ) { + HILOGE("Failed to resolve buf and options"); + return FsResult::Error(EINVAL); + } + + return DoWrite(fd, buf, len, offset); +} + +FsResult WriteCore::DoWrite(const int32_t fd, void *buf, const size_t len, const int64_t offset) +{ + uv_buf_t buffer = uv_buf_init(static_cast(buf), static_cast(len)); + unique_ptr write_req = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!write_req) { + return FsResult::Error(ENOMEM); + } + int ret = uv_fs_write(nullptr, write_req.get(), fd, &buffer, 1, offset, nullptr); + if (ret < 0) { + HILOGE("Failed to write file for %{public}d", ret); + return FsResult::Error(ret); + } + return FsResult::Success(static_cast(ret)); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/write_core.h b/interfaces/kits/js/src/mod_fs/properties/write_core.h new file mode 100644 index 0000000000000000000000000000000000000000..5d4d2192be0a740a16a89ee1213f5db1d448dd02 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/write_core.h @@ -0,0 +1,49 @@ +/* + * 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_WRITE_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_WRITE_CORE_H + +#include "filemgmt_libfs.h" +#include "filemgmt_libhilog.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +struct WriteOptions { + optional length = nullopt; + optional offset = nullopt; + optional encoding = nullopt; +}; + +class WriteCore final { +public: + static FsResult DoWrite( + const int32_t fd, const string &buffer, const optional &options = nullopt); + static FsResult DoWrite( + const int32_t fd, const ArrayBuffer &buffer, const optional &options = nullopt); + +private: + static FsResult DoWrite(const int32_t fd, void *buf, const size_t len, const int64_t offset); +}; + +const string PROCEDURE_WRITE_NAME = "FileIOWrite"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_WRITE_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/ani/bind_function_class.cpp b/interfaces/kits/js/src/mod_hash/ani/bind_function_class.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ab549948f7657e1acd6b2f77b61051469aabf57 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/bind_function_class.cpp @@ -0,0 +1,60 @@ +/* + * 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 +#include "ani_signature.h" +#include "bind_function.h" +#include "hash_ani.h" + +using namespace OHOS::FileManagement::ModuleFileIO::ANI; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static ani_status BindStaticMethods(ani_env *env) +{ + auto classDesc = Impl::HashImpl::classDesc.c_str(); + std::array methods = { + ani_native_function { "hashSync", nullptr, reinterpret_cast(HashAni::HashSync) }, + }; + return BindClass(env, classDesc, methods); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + if (vm == nullptr) { + HILOGE("Invalid parameter vm"); + return ANI_INVALID_ARGS; + } + + if (result == nullptr) { + HILOGE("Invalid parameter result"); + return ANI_INVALID_ARGS; + } + + ani_env *env; + ani_status status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + HILOGE("Invalid ani version!"); + return ANI_INVALID_VERSION; + } + + status = BindStaticMethods(env); + if (status != ANI_OK) { + HILOGE("Cannot bind native static methods for hash!"); + return status; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets b/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets new file mode 100644 index 0000000000000000000000000000000000000000..dfa16ab00530db92e6dc328c889cb035d50080d4 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets @@ -0,0 +1,93 @@ +/* + * 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. + */ + +import { BusinessError, AsyncCallback } from '@ohos.base'; +import stream from '@ohos.util.stream'; + +export default namespace hash { + export function hash(path: string, algorithm: string): Promise { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute(HashImpl.hashSync, path, algorithm); + promise.then((ret: NullishType): void => { + let res = ret as string; + resolve(res); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + export function hash(path: string, algorithm: string, callback: AsyncCallback): void { + let promise = taskpool.execute(HashImpl.hashSync, path, algorithm); + promise.then((ret: NullishType) => { + let e = new BusinessError(); + e.code = 0; + let res = ret as string; + callback(e, res); + }).catch((e: BusinessError): void => { + callback(e, ""); + }); + } + + export function createHash(algorithm: string): HashStream { + return new HashStream(algorithm); + } + + export class HashStream extends stream.Transform { + hs: hash.HashStream; + hashBuf?: ArrayBuffer; + + constructor(algorithm: string) { + super(); + this.hs = new hash.HashStream(algorithm); + } + + digest(): string { + return this.hs.digest(); + } + + update(data: ArrayBuffer): void { + this.hs.update(data); + } + + doTransform(chunk: string, encoding: string, callback: () => void): void { + let charCodes: number[] = []; + for (let i = 0; i < chunk.length; i++) { + charCodes = [...charCodes, chunk.charCodeAt(i)]; + } + const buf = new Uint8Array(charCodes).buffer; + this.hs.update((buf as ArrayBuffer)); + this.push(chunk); + callback(); + } + + doWrite(chunk: string | Uint8Array, encoding: string, callback: () => void): void { + callback(); + } + + doFlush(callback: () => void): void { + callback(); + } + } +} + +class HashImpl { + + static { + loadLibrary("ani_file_hash"); + } + + static native hashSync(path: string, algorithm: string): string; +} diff --git a/interfaces/kits/js/src/mod_hash/ani/hash_ani.cpp b/interfaces/kits/js/src/mod_hash/ani/hash_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6acb4389cdaba7a384403d9e61541fbe9dd6e214 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/hash_ani.cpp @@ -0,0 +1,68 @@ +/* + * 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 "hash_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "hash_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; + +ani_string HashAni::HashSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string algorithm) +{ + auto [succPath, srcPath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto [succAlg, algType] = TypeConverter::ToUTF8String(env, algorithm); + if (!succAlg) { + HILOGE("Invalid algorithm"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto ret = HashCore::DoHash(srcPath, algType); + if (!ret.IsSuccess()) { + HILOGE("DoHash failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + const auto &res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Convert hash value to ani string failed"); + 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_hash/ani/hash_ani.h b/interfaces/kits/js/src/mod_hash/ani/hash_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..7b0890fe78e7ad5dbf86a84553300d1736a5d775 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/hash_ani.h @@ -0,0 +1,36 @@ +/* + * 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_HASH_PROPERTIES_HASH_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_HASH_PROPERTIES_HASH_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class HashAni final { +public: + static ani_string HashSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string algorithm); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_HASH_PROPERTIES_HASH_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/hash_core.cpp b/interfaces/kits/js/src/mod_hash/hash_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ed75b4b0cd462c8fef0bc8d76009e7bc32d0fd93 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/hash_core.cpp @@ -0,0 +1,63 @@ +/* + * 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 "hash_core.h" + +#include +#include +#include + +#include "filemgmt_libhilog.h" +#include "hash_file.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static HASH_ALGORITHM_TYPE GetHashAlgorithm(const string &alg) +{ + return (algorithmMaps.find(alg) != algorithmMaps.end()) ? algorithmMaps.at(alg) : HASH_ALGORITHM_TYPE_UNSUPPORTED; +} + +FsResult HashCore::DoHash(const string &path, const string &algorithm) +{ + HASH_ALGORITHM_TYPE algType = GetHashAlgorithm(algorithm); + if (algType == HASH_ALGORITHM_TYPE_UNSUPPORTED) { + HILOGE("Invalid algoritm"); + return FsResult::Error(EINVAL); + } + + int ret = EIO; + auto arg = make_shared(); + string &res = *arg; + if (algType == HASH_ALGORITHM_TYPE_MD5) { + tie(ret, res) = DistributedFS::HashFile::HashWithMD5(path); + } else if (algType == HASH_ALGORITHM_TYPE_SHA1) { + tie(ret, res) = DistributedFS::HashFile::HashWithSHA1(path); + } else if (algType == HASH_ALGORITHM_TYPE_SHA256) { + tie(ret, res) = DistributedFS::HashFile::HashWithSHA256(path); + } + + if (ret) { + return FsResult::Error(ret); + } + + return FsResult::Success(*arg); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/hash_core.h b/interfaces/kits/js/src/mod_hash/hash_core.h new file mode 100644 index 0000000000000000000000000000000000000000..47119f1ac3e43d512c900cd81b3e8dc2f35e49c0 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/hash_core.h @@ -0,0 +1,48 @@ +/* + * 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_HASH_PROPERTIES_HASH_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_HASH_PROPERTIES_HASH_CORE_H + +#include +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +enum HASH_ALGORITHM_TYPE { + HASH_ALGORITHM_TYPE_MD5, + HASH_ALGORITHM_TYPE_SHA1, + HASH_ALGORITHM_TYPE_SHA256, + HASH_ALGORITHM_TYPE_UNSUPPORTED, +}; + +const std::map algorithmMaps = { + {"md5", HASH_ALGORITHM_TYPE_MD5}, + {"sha1", HASH_ALGORITHM_TYPE_SHA1}, + {"sha256", HASH_ALGORITHM_TYPE_SHA256}, +}; + +class HashCore final { +public: + static FsResult DoHash(const std::string &path, const std::string &algorithm); +}; + +const std::string PROCEDURE_HASH_NAME = "FileIOHash"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_HASH_PROPERTIES_HASH_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_securitylabel/ani/bind_function_class.cpp b/interfaces/kits/js/src/mod_securitylabel/ani/bind_function_class.cpp new file mode 100644 index 0000000000000000000000000000000000000000..947e460b65992a5ec8c5042a6dd205d03ef42c56 --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/ani/bind_function_class.cpp @@ -0,0 +1,63 @@ +/* + * 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 +#include "ani_signature.h" +#include "bind_function.h" +#include "securitylabel_ani.h" + +using namespace OHOS::FileManagement::ModuleFileIO::ANI; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static ani_status BindStaticMethods(ani_env *env) +{ + auto classDesc = Impl::SecurityLabelImpl::classDesc.c_str(); + std::array methods = { + ani_native_function { + "setSecurityLabelSync", nullptr, reinterpret_cast(SecurityLabelAni::SetSecurityLabelSync) }, + ani_native_function { + "getSecurityLabelSync", nullptr, reinterpret_cast(SecurityLabelAni::GetSecurityLabelSync) }, + }; + return BindClass(env, classDesc, methods); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + if (vm == nullptr) { + HILOGE("Invalid parameter vm"); + return ANI_INVALID_ARGS; + } + + if (result == nullptr) { + HILOGE("Invalid parameter result"); + return ANI_INVALID_ARGS; + } + + ani_env *env; + ani_status status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + HILOGE("Invalid ani version!"); + return ANI_INVALID_VERSION; + } + + status = BindStaticMethods(env); + if (status != ANI_OK) { + HILOGE("Cannot bind native static methods for securitylabel!"); + return status; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} diff --git a/interfaces/kits/js/src/mod_securitylabel/ani/ets/@ohos.file.securityLabel.ets b/interfaces/kits/js/src/mod_securitylabel/ani/ets/@ohos.file.securityLabel.ets new file mode 100644 index 0000000000000000000000000000000000000000..06e659dc275ae1890e009c02fc830bd8e766dbea --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/ani/ets/@ohos.file.securityLabel.ets @@ -0,0 +1,86 @@ +/* + * 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. + */ + +import { BusinessError, AsyncCallback } from '@ohos.base'; + +namespace securityLabel { + export type DataLevel = 's0' | 's1' | 's2' | 's3' | 's4'; + + export function setSecurityLabel(path: string, type: DataLevel): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string, type: DataLevel): void => SecurityLabelImpl.setSecurityLabelSync(path, type), path, type); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + export function setSecurityLabel(path: string, type: DataLevel, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string, type: DataLevel): void => SecurityLabelImpl.setSecurityLabelSync(path, type), path, type); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); + } + + export function setSecurityLabelSync(path: string, type: DataLevel): void { + return SecurityLabelImpl.setSecurityLabelSync(path, type); + } + + export function getSecurityLabel(path: string): Promise { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string): string => SecurityLabelImpl.getSecurityLabelSync(path), path); + promise.then((ret: NullishType): void => { + let r = ret as string; + resolve(r); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + export function getSecurityLabel(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): string => SecurityLabelImpl.getSecurityLabelSync(path), path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as string; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, ""); + }); + } + + export function getSecurityLabelSync(path: string): string { + return SecurityLabelImpl.getSecurityLabelSync(path); + } +} + +export default securityLabel; + +class SecurityLabelImpl { + + static { + loadLibrary("ani_file_securitylabel"); + } + + static native setSecurityLabelSync(path: string, type: securityLabel.DataLevel): void; + static native getSecurityLabelSync(path: string): string; +} diff --git a/interfaces/kits/js/src/mod_securitylabel/ani/securitylabel_ani.cpp b/interfaces/kits/js/src/mod_securitylabel/ani/securitylabel_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4d6fd2b3211890d4e1092c8925da40bddbe0269f --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/ani/securitylabel_ani.cpp @@ -0,0 +1,89 @@ +/* + * 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 "securitylabel_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "securitylabel_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleSecurityLabel; + +void SecurityLabelAni::SetSecurityLabelSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string level) +{ + auto [succPath, srcPath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto [succLevel, dataLevel] = TypeConverter::ToUTF8String(env, level); + if (!succLevel) { + HILOGE("Invalid dataLevel"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto ret = DoSetSecurityLabel(srcPath, dataLevel); + if (!ret.IsSuccess()) { + HILOGE("Set securitylabel failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +ani_string SecurityLabelAni::GetSecurityLabelSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path) +{ + auto [succPath, srcPath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto ret = DoGetSecurityLabel(srcPath); + if (!ret.IsSuccess()) { + HILOGE("Get securitylabel failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + string res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Create ani_string error"); + 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_securitylabel/ani/securitylabel_ani.h b/interfaces/kits/js/src/mod_securitylabel/ani/securitylabel_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..8bb5741c9c347700ded871b900efc44297c823d9 --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/ani/securitylabel_ani.h @@ -0,0 +1,37 @@ +/* + * 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 SECURITYLABEL_ANI_H +#define SECURITYLABEL_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class SecurityLabelAni final { +public: + static void SetSecurityLabelSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string level); + static ani_string GetSecurityLabelSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // SECURITYLABEL_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_securitylabel/securitylabel_core.cpp b/interfaces/kits/js/src/mod_securitylabel/securitylabel_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d68002e8aa8ddcab3863ebed88d44bcc22d1fa13 --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/securitylabel_core.cpp @@ -0,0 +1,48 @@ +/* + * 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 "securitylabel_core.h" + +#include "filemgmt_libhilog.h" +#include "security_label.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleSecurityLabel { +using namespace std; +FsResult DoSetSecurityLabel(const string &path, const string &dataLevel) +{ + if (DATA_LEVEL.find(dataLevel) == DATA_LEVEL.end()) { + HILOGE("Invalid Argument of dataLevelEnum"); + return FsResult::Error(EINVAL); + } + + bool ret = SecurityLabel::SetSecurityLabel(path, dataLevel); + if (!ret) { + return FsResult::Error(errno); + } + + return FsResult::Success(); +} + +FsResult DoGetSecurityLabel(const string &path) +{ + string ret = SecurityLabel::GetSecurityLabel(path); + return FsResult::Success(move(ret)); +} + +} // namespace ModuleSecurityLabel +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_securitylabel/securitylabel_core.h b/interfaces/kits/js/src/mod_securitylabel/securitylabel_core.h new file mode 100644 index 0000000000000000000000000000000000000000..cb7766eaf5a6087c1e449e2077046ee4a63a9f33 --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/securitylabel_core.h @@ -0,0 +1,32 @@ +/* + * 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 SECURITYLABEL_CORE_H +#define SECURITYLABEL_CORE_H + +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleSecurityLabel { +using namespace ModuleFileIO; + +FsResult DoSetSecurityLabel(const string &path, const string &dataLevel); +FsResult DoGetSecurityLabel(const string &path); + +} // namespace ModuleSecurityLabel +} // namespace FileManagement +} // namespace OHOS +#endif // SECURITYLABEL_CORE_H \ No newline at end of file diff --git a/interfaces/test/unittest/BUILD.gn b/interfaces/test/unittest/BUILD.gn index ad60f3a1211394a32365a2579f6f3d23e668c112..5aeda1645edd88a73d1107d5e434d2f809a486a6 100644 --- a/interfaces/test/unittest/BUILD.gn +++ b/interfaces/test/unittest/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Copyright (c) 2022-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 @@ -13,11 +13,15 @@ import("//foundation/filemanagement/file_api/file_api.gni") -group("unittest") { +group("file_api_unittest") { testonly = true deps = [ "class_file:class_file_test", "filemgmt_libn_test:filemgmt_libn_test", + "js:ani_file_fs_mock_test", + "js:ani_file_fs_test", + "js:ani_file_hash_test", + "js:ani_file_securitylabel_test", "remote_uri:remote_uri_test", "task_signal:task_signal_test", ] diff --git a/interfaces/test/unittest/js/BUILD.gn b/interfaces/test/unittest/js/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..c7b47c5cb680f45ce3e3d75d927db8a13c2eacf0 --- /dev/null +++ b/interfaces/test/unittest/js/BUILD.gn @@ -0,0 +1,164 @@ +# 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. + +import("//build/test.gni") +import("//foundation/filemanagement/file_api/file_api.gni") + +ohos_unittest("ani_file_fs_mock_test") { + branch_protector_ret = "pac_ret" + testonly = true + + module_out_path = "file_api/file_api" + + include_dirs = [ + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", + "${file_api_path}/interfaces/test/unittest/js/mod_fs/properties/mock", + ] + + sources = [ + "mod_fs/properties/mkdir_core_mock_test.cpp", + "mod_fs/properties/mock/system_mock.cpp", + "mod_fs/properties/mock/uv_fs_mock.cpp", + "mod_fs/properties/unlink_core_mock_test.cpp", + "mod_fs/properties/write_core_mock_test.cpp", + ] + + deps = [ + "${file_api_path}/interfaces/kits/native:remote_uri_native", + "${file_api_path}/interfaces/kits/native:task_signal_native", + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + "${file_api_path}/interfaces/kits/js:ani_file_fs", + ] + + external_deps = [ + "ability_runtime:ability_manager", + "app_file_service:fileuri_native", + "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "libuv:uv", + ] + + defines = [ + "private=public", + ] +} + +ohos_unittest("ani_file_fs_test") { + branch_protector_ret = "pac_ret" + testonly = true + + module_out_path = "file_api/file_api" + + resource_config_file = "../resource/ohos_test.xml" + + include_dirs = [ + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_atomicfile", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_file", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_randomaccessfile", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_readeriterator", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stat", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stream", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_tasksignal", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", + ] + + sources = [ + "mod_fs/properties/listfile_core_test.cpp", + "mod_fs/properties/read_text_core_test.cpp", + "mod_fs/properties/write_core_test.cpp", + ] + + deps = [ + "${file_api_path}/interfaces/kits/native:remote_uri_native", + "${file_api_path}/interfaces/kits/native:task_signal_native", + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + "${file_api_path}/interfaces/kits/js:ani_file_fs", + ] + + external_deps = [ + "ability_runtime:ability_manager", + "app_file_service:fileuri_native", + "c_utils:utils", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "libuv:uv", + ] + + defines = [ + "private=public", + ] +} + +ohos_unittest("ani_file_hash_test") { + module_out_path = "file_api/file_api" + + resource_config_file = "../resource/ohos_test.xml" + + sources = [ + "mod_hash/hash_core_test.cpp", + ] + + include_dirs = [ + "mock/libuv", + "${file_api_path}/interfaces/kits/js/src/mod_hash", + ] + + deps = [ + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${file_api_path}/interfaces/kits/js:ani_file_hash", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "libuv:uv", + "googletest:gmock_main", + "googletest:gtest_main", + ] +} + +ohos_unittest("ani_file_securitylabel_test") { + module_out_path = "file_api/file_api" + + resource_config_file = "../resource/ohos_test.xml" + + sources = [ + "mod_securitylabel/securitylabel_core_test.cpp", + ] + + include_dirs = [ + "${file_api_path}/interfaces/kits/js/src/mod_securitylabel", + ] + + deps = [ + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${file_api_path}/interfaces/kits/js:ani_file_securitylabel", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "googletest:gmock_main", + "googletest:gtest_main", + ] +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/listfile_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/listfile_core_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f3df50ccca62fb968fc535fc01c301ce96cb71c --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/listfile_core_test.cpp @@ -0,0 +1,526 @@ +/* +* 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 +#include +#include +#include "listfile_core.h" + +#define DIR_PATH "/data/test/ListFileCoreTest" +#define EMPTY_PATH "/data/test/Empty" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +namespace fs = std::filesystem; + +static void create_file(const fs::path& path, const std::vector& data, bool binary = true) +{ + fs::create_directories(path.parent_path()); // 确保目录存在 + std::ofstream file(path, binary ? std::ios::binary : std::ios::out); + if (!file) { + std::cerr << "创建文件失败: " << path << std::endl; + return; + } + file.write(reinterpret_cast(data.data()), data.size()); + std::cout << "已创建文件: " << path << std::endl; +} + +static void WriteBuffer(const string filename) +{ + const int targetSize = 1024; + std::vector buffer(targetSize, 0); + std::ofstream file(filename, std::ios::binary); + file.write(buffer.data(), buffer.size()); +} + +class ListFileCoreTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + fs::create_directory(EMPTY_PATH); + const std::vector directories = { + "/data/test/ListFileCoreTest", // 单级目录 + "/data/test/ListFileCoreTest/level1", // 二级目录 + "/data/test/ListFileCoreTest/level1/level2" // 三级目录 + }; + + // 为每个文件类型创建3个文件 + for (int i = 0; i < 3; ++i) { + create_file(directories[i] / ("text_" + std::to_string(i + 1) + ".txt"), + {'F', 'i', 'l', 'e', ' ', char('0' + i + 1)}, false); + + create_file(directories[i] / ("image_" + std::to_string(i + 1) + ".png"), + {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}); + + create_file(directories[i] / ("photo_" + std::to_string(i + 1) + ".jpg"), + {0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46}); + + create_file(directories[i] / ("data_" + std::to_string(i + 1) + ".data"), + {0xAB, 0xCD, 0xEF, char(i), char(i + 1), char(i + 2)}); + } + + WriteBuffer("/data/test/ListFileCoreTest/text_1.txt"); + }; + static void TearDownTestCase() + { + rmdir(DIR_PATH); + rmdir(EMPTY_PATH); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** +* @tc.name: DoListFileCoreTest_0001 +* @tc.desc: Test function of DoListFileCore() interface for error suffix. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0001"; + FsListFileOptions opt; + FsFileFilter filter; + // filter.SetSuffix({"txt"}); // 无效后缀(缺少`.`) + std::vector suffixVector = {"txt"}; + std::optional> optionalSuffix = suffixVector; + filter.SetSuffix(optionalSuffix); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + EXPECT_FALSE(result.IsSuccess()); + + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0001"; +} + +/** +* @tc.name: DoListFileCoreTest_0002 +* @tc.desc: Test function of DoListFileCore() interface for error suffix. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0002"; + FsListFileOptions opt; + FsFileFilter filter; + std::vector suffixVector = {".tx@t"}; + std::optional> optionalSuffix = suffixVector; + filter.SetSuffix(optionalSuffix); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + EXPECT_FALSE(result.IsSuccess()); + + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0002"; +} + +/** +* @tc.name: DoListFileCoreTest_0003 +* @tc.desc: Test function of DoListFileCore() interface for error listNum. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0003"; + FsListFileOptions opt; + opt.listNum = -5; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + EXPECT_FALSE(result.IsSuccess()); + + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0003"; +} + +/** +* @tc.name: DoListFileCoreTest_0004 +* @tc.desc: Test function of DoListFileCore() interface for current suffix. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0004"; + FsListFileOptions opt; + FsFileFilter filter; + std::vector suffixVector = {".txt"}; + std::optional> optionalSuffix = suffixVector; + filter.SetSuffix(optionalSuffix); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + ASSERT_TRUE(result.IsSuccess()); + + auto files = result.GetData().value(); + EXPECT_EQ(files.size(), 2); + EXPECT_EQ(files[0], "text_1.txt"); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0004"; +} + +/** +* @tc.name: DoListFileCoreTest_0005 +* @tc.desc: Test function of DoListFileCore() interface for no maching suffix . +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0005"; + FsListFileOptions opt; + FsFileFilter filter; + std::vector suffixVector = {".abc"}; + std::optional> optionalSuffix = suffixVector; + filter.SetSuffix(optionalSuffix); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + ASSERT_TRUE(result.IsSuccess()); + + auto files = result.GetData().value(); + EXPECT_FALSE(files[0].empty()); + EXPECT_EQ(files[0], "level1"); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0005"; +} + +/** +* @tc.name: DoListFileCoreTest_0006 +* @tc.desc: Test function of DoListFileCore() interface for current display name . +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0006"; + FsListFileOptions opt; + FsFileFilter filter; + std::vector displayNameVector = {"text*.txt"}; + std::optional> optionalDisplayName = displayNameVector; + filter.SetDisplayName(optionalDisplayName); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + ASSERT_TRUE(result.IsSuccess()); + + auto files = result.GetData().value(); + EXPECT_EQ(files.size(), 1); + EXPECT_EQ(files[0], "text_1.txt"); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0006"; +} + +/** +* @tc.name: DoListFileCoreTest_0007 +* @tc.desc: Test function of DoListFileCore() interface for current fileSizeOver . +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0007"; + FsListFileOptions opt; + FsFileFilter filter; + filter.SetFileSizeOver(500); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + ASSERT_TRUE(result.IsSuccess()); + + auto files = result.GetData().value(); + EXPECT_EQ(files.size(), 2); + EXPECT_EQ(files[0], "text_1.txt"); + EXPECT_EQ(files[1], "level1"); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0007"; +} + +/** +* @tc.name: DoListFileCoreTest_0008 +* @tc.desc: Test function of DoListFileCore() interface for displayMame = 0 . +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0008, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0008"; + FsListFileOptions opt; + FsFileFilter filter; + std::vector displayNameVector = {}; + std::optional> optionalDisplayName = displayNameVector; + filter.SetDisplayName(optionalDisplayName); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + EXPECT_FALSE(result.IsSuccess()); + + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0008"; +} + +/** +* @tc.name: DoListFileCoreTest_0009 +* @tc.desc: Test function of DoListFileCore() interface for error fileSizeOver . +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0009, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0009"; + FsListFileOptions opt; + FsFileFilter filter; + filter.SetFileSizeOver(-1); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + EXPECT_FALSE(result.IsSuccess()); + + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0009"; +} + +/** +* @tc.name: DoListFileCoreTest_0010 +* @tc.desc: Test function of DoListFileCore() interface for error lstModitiedAfter . +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0010, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0010"; + FsListFileOptions opt; + FsFileFilter filter; + filter.SetLastModifiedAfter(-1); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + EXPECT_FALSE(result.IsSuccess()); + + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0010"; +} + +/** +* @tc.name: DoListFileCoreTest_0011 +* @tc.desc: Test function of DoListFileCore() interface for true recursion . +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0011, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0011"; + FsListFileOptions opt; + opt.recursion = true; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + ASSERT_TRUE(result.IsSuccess()); + + auto files = result.GetData().value(); + EXPECT_EQ(files.size(), 12); + EXPECT_EQ(files[0], "/text_1.txt"); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0011"; +} + +/** +* @tc.name: DoListFileCoreTest_0012 +* @tc.desc: Test function of DoListFileCore() interface for empty directory . +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0012, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0012"; + auto result = ListFileCore::DoListFile(EMPTY_PATH); + ASSERT_TRUE(result.IsSuccess()); + + auto files = result.GetData().value(); + EXPECT_TRUE(files.empty()); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0012"; +} + +/** +* @tc.name: DoListFileCoreTest_0013 +* @tc.desc: Test function of DoListFileCore() interface for current listNum. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0013, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0013"; + FsListFileOptions opt; + opt.listNum = 3; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + ASSERT_TRUE(result.IsSuccess()); + + auto files = result.GetData().value(); + EXPECT_EQ(files.size(), 3); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0013"; +} + +/** +* @tc.name: DoListFileCoreTest_0014 +* @tc.desc: Test function of DoListFileCore() interface for no such file or directory. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0014, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0014"; + auto result = ListFileCore::DoListFile("/data/local/tmp/ascecedssw"); + EXPECT_FALSE(result.IsSuccess()); + + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900002); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0014"; +} + +/** +* @tc.name: DoListFileCoreTest_0015 +* @tc.desc: Test function of DoListFileCore() interface for >256 length suffix. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0015, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0015"; + FsListFileOptions opt; + FsFileFilter filter; + + const size_t targetLength = 257; + std::string str = "."; + for (size_t i = 1; i < targetLength; ++i) { + str += std::to_string(i % 10); + } + + std::vector suffixVector = {str}; + std::optional> optionalSuffix = suffixVector; + filter.SetSuffix(optionalSuffix); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + EXPECT_FALSE(result.IsSuccess()); + + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0015"; +} + +/** +* @tc.name: DoListFileCoreTest_0016 +* @tc.desc: Test function of DoListFileCore() interface for empty suffix. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0016, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0016"; + FsListFileOptions opt; + FsFileFilter filter; + std::vector suffixVector = {}; + std::optional> optionalSuffix = suffixVector; + filter.SetSuffix(optionalSuffix); + opt.filter = filter; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + EXPECT_FALSE(result.IsSuccess()); + + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0016"; +} + +/** +* @tc.name: DoListFileCoreTest_0017 +* @tc.desc: Test function of DoListFileCore() interface for 0 listNum. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0017, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ListFileCoreTest-begin DoListFileCoreTest_0017"; + FsListFileOptions opt; + opt.listNum = 0; + + auto result = ListFileCore::DoListFile(DIR_PATH, opt); + ASSERT_TRUE(result.IsSuccess()); + + auto files = result.GetData().value(); + EXPECT_EQ(files.size(), 5); + + GTEST_LOG_(INFO) << "ListFileCoreTest-end DoListFileCoreTest_0017"; +} + +} +} +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/mkdir_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/mkdir_core_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34c0d40b50f042e93ad92e7d49a34670ed9e9ff8 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/mkdir_core_mock_test.cpp @@ -0,0 +1,183 @@ +/* + * 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 +#include +#include +#include + +#include "mkdir_core.h" +#include "mock/uv_fs_mock.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class MkdirCoreMockTest : public testing::Test { +public: + static filesystem::path tempFilePath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +filesystem::path MkdirCoreMockTest::tempFilePath; + +void MkdirCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + tempFilePath = filesystem::temp_directory_path() / "test"; + std::filesystem::create_directory(tempFilePath); + uvMock = std::make_shared(); + Uvfs::ins = uvMock; +} + +void MkdirCoreMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + filesystem::remove_all(tempFilePath); + Uvfs::ins = nullptr; + uvMock = nullptr; +} + +void MkdirCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void MkdirCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: MkdirCoreMockTest_DoMkdir_0001 + * @tc.desc: Test function of DoMkdir() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MkdirCoreMockTest-begin MkdirCoreMockTest_DoMkdir_0001"; + + EXPECT_CALL(*uvMock, uv_fs_mkdir(_, _, _, _, _)).WillOnce(Return(0)); + + string path = tempFilePath.string() + "/test01"; + auto ret = MkdirCore::DoMkdir(path); + EXPECT_EQ(ret.IsSuccess(), true); + + GTEST_LOG_(INFO) << "MkdirCoreMockTest-end MkdirCoreMockTest_DoMkdir_0001"; +} + +/** + * @tc.name: MkdirCoreMockTest_DoMkdir_0002 + * @tc.desc: Test function of DoMkdir() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MkdirCoreMockTest-begin MkdirCoreMockTest_DoMkdir_0002"; + + EXPECT_CALL(*uvMock, uv_fs_access(_, _, _, _, _)).WillOnce(Return(-2)).WillOnce(Return(0)); + + string path = tempFilePath.string() + "/test02/testDir"; + auto ret = MkdirCore::DoMkdir(path, true); + EXPECT_EQ(ret.IsSuccess(), true); + + GTEST_LOG_(INFO) << "MkdirCoreMockTest-end MkdirCoreMockTest_DoMkdir_0002"; +} + +/** + * @tc.name: MkdirCoreMockTest_DoMkdir_0003 + * @tc.desc: Test function of DoMkdir() interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MkdirCoreMockTest-begin MkdirCoreMockTest_DoMkdir_0003"; + + EXPECT_CALL(*uvMock, uv_fs_mkdir(_, _, _, _, _)).WillOnce(Return(1)); + + string path = tempFilePath.string() + "/test03"; + auto ret = MkdirCore::DoMkdir(path); + EXPECT_EQ(ret.IsSuccess(), false); + + GTEST_LOG_(INFO) << "MkdirCoreMockTest-end MkdirCoreMockTest_DoMkdir_0003"; +} + +/** + * @tc.name: MkdirCoreMockTest_DoMkdir_0004 + * @tc.desc: Test function of DoMkdir() interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MkdirCoreMockTest-begin MkdirCoreMockTest_DoMkdir_0004"; + + EXPECT_CALL(*uvMock, uv_fs_access(_, _, _, _, _)).WillOnce(Return(0)); + + string path = "/"; + auto ret = MkdirCore::DoMkdir(path, true); + EXPECT_EQ(ret.IsSuccess(), false); + auto err = ret.GetError(); + int errCode = err.GetErrNo(); + EXPECT_EQ(errCode, 13900015); + auto msg = err.GetErrMsg(); + EXPECT_EQ(msg, "File exists"); + + GTEST_LOG_(INFO) << "MkdirCoreMockTest-end MkdirCoreMockTest_DoMkdir_0004"; +} + +/** + * @tc.name: MkdirCoreMockTest_DoMkdir_0005 + * @tc.desc: Test function of DoMkdir() interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MkdirCoreMockTest-begin MkdirCoreMockTest_DoMkdir_0005"; + + EXPECT_CALL(*uvMock, uv_fs_access(_, _, _, _, _)).WillOnce(Return(2)); + + string path = ""; + auto ret = MkdirCore::DoMkdir(path, true); + EXPECT_EQ(ret.IsSuccess(), false); + auto err = ret.GetError(); + int errCode = err.GetErrNo(); + EXPECT_EQ(errCode, 13900002); + auto msg = err.GetErrMsg(); + EXPECT_EQ(msg, "No such file or directory"); + + GTEST_LOG_(INFO) << "MkdirCoreMockTest-end MkdirCoreMockTest_DoMkdir_0005"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.cpp b/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5878a93046576b034577b1d1431decb895cdb2dc --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.cpp @@ -0,0 +1,40 @@ +/* + * 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 "system_mock.h" + +using namespace OHOS::FileManagement::ModuleFileIO; + +extern "C" { +int setxattr(const char *path, const char *name, const void *value, size_t size, int flags) +{ + return System::ins->setxattr(path, name, value, size, flags); +} + +int getxattr(const char *path, const char *name, void *value, size_t size) +{ + return System::ins->getxattr(path, name, value, size); +} + +int fgetxattr(int filedes, const char *name, void *value, size_t size) +{ + return System::ins->fgetxattr(filedes, name, value, size); +} + +int flock(int fd, int operation) +{ + return System::ins->flock(fd, operation); +} +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.h b/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..3ff74be78027d70a93550e1fbb0a4d59a0331885 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.h @@ -0,0 +1,46 @@ +/* + * 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_TEST_UNITTEST_JS_MOD_FS_PROPERTIES_MOCK_SYSTEM_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_PROPERTIES_MOCK_SYSTEM_MOCK_H + +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO { + +class System { +public: + static inline std::shared_ptr ins = nullptr; + +public: + virtual ~System() = default; + virtual int setxattr(const char *path, const char *name, const void *value, size_t size, int flags) = 0; + virtual int getxattr(const char *path, const char *name, void *value, size_t size) = 0; + virtual int fgetxattr(int filedes, const char *name, void *value, size_t size) = 0; + virtual int flock(int fd, int operation) = 0; +}; + +class SystemMock : public System { +public: + MOCK_METHOD5(setxattr, int(const char *path, const char *name, const void *value, size_t size, int flags)); + MOCK_METHOD4(getxattr, int(const char *path, const char *name, void *value, size_t size)); + MOCK_METHOD4(fgetxattr, int(int filedes, const char *name, void *value, size_t size)); + MOCK_METHOD2(flock, int(int fd, int operation)); +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_PROPERTIES_MOCK_SYSTEM_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/mock/uv_fs_mock.cpp b/interfaces/test/unittest/js/mod_fs/properties/mock/uv_fs_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b656a1ad103d4e47cc0346e49b7d1fc1e074035c --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/mock/uv_fs_mock.cpp @@ -0,0 +1,137 @@ +/* + * 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 "uv_fs_mock.h" + + +using namespace OHOS::FileManagement::ModuleFileIO; + +int uv_fs_read(uv_loop_t *loop, uv_fs_t *req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t off, + uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_read(loop, req, file, bufs, nbufs, off, cb); +} + +int uv_fs_readlink(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_readlink(loop, req, path, cb); +} + +int uv_fs_stat(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_stat(loop, req, path, cb); +} + +int uv_fs_utime(uv_loop_t *loop, uv_fs_t *req, const char *path, double atime, double mtime, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_utime(loop, req, path, atime, mtime, cb); +} + +int uv_fs_scandir(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_scandir(loop, req, path, flags, cb); +} + +int uv_fs_scandir_next(uv_fs_t *req, uv_dirent_t *ent) +{ + return Uvfs::ins->uv_fs_scandir_next(req, ent); +} + +int uv_fs_rmdir(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_rmdir(loop, req, path, cb); +} + +int uv_fs_symlink(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *new_path, int flags, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_symlink(loop, req, path, new_path, flags, cb); +} + +int uv_fs_open(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, int mode, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_open(loop, req, path, flags, mode, cb); +} + +int uv_fs_ftruncate(uv_loop_t *loop, uv_fs_t *req, uv_file fd, int64_t offset, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_ftruncate(loop, req, fd, offset, cb); +} + +int uv_fs_write(uv_loop_t *loop, uv_fs_t *req, uv_file fd, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, + uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_write(loop, req, fd, bufs, nbufs, offset, cb); +} + +int uv_fs_realpath(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_realpath(loop, req, path, cb); +} + +int uv_fs_close(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_close(loop, req, file, cb); +} + +int uv_fs_fdatasync(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_fdatasync(loop, req, file, cb); +} + +int uv_fs_mkdir(uv_loop_t *loop, uv_fs_t *req, const char *path, int mode, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_mkdir(loop, req, path, mode, cb); +} + +int uv_fs_access(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_access(loop, req, path, flags, cb); +} + +int uv_fs_mkdtemp(uv_loop_t *loop, uv_fs_t *req, const char *tpl, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_mkdtemp(loop, req, tpl, cb); +} + +int uv_fs_unlink(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_unlink(loop, req, path, cb); +} + +void uv_fs_req_cleanup(uv_fs_t *req) +{ + return; +} + +int uv_fs_rename(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *newPath, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_rename(loop, req, path, newPath, cb); +} + +int uv_fs_fsync(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_fsync(loop, req, file, cb); +} + +int uv_fs_sendfile(uv_loop_t *loop, uv_fs_t *req, uv_file outFd, uv_file inFd, int64_t off, size_t len, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_sendfile(loop, req, outFd, inFd, off, len, cb); +} + +int uv_fs_lstat(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) +{ + return Uvfs::ins->uv_fs_lstat(loop, req, path, cb); +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/mock/uv_fs_mock.h b/interfaces/test/unittest/js/mod_fs/properties/mock/uv_fs_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..1fa703a0fe7ba997c03ec58c580c35c2220b40a8 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/mock/uv_fs_mock.h @@ -0,0 +1,91 @@ +/* + * 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 UV_FS_READ_MOCK_H +#define UV_FS_READ_MOCK_H + +#include "uv.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO { + +class Uvfs { +public: + static inline std::shared_ptr ins = nullptr; +public: + virtual ~Uvfs() = default; + virtual int uv_fs_read(uv_loop_t *loop, uv_fs_t *req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, + int64_t off, uv_fs_cb cb) = 0; + virtual int uv_fs_readlink(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) = 0; + virtual int uv_fs_stat(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) = 0; + virtual int uv_fs_utime(uv_loop_t *loop, uv_fs_t *req, const char *path, double atime, + double mtime, uv_fs_cb cb) = 0; + virtual int uv_fs_scandir(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, uv_fs_cb cb) = 0; + virtual int uv_fs_scandir_next(uv_fs_t *req, uv_dirent_t *ent) = 0; + virtual int uv_fs_rmdir(uv_loop_t *loop, uv_fs_t *req, const char* path, uv_fs_cb cb) = 0; + virtual int uv_fs_symlink(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *new_path, int flags, + uv_fs_cb cb) = 0; + virtual int uv_fs_open(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, int mode, uv_fs_cb cb) = 0; + virtual int uv_fs_ftruncate(uv_loop_t *loop, uv_fs_t *req, uv_file fd, int64_t offset, uv_fs_cb cb) = 0; + virtual int uv_fs_write(uv_loop_t *loop, uv_fs_t *req, uv_file fd, const uv_buf_t bufs[], unsigned int nbufs, + int64_t offset, uv_fs_cb cb) = 0; + virtual int uv_fs_realpath(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) = 0; + virtual int uv_fs_close(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb) = 0; + virtual int uv_fs_fdatasync(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb) = 0; + virtual int uv_fs_mkdir(uv_loop_t *loop, uv_fs_t *req, const char *path, int mode, uv_fs_cb cb) = 0; + virtual int uv_fs_access(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, uv_fs_cb cb) = 0; + virtual int uv_fs_mkdtemp(uv_loop_t *loop, uv_fs_t *req, const char *tpl, uv_fs_cb cb) = 0; + virtual int uv_fs_unlink(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) = 0; + virtual int uv_fs_rename(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *newPath, uv_fs_cb cb) = 0; + virtual int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) = 0; + virtual int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file outFd, uv_file inFd, + int64_t off, size_t len, uv_fs_cb cb) = 0; + virtual int uv_fs_lstat(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb) = 0; +}; + +class UvfsMock : public Uvfs { +public: + MOCK_METHOD7(uv_fs_read, int(uv_loop_t *loop, uv_fs_t *req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, + int64_t off, uv_fs_cb cb)); + MOCK_METHOD4(uv_fs_readlink, int(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)); + MOCK_METHOD4(uv_fs_stat, int(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)); + MOCK_METHOD6(uv_fs_utime, int(uv_loop_t *loop, uv_fs_t *req, const char *path, double atime, double mtime, + uv_fs_cb cb)); + MOCK_METHOD5(uv_fs_scandir, int(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, uv_fs_cb cb)); + MOCK_METHOD2(uv_fs_scandir_next, int(uv_fs_t *req, uv_dirent_t *ent)); + MOCK_METHOD4(uv_fs_rmdir, int(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)); + MOCK_METHOD6(uv_fs_symlink, int(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *new_path, int flags, + uv_fs_cb cb)); + MOCK_METHOD6(uv_fs_open, int(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, int mode, uv_fs_cb cb)); + MOCK_METHOD5(uv_fs_ftruncate, int(uv_loop_t *loop, uv_fs_t *req, uv_file fd, int64_t offset, uv_fs_cb cb)); + MOCK_METHOD7(uv_fs_write, int(uv_loop_t *loop, uv_fs_t *req, uv_file fd, const uv_buf_t bufs[], unsigned int nbufs, + int64_t offset, uv_fs_cb cb)); + MOCK_METHOD4(uv_fs_realpath, int(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)); + MOCK_METHOD4(uv_fs_close, int(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb)); + MOCK_METHOD4(uv_fs_fdatasync, int(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb)); + MOCK_METHOD5(uv_fs_mkdir, int(uv_loop_t *loop, uv_fs_t *req, const char *path, int mode, uv_fs_cb cb)); + MOCK_METHOD5(uv_fs_access, int(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, uv_fs_cb cb)); + MOCK_METHOD4(uv_fs_mkdtemp, int(uv_loop_t *loop, uv_fs_t *req, const char *tpl, uv_fs_cb cb)); + MOCK_METHOD4(uv_fs_unlink, int(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)); + MOCK_METHOD5(uv_fs_rename, int(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *newPath, uv_fs_cb cb)); + MOCK_METHOD4(uv_fs_fsync, int(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)); + MOCK_METHOD7(uv_fs_sendfile, int(uv_loop_t* loop, uv_fs_t* req, uv_file outFd, uv_file inFd, + int64_t off, size_t len, uv_fs_cb cb)); + MOCK_METHOD4(uv_fs_lstat, int(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)); +}; + +} // OHOS::FileManagement::ModuleFileIO +#endif \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/read_text_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/read_text_core_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56b6e4bb352dd1cb9eda26155c25551b0d1c26ef --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/read_text_core_test.cpp @@ -0,0 +1,246 @@ +/* +* 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 +#include + +#define FILE_INFO "hello world" +#define FILE_PATH "/data/test/ReadTextCoreTest.txt" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +const string content = "hello world"; + +class ReadTextCoreTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + int32_t fd = open(FILE_PATH, CREATE | O_RDWR, 0644); + write(fd, content.c_str(), content.length()); + close(fd); + }; + static void TearDownTestCase() + { + rmdir(FILE_PATH); + }; + void SetUp() {}; + void TearDown() {}; +}; +/** +* @tc.name: DoReadTextTest_0001 +* @tc.desc: Test function of DoReadText() interface for single argument. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ReadTextCoreTest, DoReadTextTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadTextCoreTest-begin DoReadTextTest_0001"; + auto ret = ReadTextCore::DoReadText(FILE_PATH); + EXPECT_TRUE(ret.IsSuccess()); + + const auto &resText = ret.GetData().value(); + string res = std::get<0>(resText); + EXPECT_EQ(res, FILE_INFO); + + GTEST_LOG_(INFO) << "ReadTextCoreTest-end DoReadTextTest_0001"; +} + +/** +* @tc.name: DoReadTextTest_0002 +* @tc.desc: Test function of DoReadText() interface for invalid offset. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ReadTextCoreTest, DoReadTextTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadTextCoreTest-begin DoReadTextTest_0002"; + ReadTextOptions options; + options.offset = -1; + auto ret = ReadTextCore::DoReadText(FILE_PATH, options); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ReadTextCoreTest-end DoReadTextTest_0002"; +} + +/** +* @tc.name: DoReadTextTest_0003 +* @tc.desc: Test function of DoReadText() interface for invalid length < 0. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ReadTextCoreTest, DoReadTextTest_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadTextCoreTest-begin DoReadTextTest_0003"; + ReadTextOptions options; + options.length = -5; + auto ret = ReadTextCore::DoReadText(FILE_PATH, options); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ReadTextCoreTest-end DoReadTextTest_0003"; +} + +/** +* @tc.name: DoReadTextTest_0004 +* @tc.desc: Test function of DoReadText() interface for invalid length > UINT_MAX. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ReadTextCoreTest, DoReadTextTest_0004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadTextCoreTest-begin DoReadTextTest_0004"; + ReadTextOptions options; + options.length = static_cast(UINT_MAX) + 1; + auto ret = ReadTextCore::DoReadText(FILE_PATH, options); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ReadTextCoreTest-end DoReadTextTest_0004"; +} + +/** +* @tc.name: DoReadTextTest_0005 +* @tc.desc: Test function of DoReadText() interface for invalid encoding. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ReadTextCoreTest, DoReadTextTest_0005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadTextCoreTest-begin DoReadTextTest_0005"; + ReadTextOptions options; + options.encoding = "gbk"; + auto ret = ReadTextCore::DoReadText(FILE_PATH, options); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ReadTextCoreTest-end DoReadTextTest_0005"; +} + +/** +* @tc.name: DoReadTextTest_0006 +* @tc.desc: Test function of DoReadText() interface for no such file or directory. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ReadTextCoreTest, DoReadTextTest_0006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadTextCoreTest-begin DoReadTextTest_0006"; + auto ret = ReadTextCore::DoReadText("ReadTextCoreTest-begin-DoReadTextTest_0006.txt"); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900002); + + GTEST_LOG_(INFO) << "ReadTextCoreTest-end DoReadTextTest_0006"; +} + +/** +* @tc.name: DoReadTextTest_0007 +* @tc.desc: Test function of DoReadText() interface for huge offset. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ReadTextCoreTest, DoReadTextTest_0007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadTextCoreTest-begin DoReadTextTest_0007"; + ReadTextOptions options; + options.offset = 1000000; // 假设文件较小 + auto ret = ReadTextCore::DoReadText(FILE_PATH, options); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "ReadTextCoreTest-end DoReadTextTest_0007"; +} + +/** +* @tc.name: DoReadTextTest_0008 +* @tc.desc: Test function of DoReadText() interface for no such file or directory. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ReadTextCoreTest, DoReadTextTest_0008, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadTextCoreTest-begin DoReadTextTest_0008"; + ReadTextOptions options; + options.length = 1000000; // 超过实际大小 + auto ret = ReadTextCore::DoReadText(FILE_PATH, options); + ASSERT_TRUE(ret.IsSuccess()); + + const auto &resText = ret.GetData().value(); + string res = std::get<0>(resText); + EXPECT_EQ(res, FILE_INFO); + + GTEST_LOG_(INFO) << "ReadTextCoreTest-end DoReadTextTest_0008"; +} + +/** +* @tc.name: DoReadTextTest_0009 +* @tc.desc: Test function of DoReadText() interface for success. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +* @tc.require: AR000IGDNF +*/ +HWTEST_F(ReadTextCoreTest, DoReadTextTest_0009, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadTextCoreTest-begin DoReadTextTest_0009"; + ReadTextOptions options; + options.offset = 2; + options.length = 5; + auto ret = ReadTextCore::DoReadText(FILE_PATH, options); + ASSERT_TRUE(ret.IsSuccess()); + + const auto &resText = ret.GetData().value(); + string res = std::get<0>(resText); + std::string extracted = std::string(FILE_INFO).substr( + options.offset.value(), options.length.value()); + EXPECT_EQ(res, extracted); + + GTEST_LOG_(INFO) << "ReadTextCoreTest-end DoReadTextTest_0009"; +} + +} +} +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/unlink_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/unlink_core_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1adefab1f86904dd78b9c12e9bcc30830e47e160 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/unlink_core_mock_test.cpp @@ -0,0 +1,108 @@ +/* + * 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 +#include +#include +#include + +#include "mock/uv_fs_mock.h" +#include "unlink_core.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class UnlinkCoreTest : public testing::Test { +public: + static filesystem::path tempFilePath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +filesystem::path UnlinkCoreTest::tempFilePath; + +void UnlinkCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + tempFilePath = filesystem::temp_directory_path() / "unlink_test_file.txt"; + ofstream(tempFilePath) << "Test content\n123\n456"; + uvMock = std::make_shared(); + Uvfs::ins = uvMock; +} + +void UnlinkCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + filesystem::remove(tempFilePath); + Uvfs::ins = nullptr; + uvMock = nullptr; +} + +void UnlinkCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void UnlinkCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: UnlinkCoreTest_DoUnlink_001 + * @tc.desc: Test function of UnlinkCore::DoUnlink interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(UnlinkCoreTest, UnlinkCoreTest_DoUnlink_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin UnlinkCoreTest_DoUnlink_001"; + + EXPECT_CALL(*uvMock, uv_fs_unlink(_, _, _, _)).WillOnce(Return(1)); + + string path = tempFilePath.string(); + auto res = UnlinkCore::DoUnlink(path); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "NClassTest-end UnlinkCoreTest_DoUnlink_001"; +} + +/** + * @tc.name: UnlinkCoreTest_DoUnlink_002 + * @tc.desc: Test function of UnlinkCore::DoUnlink interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(UnlinkCoreTest, UnlinkCoreTest_DoUnlink_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin UnlinkCoreTest_DoUnlink_002"; + + EXPECT_CALL(*uvMock, uv_fs_unlink(_, _, _, _)).WillOnce(Return(-1)); + + string path = tempFilePath.string(); + auto res = UnlinkCore::DoUnlink(path); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "NClassTest-end UnlinkCoreTest_DoUnlink_002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/write_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/write_core_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e16651fad8e2df9ddd2b1c8be011c3820808b48e --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/write_core_mock_test.cpp @@ -0,0 +1,122 @@ +/* + * 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 "write_core.h" +#include "uv_fs_mock.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class WriteCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +void WriteCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + uvMock = std::make_shared(); + Uvfs::ins = uvMock; +} + +void WriteCoreMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + Uvfs::ins = nullptr; + uvMock = nullptr; +} + +void WriteCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void WriteCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: WriteCoreMockTest_DoWrite1_001 + * @tc.desc: Test function of WriteCore::DoWrite3 interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WriteCoreMockTest, WriteCoreMockTest_DoWrite1_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WriteCoreMockTest-begin WriteCoreMockTest_DoWrite1_001"; + + int32_t fd = 1; + string buffer; + + EXPECT_CALL(*uvMock, uv_fs_write(_, _, _, _, _, _, _)).WillOnce(Return(-1)); + auto res = WriteCore::DoWrite(fd, buffer); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "WriteCoreMockTest-end WriteCoreMockTest_DoWrite1_001"; +} + +/** + * @tc.name: WriteCoreMockTest_DoWrite1_002 + * @tc.desc: Test function of WriteCore::DoWrite3 interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WriteCoreMockTest, WriteCoreMockTest_DoWrite1_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WriteCoreMockTest-begin WriteCoreMockTest_DoWrite1_002"; + + int32_t fd = 1; + string buffer; + + EXPECT_CALL(*uvMock, uv_fs_write(_, _, _, _, _, _, _)).WillOnce(Return(1)); + auto res = WriteCore::DoWrite(fd, buffer); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "WriteCoreMockTest-end WriteCoreMockTest_DoWrite1_002"; +} + +/** + * @tc.name: WriteCoreMockTest_DoWrite2_003 + * @tc.desc: Test function of WriteCore::DoWrite2 interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WriteCoreMockTest, WriteCoreMockTest_DoWrite2_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WriteCoreMockTest-begin WriteCoreMockTest_DoWrite2_003"; + + int32_t fd = -1; + string buffer; + + EXPECT_CALL(*uvMock, uv_fs_write(_, _, _, _, _, _, _)).WillOnce(Return(-1)); + auto res = WriteCore::DoWrite(fd, buffer); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "WriteCoreMockTest-end WriteCoreMockTest_DoWrite2_003"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/write_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/write_core_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1741f168f8781985786a0559a8b297b628df4402 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/write_core_test.cpp @@ -0,0 +1,148 @@ +/* + * 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 "write_core.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class WriteCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void WriteCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void WriteCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void WriteCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void WriteCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: WriteCoreTest_DoWrite1_001 + * @tc.desc: Test function of WriteCore::DoWrite1 interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WriteCoreTest, WriteCoreTest_DoWrite1_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WriteCoreTest-begin WriteCoreTest_DoWrite1_001"; + int32_t fd = -1; + string buffer; + auto res = WriteCore::DoWrite(fd, buffer); + + EXPECT_EQ(res.IsSuccess(), false); + GTEST_LOG_(INFO) << "WriteCoreTest-end WriteCoreTest_DoWrite1_001"; +} + +/** + * @tc.name: WriteCoreTest_DoWrite2_001 + * @tc.desc: Test function of WriteCore::DoWrite2 interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WriteCoreTest, WriteCoreTest_DoWrite2_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WriteCoreTest-begin WriteCoreTest_DoWrite2_001"; + int32_t fd = -1; + string buffer; + + auto res = WriteCore::DoWrite(fd, buffer); + EXPECT_EQ(res.IsSuccess(), false); + GTEST_LOG_(INFO) << "WriteCoreTest-end WriteCoreTest_DoWrite2_001"; +} + +#if defined(_WIN64) || defined(__X86_64__) || defined(__ppc64__) || defined(__LP64__) +/** + * @tc.name: WriteCoreTest_DoWrite1_002 + * @tc.desc: Test function of WriteCore::DoWrite1 interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WriteCoreTest, WriteCoreTest_DoWrite1_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WriteCoreTest-begin WriteCoreTest_DoWrite1_002"; + int32_t fd = -1; + ArrayBuffer buffer(nullptr, 0); + + auto res = WriteCore::DoWrite(fd, buffer); + EXPECT_EQ(res.IsSuccess(), false); + GTEST_LOG_(INFO) << "WriteCoreTest-end WriteCoreTest_DoWrite1_002"; +} +#else +#endif + +/** + * @tc.name: WriteCoreTest_DoWrite1_003 + * @tc.desc: Test function of WriteCore::DoWrite1 interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WriteCoreTest, WriteCoreTest_DoWrite1_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WriteCoreTest-begin WriteCoreTest_DoWrite1_003"; + int32_t fd = 1; + ArrayBuffer buffer(nullptr, 1); + std::optional options = std::make_optional(WriteOptions()); + options->offset = std::make_optional(-1); + + auto res = WriteCore::DoWrite(fd, buffer, options); + EXPECT_EQ(res.IsSuccess(), false); + GTEST_LOG_(INFO) << "WriteCoreTest-end WriteCoreTest_DoWrite1_003"; +} + +/** + * @tc.name: WriteCoreTest_DoWrite1_004 + * @tc.desc: Test function of WriteCore::DoWrite1 interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WriteCoreTest, WriteCoreTest_DoWrite1_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WriteCoreTest-begin WriteCoreTest_DoWrite1_004"; + int32_t fd = 1; + ArrayBuffer buffer(nullptr, 1); + + auto res = WriteCore::DoWrite(fd, buffer); + EXPECT_EQ(res.IsSuccess(), false); + GTEST_LOG_(INFO) << "WriteCoreTest-end WriteCoreTest_DoWrite1_004"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_hash/hash_core_test.cpp b/interfaces/test/unittest/js/mod_hash/hash_core_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..069a3230e9d756b9f4a145bbd6e918432ddfa557 --- /dev/null +++ b/interfaces/test/unittest/js/mod_hash/hash_core_test.cpp @@ -0,0 +1,136 @@ +/* + * 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 +#include +#include +#include "hash_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static const string g_filePath = "/data/test/HashCoreTest.txt"; +class HashCoreTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + int32_t fd = open(g_filePath.c_str(), O_CREAT | O_RDWR, 0644); + close(fd); + }; + static void TearDownTestCase() + { + rmdir(g_filePath.c_str()); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: DoHashTest_0001 + * @tc.desc: Test function of DoHash() interface for invalid alg. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(HashCoreTest, DoHashTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HashCoreTest-begin DoHashTest_0001"; + string alg = "sha128"; + auto ret = HashCore::DoHash(g_filePath, alg); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "HashCoreTest-end DoHashTest_0001"; +} + +/** + * @tc.name: DoHashTest_0002 + * @tc.desc: Test function of DoHash() interface for md5 success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(HashCoreTest, DoHashTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HashCoreTest-begin DoHashTest_0002"; + auto ret = HashCore::DoHash(g_filePath, "md5"); + ASSERT_TRUE(ret.IsSuccess()); + + GTEST_LOG_(INFO) << "HashCoreTest-end DoHashTest_0002"; +} + +/** + * @tc.name: DoHashTest_0003 + * @tc.desc: Test function of DoHash() interface for sha1 success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(HashCoreTest, DoHashTest_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HashCoreTest-begin DoHashTest_0003"; + auto ret = HashCore::DoHash(g_filePath, "sha1"); + ASSERT_TRUE(ret.IsSuccess()); + + GTEST_LOG_(INFO) << "HashCoreTest-end DoHashTest_0003"; +} + +/** + * @tc.name: DoHashTest_0004 + * @tc.desc: Test function of DoHash() interface for sha256 success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(HashCoreTest, DoHashTest_0004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HashCoreTest-begin DoHashTest_0004"; + auto ret = HashCore::DoHash(g_filePath, "sha256"); + ASSERT_TRUE(ret.IsSuccess()); + + GTEST_LOG_(INFO) << "HashCoreTest-end DoHashTest_0004"; +} + +/** + * @tc.name: DoHashTest_0005 + * @tc.desc: Test function of DoHash() interface for no such file or directory. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(HashCoreTest, DoHashTest_0005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "HashCoreTest-begin DoHashTest_0005"; + auto ret = HashCore::DoHash("/data/local/tmp/azuxyicayhyskjeh", "sha256"); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900002); + + GTEST_LOG_(INFO) << "HashCoreTest-end DoHashTest_0005"; +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_securitylabel/securitylabel_core_test.cpp b/interfaces/test/unittest/js/mod_securitylabel/securitylabel_core_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f320af0371ac30c73381a072a2a449b71ebe3a99 --- /dev/null +++ b/interfaces/test/unittest/js/mod_securitylabel/securitylabel_core_test.cpp @@ -0,0 +1,144 @@ +/* + * 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 +#include +#include +#include "securitylabel_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleSecurityLabel { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; + +static const string g_filePath = "/data/test/SecurityLabelCoreTest.txt"; +static const string g_validFilePath = "/data/test/validFilePath"; + +class SecurityLabelCoreTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + int32_t fd = open(g_filePath.c_str(), O_CREAT | O_RDWR, 0644); + close(fd); + }; + static void TearDownTestCase() + { + rmdir(g_filePath.c_str()); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: DoSetSecurityLabel_0001 + * @tc.desc: Test function of DoSetSecurityLabel() interface for invalid level. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(SecurityLabelCoreTest, DoSetSecurityLabel_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SecurityLabelCoreTest-begin DoSetSecurityLabel_0001"; + auto ret = DoSetSecurityLabel(g_filePath, "abc"); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "SecurityLabelCoreTest-end DoSetSecurityLabel_0001"; +} + +/** + * @tc.name: DoSetSecurityLabel_0002 + * @tc.desc: Test function of DoSetSecurityLabel() interface for invalid path. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(SecurityLabelCoreTest, DoSetSecurityLabel_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SecurityLabelCoreTest-begin DoSetSecurityLabel_0002"; + auto ret = DoSetSecurityLabel(g_validFilePath, "s1"); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900002); + + GTEST_LOG_(INFO) << "SecurityLabelCoreTest-end DoSetSecurityLabel_0002"; +} + +/** + * @tc.name: DoSetSecurityLabel_0003 + * @tc.desc: Test function of DoSetSecurityLabel() interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(SecurityLabelCoreTest, DoSetSecurityLabel_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SecurityLabelCoreTest-begin DoSetSecurityLabel_0003"; + auto ret = DoSetSecurityLabel(g_filePath, "s2"); + ASSERT_TRUE(ret.IsSuccess()); + + GTEST_LOG_(INFO) << "SecurityLabelCoreTest-end DoSetSecurityLabel_0003"; +} + +/** + * @tc.name: DoGetSecurityLabel_0001 + * @tc.desc: Test function of DoGetSecurityLabel() interface for invalid path. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(SecurityLabelCoreTest, DoGetSecurityLabel_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SecurityLabelCoreTest-begin DoGetSecurityLabel_0001"; + auto ret = DoGetSecurityLabel(g_validFilePath); + EXPECT_TRUE(ret.IsSuccess()); + + const string level = ret.GetData().value(); + EXPECT_EQ(level, "s3"); + + GTEST_LOG_(INFO) << "SecurityLabelCoreTest-end DoGetSecurityLabel_0001"; +} + +/** + * @tc.name: DoGetSecurityLabel_0002 + * @tc.desc: Test function of DoGetSecurityLabel() interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000IGDNF + */ +HWTEST_F(SecurityLabelCoreTest, DoGetSecurityLabel_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SecurityLabelCoreTest-begin DoGetSecurityLabel_0002"; + auto ret = DoGetSecurityLabel(g_filePath); + EXPECT_TRUE(ret.IsSuccess()); + + const string level = ret.GetData().value(); + EXPECT_EQ(level, "s2"); + + GTEST_LOG_(INFO) << "SecurityLabelCoreTest-end DoGetSecurityLabel_0002"; +} + +} // namespace ModuleSecurityLabel +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/utils/filemgmt_libfs/BUILD.gn b/utils/filemgmt_libfs/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..39bd586157bfa89fb951ac0308315a9126974afd --- /dev/null +++ b/utils/filemgmt_libfs/BUILD.gn @@ -0,0 +1,72 @@ +# 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. + +import("//build/ohos.gni") +import("//foundation/filemanagement/file_api/file_api.gni") + +config("libfs_public_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "${utils_path}/common/include", + ] +} + +ohos_shared_library("filemgmt_libfs") { + cflags_cc = [ "-std=c++17" ] + if (!use_mingw_win && !use_mac) { + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc += [ + "-fvisibility-inlines-hidden", + "-Oz", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + } + + sources = [ "src/fs_error.cpp" ] + + if (use_mingw_win) { + defines = [ "WIN_PLATFORM" ] + } + if (use_mac) { + defines = [ "IOS_PLATFORM" ] + } + + public_configs = [ ":libfs_public_config" ] + + deps = [ "${utils_path}/filemgmt_libhilog:filemgmt_libhilog" ] + + external_deps = [ + "hilog:libhilog", + "libuv:uv", + ] + + use_exceptions = true + + subsystem_name = "filemanagement" + innerapi_tags = [ "platformsdk" ] + part_name = "file_api" +} diff --git a/utils/filemgmt_libfs/include/filemgmt_libfs.h b/utils/filemgmt_libfs/include/filemgmt_libfs.h new file mode 100644 index 0000000000000000000000000000000000000000..facda9a16481c7367cc1e0e179b4933ac5202837 --- /dev/null +++ b/utils/filemgmt_libfs/include/filemgmt_libfs.h @@ -0,0 +1,23 @@ +/* + * 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 FILEMGMT_LIBN_FILEMGMT_LIBFS_H +#define FILEMGMT_LIBN_FILEMGMT_LIBFS_H + +#include "fs_array_buffer.h" +#include "fs_error.h" +#include "fs_result.h" + +#endif // FILEMGMT_LIBN_FILEMGMT_LIBFS_H \ No newline at end of file diff --git a/utils/filemgmt_libfs/include/fs_array_buffer.h b/utils/filemgmt_libfs/include/fs_array_buffer.h new file mode 100644 index 0000000000000000000000000000000000000000..52b28a996b7e93c9fd1b2a411330507c0c11c7bc --- /dev/null +++ b/utils/filemgmt_libfs/include/fs_array_buffer.h @@ -0,0 +1,31 @@ +/* + * 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 FILEMANAGEMENT_FS_ARRAY_BUFFER_H +#define FILEMANAGEMENT_FS_ARRAY_BUFFER_H + +#include + +namespace OHOS::FileManagement::ModuleFileIO { + +struct ArrayBuffer { + void *buf; + size_t length; + + ArrayBuffer(void *buffer, size_t len) : buf(buffer), length(len) {} +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // FILEMANAGEMENT_FS_ARRAY_BUFFER_H \ No newline at end of file diff --git a/utils/filemgmt_libfs/include/fs_error.h b/utils/filemgmt_libfs/include/fs_error.h new file mode 100644 index 0000000000000000000000000000000000000000..94525eec342459861a8b37682b4714ccfad86a6f --- /dev/null +++ b/utils/filemgmt_libfs/include/fs_error.h @@ -0,0 +1,428 @@ +/* + * 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 FILEMANAGEMENT_FS_ERROR_H +#define FILEMANAGEMENT_FS_ERROR_H + +#include +#include +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +#if (defined IOS_PLATFORM) || (defined WIN_PLATFORM) +constexpr int EBADR = 53; +constexpr int EBADFD = 77; +constexpr int ERESTART = 85; +#endif +#ifdef WIN_PLATFORM +constexpr int EDQUOT = 122; +#endif +constexpr int UNKNOWN_ERR = -1; +constexpr int NO_TASK_ERR = -2; +constexpr int CANCEL_ERR = -3; +constexpr int ERRNO_NOERR = 0; +constexpr int ECONNECTIONFAIL = 45; +constexpr int ECONNECTIONABORT = 46; +constexpr int STORAGE_SERVICE_SYS_CAP_TAG = 13600000; +constexpr int FILEIO_SYS_CAP_TAG = 13900000; +constexpr int USER_FILE_MANAGER_SYS_CAP_TAG = 14000000; +constexpr int USER_FILE_SERVICE_SYS_CAP_TAG = 14300000; +constexpr int DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG = 22400000; +constexpr int SOFTBUS_TRANS_FILE_PERMISSION_DENIED = -426114938; +constexpr int SOFTBUS_TRANS_FILE_DISK_QUOTA_EXCEEDED = -426114937; +constexpr int SOFTBUS_TRANS_FILE_NO_MEMORY = -426114936; +constexpr int SOFTBUS_TRANS_FILE_NETWORK_ERROR = -426114935; +constexpr int SOFTBUS_TRANS_FILE_NOT_FOUND = -426114934; +constexpr int SOFTBUS_TRANS_FILE_EXISTED = -426114933; +constexpr int DFS_CANCEL_SUCCESS = 204; +const std::string FILEIO_TAG_ERR_CODE = "code"; +const std::string FILEIO_TAG_ERR_DATA = "data"; + +enum ErrCodeSuffixOfFileIO { + E_PERM = 1, + E_NOENT, + E_SRCH, + E_INTR, + E_IO, + E_NXIO, + E_2BIG, + E_BADF, + E_CHILD, + E_AGAIN, + E_NOMEM, + E_ACCES, + E_FAULT, + E_BUSY, + E_EXIST, + E_XDEV, + E_NODEV, + E_NOTDIR, + E_ISDIR, + E_INVAL, + E_NFILE, + E_MFILE, + E_TXTBSY, + E_FBIG, + E_NOSPC, + E_SPIPE, + E_ROFS, + E_MLINK, + E_DEADLK, + E_NAMETOOLONG, + E_NOSYS, + E_NOTEMPTY, + E_LOOP, + E_WOULDBLOCK, + E_BADR, + E_NOSTR, + E_NODATA, + E_OVERFLOW, + E_BADFD, + E_RESTART, + E_DQUOT, + E_UKERR, + E_NOLCK, + E_NETUNREACH, + E_CONNECTION_FAIL, + E_CONNECTION_ABORT, + E_NOTASK, + E_UNCANCELED, + E_CANCELED, +}; + +enum ErrCodeSuffixOfUserFileManager { + E_DISPLAYNAME = 1, + E_URIM, + E_SUFFIX, + E_TRASH, + E_OPEN_MODE, + E_NOT_ALBUM, + E_ROOT_DIR, + E_MOVE_DENIED, + E_RENAME_DENIED, + E_RELATIVEPATH, + E_INNER_FAIL, + E_FILE_TYPE, + E_FILE_KEY, + E_INPUT +}; + +enum ErrCodeSuffixOfStorageService { + E_IPCSS = 1, + E_NOTSUPPORTEDFS, + E_MOUNT, + E_UNMOUNT, + E_VOLUMESTATE, + E_PREPARE, + E_DELETE, + E_NOOBJECT, + E_OUTOFRANGE +}; + +enum ErrCodeSuffixOfUserFileService { + E_IPCS = 1, + E_URIS, + E_GETINFO, + E_GETRESULT, + E_REGISTER, + E_REMOVE, + E_INIT, + E_NOTIFY, + E_CONNECT, + E_CALLBACK_AND_URI_HAS_NOT_RELATIONS, + E_CALLBACK_IS_NOT_REGISTER, + E_CAN_NOT_FIND_URI, + E_DO_NOT_HAVE_PARENT, + E_LOAD_SA, + E_COUNT +}; + +enum ErrCodeSuffixOfDistributedFile { + E_CLOUD_NOT_READY = 1, + E_NETWORK_ERR, + E_BATTERY_WARNING, + E_EXCEED_MAX_LIMIT, + E_DATABASE_FAILED +}; + +enum CommonErrCode { + E_PERMISSION = 201, + E_PERMISSION_SYS = 202, + E_PARAMS = 401, + E_DEVICENOTSUPPORT = 801, + E_OSNOTSUPPORT = 901, + E_UNKNOWN_ERROR = 13900042 +}; + +static inline std::unordered_map softbusErr2ErrCodeTable { + { SOFTBUS_TRANS_FILE_PERMISSION_DENIED, EPERM }, + { SOFTBUS_TRANS_FILE_DISK_QUOTA_EXCEEDED, EIO }, + { SOFTBUS_TRANS_FILE_NO_MEMORY, ENOMEM }, + { SOFTBUS_TRANS_FILE_NETWORK_ERROR, ENETUNREACH }, + { SOFTBUS_TRANS_FILE_NOT_FOUND, ENOENT }, + { SOFTBUS_TRANS_FILE_EXISTED, EEXIST }, + { DFS_CANCEL_SUCCESS, ECANCELED }, +}; + +static inline std::unordered_map uvCode2ErrCodeTable { + { "EPERM", EPERM }, + { "ENOENT", ENOENT }, + { "ESRCH", ESRCH }, + { "EINTR", EINTR }, + { "EIO", EIO }, + { "ENXIO", ENXIO }, + { "E2BIG", E2BIG }, + { "EBADF", EBADF }, + { "ECHILD", ECHILD }, + { "EAGAIN", EAGAIN }, + { "ENOMEM", ENOMEM }, + { "EACCES", EACCES }, + { "EFAULT", EFAULT }, + { "EBUSY", EBUSY }, + { "EEXIST", EEXIST }, + { "EXDEV", EXDEV }, + { "ENODEV", ENODEV }, + { "ENOTDIR", ENOTDIR }, + { "EISDIR", EISDIR }, + { "EINVAL", EINVAL }, + { "ENFILE", ENFILE }, + { "EMFILE", EMFILE }, + { "ETXTBSY", ETXTBSY }, + { "EFBIG", EFBIG }, + { "ENOSPC", ENOSPC }, + { "ESPIPE", ESPIPE }, + { "EROFS", EROFS }, + { "EMLINK", EMLINK }, + { "EDEADLK", EDEADLK }, + { "ENAMETOOLONG", ENAMETOOLONG }, + { "ENOSYS", ENOSYS }, + { "ENOTEMPTY", ENOTEMPTY }, + { "ELOOP", ELOOP }, + { "EWOULDBLOCK", EWOULDBLOCK }, + { "EBADR", EBADR }, + { "ENOSTR", ENOSTR }, + { "ENODATA", ENODATA }, + { "EOVERFLOW", EOVERFLOW }, + { "EBADFD", EBADFD }, + { "ERESTART", ERESTART }, + { "EDQUOT", EDQUOT }, + { "ENETUNREACH", ENETUNREACH }, + { "ECONNECTIONFAIL", ECONNECTIONFAIL }, + { "ECONNECTIONABORT", ECONNECTIONABORT }, + { "ECANCELED", ECANCELED }, +}; + +static inline std::unordered_map> errCodeTable { + { ERRNO_NOERR, { ERRNO_NOERR, "No error imformation" } }, + { EPERM, { FILEIO_SYS_CAP_TAG + E_PERM, "Operation not permitted" } }, + { ENOENT, { FILEIO_SYS_CAP_TAG + E_NOENT, "No such file or directory" } }, + { ESRCH, { FILEIO_SYS_CAP_TAG + E_SRCH, "No such process" } }, + { EINTR, { FILEIO_SYS_CAP_TAG + E_INTR, "Interrupted system call" } }, + { EIO, { FILEIO_SYS_CAP_TAG + E_IO, "I/O error" } }, + { ENXIO, { FILEIO_SYS_CAP_TAG + E_NXIO, "No such device or address" } }, + { E2BIG, { FILEIO_SYS_CAP_TAG + E_2BIG, "Arg list too long" } }, + { EBADF, { FILEIO_SYS_CAP_TAG + E_BADF, "Bad file descriptor" } }, + { ECHILD, { FILEIO_SYS_CAP_TAG + E_CHILD, "No child processes" } }, + { EAGAIN, { FILEIO_SYS_CAP_TAG + E_AGAIN, "Try again" } }, + { ENOMEM, { FILEIO_SYS_CAP_TAG + E_NOMEM, "Out of memory" } }, + { EACCES, { FILEIO_SYS_CAP_TAG + E_ACCES, "Permission denied" } }, + { EFAULT, { FILEIO_SYS_CAP_TAG + E_FAULT, "Bad address" } }, + { EBUSY, { FILEIO_SYS_CAP_TAG + E_BUSY, "Device or resource busy" } }, + { EEXIST, { FILEIO_SYS_CAP_TAG + E_EXIST, "File exists" } }, + { EXDEV, { FILEIO_SYS_CAP_TAG + E_XDEV, "Cross-device link" } }, + { ENODEV, { FILEIO_SYS_CAP_TAG + E_NODEV, "No such device" } }, + { ENOTDIR, { FILEIO_SYS_CAP_TAG + E_NOTDIR, "Not a directory" } }, + { EISDIR, { FILEIO_SYS_CAP_TAG + E_ISDIR, "Is a directory" } }, + { EINVAL, { FILEIO_SYS_CAP_TAG + E_INVAL, "Invalid argument" } }, + { ENFILE, { FILEIO_SYS_CAP_TAG + E_NFILE, "File table overflow" } }, + { EMFILE, { FILEIO_SYS_CAP_TAG + E_MFILE, "Too many open files" } }, + { ETXTBSY, { FILEIO_SYS_CAP_TAG + E_TXTBSY, "Text file busy" } }, + { EFBIG, { FILEIO_SYS_CAP_TAG + E_FBIG, "File too large" } }, + { ENOSPC, { FILEIO_SYS_CAP_TAG + E_NOSPC, "No space left on device" } }, + { ESPIPE, { FILEIO_SYS_CAP_TAG + E_SPIPE, "Illegal seek" } }, + { EROFS, { FILEIO_SYS_CAP_TAG + E_ROFS, "Read-only file system" } }, + { EMLINK, { FILEIO_SYS_CAP_TAG + E_MLINK, "Too many links" } }, + { EDEADLK, { FILEIO_SYS_CAP_TAG + E_DEADLK, "Resource deadlock would occur" } }, + { ENAMETOOLONG, { FILEIO_SYS_CAP_TAG + E_NAMETOOLONG, "File name too long" } }, + { ENOSYS, { FILEIO_SYS_CAP_TAG + E_NOSYS, "Function not implemented" } }, + { ENOTEMPTY, { FILEIO_SYS_CAP_TAG + E_NOTEMPTY, "Directory not empty" } }, + { ELOOP, { FILEIO_SYS_CAP_TAG + E_LOOP, "Too many symbolic links encountered" } }, + { EWOULDBLOCK, { FILEIO_SYS_CAP_TAG + E_WOULDBLOCK, "Operation would block" } }, + { EBADR, { FILEIO_SYS_CAP_TAG + E_BADR, "Invalid request descriptor" } }, + { ENOSTR, { FILEIO_SYS_CAP_TAG + E_NOSTR, "Device not a stream" } }, + { ENODATA, { FILEIO_SYS_CAP_TAG + E_NODATA, "No data available" } }, + { EOVERFLOW, { FILEIO_SYS_CAP_TAG + E_OVERFLOW, "Value too large for defined data type" } }, + { EBADFD, { FILEIO_SYS_CAP_TAG + E_BADFD, "File descriptor in bad state" } }, + { ERESTART, { FILEIO_SYS_CAP_TAG + E_RESTART, "Interrupted system call should be restarted" } }, + { EDQUOT, { FILEIO_SYS_CAP_TAG + E_DQUOT, "Quota exceeded" } }, + { UNKNOWN_ERR, { FILEIO_SYS_CAP_TAG + E_UKERR, "Unknown error" } }, + { ENOLCK, { FILEIO_SYS_CAP_TAG + E_NOLCK, "No record locks available" } }, + { ENETUNREACH, { FILEIO_SYS_CAP_TAG + E_NETUNREACH, "Network is unreachable" } }, + { ECONNECTIONFAIL, { FILEIO_SYS_CAP_TAG + E_CONNECTION_FAIL, "Connection failed" } }, + { ECONNECTIONABORT, { FILEIO_SYS_CAP_TAG + E_CONNECTION_ABORT, "Software caused connection abort" } }, + { NO_TASK_ERR, { FILEIO_SYS_CAP_TAG + E_NOTASK, "No task can be canceled" } }, + { CANCEL_ERR, { FILEIO_SYS_CAP_TAG + E_UNCANCELED, "Failed to cancel" } }, + { ECANCELED, { FILEIO_SYS_CAP_TAG + E_CANCELED, "Operation canceled" } }, + { FILEIO_SYS_CAP_TAG + E_PERM, { FILEIO_SYS_CAP_TAG + E_PERM, "Operation not permitted" } }, + { FILEIO_SYS_CAP_TAG + E_NOENT, { FILEIO_SYS_CAP_TAG + E_NOENT, "No such file or directory" } }, + { FILEIO_SYS_CAP_TAG + E_SRCH, { FILEIO_SYS_CAP_TAG + E_SRCH, "No such process" } }, + { FILEIO_SYS_CAP_TAG + E_INTR, { FILEIO_SYS_CAP_TAG + E_INTR, "Interrupted system call" } }, + { FILEIO_SYS_CAP_TAG + E_IO, { FILEIO_SYS_CAP_TAG + E_IO, "I/O error" } }, + { FILEIO_SYS_CAP_TAG + E_NXIO, { FILEIO_SYS_CAP_TAG + E_NXIO, "No such device or address" } }, + { FILEIO_SYS_CAP_TAG + E_2BIG, { FILEIO_SYS_CAP_TAG + E_2BIG, "Arg list too long" } }, + { FILEIO_SYS_CAP_TAG + E_BADF, { FILEIO_SYS_CAP_TAG + E_BADF, "Bad file descriptor" } }, + { FILEIO_SYS_CAP_TAG + E_CHILD, { FILEIO_SYS_CAP_TAG + E_CHILD, "No child processes" } }, + { FILEIO_SYS_CAP_TAG + E_AGAIN, { FILEIO_SYS_CAP_TAG + E_AGAIN, "Try again" } }, + { FILEIO_SYS_CAP_TAG + E_NOMEM, { FILEIO_SYS_CAP_TAG + E_NOMEM, "Out of memory" } }, + { FILEIO_SYS_CAP_TAG + E_ACCES, { FILEIO_SYS_CAP_TAG + E_ACCES, "Permission denied" } }, + { FILEIO_SYS_CAP_TAG + E_FAULT, { FILEIO_SYS_CAP_TAG + E_FAULT, "Bad address" } }, + { FILEIO_SYS_CAP_TAG + E_BUSY, { FILEIO_SYS_CAP_TAG + E_BUSY, "Device or resource busy" } }, + { FILEIO_SYS_CAP_TAG + E_EXIST, { FILEIO_SYS_CAP_TAG + E_EXIST, "File exists" } }, + { FILEIO_SYS_CAP_TAG + E_XDEV, { FILEIO_SYS_CAP_TAG + E_XDEV, "Cross-device link" } }, + { FILEIO_SYS_CAP_TAG + E_NODEV, { FILEIO_SYS_CAP_TAG + E_NODEV, "No such device" } }, + { FILEIO_SYS_CAP_TAG + E_NOTDIR, { FILEIO_SYS_CAP_TAG + E_NOTDIR, "Not a directory" } }, + { FILEIO_SYS_CAP_TAG + E_ISDIR, { FILEIO_SYS_CAP_TAG + E_ISDIR, "Is a directory" } }, + { FILEIO_SYS_CAP_TAG + E_INVAL, { FILEIO_SYS_CAP_TAG + E_INVAL, "Invalid argument" } }, + { FILEIO_SYS_CAP_TAG + E_NFILE, { FILEIO_SYS_CAP_TAG + E_NFILE, "File table overflow" } }, + { FILEIO_SYS_CAP_TAG + E_MFILE, { FILEIO_SYS_CAP_TAG + E_MFILE, "Too many open files" } }, + { FILEIO_SYS_CAP_TAG + E_TXTBSY, { FILEIO_SYS_CAP_TAG + E_TXTBSY, "Text file busy" } }, + { FILEIO_SYS_CAP_TAG + E_FBIG, { FILEIO_SYS_CAP_TAG + E_FBIG, "File too large" } }, + { FILEIO_SYS_CAP_TAG + E_NOSPC, { FILEIO_SYS_CAP_TAG + E_NOSPC, "No space left on device" } }, + { FILEIO_SYS_CAP_TAG + E_SPIPE, { FILEIO_SYS_CAP_TAG + E_SPIPE, "Illegal seek" } }, + { FILEIO_SYS_CAP_TAG + E_ROFS, { FILEIO_SYS_CAP_TAG + E_ROFS, "Read-only file system" } }, + { FILEIO_SYS_CAP_TAG + E_MLINK, { FILEIO_SYS_CAP_TAG + E_MLINK, "Too many links" } }, + { FILEIO_SYS_CAP_TAG + E_DEADLK, { FILEIO_SYS_CAP_TAG + E_DEADLK, "Resource deadlock would occur" } }, + { FILEIO_SYS_CAP_TAG + E_NAMETOOLONG, { FILEIO_SYS_CAP_TAG + E_NAMETOOLONG, "File name too long" } }, + { FILEIO_SYS_CAP_TAG + E_NOSYS, { FILEIO_SYS_CAP_TAG + E_NOSYS, "Function not implemented" } }, + { FILEIO_SYS_CAP_TAG + E_NOTEMPTY, { FILEIO_SYS_CAP_TAG + E_NOTEMPTY, "Directory not empty" } }, + { FILEIO_SYS_CAP_TAG + E_LOOP, { FILEIO_SYS_CAP_TAG + E_LOOP, "Too many symbolic links encountered" } }, + { FILEIO_SYS_CAP_TAG + E_WOULDBLOCK, { FILEIO_SYS_CAP_TAG + E_WOULDBLOCK, "Operation would block" } }, + { FILEIO_SYS_CAP_TAG + E_BADR, { FILEIO_SYS_CAP_TAG + E_BADR, "Invalid request descriptor" } }, + { FILEIO_SYS_CAP_TAG + E_NOSTR, { FILEIO_SYS_CAP_TAG + E_NOSTR, "Device not a stream" } }, + { FILEIO_SYS_CAP_TAG + E_NODATA, { FILEIO_SYS_CAP_TAG + E_NODATA, "No data available" } }, + { FILEIO_SYS_CAP_TAG + E_OVERFLOW, { FILEIO_SYS_CAP_TAG + E_OVERFLOW, "Value too large for defined data type" } }, + { FILEIO_SYS_CAP_TAG + E_BADFD, { FILEIO_SYS_CAP_TAG + E_BADFD, "File descriptor in bad state" } }, + { FILEIO_SYS_CAP_TAG + E_RESTART, + { FILEIO_SYS_CAP_TAG + E_RESTART, "Interrupted system call should be restarted" } }, + { FILEIO_SYS_CAP_TAG + E_DQUOT, { FILEIO_SYS_CAP_TAG + E_DQUOT, "Quota exceeded" } }, + { FILEIO_SYS_CAP_TAG + E_UKERR, { FILEIO_SYS_CAP_TAG + E_UKERR, "Unknown error" } }, + { FILEIO_SYS_CAP_TAG + E_NOLCK, { FILEIO_SYS_CAP_TAG + E_NOLCK, "No record locks available" } }, + { FILEIO_SYS_CAP_TAG + E_NETUNREACH, { FILEIO_SYS_CAP_TAG + E_NETUNREACH, "Network is unreachable" } }, + { FILEIO_SYS_CAP_TAG + E_CONNECTION_FAIL, { FILEIO_SYS_CAP_TAG + E_CONNECTION_FAIL, "Connection failed" } }, + { FILEIO_SYS_CAP_TAG + E_CONNECTION_ABORT, + { FILEIO_SYS_CAP_TAG + E_CONNECTION_ABORT, "Software caused connection abort" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_DISPLAYNAME, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_DISPLAYNAME, "Invalid display name" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_URIM, { USER_FILE_MANAGER_SYS_CAP_TAG + E_URIM, "Invalid uri" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_SUFFIX, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_SUFFIX, "Invalid file extension" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_TRASH, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_TRASH, "File has been put into trash bin" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_OPEN_MODE, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_OPEN_MODE, "Invalid open mode" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_NOT_ALBUM, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_NOT_ALBUM, "The uri is not album" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_ROOT_DIR, { USER_FILE_MANAGER_SYS_CAP_TAG + E_ROOT_DIR, "Invalid root dir" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_MOVE_DENIED, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_MOVE_DENIED, "Failed to move as dir check failed" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_RENAME_DENIED, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_RENAME_DENIED, "Failed to rename as dir check failed" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_RELATIVEPATH, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_RELATIVEPATH, "Relative path not exist or invalid" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_INNER_FAIL, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_INNER_FAIL, "MediaLibrary inner fail" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_FILE_TYPE, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_FILE_TYPE, "File type is not allow in the directory" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_FILE_KEY, { USER_FILE_MANAGER_SYS_CAP_TAG + E_FILE_KEY, "Member not exist" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_INPUT, { USER_FILE_MANAGER_SYS_CAP_TAG + E_INPUT, "Wrong input parameter" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_IPCSS, { STORAGE_SERVICE_SYS_CAP_TAG + E_IPCSS, "IPC error" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_NOTSUPPORTEDFS, + { STORAGE_SERVICE_SYS_CAP_TAG + E_NOTSUPPORTEDFS, "Not supported filesystem" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_MOUNT, { STORAGE_SERVICE_SYS_CAP_TAG + E_MOUNT, "Failed to mount" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_UNMOUNT, { STORAGE_SERVICE_SYS_CAP_TAG + E_UNMOUNT, "Failed to unmount" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_VOLUMESTATE, + { STORAGE_SERVICE_SYS_CAP_TAG + E_VOLUMESTATE, "Incorrect volume state" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_PREPARE, + { STORAGE_SERVICE_SYS_CAP_TAG + E_PREPARE, "Prepare directory or node error" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_DELETE, + { STORAGE_SERVICE_SYS_CAP_TAG + E_DELETE, "Delete directory or node error" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_NOOBJECT, { STORAGE_SERVICE_SYS_CAP_TAG + E_NOOBJECT, "No such object" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_OUTOFRANGE, + { STORAGE_SERVICE_SYS_CAP_TAG + E_OUTOFRANGE, "User id out of range" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_NOOBJECT, { STORAGE_SERVICE_SYS_CAP_TAG + E_NOOBJECT, "No such object" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_IPCS, { USER_FILE_SERVICE_SYS_CAP_TAG + E_IPCS, "IPC error" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_URIS, { USER_FILE_SERVICE_SYS_CAP_TAG + E_URIS, "Invalid uri" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_GETINFO, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_GETINFO, "Fail to get fileextension info" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_GETRESULT, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_GETRESULT, "Get wrong result" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_REGISTER, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_REGISTER, "Fail to register notification" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_REMOVE, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_REMOVE, "Fail to remove notification" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_INIT, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_INIT, "Fail to init notification agent" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_NOTIFY, { USER_FILE_SERVICE_SYS_CAP_TAG + E_NOTIFY, "Fail to notify agent" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CONNECT, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CONNECT, "Fail to connect file access extension ability" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CALLBACK_AND_URI_HAS_NOT_RELATIONS, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CALLBACK_AND_URI_HAS_NOT_RELATIONS, + "The uri has no relationship with the callback and cannot be unregistered" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CALLBACK_IS_NOT_REGISTER, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CALLBACK_IS_NOT_REGISTER, + "Cannot unregister the callback that has not been registered" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CAN_NOT_FIND_URI, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CAN_NOT_FIND_URI, "Can not find registered uri" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_DO_NOT_HAVE_PARENT, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_DO_NOT_HAVE_PARENT, "Do not have parent uri" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_LOAD_SA, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_LOAD_SA, "Fail to load system ability" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_COUNT, { USER_FILE_SERVICE_SYS_CAP_TAG + E_COUNT, "Too many records" } }, + { E_PERMISSION, { E_PERMISSION, "Permission verification failed" } }, + { E_PERMISSION_SYS, { E_PERMISSION_SYS, "The caller is not a system application" } }, + { E_PARAMS, { E_PARAMS, "The input parameter is invalid" } }, + { E_DEVICENOTSUPPORT, { E_DEVICENOTSUPPORT, "The device doesn't support this api" } }, + { E_OSNOTSUPPORT, { E_OSNOTSUPPORT, "The os doesn't support this api" } }, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_CLOUD_NOT_READY, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_CLOUD_NOT_READY, "Cloud status not ready" } }, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_NETWORK_ERR, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_NETWORK_ERR, "Network unavailable" } }, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_BATTERY_WARNING, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_BATTERY_WARNING, "Battery level warning" } }, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_EXCEED_MAX_LIMIT, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_EXCEED_MAX_LIMIT, "Exceed the maximum limit" } }, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_DATABASE_FAILED, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_DATABASE_FAILED, "Database operation failed" } }, +}; + +class FsError { +public: + FsError(int errCode); + int GetErrNo() const; + const std::string &GetErrMsg() const; + ~FsError() = default; + explicit operator bool() const; + +private: + int errno_ = ERRNO_NOERR; + std::string errMsg_; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // FILEMANAGEMENT_FS_ERROR_H \ No newline at end of file diff --git a/utils/filemgmt_libfs/include/fs_result.h b/utils/filemgmt_libfs/include/fs_result.h new file mode 100644 index 0000000000000000000000000000000000000000..0aaab49eabaa8b99b1bc64ecee284209d7bf2b2b --- /dev/null +++ b/utils/filemgmt_libfs/include/fs_result.h @@ -0,0 +1,148 @@ +/* + * 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 FILEMANAGEMENT_FS_RESULT_H +#define FILEMANAGEMENT_FS_RESULT_H + +#include "fs_error.h" + +#include +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO { + +template +class FsResult { + using OptionalData = std::optional; + +public: + static FsResult Success() + { + return FsResult(FsError(ERRNO_NOERR), std::nullopt); + } + + static FsResult Success(const T &data) + { + return FsResult(FsError(ERRNO_NOERR), std::make_optional(data)); + } + + static FsResult Success(T &&data) + { + return FsResult(FsError(ERRNO_NOERR), std::make_optional(std::move(data))); + } + + template , int> = 0> + static FsResult Success(const char *data) + { + return FsResult(FsError(ERRNO_NOERR), std::make_optional(std::string(data))); + } + + static FsResult Error(const int32_t code) + { + return FsResult(FsError(code), std::nullopt); + } + + bool IsSuccess() const + { + return !error_; + } + + const OptionalData &GetData() const + { + return data_; + } + + OptionalData &GetData() + { + return data_; + } + + const FsError &GetError() const + { + return error_; + } + + FsResult(const FsResult &) = delete; + FsResult &operator=(const FsResult &) = delete; + + FsResult(FsResult &&other) noexcept : error_(std::move(other.error_)), data_(std::move(other.data_)) {} + + FsResult &operator=(FsResult &&other) noexcept + { + if (this != &other) { + error_ = std::move(other.error_); + data_ = std::move(other.data_); + } + return *this; + } + + ~FsResult() = default; + +private: + FsError error_; + OptionalData data_; + + FsResult(const FsError &err, const OptionalData &data) : error_(err), data_(data) {} + + FsResult(const FsError &err, OptionalData &&data) : error_(err), data_(std::move(data)) {} +}; + +template <> +class FsResult { +private: + FsError error_; + explicit FsResult(const FsError &err) : error_(err) {} + +public: + static FsResult Success() + { + return FsResult(FsError(ERRNO_NOERR)); + } + + static FsResult Error(const int32_t code) + { + return FsResult(FsError(code)); + } + + bool IsSuccess() const + { + return !error_; + } + + const FsError &GetError() const + { + return error_; + } + + FsResult(const FsResult &) = delete; + FsResult &operator=(const FsResult &) = delete; + + FsResult(FsResult &&other) noexcept : error_(std::move(other.error_)) {} + + FsResult &operator=(FsResult &&other) noexcept + { + if (this != &other) { + error_ = std::move(other.error_); + } + return *this; + } + + ~FsResult() = default; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // FILEMANAGEMENT_FS_RESULT_H \ No newline at end of file diff --git a/utils/filemgmt_libfs/src/fs_error.cpp b/utils/filemgmt_libfs/src/fs_error.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3636a7d5f966a4633f5f57b73d7d705af0196de5 --- /dev/null +++ b/utils/filemgmt_libfs/src/fs_error.cpp @@ -0,0 +1,62 @@ +/* + * 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 "fs_error.h" +#include "uv.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +static int ConvertUVCode2ErrCode(int errCode) +{ + if (errCode >= 0) { + return errCode; + } + auto uvCode = string_view(uv_err_name(errCode)); + if (uvCode2ErrCodeTable.find(uvCode) != uvCode2ErrCodeTable.end()) { + return uvCode2ErrCodeTable.at(uvCode); + } + return UNKNOWN_ERR; +} + +FsError::FsError(int errCode) +{ + int genericCode = ConvertUVCode2ErrCode(errCode); + auto it = errCodeTable.find(genericCode); + if (it != errCodeTable.end()) { + errno_ = it->second.first; + errMsg_ = it->second.second; + } else { + errno_ = errCodeTable.at(UNKNOWN_ERR).first; + errMsg_ = errCodeTable.at(UNKNOWN_ERR).second + ", errno is " + to_string(abs(errCode)); + } +} + +int FsError::GetErrNo() const +{ + return errno_; +} + +const std::string &FsError::GetErrMsg() const +{ + return errMsg_; +} + +FsError::operator bool() const +{ + return errno_ != ERRNO_NOERR; +} + +} // namespace OHOS::FileManagement::ModuleFileIO