diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index 645ed82ba8c0cfc0b754d203b046822f3e5d6cd8..a5286db0ad3525b80beb0c7cf37ee280d62edd60 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -666,6 +666,7 @@ ohos_shared_library("ani_file_fs") { include_dirs = [ "include/ipc", "src/mod_fs/ani", + "src/mod_fs/ani/cleaner", "src/mod_fs/class_atomicfile", "src/mod_fs/class_atomicfile/ani", "src/mod_fs/class_file", @@ -682,6 +683,7 @@ ohos_shared_library("ani_file_fs") { "src/mod_fs/class_tasksignal/ani", "src/mod_fs/class_watcher", "src/mod_fs/class_watcher/ani", + "src/mod_fs/common/obj", "src/mod_fs/properties", "src/mod_fs/properties/ani", "src/mod_fs/properties/copy_listener", @@ -693,6 +695,7 @@ ohos_shared_library("ani_file_fs") { "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/ani/cleaner/cleaner_ani.cpp", "src/mod_fs/class_atomicfile/ani/atomicfile_ani.cpp", "src/mod_fs/class_atomicfile/fs_atomicfile.cpp", "src/mod_fs/class_file/ani/file_ani.cpp", @@ -861,6 +864,7 @@ ohos_shared_library("ani_file_hash") { include_dirs = [ "src/mod_hash", "src/mod_hash/ani", + "src/mod_hash/ani/cleaner", "src/mod_hash/class_hashstream", "src/mod_hash/class_hashstream/ani", ] @@ -872,6 +876,7 @@ ohos_shared_library("ani_file_hash") { "src/common/file_helper/hash_file.cpp", "src/mod_fs/fs_utils.cpp", "src/mod_hash/ani/bind_function_class.cpp", + "src/mod_hash/ani/cleaner/cleaner_ani.cpp", "src/mod_hash/ani/hash_ani.cpp", "src/mod_hash/class_hashstream/ani/hashstream_ani.cpp", "src/mod_hash/class_hashstream/hs_hashstream.cpp", diff --git a/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp b/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp index 1f65c2d5a091308959b163073027a8a3715023f7..5990f58f16634a78182eeef4fde2c6d058eed377 100644 --- a/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp +++ b/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp @@ -99,7 +99,8 @@ const string FS::ReaderIteratorInner::ctorSig = Builder::BuildSignatureDescripto const Type FS::ReaderIteratorResultInner::classType = Builder::BuildClass("@ohos.file.fs.fileIo.ReaderIteratorResultInner"); const string FS::ReaderIteratorResultInner::classDesc = FS::ReaderIteratorResultInner::classType.Descriptor(); -const string FS::ReaderIteratorResultInner::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); +const string FS::ReaderIteratorResultInner::ctorSig = + Builder::BuildSignatureDescriptor({ BasicTypes::booleanType, BuiltInTypes::stringType }); // FS::StatInner const Type FS::StatInner::classType = Builder::BuildClass("@ohos.file.fs.fileIo.StatInner"); const string FS::StatInner::classDesc = FS::StatInner::classType.Descriptor(); @@ -137,6 +138,8 @@ const string FS::WriteStream::ctorSig = const Type FS::AtomicFile::classType = Builder::BuildClass("@ohos.file.fs.fileIo.AtomicFile"); const string FS::AtomicFile::classDesc = FS::AtomicFile::classType.Descriptor(); const string FS::AtomicFile::ctorSig = Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType }); +const string FS::AtomicFile::bindNativePtr = "bindNativePtr"; +const string FS::AtomicFile::bindNativePtrSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); // FS::ReadStreamOptionsInner const Type FS::ReadStreamOptionsInner::classType = Builder::BuildClass("@ohos.file.fs.ReadStreamOptionsInner"); const string FS::ReadStreamOptionsInner::classDesc = FS::ReadStreamOptionsInner::classType.Descriptor(); @@ -165,5 +168,12 @@ const string Impl::StatvfsImpl::classDesc = Impl::StatvfsImpl::classType.Descrip const Type HASH::HashStreamImpl::classType = Builder::BuildClass("@ohos.file.hash.HashStreamImpl"); const string HASH::HashStreamImpl::classDesc = HASH::HashStreamImpl::classType.Descriptor(); const string HASH::HashStreamImpl::ctorSig = Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType }); +const string HASH::HashStreamImpl::bindNativePtrSig = Builder::BuildSignatureDescriptor({ BasicTypes::longType }); +// FS::CleanerImpl +const Type FS::CleanerImpl::classType = Builder::BuildClass("@ohos.file.fs.Cleaner"); +const string FS::CleanerImpl::classDesc = FS::CleanerImpl::classType.Descriptor(); +// HASH::CleanerImpl +const Type HASH::CleanerImpl::classType = Builder::BuildClass("@ohos.file.hash.Cleaner"); +const string HASH::CleanerImpl::classDesc = HASH::CleanerImpl::classType.Descriptor(); } // namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/ani_signature.h b/interfaces/kits/js/src/common/ani_helper/ani_signature.h index 71ed2a8f4ccd1514a09c421b7658dac24d74e59c..a40f932d469a9db35f26eaadd05f8ff37542e2c7 100644 --- a/interfaces/kits/js/src/common/ani_helper/ani_signature.h +++ b/interfaces/kits/js/src/common/ani_helper/ani_signature.h @@ -207,6 +207,8 @@ struct AtomicFile : public BaseType { static const Type classType; static const string classDesc; static const string ctorSig; + static const string bindNativePtr; + static const string bindNativePtrSig; }; struct ReadStreamOptionsInner : public BaseType { @@ -219,6 +221,11 @@ struct WriteStreamOptionsInner : public BaseType { static const string classDesc; }; +struct CleanerImpl : public BaseType { + static const Type classType; + static const string classDesc; +}; + } // namespace FS namespace Impl { @@ -256,6 +263,12 @@ struct HashStreamImpl : public BaseType { static const Type classType; static const string classDesc; static const string ctorSig; + static const string bindNativePtrSig; +}; + +struct CleanerImpl : public BaseType { + static const Type classType; + static const string classDesc; }; } // namespace HASH 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 index d6221d30ca707bc3e12b260f1869f6441fadfa15..687f2c6af4867ed46f08c4ca3d1f9199aa3cf210 100644 --- a/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp +++ b/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp @@ -21,6 +21,7 @@ #include "ani_signature.h" #include "atomicfile_ani.h" #include "bind_function.h" +#include "cleaner_ani.h" #include "close_ani.h" #include "connectdfs_ani.h" #include "copy_ani.h" @@ -34,8 +35,8 @@ #include "fdopen_stream_ani.h" #include "file_ani.h" #include "filemgmt_libhilog.h" -#include "fsync_ani.h" #include "fs_watcher_ani.h" +#include "fsync_ani.h" #include "listfile_ani.h" #include "lseek_ani.h" #include "lstat_ani.h" @@ -239,6 +240,17 @@ static ani_status BindStaticMethods(ani_env *env) return BindClass(env, classDesc, methods); } +static ani_status BindCleanerMethods(ani_env *env) +{ + auto classDesc = FS::CleanerImpl::classDesc.c_str(); + + std::array methods = { + ani_native_function { "clean", nullptr, reinterpret_cast(CleanerAni::Clean) }, + }; + + return BindClass(env, classDesc, methods); +} + static ani_status DoBindMethods(ani_env *env) { ani_status status; @@ -287,6 +299,11 @@ static ani_status DoBindMethods(ani_env *env) return status; }; + if ((status = BindCleanerMethods(env)) != ANI_OK) { + HILOGE("Cannot bind native methods for Cleaner Class!"); + return status; + }; + return ANI_OK; } diff --git a/interfaces/kits/js/src/mod_fs/ani/cleaner/cleaner_ani.cpp b/interfaces/kits/js/src/mod_fs/ani/cleaner/cleaner_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbf9b42310b8299769a8458a2253b3dc32975849 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/ani/cleaner/cleaner_ani.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cleaner_ani.h" + +#include "filemgmt_libhilog.h" +#include "fs_atomicfile.h" +#include "fs_file.h" +#include "fs_randomaccessfile.h" +#include "fs_reader_iterator.h" +#include "fs_stat.h" +#include "fs_stream.h" +#include "fs_watcher.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI; + +static void DoCleanByClassType(ani_env *env, ani_long ptr, ani_ref classTypeObj) +{ + auto [succ, classType] = TypeConverter::ToUTF8String(env, static_cast(classTypeObj)); + if (!succ) { + HILOGE("Clean ParseString failed."); + return; + } + if (classType == "File") { + delete reinterpret_cast(ptr); + } else if (classType == "RandomAccessFile") { + delete reinterpret_cast(ptr); + } else if (classType == "ReaderIterator") { + delete reinterpret_cast(ptr); + } else if (classType == "Stat") { + delete reinterpret_cast(ptr); + } else if (classType == "Stream") { + delete reinterpret_cast(ptr); + } else if (classType == "AtomicFile") { + delete reinterpret_cast(ptr); + } else { + HILOGE("Clean unsupport className: %{public}s", classType.c_str()); + } + return; +} + +void CleanerAni::Clean(ani_env *env, ani_object object) +{ + if (env == nullptr) { + HILOGE("env is nullptr"); + return; + } + ani_long ptr; + ani_status status = env->Object_GetFieldByName_Long(object, "ptr", &ptr); + if (status != ANI_OK) { + HILOGE("Clean Object_GetFieldByName_Long status: %{public}d", status); + return; + } + + ani_ref classTypeObj = nullptr; + if ((status = env->Object_GetFieldByName_Ref(object, "classType", &classTypeObj)) != ANI_OK) { + HILOGE("Clean Object_GetFieldByName_Ref status: %{public}d", status); + return; + } + + DoCleanByClassType(env, ptr, classTypeObj); +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/ani/cleaner/cleaner_ani.h b/interfaces/kits/js/src/mod_fs/ani/cleaner/cleaner_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..9217ad0928a4b4fc76ddcdd38713eb3fe1b090e3 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/ani/cleaner/cleaner_ani.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_ANI_CLEANER_CLEANER_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_ANI_CLEANER_CLEANER_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class CleanerAni final { +public: + static void Clean(ani_env *env, ani_object object); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_ANI_CLEANER_CLEANER_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets index 85d4d98918332f83cb598ceeddf7826de66e855b..4b01ef4305bb790b6131b6dfc9300fcb8833c68f 100644 --- a/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets +++ b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets @@ -25,6 +25,22 @@ function createBusinessError(code: int, msg: string): BusinessError { return err; } +class Cleaner { + private ptr: long = 0 + private classType: string = ""; + constructor(ptr: long, classType: string) { + this.ptr = ptr + this.classType = classType + } + native clean(): void +} + +function CleanerCallback(cleaner: Cleaner): void { + cleaner.clean() +} + +let destroyRegister = new FinalizationRegistry(CleanerCallback) + namespace fileIo { export namespace OpenMode { export const READ_ONLY = 0o0; @@ -1253,6 +1269,9 @@ export class ProgressInner implements Progress { export type ProgressListener = (progress: Progress) => void; export class TaskSignal { + static { + loadLibrary("ani_file_fs"); + } private nativeTaskSignal: long = 0; native constructor(); private native onCancelNative(): void; @@ -1320,11 +1339,21 @@ export class RandomAccessFileInner implements RandomAccessFile { filePointer: long = -1; private nativePtr: long = 0; + private cleaner: Cleaner | null = null; constructor(ptr: long) { if (this.nativePtr === 0) { this.nativePtr = ptr; } + this.registerCleaner(this.nativePtr) + } + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr, "RandomAccessFile"); + destroyRegister.register(this, this.cleaner!, this); + } + unregisterCleaner(): void { + destroyRegister.unregister(this); } setFilePointer(filePointer: long): void { @@ -1459,11 +1488,20 @@ export class FileInner implements File { name: String = ""; private nativePtr: long = 0; + private cleaner: Cleaner | null = null; constructor(ptr: long) { if (this.nativePtr === 0) { this.nativePtr = ptr; } + this.registerCleaner(this.nativePtr) + } + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr, "File"); + destroyRegister.register(this, this.cleaner!, this); + } + unregisterCleaner(): void { + destroyRegister.unregister(this); } native getParent(): String; @@ -1520,16 +1558,13 @@ export enum LocationType { export class ReaderIteratorResultInner implements ReaderIteratorResult { - private nativePtr: long = 0; - - constructor(ptr: long) { - if (this.nativePtr === 0) { - this.nativePtr = ptr; - } - } - done: boolean = false; value: string = ""; + + constructor(done: boolean, value: string) { + this.done = done; + this.value = value; + } } export interface ReaderIterator { @@ -1538,11 +1573,20 @@ export interface ReaderIterator { export class ReaderIteratorInner implements ReaderIterator { private nativePtr: long = 0; + private cleaner: Cleaner | null = null; constructor(ptr: long) { if (this.nativePtr === 0) { this.nativePtr = ptr; } + this.registerCleaner(this.nativePtr) + } + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr, "ReaderIterator"); + destroyRegister.register(this, this.cleaner!, this); + } + unregisterCleaner(): void { + destroyRegister.unregister(this); } native next(): ReaderIteratorResult; @@ -1586,11 +1630,20 @@ export class StatInner implements Stat { location: LocationType = LocationType.LOCAL; private nativeStat: long = 0; + private cleaner: Cleaner | null = null; constructor(stat: long) { if (this.nativeStat === 0) { this.nativeStat = stat; } + this.registerCleaner(this.nativeStat) + } + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr, "Stat"); + destroyRegister.register(this, this.cleaner!, this); + } + unregisterCleaner(): void { + destroyRegister.unregister(this); } native isBlockDevice(): boolean; @@ -1622,11 +1675,20 @@ export interface Stream { export class StreamInner implements Stream { private nativePtr: long = 0; + private cleaner: Cleaner | null = null; constructor(ptr: long) { if (this.nativePtr === 0) { this.nativePtr = ptr; } + this.registerCleaner(this.nativePtr) + } + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr, "Stream"); + destroyRegister.register(this, this.cleaner!, this); + } + unregisterCleaner(): void { + destroyRegister.unregister(this); } close(): Promise { @@ -1927,9 +1989,25 @@ export class AtomicFile { } private nativePtr: long = 0; + private cleaner: Cleaner | null = null; private native getPath(): string; private writeStream: WriteStream | null = null; + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr, "AtomicFile"); + destroyRegister.register(this, this.cleaner!, this); + } + unregisterCleaner(): void { + destroyRegister.unregister(this); + } + bindNativePtr(ptr: long): void { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + this.registerCleaner(this.nativePtr) + + } + native constructor(path: string); native getBaseFile(): File; diff --git a/interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.cpp b/interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.cpp index 8756289dad0201211775b0198be5065e5a297853..1d18c6e05f18f8e8244b164d3a6295b831175a08 100644 --- a/interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.cpp +++ b/interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.cpp @@ -37,6 +37,18 @@ const std::string READ_STREAM_CLASS = "ReadStream"; const std::string WRITE_STREAM_CLASS = "WriteStream"; const std::string TEMP_FILE_SUFFIX = "_XXXXXX"; +void CallBindNativePtr(ani_env *env, ani_object obj, FsAtomicFile *fsAtomicFile) +{ + auto bindNativePtrSig = FS::AtomicFile::bindNativePtrSig.c_str(); + auto ptr = FS::AtomicFile::bindNativePtr.c_str(); + ani_long longValue = reinterpret_cast(fsAtomicFile); + ani_status ret = env->Object_CallMethodByName_Void(obj, ptr, bindNativePtrSig, longValue); + if (ret != ANI_OK) { + HILOGE("Object_CallMethodByName_Void failed. ret = %{public}d", static_cast(ret)); + return; + } +} + void AtomicFileAni::Constructor(ani_env *env, ani_object obj, ani_string pathObj) { auto [succ, filePath] = TypeConverter::ToUTF8String(env, pathObj); @@ -59,6 +71,7 @@ void AtomicFileAni::Constructor(ani_env *env, ani_object obj, ani_string pathObj ErrorHandler::Throw(env, EIO); return; } + CallBindNativePtr(env, obj, ret.GetData().value()); } static FsAtomicFile *Unwrap(ani_env *env, ani_object object) diff --git a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.h b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.h index bbbd518021120254e23150660b8e0c20294e516a..72b87cbcee9d45107b820dba9c52160fd74a2ae3 100644 --- a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.h +++ b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.h @@ -18,23 +18,14 @@ #include "filemgmt_libfs.h" #include "randomaccessfile_entity.h" +#include "write_options.h" +#include "read_options.h" namespace OHOS { namespace FileManagement { namespace ModuleFileIO { using namespace std; -struct WriteOptions { - optional length = nullopt; - optional offset = nullopt; - optional encoding = nullopt; -}; - -struct ReadOptions { - optional offset = nullopt; - optional length = nullopt; -}; - class FsRandomAccessFile { public: inline static const string className_ = "RandomAccessFile"; diff --git a/interfaces/kits/js/src/mod_fs/class_stream/fs_stream.h b/interfaces/kits/js/src/mod_fs/class_stream/fs_stream.h index a6b9661e006e246e3396e9698695b2f74c8733c9..66cf6b9c6f68b0a0626480ba230a334c287cef9f 100644 --- a/interfaces/kits/js/src/mod_fs/class_stream/fs_stream.h +++ b/interfaces/kits/js/src/mod_fs/class_stream/fs_stream.h @@ -24,23 +24,14 @@ #include "filemgmt_libfs.h" #include "fs_utils.h" +#include "read_options.h" +#include "write_options.h" namespace OHOS { namespace FileManagement { namespace ModuleFileIO { using namespace std; -struct WriteOptions { - optional length = nullopt; - optional offset = nullopt; - optional encoding = nullopt; -}; - -struct ReadOptions { - optional length = nullopt; - optional offset = nullopt; -}; - class FsStream final { public: StreamEntity *GetStreamEntity() const diff --git a/interfaces/kits/js/src/mod_fs/common/obj/read_options.h b/interfaces/kits/js/src/mod_fs/common/obj/read_options.h new file mode 100644 index 0000000000000000000000000000000000000000..0303bc98ae210e76c27a5ba06374e861ee4c0c6c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/common/obj/read_options.h @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_COMMON_OBJ_READ_OPTIONS_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_COMMON_OBJ_READ_OPTIONS_H + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +struct ReadOptions { + optional offset = nullopt; + optional length = nullopt; +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_COMMON_OBJ_READ_OPTIONS_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/common/obj/write_options.h b/interfaces/kits/js/src/mod_fs/common/obj/write_options.h new file mode 100644 index 0000000000000000000000000000000000000000..64964ba4ba6ef6580072a5026036fa488e385bb1 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/common/obj/write_options.h @@ -0,0 +1,33 @@ +/* +* 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_COMMON_OBJ_WRITE_OPTIONS_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_COMMON_OBJ_WRITE_OPTIONS_H + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +struct WriteOptions { + optional length = nullopt; + optional offset = nullopt; + optional encoding = nullopt; +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_COMMON_OBJ_WRITE_OPTIONS_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/read_core.h b/interfaces/kits/js/src/mod_fs/properties/read_core.h index 5c99656734e0eb1da8a184e8ee43df0eba6fb987..69750786c39a66ff1af8036ea6ebb91a203adcf0 100644 --- a/interfaces/kits/js/src/mod_fs/properties/read_core.h +++ b/interfaces/kits/js/src/mod_fs/properties/read_core.h @@ -19,15 +19,11 @@ #include #include "filemgmt_libfs.h" #include "fs_utils.h" +#include "read_options.h" namespace OHOS::FileManagement::ModuleFileIO { using namespace std; -struct ReadOptions final { - optional offset = nullopt; - optional length = nullopt; -}; - class ReadCore final { public: static FsResult DoRead( diff --git a/interfaces/kits/js/src/mod_fs/properties/write_core.h b/interfaces/kits/js/src/mod_fs/properties/write_core.h index f50ae27c856a36f9fa6e15a2884eb4e9d746bf81..119c354bf819608f4103e4d667b76a99ae2f8e45 100644 --- a/interfaces/kits/js/src/mod_fs/properties/write_core.h +++ b/interfaces/kits/js/src/mod_fs/properties/write_core.h @@ -19,18 +19,13 @@ #include "filemgmt_libfs.h" #include "filemgmt_libhilog.h" #include "fs_utils.h" +#include "write_options.h" namespace OHOS { namespace FileManagement { namespace ModuleFileIO { using namespace std; -struct WriteOptions { - optional length = nullopt; - optional offset = nullopt; - optional encoding = nullopt; -}; - class WriteCore final { public: static FsResult DoWrite( 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 index 9f8f7b08f551f2fea4dadf773329500dede24795..e87151d19093a5a40eaba1838a7bf52678e5a915 100644 --- a/interfaces/kits/js/src/mod_hash/ani/bind_function_class.cpp +++ b/interfaces/kits/js/src/mod_hash/ani/bind_function_class.cpp @@ -16,6 +16,7 @@ #include #include "ani_signature.h" #include "bind_function.h" +#include "cleaner_ani.h" #include "hash_ani.h" #include "hashstream_ani.h" @@ -44,6 +45,17 @@ static ani_status BindHashStreamMethods(ani_env *env) return BindClass(env, classDesc, methods); } +static ani_status BindCleanerMethods(ani_env *env) +{ + auto classDesc = HASH::CleanerImpl::classDesc.c_str(); + + std::array methods = { + ani_native_function { "clean", nullptr, reinterpret_cast(CleanerAni::Clean) }, + }; + + return BindClass(env, classDesc, methods); +} + ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { if (vm == nullptr) { @@ -75,6 +87,12 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) return status; }; + status = BindCleanerMethods(env); + if (status != ANI_OK) { + HILOGE("Cannot bind native static methods for cleaner!"); + return status; + }; + *result = ANI_VERSION_1; return ANI_OK; } diff --git a/interfaces/kits/js/src/mod_hash/ani/cleaner/cleaner_ani.cpp b/interfaces/kits/js/src/mod_hash/ani/cleaner/cleaner_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56fef88ac11fc982e22db55c7f6e6ced4e469573 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/cleaner/cleaner_ani.cpp @@ -0,0 +1,69 @@ +/* + * 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 "cleaner_ani.h" + +#include "filemgmt_libhilog.h" +#include "hs_hashstream.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI; + +static void DoCleanByClassType(ani_env *env, ani_long ptr, ani_ref classTypeObj) +{ + auto [succ, classType] = TypeConverter::ToUTF8String(env, static_cast(classTypeObj)); + if (!succ) { + HILOGE("Clean ParseString failed."); + return; + } + if (classType == "HashStream") { + delete reinterpret_cast(ptr); + } else { + HILOGE("Clean unsupport className: %{public}s", classType.c_str()); + } + return; +} +void CleanerAni::Clean(ani_env *env, ani_object object) +{ + if (env == nullptr) { + HILOGE("env is nullptr"); + return; + } + ani_long ptr; + ani_status status = env->Object_GetFieldByName_Long(object, "ptr", &ptr); + if (status != ANI_OK) { + HILOGE("Clean Object_GetFieldByName_Long status: %{public}d", status); + return; + } + + ani_ref classTypeObj = nullptr; + if ((status = env->Object_GetFieldByName_Ref(object, "classType", &classTypeObj)) != ANI_OK) { + HILOGE("Clean Object_GetFieldByName_Ref status: %{public}d", status); + return; + } + + DoCleanByClassType(env, ptr, classTypeObj); +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/ani/cleaner/cleaner_ani.h b/interfaces/kits/js/src/mod_hash/ani/cleaner/cleaner_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..a8ca237a231aef7bdb7f5a38603d1dadf2f40bdd --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/ani/cleaner/cleaner_ani.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_HASH_ANI_CLEANER_CLEANER_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_HASH_ANI_CLEANER_CLEANER_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class CleanerAni final { +public: + static void Clean(ani_env *env, ani_object object); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_HASH_ANI_CLEANER_CLEANER_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets b/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets index ce70303878b1d9179d3349558c56d4fe662912e1..8dbf484cb9360d77523b4a670cae2266cfbfcb60 100644 --- a/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets +++ b/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets @@ -16,6 +16,22 @@ import { BusinessError, AsyncCallback } from '@ohos.base'; import stream from '@ohos.util.stream'; +class Cleaner { + private ptr: long = 0 + private classType: string = ""; + constructor(ptr: long, classType: string) { + this.ptr = ptr + this.classType = classType + } + native clean(): void +} + +function CleanerCallback(cleaner: Cleaner): void { + cleaner.clean() +} + +let destroyRegister = new FinalizationRegistry(CleanerCallback) + export default namespace hash { export function hash(path: string, algorithm: string): Promise { return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void) => { @@ -89,6 +105,22 @@ export class HashStreamImpl extends stream.Transform { loadLibrary("ani_file_hash"); } private nativePtr: long = 0; + private cleaner: Cleaner | null = null; + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr, "HashStream"); + destroyRegister.register(this, this.cleaner!, this); + } + unregisterCleaner(): void { + destroyRegister.unregister(this); + } + bindNativePtr(ptr: long): void { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + this.registerCleaner(this.nativePtr) + + } native constructor(alg: string); native digest(): string; diff --git a/interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.cpp b/interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.cpp index 440f5c6a5c94a7243c613652a6b9f91f6db43ea1..484eb1232d585a2db4ffb000fce05930769004b1 100644 --- a/interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.cpp +++ b/interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.cpp @@ -93,6 +93,17 @@ ani_string HashStreamAni::Digest(ani_env *env, [[maybe_unused]] ani_object objec return result; } +void CallBindNativePtr(ani_env *env, ani_object obj, HsHashStream *hsHashStream) +{ + auto bindNativePtrSig = HASH::HashStreamImpl::bindNativePtrSig.c_str(); + ani_long longValue = reinterpret_cast(hsHashStream); + ani_status ret = env->Object_CallMethodByName_Void(obj, "bindNativePtr", bindNativePtrSig, longValue); + if (ret != ANI_OK) { + HILOGE("Object_CallMethodByName_Void failed. ret = %{public}d", static_cast(ret)); + return; + } +} + void HashStreamAni::Constructor(ani_env *env, ani_object obj, ani_string alg) { auto [succ, algorithm] = TypeConverter::ToUTF8String(env, alg); @@ -115,6 +126,8 @@ void HashStreamAni::Constructor(ani_env *env, ani_object obj, ani_string alg) ErrorHandler::Throw(env, EIO); return; } + + CallBindNativePtr(env, obj, ret.GetData().value()); } } // namespace ANI diff --git a/interfaces/test/unittest/js/BUILD.gn b/interfaces/test/unittest/js/BUILD.gn index ca5d5eabe09fe0d1a8959950a88430cb4fc761f0..9b7da2ad98b7a05927de9a73025459fee0132a3a 100644 --- a/interfaces/test/unittest/js/BUILD.gn +++ b/interfaces/test/unittest/js/BUILD.gn @@ -135,6 +135,7 @@ ohos_unittest("ani_file_fs_mock_test") { "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stream", "${file_api_path}/interfaces/kits/js/src/mod_fs/class_tasksignal", "${file_api_path}/interfaces/kits/js/src/mod_fs/class_watcher", + "${file_api_path}/interfaces/kits/js/src/mod_fs/common/obj", "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", "${file_api_path}/interfaces/kits/js/src/mod_fs/properties/copy_listener", "${file_api_path}/interfaces/test/unittest/js/mod_fs/class_stream/mock", @@ -229,7 +230,6 @@ ohos_unittest("ani_file_fs_test") { "${file_api_path}/interfaces/kits/js/src/common", "${file_api_path}/interfaces/kits/js/src/common/file_helper", "${file_api_path}/interfaces/kits/js/src/mod_fs", - "${file_api_path}/interfaces/kits/js/src/mod_fs/class_watcher", "${file_api_path}/interfaces/kits/js/src/mod_fs/class_atomicfile", "${file_api_path}/interfaces/kits/js/src/mod_fs/class_file", "${file_api_path}/interfaces/kits/js/src/mod_fs/class_randomaccessfile", @@ -237,6 +237,8 @@ ohos_unittest("ani_file_fs_test") { "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stat", "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stream", "${file_api_path}/interfaces/kits/js/src/mod_fs/class_tasksignal", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_watcher", + "${file_api_path}/interfaces/kits/js/src/mod_fs/common/obj", "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", "${file_api_path}/interfaces/kits/js/src/mod_fs/properties/copy_listener", ]