diff --git a/bundle.json b/bundle.json index 60c317e0ee82d0dfa042e4d82b12deac16187a5f..866b072e249a37669b2779c79740750dd42a8933 100644 --- a/bundle.json +++ b/bundle.json @@ -43,7 +43,8 @@ "napi", "samgr", "app_file_service", - "os_account" + "os_account", + "libuv" ], "third_party": [ "e2fsprogs", @@ -51,6 +52,9 @@ ] }, "build": { + "sub_component": [ + "//foundation/filemanagement/file_api/interfaces/kits/js:ani_file_api" + ], "group_type": { "base_group": [], "fwk_group": [ @@ -97,6 +101,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": { diff --git a/file_api.gni b/file_api.gni index 7fc94ace62004264471a75000deb0900070d3727..dd1e63206106df86c58851de098c3a3e12b6e9bc 100644 --- a/file_api.gni +++ b/file_api.gni @@ -23,3 +23,5 @@ utils_path = "${file_api_path}/utils" use_mac = "${current_os}_${current_cpu}" == "mac_x64" || "${current_os}_${current_cpu}" == "mac_arm64" use_mingw_win = "${current_os}_${current_cpu}" == "mingw_x86_64" + +ani_api = "//arkcompiler/runtime_core/static_core/plugins/ets/runtime/ani" diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index 3c9b376ee82976d069e931c0d2a606ad992a0b33..df925375015129dfd9b22f8532fb3be43561ac98 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -13,6 +13,7 @@ import("//build/ohos.gni") import("//foundation/filemanagement/file_api/file_api.gni") +import("//build/config/components/ets_frontend/ets2abc_config.gni") file_common_src = [ "src/common/file_helper/fd_guard.cpp", @@ -618,3 +619,268 @@ group("build_kits_js") { ":statvfs", ] } + +group("ani_file_api") { + deps = [ + ":ani_fs_class", + ":ani_hash_class", + ":ani_securitylabel_class", + ] +} + +config("ani_config") { + include_dirs = [ + "${ani_api}", + "${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", + "//third_party/libuv/include", + "${filemanagement_service_path}/distributedfiledaemon/include/ipc", + ] + + cflags = [ + "-fvisibility=hidden", + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc = [ + "-std=c++17", + "-fvisibility-inlines-hidden", + "-Oz", + "-Wno-unused-function", + ] +} + +ohos_shared_library("ani_fs_class") { + public_configs = [ ":ani_config" ] + include_dirs = [ + "src/mod_fs/ani", + "src/mod_fs/class_stat", + "src/mod_fs/properties", + "src/mod_fs/properties/ani", + "${src_path}/mod_fs/properties/copy_listener", + ] + sources = [ + "src/mod_fs/fs_utils.cpp", + "src/common/ani_helper/bind_function.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/class_stat/fs_stat.cpp", + "src/mod_fs/properties/ani/access_ani.cpp", + "src/mod_fs/properties/ani/mkdir_ani.cpp", + "src/mod_fs/properties/ani/unlink_ani.cpp", + "src/mod_fs/properties/ani/move_ani.cpp", + "src/mod_fs/properties/ani/rmdir_ani.cpp", + "src/mod_fs/properties/access_core.cpp", + "src/mod_fs/properties/ani/copy_file_ani.cpp", + "src/mod_fs/properties/ani/stat_ani.cpp", + "src/mod_fs/properties/copy_file_core.cpp", + "src/mod_fs/properties/mkdir_core.cpp", + "src/mod_fs/properties/stat_core.cpp", + "src/mod_fs/properties/unlink_core.cpp", + "src/mod_fs/properties/move_core.cpp", + "src/mod_fs/properties/rmdir_core.cpp", + ] + deps = [ + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + "${file_api_path}/interfaces/kits/rust:rust_file", + ":ani_fs_abc_etc", + ] + use_exceptions = true + external_deps = [ + "hilog:libhilog", + "libuv:uv", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "ipc:ipc_core", + "c_utils:utils", + ] + + cflags = [ + "-fvisibility=hidden", + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc = [ + "-std=c++17", + "-fvisibility-inlines-hidden", + "-Oz", + "-Wno-unused-function", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + subsystem_name = "filemanagement" + part_name = "file_api" +} + +generate_static_abc("ani_fs_abc") { + arktsconfig = "src/mod_fs/ani/arktsconfig.json" + dst_file = "$target_out_dir/ani_fs.abc" + out_puts = [ "$target_out_dir/ani_fs.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ani_fs.abc" + cache_path = "$target_out_dir/cache" +} + +ohos_prebuilt_etc("ani_fs_abc_etc") { + source = "$target_out_dir/ani_fs.abc" + module_install_dir = "fs" + subsystem_name = "filemanagement" + part_name = "file_api" + deps = [ ":ani_fs_abc" ] +} + +ohos_shared_library("ani_hash_class") { + public_configs = [ ":ani_config" ] + include_dirs = [ + "src/mod_hash", + "src/mod_hash/ani", + ] + sources = [ + "src/mod_fs/fs_utils.cpp", + "src/common/ani_helper/bind_function.cpp", + "src/common/ani_helper/type_converter.cpp", + "src/common/file_helper/fd_guard.cpp", + "src/mod_hash/ani/bind_function_class.cpp", + "src/common/file_helper/hash_file.cpp", + "src/mod_hash/ani/hash_ani.cpp", + "src/mod_hash/hash_core.cpp", + ] + + deps = [ + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + "//third_party/openssl:libcrypto_shared", + ":ani_hash_abc_etc", + ] + external_deps = [ + "hilog:libhilog", + "libuv:uv", + ] + use_exceptions = true + cflags = [ + "-fvisibility=hidden", + "-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 + } + subsystem_name = "filemanagement" + part_name = "file_api" +} + + +generate_static_abc("ani_hash_abc") { + arktsconfig = "src/mod_hash/ani/arktsconfig.json" + dst_file = "$target_out_dir/ani_hash.abc" + out_puts = [ "$target_out_dir/ani_hash.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ani_hash.abc" + cache_path = "$target_out_dir/cache" +} + +ohos_prebuilt_etc("ani_hash_abc_etc") { + source = "$target_out_dir/ani_hash.abc" + module_install_dir = "hash" + subsystem_name = "filemanagement" + part_name = "file_api" + deps = [ ":ani_hash_abc" ] +} + + +ohos_shared_library("ani_securitylabel_class") { + public_configs = [ ":ani_config" ] + include_dirs = [ + "src/mod_securitylabel/ani", + "src/mod_securitylabel", + ] + sources = [ + "src/mod_fs/fs_utils.cpp", + "src/common/ani_helper/bind_function.cpp", + "src/common/ani_helper/type_converter.cpp", + "src/common/file_helper/fd_guard.cpp", + "src/mod_securitylabel/ani/bind_function_class.cpp", + "src/mod_securitylabel/ani/securitylabel_ani.cpp", + "src/mod_securitylabel/securitylabel_core.cpp", + ] + + deps = [ + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ":ani_securitylabel_abc_etc", + ] + external_deps = [ + "hilog:libhilog", + "libuv:uv", + ] + use_exceptions = true + cflags = [ + "-fvisibility=hidden", + "-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 + } + subsystem_name = "filemanagement" + part_name = "file_api" +} + + +generate_static_abc("ani_securitylabel_abc") { + arktsconfig = "src/mod_securitylabel/ani/arktsconfig.json" + dst_file = "$target_out_dir/ani_securitylabel.abc" + out_puts = [ "$target_out_dir/ani_securitylabel.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ani_securitylabel.abc" + cache_path = "$target_out_dir/cache" +} + +ohos_prebuilt_etc("ani_securitylabel_abc_etc") { + source = "$target_out_dir/ani_securitylabel.abc" + module_install_dir = "securitylabel" + subsystem_name = "filemanagement" + part_name = "file_api" + deps = [ ":ani_securitylabel_abc" ] +} diff --git a/interfaces/kits/js/src/common/ani_helper/bind_function.cpp b/interfaces/kits/js/src/common/ani_helper/bind_function.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f87aa757d517763d5f452bec0763e5cf9b28e305 --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/bind_function.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 "bind_function.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +ANI_EXPORT ani_status BindClass(ani_vm *vm, const char *className, const std::vector &methods) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + HILOGE("Unsupported ANI_VERSION_1 Fail!!!"); + return ANI_OUT_OF_REF; + } + + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Not found '%{private}s'", className); + return ANI_INVALID_ARGS; + } + + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + HILOGE("Cannot bind native methods to '%{private}s'", className); + return ANI_INVALID_TYPE; + }; + return ANI_OK; +} + +ANI_EXPORT ani_status BindNamespace(ani_vm *vm, const char *namespaceStr, + const std::vector& functions) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + HILOGE("Unsupported ANI_VERSION_1 Fail!!!"); + return ANI_OUT_OF_REF; + } + + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceStr, &ns)) { + HILOGE("Not found '%{private}s'", namespaceStr); + return ANI_INVALID_ARGS; + } + + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size())) { + HILOGE("Cannot bind native methods to '%{private}s'", namespaceStr); + return ANI_INVALID_TYPE; + }; + return ANI_OK; +} +} //ANI +} //ModuleFileIO +} //FileManagement +} //OHOS 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..e100e14e750eef1ace9107f62dc1f563c67c733b --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/bind_function.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FILEMANAGEMENT_ANI_BIND_FUNCTION_H +#define FILEMANAGEMENT_ANI_BIND_FUNCTION_H + +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +ANI_EXPORT ani_status BindClass(ani_vm *vm, const char *className, const std::vector &methods); +ANI_EXPORT ani_status BindNamespace(ani_vm *vm, const char *namespaceStr, + const std::vector& functions); +} //ANI +} //ModuleFileIO +} //FileManagement +} //OHOS + +#endif // FILEMANAGEMENT_ANI_BIND_FUNCTION_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..d3a0fec80043e9ec366559adcca160c7c378018d --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/type_converter.cpp @@ -0,0 +1,142 @@ +/* + * 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 "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { + +std::tuple TypeConverter::ToUTF8StringPath(ani_env *env, const ani_string &path) +{ + 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, move(result)}; +} + +std::tuple> TypeConverter::ToOptionalInt32(ani_env *env, + const ani_object &intOp) +{ + ani_boolean isUndefined; + env->Reference_IsUndefined(intOp, &isUndefined); + if (isUndefined) { + HILOGE("isUndefined"); + return {true, std::nullopt}; + } + + ani_int result; + if (ANI_OK != env->Object_CallMethodByName_Int(intOp, "intValue", nullptr, &result)) { + HILOGE("Object_CallMethodByName_Int Fail!!!"); + return {false, {}}; + } + + return {true, std::make_optional(result)}; +} + +std::tuple> TypeConverter::ToOptionalInt32(ani_env *env, + const ani_enum_item enumItem) +{ + ani_boolean isUndefined; + env->Reference_IsUndefined(enumItem, &isUndefined); + if(isUndefined) + { + HILOGE("processEnumOptional NOT Pass Value "); + return {true, std::nullopt}; + } + + ani_int intValue; + if(ANI_OK != env->EnumItem_GetValue_Int(enumItem, &intValue)) { + HILOGE("Enum_GetEnumItemByIndex FAILD"); + return {false, std::nullopt}; + } + HILOGE("Enum_GetEnumItemByIndex Success %d", intValue); + return {true, std::make_optional(intValue)}; +} + +static std::unique_ptr ToUniquePtrChars(const char *chars) +{ + if (chars == nullptr) { + return nullptr; + } + size_t length = std::strlen(chars); + auto result = std::make_unique(length + 1); + std::strcpy(result.get(), chars); + return result; +} + +static tuple StringToFileInfo(ani_env *env, const ani_string &path) +{ + auto [succ, utf8Path] = TypeConverter::ToUTF8StringPath(env, path); + if (!succ) { + return {false, FileInfo{false, {}, {}}}; + } + + auto chars = ToUniquePtrChars(move(utf8Path.c_str())); + return {true, FileInfo{true, move(chars), {}}}; +} + +static tuple NumToFileInfo(ani_env *env, const ani_double &value) +{ + auto fd = static_cast(double(value)); + auto fdg = OHOS::FileManagement::CreateUniquePtr(fd, false); + if (fdg == nullptr) { + HILOGE("Failed to request heap memory."); + return { false, FileInfo { false, {}, {} } }; + } + + return { true, FileInfo { false, {}, move(fdg) } }; +} + +std::tuple TypeConverter::ToFileInfo(ani_env *env, const ani_object &unionObj) +{ + ani_class stringClass; + env->FindClass("Lstd/core/String;", &stringClass); + + ani_class numClass; + env->FindClass("Lstd/core/Double;", &numClass); + + ani_boolean isString; + env->Object_InstanceOf(unionObj, stringClass, &isString); + if (isString) { + return StringToFileInfo(env, static_cast(unionObj)); + } + + ani_boolean isNum; + env->Object_InstanceOf(unionObj, numClass, &isNum); + if (isNum) { + ani_status ret; + ani_double value; + if ((ret = env->Object_CallMethodByName_Double(unionObj, "doubleValue", nullptr, &value)) != ANI_OK) { + HILOGE("Class_CallMethod doubleValue Fail, err: %{public}d", ret); + return { false, FileInfo { false, {}, {} } }; + } + + return NumToFileInfo(env, value); + } + + return { false, FileInfo { false, {}, {} } }; +} + +} // 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..b9693ed043e150005d6d075c2523c8a4f6754419 --- /dev/null +++ b/interfaces/kits/js/src/common/ani_helper/type_converter.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 FILEMANAGEMENT_ANI_TYPE_CONVERTER_H +#define FILEMANAGEMENT_ANI_TYPE_CONVERTER_H + +#include +#include +#include + +#include "file_utils.h" +#include "fs_utils.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI +{ +using OHOS::FileManagement::ModuleFileIO::FileInfo; +inline const std::string EMPTY_STRING = ""; + +class TypeConverter { +public: + static std::tuple ToUTF8StringPath(ani_env *env, const ani_string &path); + static std::tuple> ToOptionalInt32(ani_env *env, + const ani_object &intOp); + static std::tuple> ToOptionalInt32(ani_env *env, + const ani_enum_item enumItem); + static std::tuple ToFileInfo(ani_env *env, const ani_object &unionObj); +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI + +#endif // FILEMANAGEMENT_ANI_TYPE_CONVERTER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/ani/arktsconfig.json b/interfaces/kits/js/src/mod_fs/ani/arktsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..ae12d05b6be6cd0eb77adb251ee4c798879bef53 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/ani/arktsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "package": "", + "baseUrl": ".", + "outDir": "./dist", + "paths": { + "std": [ + "../../../../../../../../../arkcompiler/runtime_core/static_core/plugins/ets/stdlib/std" + ], + "escompat": [ + "../../../../../../../../../arkcompiler/runtime_core/static_core/plugins/ets/stdlib/escompat" + ] + } + }, + "include": [ + "*.ets" + ] +} 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..4befcd556e1423215a716b60a3904d064403965c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp @@ -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. + */ + + +#include +#include +#include + +#include "access_ani.h" +#include "bind_function.h" +#include "copy_file_ani.h" +#include "mkdir_ani.h" +#include "move_ani.h" +#include "stat_ani.h" +#include "unlink_ani.h" +#include "rmdir_ani.h" + +using namespace OHOS::FileManagement::ModuleFileIO::ANI; + +static ani_status BindStatMethods(ani_vm *vm) +{ + static const char *className = "Lfile_fs_class/StatInner;"; + + std::vector methods = { + ani_native_function {"isBlockDevice", ":Z", reinterpret_cast(StatAni::IsBlockDevice) }, + ani_native_function {"isCharacterDevice", ":Z", reinterpret_cast(StatAni::IsCharacterDevice) }, + ani_native_function {"isDirectory", ":Z", reinterpret_cast(StatAni::IsDirectory) }, + ani_native_function {"isFIFO", ":Z", reinterpret_cast(StatAni::IsFIFO) }, + ani_native_function {"isFile", ":Z", reinterpret_cast(StatAni::IsFile) }, + ani_native_function {"isSocket", ":Z", reinterpret_cast(StatAni::IsSocket) }, + ani_native_function {"isSymbolicLink", ":Z", reinterpret_cast(StatAni::IsSymbolicLink) }, + }; + + return BindClass(vm, className, methods); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { + if (ANI_OK != BindStatMethods(vm)) { + std::cerr << "Cannot bind native stat methods" << std::endl; + return (ani_status)3; + }; + + static const char *className = "Lfile_fs_class/fileIo;"; + + std::vector functions = { + ani_native_function {"doAccessSync", nullptr, reinterpret_cast(AccessAni::AccessSync3)}, + ani_native_function {"unlinkSync", "Lstd/core/String;:I", reinterpret_cast(UnlinkAni::UnlinkSync)}, + ani_native_function {"mkdirSync", "Lstd/core/String;:I", reinterpret_cast(MkdirkAni::MkdirSync0)}, + ani_native_function {"mkdirSync", "Lstd/core/String;Z:I", reinterpret_cast(MkdirkAni::MkdirSync1)}, + ani_native_function {"moveFileSync", "Lstd/core/String;Lstd/core/String;Lstd/core/Int;:V", reinterpret_cast(MoveAni::MoveFileSync)}, + ani_native_function {"copyFileSync", nullptr, reinterpret_cast(CopyFileAni::CopyFileSync)}, + ani_native_function {"statSync", nullptr, reinterpret_cast(StatAni::StatSync)}, + ani_native_function {"rmdirSync", "Lstd/core/String;:V", reinterpret_cast(RmdirAni::rmdirSync)}, + }; + + *result = ANI_VERSION_1; + + return BindClass(vm, className, functions); +} + diff --git a/interfaces/kits/js/src/mod_fs/ani/file_fs_class.ets b/interfaces/kits/js/src/mod_fs/ani/file_fs_class.ets new file mode 100644 index 0000000000000000000000000000000000000000..57b48893cd292733f29623e038f0e9e2bacafc39 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/ani/file_fs_class.ets @@ -0,0 +1,463 @@ +/* + * 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. + */ + +export default fileIo; + +loadLibrary("ani_fs_class.z") + + +export class BusinessError { + code: number = 0; + data?: T; +} + +export type AsyncCallback = (err: BusinessError, data?: T) => void; + + +enum AccessModeType { + EXIST = 0, + + WRITE = 2, + + READ = 4, + + READ_WRITE = 6, +} + +enum AccessFlagType { + LOCAL = 0, +} + + +class fileIo { + + static native doAccessSync(path:string, mode?:AccessModeType, flag?:AccessFlagType):boolean; + static native unlinkSync(path: string): int; + static native mkdirSync(path: string): int; + static native mkdirSync(path: string, recursion: boolean): int; + static native moveFileSync(src: String, dest: String, mode?: int): void; + static native rmdirSync(path: string): void; + + static accessSync(path: string, mode?: AccessModeType): boolean { + return fileIo.doAccessSync(path, mode); + } + + static accessSync(path: string, mode: AccessModeType, flag: AccessFlagType): boolean{ + return fileIo.doAccessSync(path, mode, flag); + } + + static accessSync1(path: string):boolean { + return fileIo.accessSync(path); + } + + static accessSync2(path: string, mode: AccessModeType):boolean { + return fileIo.accessSync(path, mode); + } + + static accessSync3(path: string, mode: AccessModeType, flag: AccessFlagType): boolean + { + return fileIo.accessSync(path, mode, flag); + } + + static access(path: string, mode?: AccessModeType): Promise { + return new Promise((resolve:(result:boolean)=>void, reject:(e:BusinessError)=>void) => { + if (mode === undefined) { + let promise = taskpool.execute(fileIo.accessSync1, path); // 这里调用同步方法 + promise.then((ret:NullishType) => { + if (ret === null || ret === undefined) { // 异常处理 + let err = new BusinessError(); + err.code = -1; + reject(err); + } else { + let result = ret as boolean; + resolve(result); // 正常结果 + } + }); + } else { + let promise = taskpool.execute(fileIo.accessSync2, path, mode); // 这里调用同步方法 + promise.then((ret:NullishType) => { + if (ret === null || ret === undefined) { // 异常处理 + let err = new BusinessError(); + err.code = -1; + reject(err); + } else { + let result = ret as boolean; + resolve(result); // 正常结果 + } + }); + } + + + }); + } + + static access(path: string, mode: AccessModeType, flag: AccessFlagType): Promise{ + return new Promise((resolve:(result:boolean)=>void, reject:(e:BusinessError)=>void) => { + let promise = taskpool.execute(fileIo.accessSync3, path, mode, flag); // 这里调用同步方法 + promise.then((ret:NullishType) => { + if (ret === null || ret === undefined) { // 异常处理 + let err = new BusinessError(); + err.code = -1; + reject(err); + } else { + let result = ret as boolean; + resolve(result); // 正常结果 + } + }); + }) + } + + static access(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute(fileIo.accessSync1, path); // 这里调用同步方法 + promise.then((ret:NullishType) => { + let err = new BusinessError(); + if (ret === null || ret === undefined) { // 异常处理 + err.code = -1; + callback(err,undefined); + } else { + err.code = 0; + let result = ret as boolean; + callback(err,result); // 正常结果 + } + }); + } + + static unlink(path: string): Promise { + return new Promise((resolve: (result: int) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute(fileIo.unlinkSync, path); // 这里调用同步方法 + promise.then((ret: NullishType) => { + let result = ret as int + if (ret === null || ret === undefined) { // 异常处理 + let err = new BusinessError(); + err.code = -1; + reject(err); + } else { + resolve(result); // 正常结果 + } + }); + }); + } + + static unlink(path: string, callback: AsyncCallback): void { + let p1 = taskpool.execute(fileIo.unlinkSync, path); + p1.then((ret: NullishType) => { + let err = new BusinessError(); + if (ret === null || ret === undefined) { + console.println("-------- err code = -1 -------------"); + err.code = -1 + callback(err, undefined) + }else { + console.println("-------- err code = 0 -------------"); + err.code = 0 + let r = ret as int; + callback(err, r); + } + }); + } + + static mkdir(path: string): Promise { + return new Promise((resolve: (result: int) => void, reject: (e: BusinessError) => void) => { + const mkdirSyncWrapper = (path: string) => fileIo.mkdirSync(path); + let promise = taskpool.execute(mkdirSyncWrapper, path); // 这里调用同步方法 + promise.then((ret: NullishType) => { + let result = ret as int + if (ret === null || ret === undefined) { // 异常处理 + let err = new BusinessError(); + err.code = -1; + reject(err); + } else { + resolve(result); // 正常结果 + } + }); + }); + } + + static mkdir(path: string, callback: AsyncCallback): void { + const mkdirSyncWrapper = (path: string) => fileIo.mkdirSync(path); + let p1 = taskpool.execute(mkdirSyncWrapper, path); + p1.then((ret: NullishType) => { + let err = new BusinessError(); + if (ret === null || ret === undefined) { + console.println("-------- err code = -1 -------------"); + err.code = -1 + callback(err, undefined) + }else { + console.println("-------- err code = 0 -------------"); + err.code = 0 + let r = ret as int; + callback(err, r); + } + }); + } + + static mkdir(path: string, recursion: boolean): Promise { + return new Promise((resolve: (result: int) => void, reject: (e: BusinessError) => void) => { + const mkdirSyncWrapper = (path: string, recursion: boolean) => fileIo.mkdirSync(path, recursion); + let promise = taskpool.execute(mkdirSyncWrapper, path, recursion); // 这里调用同步方法 + promise.then((ret: NullishType) => { + let result = ret as int + if (ret === null || ret === undefined) { // 异常处理 + console.println("-------- err code = -1 -------------"); + let err = new BusinessError(); + err.code = -1; + reject(err); + } else { + console.println("-------- err code = 0 -------------"); + resolve(result); // 正常结果 + } + }); + }); + } + + static mkdir(path: string, recursion: boolean, callback: AsyncCallback): void { + const mkdirSyncWrapper = (path: string, recursion: boolean,) => fileIo.mkdirSync(path, recursion); + let p1 = taskpool.execute(mkdirSyncWrapper, path, recursion); + p1.then((ret: NullishType) => { + let err = new BusinessError(); + if (ret === null || ret === undefined) { + console.println("-------- err code = -1 -------------"); + err.code = -1 + callback(err, undefined) + }else { + console.println("-------- err code = 0 -------------"); + err.code = 0 + let r = ret as int; + callback(err, r); + } + }); + } + + static native copyFileSync(src: FileDataType, dest: FileDataType, mode?: int): void; + static native statSync(file: FileDataType): Stat; +} + +type FileDataType = String | number + +enum LocationType { + LOCAl = 1, + CLOUD = 2 +} + +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; +} + +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; + + 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; +} + +function accessSyncTest() { + console.println("accessSyncTest begin") + let result1 = fileIo.accessSync("/data/zxl/hello.txt", AccessModeType.WRITE, AccessFlagType.LOCAL) + console.println("result1 from native") + console.println(result1) + console.println("accessSyncTest end") + console.println("accessSyncTest begin") + let result2 = fileIo.accessSync("/data", AccessModeType.READ) + console.println("result2 from native") + console.println(result2) + console.println("accessSyncTest end") + console.println("accessSyncTest begin") + let result3 = fileIo.accessSync("data2") + console.println("result3 from native") + console.println(result3) + console.println("accessSyncTest end") + console.println("accessSyncTest all end") +} + +function unlinkTest() { + console.println("unlinkTest begin") + const ret = fileIo.unlinkSync("liyuke") + console.println("------- end --------") + console.println(ret) + // promise异步 + try { + fileIo.unlink("src").then((result: int) => { + console.println("------- end --------") + console.println(result) + });; + } catch (error) { + console.error("Promise: Error getting temp dir:", error); + } + // callback异步 + let path = "/data/local/tmp/hello.txt"; + fileIo.unlink(path, (err: BusinessError, data?: int) => { + console.println("-------- in callback -------------"); + if (err.code) { + console.error("Callback方式: Error unlink:", err); + } else { + console.log("Callback方式: unlink:", data); + } + }); + console.println("unlinkTest end") +} + +function mkdirTest() { + console.println("mkdirTest begin") + const ret = fileIo.mkdirSync("liyuke") + console.println("------- end --------") + console.println(ret) + // promise异步 + try { + fileIo.mkdir("src").then((result: int) => { + console.println("------- end --------") + console.println(result) + });; + } catch (error) { + console.error("Promise: Error getting temp dir:", error); + } + + try { + fileIo.mkdir("test/111", true).then((result: int) => { + console.println("------- end --------") + console.println(result) + });; + } catch (error) { + console.error("Promise: Error getting temp dir:", error); + } + try { + fileIo.mkdir("test1/222", false).then((result: int) => { + console.println("------- end --------") + console.println(result) + });; +} catch (error) { + console.error("Promise: Error getting temp dir:", error); +} + // callback异步 + let path = "/data/local/tmp/hello"; + fileIo.mkdir(path, (err: BusinessError, data?: int) => { + console.println("-------- in callback -------------"); + if (err.code) { + console.error("Callback方式: Error mkdir:", err); + } else { + console.log("Callback方式: mkdir:", data); + } + }); + + path = "/data/local/tmp/111/test"; + let recursion = true; + fileIo.mkdir(path, recursion, (err: BusinessError, data?: int) => { + console.println("-------- in callback -------------"); + if (err.code) { + console.error("Callback方式: Error mkdir:", err); + } else { + console.log("Callback方式: mkdir:", data); + } + }); + path = "/data/local/tmp/222/test"; + recursion = false; + fileIo.mkdir(path, recursion, (err: BusinessError, data?: int) => { + console.println("-------- in callback -------------"); + if (err.code) { + console.error("Callback方式: Error mkdir:", err); + } else { + console.log("Callback方式: mkdir:", data); + } + }); + console.println("mkdirTest end") +} + +function moveSyncTest() { + console.println("moveSyncTest begin") + fileIo.moveFileSync("/data/local/tmp/a.txt", "/data/local/tmp/b.txt", 1) + console.println("moveSyncTest end") +} + +function copy_file_test(src: FileDataType, dest: FileDataType, mode?: int) { + fileIo.copyFileSync(src, dest, mode) +} + +function rmdirSyncTest() { + console.println("rmdirSyncTest begin") + fileIo.rmdirSync("/data/local/hello") + console.println("rmdirSyncTest end") +} + +function stat_test(file: FileDataType) { + let stat = fileIo.statSync(file) + console.info("stat, ino is " + stat.ino); + console.info("stat, mode is " + stat.mode); + console.info("stat, uid is " + stat.uid); + console.info("stat, gid is " + stat.gid); + console.info("stat, size is " + stat.size); + console.info("stat, atime is " + stat.atime); + console.info("stat, mtime is " + stat.mtime); + console.info("stat, ctime is " + stat.ctime); + console.info("stat, atimeNs is " + stat.atimeNs); + console.info("stat, mtimeNs is " + stat.mtimeNs); + console.info("stat, ctimeNs is " + stat.ctimeNs); + console.info("stat, location is " + stat.location); + console.info("stat, isBlockDevice is " + stat.isBlockDevice()); + console.info("stat, isCharacterDevice is " + stat.isCharacterDevice()); + console.info("stat, isDirectory is " + stat.isDirectory()); + console.info("stat, isFIFO is " + stat.isFIFO()); + console.info("stat, isFile is " + stat.isFile()); + console.info("stat, isSocket is " + stat.isSocket()); + console.info("stat, isSymbolicLink is " + stat.isSymbolicLink()); +} + +function main(){ + console.println("---------- hello ani --------------") + accessSyncTest() + moveSyncTest() + rmdirSyncTest() + console.println("---------- hello ani end ---------------") +} \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/ani/file_fs_namespace.ets b/interfaces/kits/js/src/mod_fs/ani/file_fs_namespace.ets new file mode 100644 index 0000000000000000000000000000000000000000..23c21d8ed318867923c590a0dd40a8176f69e2d5 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/ani/file_fs_namespace.ets @@ -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. + */ + +export default fileIo; + +loadLibrary("ani_fs_class.z") + +namespace fileIo { + export native function accessSync(path: String, mode: int): int; +} + +function accessSyncTest() { + console.println("accessSyncTest begin") + let result = fileIo.accessSync("hello", 1) + console.println("result from native") + console.println(result) + console.println("accessSyncTest end") +} + +function main() { + console.println("---------- hello ani --------------") + accessSyncTest() + console.println("---------- hello ani end ---------------") +} \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stat/fs_stat.cpp b/interfaces/kits/js/src/mod_fs/class_stat/fs_stat.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64b91476f718aeb6fb218bc985d7e9f8e73d43f9 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stat/fs_stat.cpp @@ -0,0 +1,168 @@ +/* + * 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_stat.h" + +#include +#include +#include +#include +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +#include +#endif + +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +bool FsStat::CheckStatMode(mode_t mode) +{ + return (entity.stat_.st_mode & S_IFMT) == mode; +} + +bool FsStat::IsBlockDevice() +{ + return CheckStatMode(S_IFBLK); +} + +bool FsStat::IsCharacterDevice() +{ + return CheckStatMode(S_IFCHR); +} + +bool FsStat::IsDirectory() +{ + return CheckStatMode(S_IFDIR); +} + +bool FsStat::IsFIFO() +{ + return CheckStatMode(S_IFIFO); +} + +bool FsStat::IsFile() +{ + return CheckStatMode(S_IFREG); +} + +bool FsStat::IsSocket() +{ + return CheckStatMode(S_IFSOCK); +} + +bool FsStat::IsSymbolicLink() +{ + return CheckStatMode(S_IFLNK); +} + +int64_t FsStat::GetIno() +{ + return entity.stat_.st_ino; +} + +int64_t FsStat::GetMode() +{ + return entity.stat_.st_mode & S_PERMISSION; +} + +int64_t FsStat::GetUid() +{ + return entity.stat_.st_uid; +} + +int64_t FsStat::GetGid() +{ + return entity.stat_.st_gid; +} + +int64_t FsStat::GetSize() +{ + return entity.stat_.st_size; +} + +int64_t FsStat::GetAtime() +{ + return static_cast(entity.stat_.st_atim.tv_sec); +} + +int64_t FsStat::GetMtime() +{ + return static_cast(entity.stat_.st_mtim.tv_sec); +} + +int64_t FsStat::GetCtime() +{ + return static_cast(entity.stat_.st_ctim.tv_sec); +} + +int64_t FsStat::GetAtimeNs() +{ + return static_cast(entity.stat_.st_atim.tv_sec * SECOND_TO_NANOSECOND + + entity.stat_.st_atim.tv_nsec); +} + +int64_t FsStat::GetMtimeNs() +{ + return static_cast(entity.stat_.st_mtim.tv_sec * SECOND_TO_NANOSECOND + + entity.stat_.st_mtim.tv_nsec); +} + +int64_t FsStat::GetCtimeNs() +{ + return static_cast(entity.stat_.st_ctim.tv_sec * SECOND_TO_NANOSECOND + + entity.stat_.st_ctim.tv_nsec); +} + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +int32_t FsStat::GetLocation() +{ + std::unique_ptr value = CreateUniquePtr(MAX_ATTR_NAME); + //TODO:遗留项是否要保留这个逻辑 + if (value == nullptr) { + HILOGE("Getxattr memory out, errno is %{public}d", errno); + return ENOMEM; + } + + ssize_t size = 0; + if (entity.fileInfo_->isPath) { + size = getxattr(entity.fileInfo_->path.get(), CLOUD_LOCATION_ATTR.c_str(), value.get(), MAX_ATTR_NAME); + } else { + size = fgetxattr(entity.fileInfo_->fdg->GetFD(), CLOUD_LOCATION_ATTR.c_str(), value.get(), MAX_ATTR_NAME); + } + Location defaultLocation = LOCAL; + if (size <= 0) { + if (errno != ENODATA && errno != EOPNOTSUPP) { + HILOGE("Getxattr value failed, errno is %{public}d", errno); + } + return static_cast(defaultLocation); + } + std::string location = string(value.get(), static_cast(size)); + if (!std::all_of(location.begin(), location.end(), ::isdigit)) { + HILOGE("Getxattr location is not all digit!"); + return static_cast(defaultLocation); + } + defaultLocation = static_cast(atoi(location.c_str())); + return static_cast(defaultLocation); +} +#endif + +FsStat* FsStat::Constructor(const StatEntity entity) +{ + return new FsStat(entity); +} + +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stat/fs_stat.h b/interfaces/kits/js/src/mod_fs/class_stat/fs_stat.h new file mode 100644 index 0000000000000000000000000000000000000000..d4f9e9939e3a972301f9d91ec3292e13b84d3237 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stat/fs_stat.h @@ -0,0 +1,64 @@ +/* + * 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_CLASS_STAT_FSSTAT_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STAT_FSSTAT_H + +#include "filemgmt_libfs.h" +#include "fs_stat_entity.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +const int64_t SECOND_TO_NANOSECOND = 1e9; +constexpr int S_PERMISSION = 00000777; +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +const size_t MAX_ATTR_NAME = 64; +const std::string CLOUD_LOCATION_ATTR = "user.cloud.location"; +#endif +class FsStat final { +public: + static FsStat* Constructor(const StatEntity entity); + + bool IsBlockDevice(); + bool IsCharacterDevice(); + bool IsDirectory(); + bool IsFIFO(); + bool IsFile(); + bool IsSocket(); + bool IsSymbolicLink(); + + int64_t GetIno(); + int64_t GetMode(); + int64_t GetUid(); + int64_t GetGid(); + int64_t GetSize(); + int64_t GetAtime(); + int64_t GetMtime(); + int64_t GetCtime(); + int64_t GetAtimeNs(); + int64_t GetMtimeNs(); + int64_t GetCtimeNs(); +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + int32_t GetLocation(); +#endif + +private: + const StatEntity entity; + bool CheckStatMode(mode_t mode); + FsStat(const StatEntity entity) : entity(entity) {}; +}; +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STAT_FSSTAT_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stat/fs_stat_entity.h b/interfaces/kits/js/src/mod_fs/class_stat/fs_stat_entity.h new file mode 100644 index 0000000000000000000000000000000000000000..5b4ec9317d972e04c9e0945a332c744312a98974 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stat/fs_stat_entity.h @@ -0,0 +1,37 @@ +/* + * 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_CLASS_STAT_STAT_ENTITY_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STAT_STAT_ENTITY_H + +#include +#include "fs_utils.h" +#include "uv.h" + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +enum Location { + LOCAL = 1 << 0, + CLOUD = 1 << 1 +}; +#endif +namespace OHOS::FileManagement::ModuleFileIO { +struct StatEntity { + uv_stat_t stat_; +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + std::shared_ptr fileInfo_; +#endif +}; +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STAT_STAT_ENTITY_H \ No newline at end of file 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..2f43e0ffb407d212ff292b0989a93dc05c69de97 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/fs_utils.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 "fs_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +namespace { + const vector PUBLIC_DIR_PATHS = { + "/Documents" + }; +} + +tuple FsUtils::GetActualBuf(void *rawBuf, size_t bufLen, optional offset) +{ + void *realBuf = nullptr; + int64_t opOffset = 0; + if (offset.has_value()) { + opOffset = offset.value(); + if (opOffset < 0) { + HILOGE("Invalid option.offset, positive integer is desired"); + return { false, nullptr, opOffset }; + } else if (opOffset > static_cast(bufLen)) { + HILOGE("Invalid option.offset, buffer limit exceeded"); + return { false, nullptr, opOffset }; + } else { + realBuf = static_cast(rawBuf) + opOffset; + } + } else { + realBuf = rawBuf; + } + + return { true, realBuf, opOffset }; +} + +tuple FsUtils::GetActualLen(size_t bufLen, size_t bufOff, 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 + unsigned int 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..11ba4b5617d2953d76d3470c21d99a9ddcf489e8 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/fs_utils.h @@ -0,0 +1,97 @@ +/* + * 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 "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 int RDONLY = UV_FS_O_RDONLY; +constexpr int WRONLY = UV_FS_O_WRONLY; +constexpr int RDWR = UV_FS_O_RDWR; +constexpr int CREATE = UV_FS_O_CREAT; +constexpr int TRUNC = UV_FS_O_TRUNC; +constexpr int APPEND = UV_FS_O_APPEND; +constexpr int NONBLOCK = UV_FS_O_NONBLOCK; +constexpr int DIRECTORY = UV_FS_O_DIRECTORY; +constexpr int NOFOLLOW = UV_FS_O_NOFOLLOW; +constexpr int SYNC = UV_FS_O_SYNC; + +constexpr unsigned int MODE_EXIST = 00; +constexpr unsigned int MODE_WRITE = 02; +constexpr unsigned int MODE_READ = 04; +constexpr unsigned int MODE_READ_WRITE = 06; + +constexpr unsigned int USR_READ_ONLY = 00; +constexpr unsigned int USR_WRITE_ONLY = 01; +constexpr unsigned int USR_RDWR = 02; +constexpr unsigned int USR_CREATE = 0100; +constexpr unsigned int USR_TRUNC = 01000; +constexpr unsigned int USR_APPEND = 02000; +constexpr unsigned int USR_NONBLOCK = 04000; +constexpr unsigned int USR_DIRECTORY = 0200000; +constexpr unsigned int USR_NOFOLLOW = 0400000; +constexpr unsigned int 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 GetActualBuf(void *rawBuf, size_t bufLen, optional offset = nullopt); + static tuple GetActualLen(size_t bufLen, size_t bufOff, 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/access_core.cpp b/interfaces/kits/js/src/mod_fs/properties/access_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c7279d9e1806a5a39f64166573a6152d47ddad0d --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/access_core.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022-2024 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 +#include + +#include "filemgmt_libhilog.h" +#include "access_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static int UvAccess(const std::string &path, int mode, int flag) +{ + 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 GetMode(const std::optional &modeOpt, bool *hasMode) +{ + *hasMode = modeOpt.has_value(); + if (*hasMode) { + return static_cast(modeOpt.value()); + } + return -1; +} + +static bool ValidAccessArgs(const std::string &path, const std::optional &modeOpt, int &finalMode, int &flag) +{ + if (path.empty()) { + HILOGE("Invalid path"); + return false; + } + bool hasMode = false; + int mode = GetMode(modeOpt, &hasMode); + if (mode < 0 && hasMode) { + HILOGE("Invalid mode"); + return false; + } + finalMode = hasMode ? mode : 0; + flag = static_cast(AccessFlagType::DEFAULT_FLAG); + return true; +} + +FsResult AccessCore::DoAccess(const std::string& path, const std::optional mode) +{ + int finalMode = 0; + int flag = static_cast(AccessFlagType::DEFAULT_FLAG); + if (!ValidAccessArgs(path, mode, finalMode, flag)) { + return FsResult::Error(EINVAL); + } + int ret = UvAccess(path, finalMode, flag); + if (ret < 0 && (std::string_view(uv_err_name(ret)) != "ENOENT")) { + HILOGE("Failed to access file by path"); + return FsResult::Error(ret); + } + bool isAccess = (ret == 0); + return FsResult::Success(isAccess); +} + +FsResult AccessCore::DoAccess(const std::string& path, const AccessModeType &mode, const AccessFlagType &flag) +{ + int finalMode = static_cast(mode); + int finalFlag = static_cast(flag); + if (!ValidAccessArgs(path, std::make_optional(mode), finalMode, finalFlag)) { + return FsResult::Error(EINVAL); + } + int ret = UvAccess(path, finalMode, finalFlag); + if (ret < 0 && (std::string_view(uv_err_name(ret)) != "ENOENT")) { + HILOGE("Failed to access file by path"); + return FsResult::Error(ret); + } + bool isAccess = (ret == 0); + return FsResult::Success(isAccess); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/access_core.h b/interfaces/kits/js/src/mod_fs/properties/access_core.h new file mode 100644 index 0000000000000000000000000000000000000000..ceeb4bdae94613c1a36d0cdb3cfb6a475431b690 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/access_core.h @@ -0,0 +1,57 @@ +/* + * 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_ACCESS_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ACCESS_CORE_H + +#include "fs_utils.h" +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +using namespace std; + +enum class AccessModeType { + ERROR = -1, + EXIST = 0, + WRITE = 2, + READ = 4, + READ_WRITE = 6 +}; + +enum class AccessFlagType { + DEFAULT_FLAG = -1, + LOCAL_FLAG, +}; + +class AccessCore { +public: + inline static const std::string className_ = "__properities__"; + + static FsResult DoAccess(const string &path, const optional mode = nullopt); + + static FsResult DoAccess(const string &path, const AccessModeType &mode, const AccessFlagType &flag); + +}; + +constexpr int DIR_DEFAULT_PERM = 0770; +const std::string PROCEDURE_ACCESS_NAME = "FileIOAccess"; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ACCESS_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/access_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/access_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2d9b0d649319283d113e7908252becb83b93321 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/access_ani.cpp @@ -0,0 +1,191 @@ +/* + * 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 "access_ani.h" + +#include + +#include "access_core.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +static constexpr int EXIST_VALUE = 0; +static constexpr int WRITE_VALUE = 2; +static constexpr int READ_VALUE = 4; +static constexpr int READ_WRITE_VALUE = 6; + +AccessModeType ToAccessModeType(int32_t mode) +{ + switch (mode) { + case EXIST_VALUE: + return AccessModeType::EXIST; + case WRITE_VALUE: + return AccessModeType::WRITE; + case READ_VALUE: + return AccessModeType::READ; + case READ_WRITE_VALUE: + return AccessModeType::READ_WRITE; + default: + return AccessModeType::ERROR; + } +} + +std::optional OptToAccessModeType(const std::optional& mode) +{ + if (!mode.has_value()) { + return std::nullopt; + } + + switch (mode.value()) { + case EXIST_VALUE: + return AccessModeType::EXIST; + case WRITE_VALUE: + return AccessModeType::WRITE; + case READ_VALUE: + return AccessModeType::READ; + case READ_WRITE_VALUE: + return AccessModeType::READ_WRITE; + default: + return AccessModeType::ERROR; + } +} + +AccessFlagType ToAccessFlagType(int32_t flag) +{ + switch (flag) { + case -1: + return AccessFlagType::DEFAULT_FLAG; + case 0: + return AccessFlagType::LOCAL_FLAG; + default: + return AccessFlagType::DEFAULT_FLAG; + } +} + +std::optional OptToAccessFlagType(const std::optional& flag) +{ + if (!flag.has_value()) { + return std::nullopt; + } + switch (flag.value()) { + case -1: + return AccessFlagType::DEFAULT_FLAG; + case 0: + return AccessFlagType::LOCAL_FLAG; + default: + return AccessFlagType::DEFAULT_FLAG; + } +} + + +ani_boolean AccessAni::AccessSync1(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, + ani_int mode, ani_int flag) +{ + auto [succ, pathStr] = TypeConverter::ToUTF8StringPath(env, path); + if (! succ) { + HILOGE("ERROR: ToUTF8StringPath FAILED!"); + return false; + } + + auto modeType = ToAccessModeType(mode); + auto flagType = ToAccessFlagType(flag); + HILOGE("AccessSync ToUTF8StringPath: %s, mode: %d, flag: %d", pathStr.c_str(), modeType, flagType); + auto ret = AccessCore::DoAccess(pathStr, modeType, flagType); + if (!ret.IsSuccess()) { + return false; + } + return true; +} + +ani_boolean AccessAni::AccessSync2(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, + ani_object mode) +{ + auto [succPath, pathStr] = TypeConverter::ToUTF8StringPath(env, path); + if (! succPath) { + HILOGE("Invalid path"); + return false; + } + + auto [succMode, modeOp] = TypeConverter::ToOptionalInt32(env, mode); + if (! succMode) { + HILOGE("Invalid mode"); + return false; + } + auto modeType = OptToAccessModeType(modeOp); + auto ret = AccessCore::DoAccess(pathStr, modeType); + int value = 0; + if (modeType == AccessModeType::ERROR) { + value = -1; + } else if (modeType == AccessModeType::EXIST) { + value = 0; + } else if (modeType == AccessModeType::WRITE) { + value = 2; + } else if (modeType == AccessModeType::READ) { + value = 4; + } else if (modeType == AccessModeType::READ_WRITE) { + value = 6; + } + HILOGE("AccessSync ToUTF8StringPath: %s, mode: %d", pathStr.c_str(), value); + + if (!ret.IsSuccess()) { + return false; + } + uint8_t result = ret.GetData().value(); + return result; +} + +ani_boolean AccessAni::AccessSync3(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, + ani_enum_item mode, ani_enum_item flag) +{ + ani_boolean ret = 0; + auto [succPath, pathStr] = TypeConverter::ToUTF8StringPath(env, path); + if (! succPath) { + HILOGE("Invalid path"); + return ret; + } + + auto [succMode, modeOp] = TypeConverter::ToOptionalInt32(env, mode); + if (! succMode) { + HILOGE("Invalid mode"); + return ret; + } + auto modeType = OptToAccessModeType(modeOp); + + auto [succFlag, flagOpt] = TypeConverter::ToOptionalInt32(env, flag); + if (! succFlag) { + HILOGE("Invalid flag"); + return ret; + } + auto flagType = OptToAccessFlagType(flagOpt); + HILOGE("Success"); + FsResult fsRet = FsResult::Success(false); + if (flagOpt == std::nullopt) { + fsRet = AccessCore::DoAccess(pathStr, modeType); + } else { + fsRet = AccessCore::DoAccess(pathStr, modeType.value(), flagType.value()); + } + + return fsRet.GetData().value(); +} + +} // ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/access_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/access_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..9c34ea6bbae1f73d8ce54a107e046212ae556f4e --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/access_ani.h @@ -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. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_ACCESS_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_ACCESS_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class AccessAni final { +public: + static ani_boolean AccessSync1(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, + ani_int mode, ani_int flag); + static ani_boolean AccessSync2(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, + ani_object mode); + static ani_boolean AccessSync3(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, + ani_enum_item mode, ani_enum_item flag); +}; +} // ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif //INTERFACES_KITS_JS_SRC_MOD_FS_ACCESS_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/copy_file_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/copy_file_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b717f2a3a326602f74a879315ce29fe3cb464f08 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/copy_file_ani.cpp @@ -0,0 +1,34 @@ +#include "copy_file_ani.h" +#include "copy_file_core.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI; + +void CopyFileAni::CopyFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, + ani_object src, ani_object dest, ani_object mode) { + auto [succSrc, srcFile] = TypeConverter::ToFileInfo(env, src); + auto [succDest, destFile] = TypeConverter::ToFileInfo(env, dest); + if (!succSrc || !succDest) { + HILOGE("The first/second argument requires filepath/fd"); + return; + } + + auto [succMode, optMode] = TypeConverter::ToOptionalInt32(env, mode); + if (!succMode) { + HILOGE("Failed to convert mode to int32"); + return; + } + + HILOGE("file_api begin copy file..."); + auto ret = CopyFileCore::DoCopyFile(srcFile, destFile, optMode); + if (ret.IsSuccess()) { + HILOGE("file_api copy file success."); + } else { + HILOGE("file_api copy file failed!"); + } + + return; +} \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/copy_file_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/copy_file_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..80d70b6e615e7b7b6ab6575e4ce838e2e2904f08 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/copy_file_ani.h @@ -0,0 +1,7 @@ +#include + +class CopyFileAni final { +public: + static void CopyFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, + ani_object src, ani_object dest, ani_object mode); +}; \ 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..b53557ae427ebc3f351321a9a4f3b512d27884fb --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/mkdir_ani.cpp @@ -0,0 +1,56 @@ +/* + * 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 "mkdir_ani.h" +#include "filemgmt_libhilog.h" +#include "mkdir_core.h" +#include "type_converter.h" + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI; + +ani_int MkdirkAni::MkdirSync0(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path) + +{ + auto [succ, pathStr] = TypeConverter::ToUTF8StringPath(env, path); + if (!succ) { + HILOGE("Invalid path"); + return -1; + } + auto ret = MkdirCore::DoMkdir(pathStr); + if(!ret.IsSuccess()) { + HILOGE("Mkdir faild"); + return -1; + } + return 0; + +} + +ani_int MkdirkAni::MkdirSync1(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_boolean recursion) +{ + auto [succ, pathStr] = ANI::TypeConverter::ToUTF8StringPath(env, path); + if (!succ) { + HILOGE("Invalid path"); + return -1; + } + auto ret = MkdirCore::DoMkdir(pathStr, recursion); + if(!ret.IsSuccess()) { + HILOGE("Mkdir faild"); + return -1; + } + return 0; +} 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..6499a369e853973ff2fe1a72a11043ff2c9149f3 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/mkdir_ani.h @@ -0,0 +1,25 @@ +/* + * 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 + +class MkdirkAni final +{ +public: + static ani_int MkdirSync0(ani_env *env, [[maybe_unused]] ani_class clazz, + ani_string path); + static ani_int MkdirSync1(ani_env *env, [[maybe_unused]] ani_class clazz, + ani_string path, ani_boolean recursion); +}; \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/move_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/move_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..615c3a589749950d4b25d2ffe7c6d14728a579cd --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/move_ani.cpp @@ -0,0 +1,53 @@ +/* + * 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 "move_ani.h" +#include "filemgmt_libhilog.h" +#include "move_core.h" +#include "type_converter.h" + +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI; + +void MoveAni::MoveFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, + ani_string src, ani_string dest, ani_object mode) +{ + //参数解析 + auto [succSrc, srcPath] = ANI::TypeConverter::ToUTF8StringPath(env, src); + if (!succSrc) { + HILOGE("Invalid src"); + return ; + } + auto [succDest, destPath] = ANI::TypeConverter::ToUTF8StringPath(env, dest); + if (!succDest) { + HILOGE("Invalid dest"); + return ; + } + auto [succMode, modeOp] = ANI::TypeConverter::ToOptionalInt32(env, mode); + if (!succMode) { + HILOGE("Invalid mode"); + return ; + } + + //核心逻辑 + auto ret = MoveCore::DoMove(srcPath, destPath, modeOp); + if (!ret.IsSuccess()) { + HILOGE("move feild"); + return ; + } + HILOGE("move success"); + return ; +} diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/move_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/move_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..0904e4d028ea2f331d92854a47d3d6364d10a66f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/move_ani.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. + */ + +#include + +class MoveAni final +{ + public: + static void MoveFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, + ani_string src, ani_string dest, ani_object mode); +}; \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/rmdir_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/rmdir_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f13606ae1e779c153aad7d004264e210d8ff2fa --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/rmdir_ani.cpp @@ -0,0 +1,42 @@ +/* + * 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 "rmdir_ani.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" +#include "rmdir_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; + +void RmdirAni::rmdirSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path) +{ + auto [succPath, pathStr] = TypeConverter::ToUTF8StringPath(env, path); + if (!succPath) { + HILOGE("Invalid path"); + return ; + } + RmdirentCore::DoRmdirent(pathStr); + HILOGE("rmdirSync pathStr: %s", pathStr.c_str()); +} + +} // ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/rmdir_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/rmdir_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..0945735133baa40bf79c51e343033411bd7e70d6 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/rmdir_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 RMDIR_ANI_H +#define RMDIR_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class RmdirAni final +{ +public: + static void rmdirSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path); +}; +} // ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // RMDIR_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/stat_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/stat_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2928c566149d2abff120fd613b3e71670877848 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/stat_ani.cpp @@ -0,0 +1,263 @@ +/* + * 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 "filemgmt_libhilog.h" +#include "stat_ani.h" +#include "stat_core.h" +#include "type_converter.h" + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI; + +static ani_status SetNumProperty(ani_env *env, const ani_class &cls, ani_object &object, const char *name, ani_double &value) +{ + ani_method setter; + ani_status ret; + if ((ret = env->Class_FindMethod(cls, name, nullptr, &setter)) != ANI_OK) { + HILOGE("Class_FindMethod Fail %{public}s, err: %{public}d", name, ret); + return ret; + } + + return env->Object_CallMethod_Void(object, setter, value); +} + +static ani_status SetBigIntProperty(ani_env *env, const ani_class &statCls, ani_object &statObject, const char *name, ani_double &value) +{ + ani_object object = {}; + static const char *className = "Lescompat/BigInt;"; + ani_class cls; + ani_status ret; + + if ((ret = env->FindClass(className, &cls)) != ANI_OK) { + HILOGE("Not found %{public}s, err: %{public}d", className, ret); + return ret; + } + + ani_method ctor; + if ((ret = env->Class_FindMethod(cls, "", "D:V", &ctor)) != ANI_OK) { + HILOGE("Not found ctor, err: %{public}d", ret); + return ret; + } + + if ((ret = env->Object_New(cls, ctor, &object, value)) != ANI_OK) { + HILOGE("New BigIntProperty Fail, err: %{public}d", ret); + return ret; + } + + ani_method setter; + if ((ret = env->Class_FindMethod(statCls, name, nullptr, &setter)) != ANI_OK) { + HILOGE("Class_FindMethod Fail %{public}s, err: %{public}d", name, ret); + return ret; + } + + return env->Object_CallMethod_Void(statObject, setter, object); +} + +static ani_int GetLocationEnumIndex(const Location &value) +{ + switch (value) { + case LOCAL: + return ani_int(0); + case CLOUD: + return ani_int(1); + } +} + +static ani_status SetEnumLocation(ani_env *env, const ani_class &cls, ani_object &object, const char *name, const Location &value) +{ + ani_method setter; + ani_status ret; + if ((ret = env->Class_FindMethod(cls, name, nullptr, &setter)) != ANI_OK) { + HILOGE("Class_FindMethod Fail %{public}s, err: %{public}d", name, ret); + return ret; + } + + return env->Object_CallMethod_Void(object, setter, GetLocationEnumIndex(value)); +} + +static ani_status SetProperties(ani_env *env, const ani_class &cls, + ani_object &statObject, FsStat *fsStat) +{ + ani_status ret; + + vector> numProperties = {{"mode", ani_double(static_cast(fsStat->GetMode()))}, + {"uid", ani_double(static_cast(fsStat->GetUid()))}, {"gid", ani_double(static_cast(fsStat->GetGid()))}, + {"size", ani_double(static_cast(fsStat->GetSize()))}, {"atime", ani_double(static_cast(fsStat->GetAtime()))}, + {"mtime", ani_double(static_cast(fsStat->GetMtime()))}, {"ctime", ani_double(static_cast(fsStat->GetCtime()))}}; + for (auto iter : numProperties) { + ret = SetNumProperty(env, cls, statObject, iter.first, iter.second); + if (ret != ANI_OK) { + HILOGE("Object_CallMethod_Void Fail %{public}s, err: %{public}d", iter.first, ret); + return ret; + } + } + + vector> bigIntProperties = {{"ino", ani_double(static_cast(fsStat->GetIno()))}, + {"atimeNs", ani_double(static_cast(fsStat->GetAtimeNs()))}, {"mtimeNs", ani_double(static_cast(fsStat->GetMtimeNs()))}, + {"ctimeNs", ani_double(static_cast(fsStat->GetCtimeNs()))}}; + for (auto iter : bigIntProperties) { + ret = SetBigIntProperty(env, cls, statObject, iter.first, iter.second); + if (ret != ANI_OK) { + HILOGE("Object_CallMethod_Void Fail %{public}s, err: %{public}d", iter.first, ret); + return ret; + } + } + + if ((ret = SetEnumLocation(env, cls, statObject, "location", static_cast(fsStat->GetLocation()))) != ANI_OK) { + HILOGE("Object_CallMethod_Void Fail location, err: %{public}d", ret); + return ret; + } + + return ANI_OK; +} + +static ani_object Wrap(ani_env *env, FsStat *fsStat) +{ + ani_object statObject = {}; + static const char *className = "Lfile_fs_class/StatInner;"; + ani_class cls; + ani_status ret; + + if ((ret = env->FindClass(className, &cls)) != ANI_OK) { + HILOGE("Not found %{public}s, err: %{public}d", className, ret); + return {}; + } + + ani_method ctor; + if ((ret = env->Class_FindMethod(cls, "", "J:V", &ctor)) != ANI_OK) { + HILOGE("Not found ctor, err: %{public}d", ret); + return {}; + } + + if ((ret = env->Object_New(cls, ctor, &statObject, reinterpret_cast(fsStat))) != ANI_OK) { + HILOGE("New StatInner Fail, err: %{public}d", ret); + return {}; + } + + if ((ret = SetProperties(env, cls, statObject, fsStat)) != ANI_OK) { + HILOGE("SetProperties Fail, err: %{public}d", ret); + return {}; + } + + return statObject; +} + +static FsStat* Unwrap(ani_env *env, ani_object object){ + ani_long fsStat; + auto ret = env->Object_GetFieldByName_Long(object, "nativeStat", &fsStat); + if(ret != ANI_OK){ + HILOGE("unwrap fsStat err: %{public}d", ret); + return nullptr; + } + return reinterpret_cast(fsStat); +} + +ani_object StatAni::StatSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_object file) +{ + auto [succPath, fileInfo] = TypeConverter::ToFileInfo(env, file); + if (!succPath) { + HILOGE("The first argument requires filepath/fd"); + return {}; + } + + auto ret = StatCore::DoStat(fileInfo); + if (ret.IsSuccess()) { + HILOGE("file_api stat statSync success."); + return Wrap(env, ret.GetData().value()); + } else { + HILOGE("file_api statSync failed!"); + return {}; + } +} + +ani_boolean StatAni::IsBlockDevice(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto fsStat = Unwrap(env, object); + if (fsStat == nullptr) { + return ANI_FALSE; + } + + auto ret = fsStat->IsBlockDevice(); + return ani_boolean(ret); +} + +ani_boolean StatAni::IsCharacterDevice(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto fsStat = Unwrap(env, object); + if (fsStat == nullptr) { + return ANI_FALSE; + } + + auto ret = fsStat->IsCharacterDevice(); + return ani_boolean(ret); +} + +ani_boolean StatAni::IsDirectory(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto fsStat = Unwrap(env, object); + if (fsStat == nullptr) { + return ANI_FALSE; + } + + auto ret = fsStat->IsDirectory(); + return ani_boolean(ret); +} + +ani_boolean StatAni::IsFIFO(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto fsStat = Unwrap(env, object); + if (fsStat == nullptr) { + return ANI_FALSE; + } + + auto ret = fsStat->IsFIFO(); + return ani_boolean(ret); +} + +ani_boolean StatAni::IsFile(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto fsStat = Unwrap(env, object); + if (fsStat == nullptr) { + return ANI_FALSE; + } + + auto ret = fsStat->IsFile(); + return ani_boolean(ret); +} + +ani_boolean StatAni::IsSocket(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto fsStat = Unwrap(env, object); + if (fsStat == nullptr) { + return ANI_FALSE; + } + + auto ret = fsStat->IsSocket(); + return ani_boolean(ret); +} + +ani_boolean StatAni::IsSymbolicLink(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto fsStat = Unwrap(env, object); + if (fsStat == nullptr) { + return ANI_FALSE; + } + + auto ret = fsStat->IsSymbolicLink(); + return ani_boolean(ret); +} \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/stat_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/stat_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..0e26b56416a00dee2ee28600cfba62ebb4816b88 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/stat_ani.h @@ -0,0 +1,14 @@ +#include + +class StatAni final { +public: + static ani_object StatSync(ani_env *env, [[maybe_unused]] ani_class clazz, + ani_object file); + static ani_boolean IsBlockDevice(ani_env *env, [[maybe_unused]] ani_object object); + static ani_boolean IsCharacterDevice(ani_env *env, [[maybe_unused]] ani_object object); + static ani_boolean IsDirectory(ani_env *env, [[maybe_unused]] ani_object object); + static ani_boolean IsFIFO(ani_env *env, [[maybe_unused]] ani_object object); + static ani_boolean IsFile(ani_env *env, [[maybe_unused]] ani_object object); + static ani_boolean IsSocket(ani_env *env, [[maybe_unused]] ani_object object); + static ani_boolean IsSymbolicLink(ani_env *env, [[maybe_unused]] ani_object object); +}; \ 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..cccad87341bb705b8b13f320a42dac233baf28b0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/unlink_ani.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 +#include "unlink_ani.h" +#include "filemgmt_libhilog.h" +#include "unlink_core.h" +#include "type_converter.h" + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI; + +ani_int UnlinkAni::UnlinkSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path) +{ + auto [succ, pathStr] = TypeConverter::ToUTF8StringPath(env, path); + if (!succ) { + HILOGE("Invalid path"); + return -1; + } + auto ret = UnlinkCore::DoUnlink(pathStr); + if(!ret.IsSuccess()) { + HILOGE("Unlink faild"); + return -1; + } + return 0; +} + 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..fa3e8958903937bee4767eecf34e208ab3bbcace --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/unlink_ani.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. + */ + +#include + +class UnlinkAni final +{ +public: + static ani_int UnlinkSync(ani_env *env, [[maybe_unused]] ani_class clazz, + ani_string path); +}; \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_file_core.cpp b/interfaces/kits/js/src/mod_fs/properties/copy_file_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..523db944e913912f217e42de7a9a73ac5765fdf4 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_file_core.cpp @@ -0,0 +1,209 @@ +/* + * 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 "copy_file_core.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +static int32_t IsAllPath(FileInfo &srcFile, FileInfo &destFile) +{ +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + filesystem::path srcPath(string(srcFile.path.get())); + filesystem::path dstPath(string(destFile.path.get())); + error_code errCode; + if (!filesystem::copy_file(srcPath, dstPath, filesystem::copy_options::overwrite_existing, + errCode)) { + HILOGE("Failed to copy file, error code: %{public}d", errCode.value()); + return errCode.value(); + } +#else + std::unique_ptr copyfile_req = { + new (nothrow) uv_fs_t, FsUtils::FsReqCleanup}; + if (!copyfile_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int ret = uv_fs_copyfile(nullptr, copyfile_req.get(), srcFile.path.get(), destFile.path.get(), + UV_FS_COPYFILE_FICLONE, nullptr); + if (ret < 0) { + HILOGE("Failed to copy file when all parameters are paths"); + return ret; + } +#endif + return ERRNO_NOERR; +} + +static int32_t SendFileCore(FileInfo &srcFdg, FileInfo &destFdg, struct stat &statbf) +{ + std::unique_ptr sendfile_req = { + new (nothrow) uv_fs_t, FsUtils::FsReqCleanup}; + if (!sendfile_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int64_t offset = 0; + size_t size = static_cast(statbf.st_size); + int ret = 0; + while (size > 0) { + ret = uv_fs_sendfile(nullptr, sendfile_req.get(), destFdg.fdg->GetFD(), srcFdg.fdg->GetFD(), + offset, std::min(MAX_SIZE, size), nullptr); + if (ret < 0) { + HILOGE("Failed to sendfile by ret : %{public}d", ret); + return ret; + } + if (static_cast(ret) > size) { + HILOGE("More bytes returned than the size of the file. The file size is " + "%{public}zu" + "The bytes returned is %{public}d", + size, ret); + return EIO; + } + offset += static_cast(ret); + size -= static_cast(ret); + if (ret == 0) { + break; + } + } + if (size != 0) { + HILOGE("The execution of the sendfile task was terminated, remaining file " + "size %{public}zu", size); + return EIO; + } + return ERRNO_NOERR; +} + +static int32_t TruncateCore(const FileInfo &fileInfo) +{ + std::unique_ptr ftruncate_req = { + new (nothrow) uv_fs_t, FsUtils::FsReqCleanup}; + if (!ftruncate_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int ret = uv_fs_ftruncate(nullptr, ftruncate_req.get(), fileInfo.fdg->GetFD(), 0, nullptr); + if (ret < 0) { + HILOGE("Failed to truncate dstFile with ret: %{public}d", ret); + return ret; + } + return ERRNO_NOERR; +} + +static int32_t OpenCore(FileInfo &fileInfo, const int flags, const int mode) +{ + std::unique_ptr open_req = { + new (nothrow) uv_fs_t, FsUtils::FsReqCleanup}; + if (!open_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int ret = uv_fs_open(nullptr, open_req.get(), fileInfo.path.get(), flags, mode, nullptr); + if (ret < 0) { + HILOGE("Failed to open srcFile with ret: %{public}d", ret); + return ret; + } + fileInfo.fdg = CreateUniquePtr(ret, true); + if (fileInfo.fdg == nullptr) { + HILOGE("Failed to request heap memory."); + close(ret); + return ENOMEM; + } + return ERRNO_NOERR; +} + +static int32_t OpenFile(FileInfo &srcFile, FileInfo &destFile) +{ + if (srcFile.isPath) { + auto openResult = OpenCore(srcFile, UV_FS_O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (openResult) { + return openResult; + } + } + struct stat statbf; + if (fstat(srcFile.fdg->GetFD(), &statbf) < 0) { + HILOGE("Failed to get stat of file by fd: %{public}d", srcFile.fdg->GetFD()); + return errno; + } + if (destFile.isPath) { + auto openResult = OpenCore(destFile, UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (openResult) { + return openResult; + } + } else { + auto truncateResult = TruncateCore(destFile); + if (truncateResult) { + return truncateResult; + } + auto ret = lseek(destFile.fdg->GetFD(), 0, SEEK_SET); + if (ret < 0) { + HILOGE("Failed to lseek destFile, errno: %{public}d", errno); + return errno; + } + } + if (statbf.st_size == 0) { + return ERRNO_NOERR; + } + return SendFileCore(srcFile, destFile, statbf); +} + +static tuple ValidMode(const optional &mode) +{ + int modeValue = 0; + if (mode.has_value()) { + modeValue = mode.value(); + if (modeValue) { + return {false, modeValue}; + } + } + return {true, modeValue}; +} + +FsResult CopyFileCore::DoCopyFile(FileInfo &src, FileInfo &dest, + const optional &mode) +{ + auto [succMode, modeValue] = ValidMode(mode); + if (!succMode) { + HILOGE("Failed to convert mode to int32"); + return FsResult::Error(EINVAL); + } + + if (src.isPath && dest.isPath) { + auto err = IsAllPath(src, dest); + if (err) { + return FsResult::Error(err); + } + } else { + auto err = OpenFile(src, dest); + if (err) { + return FsResult::Error(err); + } + } + return FsResult::Success(); +} + +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_file_core.h b/interfaces/kits/js/src/mod_fs/properties/copy_file_core.h new file mode 100644 index 0000000000000000000000000000000000000000..a2aef7de8dc4d371aabb3ee149c8215f28d6f103 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_file_core.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_FILE_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_FILE_CORE_H + +#include "fs_utils.h" +#include "filemgmt_libfs.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +class CopyFileCore final { +public: + static FsResult DoCopyFile(FileInfo &src, FileInfo &dest, + const optional &mode = nullopt); +}; + +constexpr size_t MAX_SIZE = 0x7ffff000; +const string PROCEDURE_COPYFILE_NAME = "FileIOCopyFile"; +} // namespace OHOS::FileManagement::ModuleFileIO + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_FILE_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..224d2f83df8ff5086aba883df43c9a58b267edf2 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/mkdir_core.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2022-2024 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 + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +#include + +#include "bundle_mgr_proxy.h" +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "rust_file.h" +#include "system_ability_definition.h" + +#endif + +#ifdef FILE_API_TRACE +#include "hitrace_meter.h" +#endif + +#include "filemgmt_libhilog.h" + + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace AppExecFwk; + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +const string CLOUDDISK_FILE_PREFIX = "/data/storage/el2/cloud"; +const string DISTRIBUTED_FILE_PREFIX = "/data/storage/el2/distributedfiles"; +const string PACKAGE_NAME_FLAG = ""; +const string USER_ID_FLAG = ""; +const string PHYSICAL_PATH_PREFIX = "/mnt/hmdfs//account/device_view/local/data/"; +const string CLOUD_FILE_LOCATION = "user.cloud.location"; +const char POSITION_LOCAL = '1'; +const char POSITION_BOTH = '3'; +const int BASE_USER_RANGE = 200000; +#endif + +enum AccessFlag : int32_t { + DEFAULT_FLAG = -1, + LOCAL_FLAG, +}; + +struct AccessArgs { + string path; + int mode = -1; + int flag = DEFAULT_FLAG; +}; + +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); +} + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +static bool IsCloudOrDistributedFilePath(const string &path) +{ + return path.find(CLOUDDISK_FILE_PREFIX) == 0 || path.find(DISTRIBUTED_FILE_PREFIX) == 0; +} + +static int GetCurrentUserId() +{ + int uid = IPCSkeleton::GetCallingUid(); + int userId = uid / BASE_USER_RANGE; + return userId; +} + +static sptr GetBundleMgrProxy() +{ + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (!systemAbilityManager) { + HILOGE("fail to get system ability mgr"); + return nullptr; + } + sptr remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (!remoteObject) { + HILOGE("fail to get bundle manager proxy"); + return nullptr; + } + + return iface_cast(remoteObject); +} + +static string GetSelfBundleName() +{ + sptr bundleMgrProxy = GetBundleMgrProxy(); + if (!bundleMgrProxy) { + HILOGE("bundleMgrProxy is nullptr"); + return ""; + } + BundleInfo bundleInfo; + auto ret = bundleMgrProxy->GetBundleInfoForSelf(0, bundleInfo); + if (ret != 0) { + HILOGE("bundleName get fail"); + return ""; + } + return bundleInfo.name; +} + +static int HandleLocalCheck(const string &path, int mode) +{ + // check if the file of /data/storage/el2/cloud is on the local + if (path.find(CLOUDDISK_FILE_PREFIX) == 0) { + char val[2] = {'\0'}; + if (getxattr(path.c_str(), CLOUD_FILE_LOCATION.c_str(), val, sizeof(val)) < 0) { + HILOGI("get cloud file location fail, err: %{public}d", errno); + return errno; + } + if (val[0] == POSITION_LOCAL || val[0] == POSITION_BOTH) { + return 0; + } + return ENOENT; + } + // check if the distributed file of /data/storage/el2/distributedfiles is on the local, + // convert into physical path(/mnt/hmdfs//account/device_view/local/data/) and check + if (path.find(DISTRIBUTED_FILE_PREFIX) == 0) { + int userId = GetCurrentUserId(); + string bundleName = GetSelfBundleName(); + string relativePath = path.substr(DISTRIBUTED_FILE_PREFIX.length()); + string physicalPath = PHYSICAL_PATH_PREFIX + relativePath; + physicalPath.replace(physicalPath.find(USER_ID_FLAG), USER_ID_FLAG.length(), to_string(userId)); + physicalPath.replace(physicalPath.find(PACKAGE_NAME_FLAG), PACKAGE_NAME_FLAG.length(), bundleName); + + return UvAccess(physicalPath, mode); + } + + return ENOENT; +} +#endif + +static int AccessCore(const string &path, int mode, int flag = DEFAULT_FLAG) +{ +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + if (flag == LOCAL_FLAG && IsCloudOrDistributedFilePath(path)) { + return HandleLocalCheck(path, mode); + } +#endif + return UvAccess(path, mode); +} + +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 = AccessCore(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 = AccessCore(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..77b342c2fb12b5b1d5c22d7756108207cdf9b59a --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/mkdir_core.h @@ -0,0 +1,35 @@ +/* + * 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 "fs_utils.h" +#include "filemgmt_libfs.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; +const std::string PROCEDURE_READTEXT_NAME = "FileIOMkdir"; +} // 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/move_core.cpp b/interfaces/kits/js/src/mod_fs/properties/move_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a73adca1d61f5e7b16ee45c519b73fc57346ac9 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/move_core.cpp @@ -0,0 +1,188 @@ +/* + * 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 "move_core.h" + +#ifdef __MUSL__ +#include +#else +#include +#endif + +#include +#include +#include "uv.h" + +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +#ifdef __MUSL__ +static bool CheckDir(const string &path) +{ + std::error_code errCode; + if (!filesystem::is_directory(filesystem::status(path, errCode))) { + return false; + } + return true; +} +#else +static bool CheckDir(const string &path) +{ + struct stat fileInformation; + if (stat(path.c_str(), &fileInformation) == 0) { + if (fileInformation.st_mode & S_IFDIR) { + return true; + } + } else { + HILOGE("Failed to stat file"); + } + return false; +} +#endif + +static tuple ValidMoveArg(const string& src, const string& dest, optional mode) +{ + if (CheckDir(src)) { + HILOGE("Invalid src"); + return { false, nullptr, nullptr, 0 }; + } + if (CheckDir(dest)) { + HILOGE("Invalid dest"); + return { false, nullptr, nullptr, 0 }; + } + int modeType = 0; + if (mode.has_value()) { + modeType = mode.value(); + if ((modeType != MODE_FORCE_MOVE && modeType != MODE_THROW_ERR)) { + HILOGE("Invalid mode"); + return { false, nullptr, nullptr, 0 }; + } + } + return { true, move(src), move(dest), modeType }; +} + +static int CopyAndDeleteFile(const string &src, const string &dest) +{ + std::unique_ptr stat_req = { + new (std::nothrow) uv_fs_t, FsUtils::FsReqCleanup }; + if (!stat_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int ret = uv_fs_stat(nullptr, stat_req.get(), src.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to stat srcPath"); + return ret; + } +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + filesystem::path dstPath(dest); + std::error_code errCode; + if (filesystem::exists(dstPath, errCode)) { + if (!filesystem::remove(dstPath, errCode)) { + HILOGE("Failed to remove dest file, error code: %{public}d", errCode.value()); + return errCode.value(); + } + } + filesystem::path srcPath(src); + if (!filesystem::copy_file(srcPath, dstPath, filesystem::copy_options::overwrite_existing, errCode)) { + HILOGE("Failed to copy file, error code: %{public}d", errCode.value()); + return errCode.value(); + } +#else + uv_fs_t copyfile_req; + ret = uv_fs_copyfile(nullptr, ©file_req, src.c_str(), dest.c_str(), MODE_FORCE_MOVE, nullptr); + uv_fs_req_cleanup(©file_req); + if (ret < 0) { + HILOGE("Failed to move file using copyfile interface."); + return ret; + } +#endif + uv_fs_t unlink_req; + ret = uv_fs_unlink(nullptr, &unlink_req, src.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to unlink src file"); + int result = uv_fs_unlink(nullptr, &unlink_req, dest.c_str(), nullptr); + if (result < 0) { + HILOGE("Failed to unlink dest file"); + return result; + } + uv_fs_req_cleanup(&unlink_req); + return ret; + } + uv_fs_req_cleanup(&unlink_req); + return ERRNO_NOERR; +} + +static int RenameFile(const string &src, const string &dest) +{ + int ret = 0; + uv_fs_t rename_req; + ret = uv_fs_rename(nullptr, &rename_req, src.c_str(), dest.c_str(), nullptr); + if (ret < 0 && (string_view(uv_err_name(ret)) == "EXDEV")) { + return CopyAndDeleteFile(src, dest); + } + if (ret < 0) { + HILOGE("Failed to move file using rename syscall."); + return ret; + } + return ERRNO_NOERR; +} + +static int MoveFile(const string &src, const string &dest, int mode) +{ + uv_fs_t access_req; + int ret = uv_fs_access(nullptr, &access_req, src.c_str(), W_OK, nullptr); + if (ret < 0) { + HILOGE("Failed to move src file due to doesn't exist or hasn't write permission"); + uv_fs_req_cleanup(&access_req); + return ret; + } + if (mode == MODE_THROW_ERR) { + ret = uv_fs_access(nullptr, &access_req, dest.c_str(), 0, nullptr); + uv_fs_req_cleanup(&access_req); + if (ret == 0) { + HILOGE("Failed to move file due to existing destPath with MODE_THROW_ERR."); + return EEXIST; + } + if (ret < 0 && (string_view(uv_err_name(ret)) != "ENOENT")) { + HILOGE("Failed to access destPath with MODE_THROW_ERR."); + return ret; + } + } else { + uv_fs_req_cleanup(&access_req); + } + return RenameFile(src, dest); +} + +FsResult MoveCore::DoMove(const std::string& src, const std::string& dest, std::optional mode) +{ + auto [succ, srcPath, destPath, modeType] = ValidMoveArg(src, dest, mode); + if (!succ) { + return FsResult::Error(EINVAL); + } + int ret = MoveFile(move(srcPath), move(destPath), modeType); + if (ret) { + 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/move_core.h b/interfaces/kits/js/src/mod_fs/properties/move_core.h new file mode 100644 index 0000000000000000000000000000000000000000..40ad540d5f018d3ae4968aceec8b2e10c760c342 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/move_core.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_PROPERTIES_MOVE_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MOVE_CORE_H + +#include + +#include "fs_utils.h" +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class MoveCore final { +public: + static FsResult DoMove(const std::string& src, const std::string& dest, std::optional mode = std::nullopt); +}; +constexpr int MODE_FORCE_MOVE = 0; +constexpr int MODE_THROW_ERR = 1; +const std::string PROCEDURE_MOVE_NAME = "FileIOMove"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/rmdir_core.cpp b/interfaces/kits/js/src/mod_fs/properties/rmdir_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d47fcb60dc48d7953d91dba71ca852c0d9eecc5a --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/rmdir_core.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 +#include +#include +#include +#include +#include +#include + +#include "rmdir_core.h" +#include "filemgmt_libhilog.h" +#include "fs_utils.h" +#include "filemgmt_libfs.h" + + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +#ifdef __MUSL__ +static int32_t RmDirent(const string &fpath) +{ + std::filesystem::path strToPath(fpath); + std::error_code errCode; + std::uintmax_t num = std::filesystem::remove_all(strToPath, errCode); + if (errCode.value() != ERRNO_NOERR) { + HILOGD("Failed to remove directory, error code: %{public}d", errCode.value()); + return errCode.value(); + } + if (!num || std::filesystem::exists(strToPath, errCode)) { + HILOGE("Failed to remove directory, dirPath does not exist"); + return ENOENT; + } + if (errCode.value() != ERRNO_NOERR) { + HILOGE("fs exists fail, error code: %{public}d", errCode.value()); + return errCode.value(); + } + return ERRNO_NOERR; +} + +#else +static int32_t RmDirent(const string &fpath) +{ + std::unique_ptr scandir_req = { + new (std::nothrow) uv_fs_t, FsUtils::FsReqCleanup }; + if (!scandir_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int ret = 0; + ret = uv_fs_scandir(nullptr, scandir_req.get(), fpath.c_str(), 0, nullptr); + if (ret < 0) { + HILOGE("Failed to scandir, ret: %{public}d", ret); + return ret; + } + uv_dirent_t dent; + while (uv_fs_scandir_next(scandir_req.get(), &dent) != UV_EOF) { + string filePath = fpath + "/" + string(dent.name); + if (dent.type == UV_DIRENT_FILE) { + std::unique_ptr unlink_req = { + new (std::nothrow) uv_fs_t, FsUtils::FsReqCleanup }; + if (!unlink_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + ret = uv_fs_unlink(nullptr, unlink_req.get(), filePath.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to unlink file, ret: %{public}d", ret); + return ret; + } + } else if (dent.type == UV_DIRENT_DIR) { + auto rmDirentRes = RmDirent(filePath); + if (rmDirentRes) { + return rmDirentRes; + } + } + } + std::unique_ptr rmdir_req = { + new (std::nothrow) uv_fs_t, FsUtils::FsReqCleanup}; + if (!rmdir_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + ret = uv_fs_rmdir(nullptr, rmdir_req.get(), fpath.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to rmdir empty dir, ret: %{public}d", ret); + return ret; + } + return ERRNO_NOERR; +} +#endif + +FsResult RmdirentCore::DoRmdirent(const string &fpath) +{ + if (fpath.empty()) { + HILOGE("Invalid path"); + return FsResult::Error(EINVAL); + } + + auto err = RmDirent(fpath); + HILOGE("DoRmdirent over!!!!"); + return FsResult::Error(err); +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/rmdir_core.h b/interfaces/kits/js/src/mod_fs/properties/rmdir_core.h new file mode 100644 index 0000000000000000000000000000000000000000..f1cd5b07b31baa1095819d0ec8621b0a58cfe43b --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/rmdir_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_RMDIR_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_RMDIR_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_utils.h" + + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class RmdirentCore final { +public: + static FsResult DoRmdirent(const string &fpath); +}; +const std::string PROCEDURE_RMDIRENT_NAME = "FileIORmDirent"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_RMDIR_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/stat_core.cpp b/interfaces/kits/js/src/mod_fs/properties/stat_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0223604aec01c4bf9acd47ce1baf92ef19430318 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/stat_core.cpp @@ -0,0 +1,138 @@ +/* + * 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. + */ +#include "stat_core.h" + +#include +#include +#include + +#include "class_stat/fs_stat_entity.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +static bool IsPath(const FileInfo & fileInfo) +{ + auto path = fileInfo.path.get(); + if (path == nullptr || strlen(path) == 0) { + return false; + } + return true; +} + +static tuple IsFd(const FileInfo & fileInfo) +{ + auto fdg = fileInfo.fdg.get(); + if (fdg == nullptr) { + return make_tuple(false, 0); + } + return make_tuple(true, fdg->GetFD()); +} + +static tuple ValidFileInfo(const FileInfo &fileInfo) +{ + auto isPath = IsPath(fileInfo); + if (isPath) { + auto &path = const_cast&>(fileInfo.path); + return { true, FileInfo { true, move(path), {} } }; + } + auto [isFd, fd] = IsFd(fileInfo); + if (isFd) { + if (fd < 0) { + HILOGE("Invalid fd"); + return { false, FileInfo { false, {}, {} } }; + } + auto fdg = CreateUniquePtr(fd, false); + if (fdg == nullptr) { + HILOGE("Failed to request heap memory."); + return { false, FileInfo { false, {}, {} } }; + } + return { true, FileInfo { false, {}, move(fdg) } }; + } + HILOGE("Invalid parameter"); + return { false, FileInfo { false, {}, {} } }; +}; + +static int32_t CheckFsStat(const FileInfo &fileInfo, uv_fs_t* req) +{ + HILOGD("stat path, ret is %{public}s", fileInfo.path.get()); + if (fileInfo.isPath) { + int ret = uv_fs_stat(nullptr, req, fileInfo.path.get(), nullptr); + if (ret < 0) { + HILOGD("Failed to stat file with path, ret is %{public}d", ret); + return ret; + } + } else { + int ret = uv_fs_fstat(nullptr, req, fileInfo.fdg->GetFD(), nullptr); + if (ret < 0) { + HILOGE("Failed to stat file with fd, ret is %{public}d", ret); + return ret; + } + } + return ERRNO_NOERR; +} +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +static FsStat* InstantiateStat(const uv_stat_t &buf, shared_ptr fileInfo) +{ + StatEntity entity; + entity.stat_ = buf; + entity.fileInfo_ = fileInfo; + auto stat = FsStat::Constructor(move(entity)); + return stat; +} +#endif + +static FsStat* InstantiateStat(const uv_stat_t &buf) +{ + StatEntity entity; + entity.stat_ = buf; + auto stat = FsStat::Constructor(move(entity)); + return stat; +} + +FsResult StatCore::DoStat(const FileInfo& fileinfo) +{ + auto [succ, info] = ValidFileInfo(fileinfo); + if (!succ) { + return FsResult::Error(EINVAL); + } + + std::unique_ptr stat_req = { + new (std::nothrow) uv_fs_t, FsUtils::FsReqCleanup }; + if (!stat_req) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + auto err = CheckFsStat(info, stat_req.get()); + if (err) { + return FsResult::Error(err); + } + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + auto arg = CreateSharedPtr(move(info)); + if (arg == nullptr) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + auto stat = InstantiateStat(stat_req->statbuf, arg); +#else + auto stat = InstantiateStat(stat_req->statbuf); +#endif + return FsResult::Success(stat); +} + +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/stat_core.h b/interfaces/kits/js/src/mod_fs/properties/stat_core.h new file mode 100644 index 0000000000000000000000000000000000000000..1ccccb8db44fb2f8975d38ec3e4ab41a9102a95a --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/stat_core.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 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_STAT_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_STAT_CORE_H + +#include "fs_utils.h" +#include "filemgmt_libfs.h" +#include "class_stat/fs_stat.h" + +namespace OHOS::FileManagement::ModuleFileIO { +class StatCore final { +public: + static FsResult DoStat(const FileInfo& fileinfo); +}; +const std::string PROCEDURE_STAT_NAME = "FileIOStat"; +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_STAT_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..2ffbb7ca63181f6210489cf27468793554598c79 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/unlink_core.cpp @@ -0,0 +1,55 @@ +/* + * 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" + +#include +#include +#include +#include +#include +#include + +#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..746071d7695b1304e5d27cd010b10005b1a99659 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/unlink_core.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_UNLINK_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_UNLINK_CORE_H + +#include "fs_utils.h" +#include "filemgmt_libfs.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_hash/ani/arktsconfig.json b/interfaces/kits/js/src/mod_hash/ani/arktsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..ae12d05b6be6cd0eb77adb251ee4c798879bef53 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/arktsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "package": "", + "baseUrl": ".", + "outDir": "./dist", + "paths": { + "std": [ + "../../../../../../../../../arkcompiler/runtime_core/static_core/plugins/ets/stdlib/std" + ], + "escompat": [ + "../../../../../../../../../arkcompiler/runtime_core/static_core/plugins/ets/stdlib/escompat" + ] + } + }, + "include": [ + "*.ets" + ] +} 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..aa172daa3db776954c81575bda0127f4aa46e1a5 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/bind_function_class.cpp @@ -0,0 +1,47 @@ +/* + * 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_ani.h" + + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + std::cerr << "Unsupported ANI_VERSION_1" << std::endl; + return (ani_status)9; + } + + static const char *className = "Lfile_hash_class/hash;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + std::cerr << "Not found '" << className << "'" << std::endl; + return (ani_status)2; + } + std::array functions = { + ani_native_function {"hashSync", "Lstd/core/String;Lstd/core/String;:Lstd/core/String;", reinterpret_cast(HashAni::HashSync)}, + }; + + if (ANI_OK != env->Class_BindNativeMethods(cls, functions.data(), functions.size())) { + std::cerr << "Cannot bind native methods to '" << className << "'" << std::endl; + return (ani_status)3; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} + diff --git a/interfaces/kits/js/src/mod_hash/ani/file_hash_class.ets b/interfaces/kits/js/src/mod_hash/ani/file_hash_class.ets new file mode 100644 index 0000000000000000000000000000000000000000..df3cb6995f49a063913c46a86c3d0b08a155dc77 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/file_hash_class.ets @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default hash; + +loadLibrary("ani_hash_class.z") + +export class BusinessError { + code: number = 0; + data?: T; +} + +export type AsyncCallback = (err: BusinessError, data?: T) => void; + +class hash { + static native hashSync(path: string, algorithm: string): string; + + // readText promise异步 + static hash(path: string, algorithm: string): Promise { + return new Promise((resolve:(result:string)=>void, reject:(e:BusinessError)=>void) => { + let promise = taskpool.execute(hash.hashSync, path, algorithm); + promise.then((ret:NullishType) => { + if (ret === null || ret === undefined) { + let err = new BusinessError(); + err.code = -1; + reject(err); + } else { + let r = ret as string; + resolve(r); + } + }); + }); + } + + // readText callback异步 + static hash(path: string, algorithm: string, callback: AsyncCallback): void { + let p1 = taskpool.execute(hash.hashSync, path, algorithm); + p1.then((ret: NullishType) => { + let err = new BusinessError(); + if (ret === null || ret === undefined) { + err.code = -1 + callback(err, undefined) + }else { + err.code = 0 + let r = ret as string; + callback(err, r); + } + }); + } +} + +function hashTest() { + let ret = hash.hashSync("/data/local/tmp/hello.txt", "sha256") + console.println("hashSync end") + console.println(ret) + + // promise异步 + try { + hash.hash("/data/local/tmp/hello.txt", "sha256").then((result: string) => { + console.println(result) + }); + } catch (error) { + console.error("Promise: Error getting temp dir:", error); + } + console.println("readText Promise async end"); + + // callback异步 + hash.hash("/data/local/tmp/hello.txt", "sha256", (err: BusinessError, data?: string) => { + if (err.code) { + console.error("Callback: Error hash:", err); + } else { + console.log("Callback: hash:", data); + } + }); + console.println("readText callback async end"); +} + +function main(){ + console.println("hello ani") + hashTest() + console.println("end ani") +} \ No newline at end of file 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..800f1dbbd5d1515f590cb61c9dbbd8b6e635328f --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/hash_ani.cpp @@ -0,0 +1,49 @@ +#include "filemgmt_libhilog.h" +#include "hash_ani.h" +#include "hash_core.h" +#include "type_converter.h" + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI; + +ani_string HashAni::HashSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string algorithm) +{ + auto [succPath, srcPath] = TypeConverter::ToUTF8StringPath(env, path); + if (succPath) { + HILOGE("zhouxin HashSync ToUTF8StringPath: %s", srcPath.c_str()); + } else { + HILOGE("zhouxin ERROR: ToUTF8StringPath FAILED!"); + return nullptr; + } + + auto [succAlg, algType] = TypeConverter::ToUTF8StringPath(env, algorithm); + if (succAlg) { + HILOGE("zhouxin HashSync algType: %s", algType.c_str()); + } else { + HILOGE("zhouxin ERROR: ToUTF8StringPath FAILED!"); + return nullptr; + } + + // 核心逻辑 + HILOGE("zhouxinzhouxin DoHash start"); + auto ret = HashCore::DoHash(srcPath, algType); + if (ret.IsSuccess()) { + HILOGE("Success:zhouxinzhouxin DoHash"); + const auto& resHash = ret.GetData().value(); + HILOGE("zhouxinzhouxin DoHash end: %s", resHash.c_str()); + + ani_string result = nullptr; + auto status = env->String_NewUTF8(resHash.c_str(), resHash.size(), &result); + if (status == ANI_OK && result != nullptr) { + return result; + } else { + // TODO: 错误处理 + return nullptr; + } + } + + HILOGE("zhouxinzhouxin DoHash failed"); + // TODO:错误处理 + return nullptr; +} \ 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..416205b9de7315f1f84a4d0647e235804c990989 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/hash_ani.h @@ -0,0 +1,7 @@ +#include + +class HashAni final +{ + public: + static ani_string HashSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string algorithm); +}; \ 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..28040a1b9316d082c8f8a285703f15d28fa2b7c3 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/hash_core.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 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..fa95d3755f3bff8edc99d6bccfa245fac2e09eab --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/hash_core.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 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/arktsconfig.json b/interfaces/kits/js/src/mod_securitylabel/ani/arktsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..ae12d05b6be6cd0eb77adb251ee4c798879bef53 --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/ani/arktsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "package": "", + "baseUrl": ".", + "outDir": "./dist", + "paths": { + "std": [ + "../../../../../../../../../arkcompiler/runtime_core/static_core/plugins/ets/stdlib/std" + ], + "escompat": [ + "../../../../../../../../../arkcompiler/runtime_core/static_core/plugins/ets/stdlib/escompat" + ] + } + }, + "include": [ + "*.ets" + ] +} 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..38157b606bd231e920c33f618f7331916f37b025 --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/ani/bind_function_class.cpp @@ -0,0 +1,47 @@ +/* + * 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_ani.h" + + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + std::cerr << "Unsupported ANI_VERSION_1" << std::endl; + return (ani_status)9; + } + + static const char *className = "Lfile_securitylabel_class/securitylabel;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + std::cerr << "Not found '" << className << "'" << std::endl; + return (ani_status)2; + } + std::array functions = { + ani_native_function {"setSecurityLabelSync", "Lstd/core/String;Lstd/core/String;:I", reinterpret_cast(SecurityLabelAni::SetSecurityLabelSync)}, + }; + + if (ANI_OK != env->Class_BindNativeMethods(cls, functions.data(), functions.size())) { + std::cerr << "Cannot bind native methods to '" << className << "'" << std::endl; + return (ani_status)3; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} + diff --git a/interfaces/kits/js/src/mod_securitylabel/ani/file_securitylabel_class.ets b/interfaces/kits/js/src/mod_securitylabel/ani/file_securitylabel_class.ets new file mode 100644 index 0000000000000000000000000000000000000000..0fe339116cca8a44218191c0a14a83ef5e604494 --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/ani/file_securitylabel_class.ets @@ -0,0 +1,97 @@ +/* + * 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. + */ + +export default securitylabel; + +loadLibrary("ani_securitylabel_class.z") + +export class BusinessError { + code: number = 0; + data?: T; +} + +export type AsyncCallback = (err: BusinessError, data?: T) => void; + +type DataLevel = 's0' | 's1' | 's2' | 's3' | 's4'; + +class securitylabel { + static native setSecurityLabelSync(path: string, type: DataLevel): int; + + // setSecurityLabel promise异步 + static setSecurityLabel(path: string, type: DataLevel): Promise { + return new Promise((resolve:(result:int)=>void, reject:(e:BusinessError)=>void) => { + let promise = taskpool.execute(securitylabel.setSecurityLabelSync, path, type); // 这里调用同步方法 + promise.then((ret:NullishType) => { + if (ret === null || ret === undefined) { // 异常处理 + let err = new BusinessError(); + err.code = -1; + reject(err); + } else { + let r = ret as int; + resolve(r); // 正常结果 + } + }); + }); + } + + // setSecurityLabel callback异步 + static setSecurityLabel(path: string, type: DataLevel, callback: AsyncCallback): void { + let p1 = taskpool.execute(securitylabel.setSecurityLabelSync, path, type); + p1.then((ret: NullishType) => { + let err = new BusinessError(); + if (ret === null || ret === undefined) { + err.code = -1 + callback(err, undefined) + }else { + err.code = 0 + let r = ret as int; + callback(err, r); + } + }); + } +} + +function setSecuritylabelTest() { + let dataType: DataLevel = "s2" + securitylabel.setSecurityLabelSync("/data/local/tmp/hello.txt", dataType) + + // promise异步 + dataType = "s3" + try { + securitylabel.setSecurityLabel("/data/local/tmp/hello.txt", dataType).then((result: int) => { + console.println(result) + }); + } catch (error) { + console.error("Promise: Error listFile:", error); + } + console.println("listFile Promise async end"); + + // callback异步 + dataType = "s4" + securitylabel.setSecurityLabel("/data/local/tmp/hello.txt", dataType, (err: BusinessError, data?: int) => { + if (err.code) { + console.error("Callback: Error listFile:", err); + } else { + console.log("Callback: listFile:", data); + } + }); + console.println("readText callback async end"); +} + +function main(){ + console.println("hello ani") + setSecuritylabelTest() + console.println("end ani") +} \ No newline at end of file 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..a5ee4a4536001e2b040095e9c36786bdb875a8af --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/ani/securitylabel_ani.cpp @@ -0,0 +1,37 @@ +#include "filemgmt_libhilog.h" +#include "securitylabel_ani.h" +#include "securitylabel_core.h" +#include "type_converter.h" + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI; +using namespace OHOS::FileManagement::ModuleSecurityLabel; + +ani_int SecurityLabelAni::SetSecurityLabelSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string level) +{ + auto [succPath, srcPath] = TypeConverter::ToUTF8StringPath(env, path); + if (succPath) { + HILOGE("zhouxin DoSetSecurityLabel ToUTF8StringPath: %s", srcPath.c_str()); + } else { + HILOGE("zhouxin ERROR: ToUTF8StringPath FAILED!"); + // TODO:错误处理 + return EINVAL; + } + + auto [succLevel, dataLevel] = TypeConverter::ToUTF8StringPath(env, level); + if (succLevel) { + HILOGE("zhouxin DoSetSecurityLabel dataLevel: %s", dataLevel.c_str()); + } else { + HILOGE("zhouxin ERROR: ToUTF8StringPath FAILED!"); + // TODO:错误处理 + return EINVAL; + } + + // 核心逻辑 + HILOGE("zhouxinzhouxin DoSetSecurityLabel start"); + DoSetSecurityLabel(srcPath, dataLevel); + HILOGE("zhouxinzhouxin DoSetSecurityLabel failed"); + // TODO:错误处理 + return 0; +} \ 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..40bafa717c5fd3e15a0546ec63d07555eb3ba588 --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/ani/securitylabel_ani.h @@ -0,0 +1,7 @@ +#include + +class SecurityLabelAni final +{ + public: + static ani_int SetSecurityLabelSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string level); +}; \ 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..3ff39ed819047d60cf3255004729b676f75161f0 --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/securitylabel_core.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-2022 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(); +} + +} // 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..782aca41d6c4298d9dab1c8ec4166e7c12ecadcb --- /dev/null +++ b/interfaces/kits/js/src/mod_securitylabel/securitylabel_core.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021-2022 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); + +} // namespace ModuleSecurityLabel +} // namespace FileManagement +} // namespace OHOS +#endif // SECURITYLABEL_CORE_H \ 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..6570eeb51b964a5fdba85797249904ab4b34cd66 --- /dev/null +++ b/utils/filemgmt_libfs/BUILD.gn @@ -0,0 +1,76 @@ +# Copyright (c) 2022 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..7e61561cc2e63ef4399683740ccf651b5a68ee50 --- /dev/null +++ b/utils/filemgmt_libfs/include/filemgmt_libfs.h @@ -0,0 +1,22 @@ +/* + * 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_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_error.h b/utils/filemgmt_libfs/include/fs_error.h new file mode 100644 index 0000000000000000000000000000000000000000..b35167333286c74de1f0f869b9a4de61486d1129 --- /dev/null +++ b/utils/filemgmt_libfs/include/fs_error.h @@ -0,0 +1,432 @@ +/* + * 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 +#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..71768d5c1da5cff2baa6b051e058a43267f1b809 --- /dev/null +++ b/utils/filemgmt_libfs/include/fs_result.h @@ -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. + */ + +#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_; + } + + // Disable the copy constructor and assignment operator. + 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_; + } + + // Disable the copy constructor and assignment operator. + 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..b3e05b470f65fda07600016d123e10aa802a2c11 --- /dev/null +++ b/utils/filemgmt_libfs/src/fs_error.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 +#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