From 0c7b97f49e452b54a38b1e09c1ef5d5eafaf034d Mon Sep 17 00:00:00 2001 From: zhongning5 Date: Fri, 13 Dec 2024 13:39:38 +0800 Subject: [PATCH] =?UTF-8?q?atomicfile=20=E6=8E=A5=E5=8F=A3=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhongning5 --- interfaces/kits/js/BUILD.gn | 1 + .../class_atomicfile/atomicfile_entity.h | 30 + .../atomicfile_n_exporter.cpp | 556 ++++++++++++++++++ .../class_atomicfile/atomicfile_n_exporter.h | 47 ++ interfaces/kits/js/src/mod_fs/module.cpp | 4 +- interfaces/kits/ts/streamrw/src/streamrw.ts | 4 + 6 files changed, 641 insertions(+), 1 deletion(-) create mode 100644 interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_entity.h create mode 100644 interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.h diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index 488ae6a96..e38d7c2e2 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -215,6 +215,7 @@ ohos_shared_library("fs") { "${filemanagement_service_path}/distributedfiledaemon/include/ipc", ] sources += [ + "src/mod_fs/class_atomicfile/atomicfile_n_exporter.cpp", "src/mod_fs/class_randomaccessfile/randomaccessfile_n_exporter.cpp", "src/mod_fs/class_readeriterator/readeriterator_n_exporter.cpp", "src/mod_fs/class_stream/stream_n_exporter.cpp", diff --git a/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_entity.h b/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_entity.h new file mode 100644 index 000000000..14dccc140 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_entity.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 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. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_ATOMIC_FILE_ENTITY_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_ATOMIC_FILE_ENTITY_H + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +struct AtomicFileEntity { + std::string baseFileName = ""; + std::string newFileName = ""; + napi_ref writeStreamObj = nullptr; +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FILEIO_CLASS_ATOMIC_FILE_ENTITY_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.cpp b/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.cpp new file mode 100644 index 000000000..a0405e026 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.cpp @@ -0,0 +1,556 @@ +/* + * Copyright (c) 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 "atomicfile_n_exporter.h" + +#include +#include +#include +#include +#include +#include + +#include "atomicfile_entity.h" +#include "class_file/file_entity.h" +#include "class_file/file_n_exporter.h" +#include "common_func.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace fs = std::filesystem; +using namespace OHOS::FileManagement::LibN; + +namespace { +const std::string READ_STREAM_CLASS = "ReadStream"; +const std::string WRITE_STREAM_CLASS = "WriteStream"; + +struct BufferData { + uint8_t* buffer = nullptr; + size_t length = 0; + + ~BufferData() + { + delete[] buffer; + } +}; +} + +static void FinalizeCallback(napi_env env, void *finalizeData, void *finalizeHint) +{ + BufferData *bufferData = static_cast(finalizeData); + delete bufferData; +} + +static AtomicFileEntity* GetAtomicFileEntity(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + HILOGE("Number of arguments unmatched"); + return nullptr; + } + + auto rafEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (rafEntity == nullptr) { + HILOGE("Failed to get atomicFile"); + return nullptr; + } + + return rafEntity; +} + +static napi_value CreateStream(napi_env env, napi_callback_info info, const std::string &streamName, + const std::string &fineName) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + const char moduleName[] = "@ohos.file.streamrw"; + napi_value streamrw; + napi_status status = napi_load_module(env, moduleName, &streamrw); + if (status != napi_ok) { + HILOGE("Failed to load module"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return nullptr; + } + + napi_value constructor = nullptr; + status = napi_get_named_property(env, streamrw, streamName.c_str(), &constructor); + if (status != napi_ok) { + HILOGE("Failed to get named property"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return nullptr; + } + + napi_value filePath = NVal::CreateUTF8String(env, fineName).val_; + napi_value argv[NARG_CNT::ONE] = {filePath}; + napi_value streamObj; + size_t argc = 1; + status = napi_new_instance(env, constructor, argc, argv, &streamObj); + if (status != napi_ok) { + HILOGE("Failed to create napi new instance"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return nullptr; + } + + return NVal(env, streamObj).val_; +} + +static int32_t CallFunctionByName(napi_env env, napi_value objStream, const std::string &funcName) +{ + napi_valuetype valuetype; + napi_typeof(env, objStream, &valuetype); + if (valuetype != napi_object) { + HILOGE("Valuetype is unmatched"); + return UNKROWN_ERR; + } + + napi_value key; + napi_status status = napi_create_string_utf8(env, funcName.c_str(), funcName.length(), &key); + if (status != napi_ok) { + HILOGE("Failed to create string utf8"); + return UNKROWN_ERR; + } + + napi_value value; + status = napi_get_property(env, objStream, key, &value); + if (status != napi_ok) { + HILOGE("Failed to get property"); + return UNKROWN_ERR; + } + + status = napi_call_function(env, objStream, value, 0, nullptr, nullptr); + if (status != napi_ok) { + HILOGE("Failed to call %{public}s function", funcName.c_str()); + return UNKROWN_ERR; + } + + return 0; +} + +static NVal InstantiateFile(napi_env env, int fd, std::string path, bool isUri) +{ + napi_value objFile = NClass::InstantiateClass(env, FileNExporter::className_, {}); + if (!objFile) { + close(fd); + HILOGE("Failed to instantiate class"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return NVal(); + } + + auto fileEntity = NClass::GetEntityOf(env, objFile); + if (fileEntity == nullptr) { + close(fd); + HILOGE("Failed to get fileEntity"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return NVal(); + } + auto fdg = CreateUniquePtr(fd, false); + if (fdg == nullptr) { + close(fd); + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return NVal(); + } + fileEntity->fd_.swap(fdg); + if (isUri) { + fileEntity->path_ = ""; + fileEntity->uri_ = path; + } else { + fileEntity->path_ = path; + fileEntity->uri_ = ""; + } + return { env, objFile }; +} + +napi_value AtomicFileNExporter::GetBaseFile(napi_env env, napi_callback_info info) +{ + auto rafEntity = GetAtomicFileEntity(env, info); + if (rafEntity == nullptr || rafEntity->baseFileName.size() >= PATH_MAX) { + HILOGE("AtomicFile Failed to get atomicFile"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return nullptr; + } + + char realPath[PATH_MAX]; + char *result = realpath(rafEntity->baseFileName.c_str(), realPath); + if (result == nullptr) { + HILOGE("Failed to resolve real path, err:%{public}d", errno); + NError(errno).ThrowErr(env); + return nullptr; + } + + int fd = open(realPath, O_RDONLY); + if (fd < 0) { + HILOGE("Failed to open file, err:%{public}d", errno); + NError(errno).ThrowErr(env); + return nullptr; + } + + return InstantiateFile(env, fd, rafEntity->baseFileName, false).val_; +} + +napi_value AtomicFileNExporter::OpenRead(napi_env env, napi_callback_info info) +{ + auto rafEntity = GetAtomicFileEntity(env, info); + if (rafEntity == nullptr) { + HILOGE("Failed to get atomicFile"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return nullptr; + } + + if (fs::exists(rafEntity->newFileName) && fs::exists(rafEntity->baseFileName)) { + if (!fs::remove(rafEntity->newFileName)) { + HILOGW("Failed to remove file"); + } + } + return CreateStream(env, info, READ_STREAM_CLASS, rafEntity->baseFileName); +} + +std::unique_ptr ReadFileToBuffer(napi_env env, FILE* fp) +{ + if (fp == nullptr) { + HILOGE("Invalid file pointer"); + return nullptr; + } + + int fd = fileno(fp); + if (fd < 0) { + HILOGE("Failed to get file descriptor, err:%{public}d", errno); + NError(errno).ThrowErr(env); + return nullptr; + } + + struct stat fileStat {}; + if (fstat(fd, &fileStat) < 0) { + HILOGE("Failed to get file stats, err:%{public}d", errno); + NError(errno).ThrowErr(env); + return nullptr; + } + + long fileSize = fileStat.st_size; + if (fileSize < 0) { + HILOGE("Invalid file size"); + NError(EIO).ThrowErr(env); + return nullptr; + } + + auto bufferData = std::make_unique(); + if (fileSize == 0) { + return bufferData; + } + bufferData->buffer = new(std::nothrow) uint8_t[fileSize]; + if (bufferData->buffer == nullptr) { + HILOGE("Failed to allocate memory"); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + bufferData->length = fread(bufferData->buffer, sizeof(uint8_t), fileSize, fp); + if ((bufferData->length != fileSize && !feof(fp)) || ferror(fp)) { + HILOGE("Failed to read file, actual length is:%zu, fileSize:%ld", bufferData->length, fileSize); + NError(EIO).ThrowErr(env); + delete[] bufferData->buffer; + bufferData->buffer = nullptr; + bufferData->length = 0; + } + + return bufferData; +} + +napi_value AtomicFileNExporter::ReadFully(napi_env env, napi_callback_info info) +{ + auto rafEntity = GetAtomicFileEntity(env, info); + if (rafEntity == nullptr || rafEntity->baseFileName.size() >= PATH_MAX) { + HILOGE("Failed to get atomicFile"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return nullptr; + } + + char realPath[PATH_MAX]; + char *result = realpath(rafEntity->baseFileName.c_str(), realPath); + if (result == nullptr) { + HILOGE("Failed to resolve file real path, err:%{public}d", errno); + NError(errno).ThrowErr(env); + return nullptr; + } + + auto file = std::unique_ptr( + std::fopen(realPath, "rb"), &std::fclose); + if (!file) { + HILOGE("Failed to open file, err:%{public}d", errno); + NError(errno).ThrowErr(env); + return nullptr; + } + + auto bufferData = ReadFileToBuffer(env, file.get()); + if (!bufferData || bufferData->buffer == nullptr) { + HILOGE("Failed to read file, err:%{public}d", errno); + return nullptr; + } + + napi_value externalBuffer = nullptr; + size_t length = bufferData->length; + napi_status status = napi_create_external_arraybuffer( + env, bufferData->buffer, bufferData->length, FinalizeCallback, bufferData.release(), &externalBuffer); + if (status != napi_ok) { + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return nullptr; + } + + napi_value outputArray = nullptr; + status = napi_create_typedarray(env, napi_int8_array, length, externalBuffer, 0, &outputArray); + if (status != napi_ok) { + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return nullptr; + } + + return outputArray; +} + +napi_value AtomicFileNExporter::StartWrite(napi_env env, napi_callback_info info) +{ + auto rafEntity = GetAtomicFileEntity(env, info); + if (rafEntity == nullptr) { + HILOGE("Failed to get atomicFile"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return nullptr; + } + + char *tmpfile = const_cast(rafEntity->newFileName.c_str()); + if (mkstemp(tmpfile) == -1) { + fs::path filePath = rafEntity->newFileName; + fs::path parentPath = filePath.parent_path(); + std::error_code errCode; + fs::create_directory(parentPath, errCode); + if (errCode.operator bool()) { + HILOGE("Fail to create directory, err:%{public}s!", errCode.message().c_str()); + NError(ENOENT).ThrowErr(env); + return nullptr; + } + fs::permissions(parentPath, fs::perms::owner_all | fs::perms::group_all | fs::perms::others_exec, + fs::perm_options::replace, errCode); + if (errCode.operator bool()) { + HILOGE("Fail to change permissions err:%{public}s!", errCode.message().c_str()); + NError(EPERM).ThrowErr(env); + return nullptr; + } + + if (mkstemp(tmpfile) == -1) { + HILOGE("Fail to create tmp file err:%{public}d!", errno); + NError(ENOENT).ThrowErr(env); + return nullptr; + } + } + + napi_value writeStream = CreateStream(env, info, WRITE_STREAM_CLASS, rafEntity->newFileName); + if (writeStream == nullptr) { + HILOGE("Failed to create write stream"); + return nullptr; + } + napi_status status = napi_create_reference(env, writeStream, 1, &rafEntity->writeStreamObj); + if (status != napi_ok) { + HILOGE("Failed to create reference"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return nullptr; + } + return writeStream; +} + +napi_value AtomicFileNExporter::FinishWrite(napi_env env, napi_callback_info info) +{ + auto rafEntity = GetAtomicFileEntity(env, info); + if (rafEntity == nullptr) { + HILOGE("Failed to get atomicFile"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return NVal::CreateUndefined(env).val_; + } + + napi_value writeStream; + napi_status status = napi_get_reference_value(env, rafEntity->writeStreamObj, &writeStream); + if (status != napi_ok) { + HILOGE("Failed to get reference value"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return NVal::CreateUndefined(env).val_; + } + + int32_t errorNumber = CallFunctionByName(env, writeStream, "closeSync"); + if (errorNumber == UNKROWN_ERR) { + NError(errorNumber).ThrowErr(env, "Internal error"); + return NVal::CreateUndefined(env).val_; + } else if (errorNumber != 0) { + NError(errorNumber).ThrowErr(env); + return NVal::CreateUndefined(env).val_; + } + + std::rename(rafEntity->newFileName.c_str(), rafEntity->baseFileName.c_str()); + status = napi_delete_reference(env, rafEntity->writeStreamObj); + if (status != napi_ok) { + HILOGE("Failed to delete reference"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return NVal::CreateUndefined(env).val_; + } + return NVal::CreateUndefined(env).val_; +} + +napi_value AtomicFileNExporter::FailWrite(napi_env env, napi_callback_info info) +{ + auto rafEntity = GetAtomicFileEntity(env, info); + if (rafEntity == nullptr) { + HILOGE("Failed to get atomicFile"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return NVal::CreateUndefined(env).val_; + } + + napi_value writeStream; + napi_status status = napi_get_reference_value(env, rafEntity->writeStreamObj, &writeStream); + if (status != napi_ok) { + HILOGE("Failed to get reference value"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return NVal::CreateUndefined(env).val_; + } + + int32_t errorNumber = CallFunctionByName(env, writeStream, "closeSync"); + if (errorNumber == UNKROWN_ERR) { + NError(errorNumber).ThrowErr(env, "Internal error"); + return NVal::CreateUndefined(env).val_; + } else if (errorNumber != 0) { + NError(errorNumber).ThrowErr(env); + return NVal::CreateUndefined(env).val_; + } + + if (!fs::remove(rafEntity->newFileName)) { + HILOGW("Failed to remove file"); + } + + status = napi_delete_reference(env, rafEntity->writeStreamObj); + if (status != napi_ok) { + HILOGE("Failed to delete reference"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + } + return NVal::CreateUndefined(env).val_; +} + +napi_value AtomicFileNExporter::Delete(napi_env env, napi_callback_info info) +{ + auto rafEntity = GetAtomicFileEntity(env, info); + if (rafEntity == nullptr) { + HILOGE("Failed to get atomicFile"); + NError(UNKROWN_ERR).ThrowErr(env, "Internal error"); + return NVal::CreateUndefined(env).val_; + } + + if (fs::exists(rafEntity->newFileName) && !fs::remove(rafEntity->newFileName)) { + HILOGE("Failed to remove file, err:%{public}d", errno); + NError(errno).ThrowErr(env); + return NVal::CreateUndefined(env).val_; + } + + if (fs::exists(rafEntity->baseFileName) && !fs::remove(rafEntity->baseFileName)) { + HILOGE("Failed to remove file, err:%{public}d", errno); + NError(errno).ThrowErr(env); + return NVal::CreateUndefined(env).val_; + } + + rafEntity->newFileName.clear(); + rafEntity->baseFileName.clear(); + + return NVal::CreateUndefined(env).val_; +} + +napi_value AtomicFileNExporter::Constructor(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetSecondArg, file, num] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!resGetSecondArg) { + HILOGE("Invalid path"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto atomicFileEntity = CreateUniquePtr(); + if (atomicFileEntity == nullptr) { + HILOGE("Failed to request heap memory"); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + std::string filePath = file.get(); + atomicFileEntity->baseFileName = filePath; + atomicFileEntity->newFileName = filePath.append("_XXXXXX"); + if (!NClass::SetEntityFor(env, funcArg.GetThisVar(), move(atomicFileEntity))) { + HILOGE("Failed to wrap entity for obj AtomicFile"); + NError(EIO).ThrowErr(env); + return nullptr; + } + + return funcArg.GetThisVar(); +} + +bool AtomicFileNExporter::Export() +{ + std::vector props = { +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + NVal::DeclareNapiFunction("getBaseFile", GetBaseFile), + NVal::DeclareNapiFunction("openRead", OpenRead), + NVal::DeclareNapiFunction("readFully", ReadFully), + NVal::DeclareNapiFunction("startWrite", StartWrite), + NVal::DeclareNapiFunction("finishWrite", FinishWrite), + NVal::DeclareNapiFunction("failWrite", FailWrite), + NVal::DeclareNapiFunction("delete", Delete), +#endif + }; + + std::string className = GetClassName(); + bool succ = false; + napi_value classValue = nullptr; + std::tie(succ, classValue) = NClass::DefineClass( + exports_.env_, className, AtomicFileNExporter::Constructor, move(props)); + if (!succ) { + HILOGE("INNER BUG. Failed to define class"); + NError(ENOMEM).ThrowErr(exports_.env_); + return false; + } + succ = NClass::SaveClass(exports_.env_, className, classValue); + if (!succ) { + HILOGE("INNER BUG. Failed to save class"); + NError(ENOMEM).ThrowErr(exports_.env_); + return false; + } + + return exports_.AddProp(className, classValue); +} + +std::string AtomicFileNExporter::GetClassName() +{ + return AtomicFileNExporter::className_; +} + +AtomicFileNExporter::AtomicFileNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {} +AtomicFileNExporter::~AtomicFileNExporter() {} +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.h b/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.h new file mode 100644 index 000000000..0c18f3cb8 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 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. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FILEIO_CLASS_ATOMIC_FILE_N_EXPORTER_H +#define INTERFACES_KITS_JS_SRC_MOD_FILEIO_CLASS_ATOMIC_FILE_N_EXPORTER_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace OHOS::FileManagement::LibN; +class AtomicFileNExporter final : public NExporter { +public: + inline static const std::string className_ = "AtomicFile"; + + bool Export() override; + std::string GetClassName() override; + + static napi_value Constructor(napi_env env, napi_callback_info info); + static napi_value GetBaseFile(napi_env env, napi_callback_info info); + static napi_value OpenRead(napi_env env, napi_callback_info info); + static napi_value ReadFully(napi_env env, napi_callback_info info); + static napi_value StartWrite(napi_env env, napi_callback_info info); + static napi_value FinishWrite(napi_env env, napi_callback_info info); + static napi_value FailWrite(napi_env env, napi_callback_info info); + static napi_value Delete(napi_env env, napi_callback_info info); + + AtomicFileNExporter(napi_env env, napi_value exports); + ~AtomicFileNExporter() override; +}; +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS +#endif \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/module.cpp b/interfaces/kits/js/src/mod_fs/module.cpp index ad976623b..7654ed068 100644 --- a/interfaces/kits/js/src/mod_fs/module.cpp +++ b/interfaces/kits/js/src/mod_fs/module.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-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 @@ -21,6 +21,7 @@ #include "class_file/file_n_exporter.h" #include "class_stat/stat_n_exporter.h" #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +#include "class_atomicfile/atomicfile_n_exporter.h" #include "class_randomaccessfile/randomaccessfile_n_exporter.h" #include "class_readeriterator/readeriterator_n_exporter.h" #include "class_stream/stream_n_exporter.h" @@ -45,6 +46,7 @@ static napi_value Export(napi_env env, napi_value exports) products.emplace_back(make_unique(env, exports)); products.emplace_back(make_unique(env, exports)); #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + products.emplace_back(make_unique(env, exports)); products.emplace_back(make_unique(env, exports)); products.emplace_back(make_unique(env, exports)); products.emplace_back(make_unique(env, exports)); diff --git a/interfaces/kits/ts/streamrw/src/streamrw.ts b/interfaces/kits/ts/streamrw/src/streamrw.ts index a81d5b5ff..58e8b8bb0 100644 --- a/interfaces/kits/ts/streamrw/src/streamrw.ts +++ b/interfaces/kits/ts/streamrw/src/streamrw.ts @@ -141,6 +141,10 @@ class WriteStream extends stream.Writable { this.stream?.close(); } + closeSync(): void { + this.stream?.closeSync(); + } + doInitialize(callback: Function): void { callback(); } -- Gitee