diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index ca5759e8954206b24c77ee10baa402dd98653a3b..4d3022ceae366f92b247cbfba62e0fc6df4bdb42 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -117,11 +117,23 @@ ohos_shared_library("fs") { "src/common/file_helper/fd_guard.cpp", "src/mod_fs/class_file/file_n_exporter.cpp", "src/mod_fs/class_stat/stat_n_exporter.cpp", + "src/mod_fs/class_stream/flush.cpp", + "src/mod_fs/class_stream/stream_n_exporter.cpp", "src/mod_fs/common_func.cpp", "src/mod_fs/module.cpp", + "src/mod_fs/properties/close.cpp", + "src/mod_fs/properties/copy_file.cpp", + "src/mod_fs/properties/create_stream.cpp", + "src/mod_fs/properties/fdatasync.cpp", + "src/mod_fs/properties/fdopen_stream.cpp", + "src/mod_fs/properties/fsync.cpp", "src/mod_fs/properties/lstat.cpp", + "src/mod_fs/properties/mkdtemp.cpp", "src/mod_fs/properties/open.cpp", "src/mod_fs/properties/prop_n_exporter.cpp", + "src/mod_fs/properties/read_text.cpp", + "src/mod_fs/properties/rename.cpp", + "src/mod_fs/properties/rmdirent.cpp", "src/mod_fs/properties/stat.cpp", "src/mod_fs/properties/symlink.cpp", "src/mod_fs/properties/truncate.cpp", diff --git a/interfaces/kits/js/src/common/napi/n_async/n_async_work_callback.cpp b/interfaces/kits/js/src/common/napi/n_async/n_async_work_callback.cpp index 53662897ee4157aef5b9fe3e02d2f18b0f50eb3e..aabbff6c3da801204fc8f5c5f1a40a0268dfa004 100644 --- a/interfaces/kits/js/src/common/napi/n_async/n_async_work_callback.cpp +++ b/interfaces/kits/js/src/common/napi/n_async/n_async_work_callback.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 diff --git a/interfaces/kits/js/src/mod_fs/class_stream/flush.cpp b/interfaces/kits/js/src/mod_fs/class_stream/flush.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d21dd570eea097df208504ab5805517874a794d --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/flush.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 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 "flush.h" + +#include +#include + +#include "class_stat/stat_entity.h" +#include "class_stat/stat_n_exporter.h" +#include "filemgmt_libhilog.h" +#include "stream_entity.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +napi_value Flush::Sync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto streamEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!streamEntity || !streamEntity->fp) { + HILOGE("Stream may has been closed"); + NError(EIO).ThrowErr(env); + return nullptr; + } + + int ret = fflush(streamEntity->fp.get()); + if (ret < 0) { + HILOGE("Failed to fflush file in the stream, ret: %{public}d", ret); + NError(errno).ThrowErr(env); + return nullptr; + } + return NVal::CreateUndefined(env).val_; +} + +napi_value Flush::Async(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto streamEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!streamEntity || !streamEntity->fp) { + HILOGE("Stream may has been closed"); + NError(EIO).ThrowErr(env); + return nullptr; + } + + auto cbExec = [streamEntity]() -> NError { + int ret = fflush(streamEntity->fp.get()); + if (ret < 0) { + HILOGE("Failed to fflush file in the stream"); + return NError(errno); + } else { + return NError(ERRNO_NOERR); + } + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return { NVal::CreateUndefined(env) }; + }; + + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::ZERO) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_STREAM_FLUSH_NAME, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[NARG_POS::FIRST]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_STREAM_FLUSH_NAME, cbExec, cbCompl).val_; + } +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stream/flush.h b/interfaces/kits/js/src/mod_fs/class_stream/flush.h new file mode 100644 index 0000000000000000000000000000000000000000..aa7be7012cdc5ecf146f7b23bd6006e1c8d0ed43 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/flush.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 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_STREAM_FLUSH_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STREAM_FLUSH_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class Flush final { +public: + static napi_value Async(napi_env env, napi_callback_info info); + static napi_value Sync(napi_env env, napi_callback_info info); +}; + +const std::string PROCEDURE_STREAM_FLUSH_NAME = "FileIOStreamFlush"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STREAM_FLUSH_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stream/stream_entity.h b/interfaces/kits/js/src/mod_fs/class_stream/stream_entity.h new file mode 100644 index 0000000000000000000000000000000000000000..11cdae1dc8c70fa34f5804158e6b4c575a94ac5e --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/stream_entity.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 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_FILEIO_CLASS_STREAM_STREAM_ENTITY_H +#define INTERFACES_KITS_JS_SRC_MOD_FILEIO_CLASS_STREAM_STREAM_ENTITY_H + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +struct StreamEntity { + std::unique_ptr fp = { nullptr, fclose }; +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FILEIO_CLASS_STREAM_STREAM_ENTITY_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.cpp b/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44ba3246b0882cd4d07e7c4820e35eb141c1aa15 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.cpp @@ -0,0 +1,391 @@ +/* + * Copyright (c) 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 "stream_n_exporter.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common_func.h" +#include "filemgmt_libhilog.h" +#include "flush.h" +#include "stream_entity.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +napi_value StreamNExporter::ReadSync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto streamEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!streamEntity || !streamEntity->fp) { + HILOGE("Stream may have been closed"); + NError(EIO).ThrowErr(env); + return nullptr; + } + FILE *filp = nullptr; + filp = streamEntity->fp.get(); + + auto [succ, buf, len, hasOffset, offset] = + CommonFunc::GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]); + if (!succ) { + HILOGE("Failed to resolve buf and options"); + return nullptr; + } + + int ret = fseek(filp, offset, SEEK_SET); + if (hasOffset && (ret < 0)) { + HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); + NError(errno).ThrowErr(env); + return nullptr; + } + + size_t actLen = fread(buf, 1, len, filp); + if (actLen != static_cast(len) && ferror(filp)) { + HILOGE("Invalid buffer size and pointer, actlen: %{public}zu", actLen); + NError(errno).ThrowErr(env); + return nullptr; + } + + return NVal::CreateInt64(env, actLen).val_; +} + +napi_value StreamNExporter::CloseSync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto streamEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!streamEntity || !streamEntity->fp) { + HILOGE("Stream may have been closed yet"); + NError(EIO).ThrowErr(env); + return nullptr; + } + streamEntity->fp.reset(); + (void)NClass::RemoveEntityOfFinal(env, funcArg.GetThisVar()); + + return NVal::CreateUndefined(env).val_; +} + +napi_value StreamNExporter::WriteSync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto streamEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!streamEntity || !streamEntity->fp) { + HILOGE("Stream may has been closed"); + NError(EIO).ThrowErr(env); + return nullptr; + } + FILE *filp = nullptr; + filp = streamEntity->fp.get(); + + auto [succ, bufGuard, buf, len, hasOffset, offset] = + CommonFunc::GetWriteArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]); + if (!succ) { + HILOGE("Failed to resolve buf and options"); + return nullptr; + } + int ret = fseek(filp, offset, SEEK_SET); + if (hasOffset && (ret < 0)) { + HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); + NError(errno).ThrowErr(env); + return nullptr; + } + + size_t writeLen = fwrite(buf, 1, len, filp); + if (writeLen != len && ferror(filp)) { + HILOGE("Failed to fwrite with len, writeLen: %{public}zu, len: %{public}" PRId64, writeLen, len); + NError(errno).ThrowErr(env); + return nullptr; + } + + return NVal::CreateInt64(env, writeLen).val_; +} + +static bool HasOption(napi_env env, napi_value optionFromJsArg) +{ + NVal op = NVal(env, optionFromJsArg); + if (op.HasProp("offset") || op.HasProp("length") || op.HasProp("encoding") || !op.TypeIs(napi_function)) { + return true; + } + return false; +} + +napi_value StreamNExporter::Write(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto streamEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!streamEntity || !streamEntity->fp) { + HILOGE("Stream may has been closed"); + NError(EIO).ThrowErr(env); + return nullptr; + } + + FILE *filp = nullptr; + filp = streamEntity->fp.get(); + + auto [succ, bufGuard, buf, len, hasOffset, offset] = + CommonFunc::GetWriteArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]); + if (!succ) { + HILOGE("Failed to resolve buf and options"); + return nullptr; + } + + auto arg = make_shared(move(bufGuard)); + if (!arg) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + auto cbExec = [arg, buf = buf, len = len, filp, hasOffset = hasOffset, offset = offset]() -> NError { + int ret = fseek(filp, offset, SEEK_SET); + if (hasOffset && (ret < 0)) { + HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); + return NError(errno); + } + arg->actLen = fwrite(buf, 1, len, filp); + if ((arg->actLen != static_cast(len)) && ferror(filp)) { + HILOGE("Invalid buffer size and pointer, actlen: %{public}zu", arg->actLen); + return NError(errno); + } + return NError(ERRNO_NOERR); + }; + + auto cbCompl = [arg](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return { NVal::CreateInt64(env, arg->actLen) }; + }; + + NVal thisVar(env, funcArg.GetThisVar()); + bool hasOp = false; + if (funcArg.GetArgc() == NARG_CNT::TWO) { + hasOp = HasOption(env, funcArg[NARG_POS::SECOND]); + } + if (funcArg.GetArgc() == NARG_CNT::ONE || (funcArg.GetArgc() == NARG_CNT::TWO && hasOp)) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_STREAM_WRITE_NAME, cbExec, cbCompl).val_; + } else { + int cbIdx = ((funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::THIRD); + NVal cb(env, funcArg[cbIdx]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_STREAM_WRITE_NAME, cbExec, cbCompl).val_; + } +} + +napi_value StreamNExporter::Read(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto streamEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!streamEntity || !streamEntity->fp) { + HILOGE("Stream may have been closed"); + NError(EIO).ThrowErr(env); + return nullptr; + } + FILE *filp = nullptr; + filp = streamEntity->fp.get(); + + auto [succ, buf, len, hasOffset, offset] = + CommonFunc::GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]); + if (!succ) { + HILOGE("Failed to resolve buf and options"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto arg = make_shared(NVal(env, funcArg[NARG_POS::FIRST])); + if (!arg) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + auto cbExec = [arg, buf = buf, len = len, filp, hasOffset = hasOffset, offset = offset]() -> NError { + int ret = fseek(filp, offset, SEEK_SET); + if (hasOffset && (ret < 0)) { + HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); + return NError(errno); + } + size_t actLen = fread(buf, 1, len, filp); + if (actLen != static_cast(len) && ferror(filp)) { + HILOGE("Invalid buffer size and pointer, actlen: %{public}zu", actLen); + return NError(errno); + } else { + arg->lenRead = actLen; + return NError(ERRNO_NOERR); + } + }; + + auto cbCompl = [arg](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return { NVal::CreateInt64(env, arg->lenRead) }; + }; + + NVal thisVar(env, funcArg.GetThisVar()); + bool hasOp = false; + if (funcArg.GetArgc() == NARG_CNT::TWO) { + hasOp = HasOption(env, funcArg[NARG_POS::SECOND]); + } + if (funcArg.GetArgc() == NARG_CNT::ONE || (funcArg.GetArgc() == NARG_CNT::TWO && hasOp)) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_STREAM_READ_NAME, cbExec, cbCompl).val_; + } else { + int cbIdx = ((funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::THIRD); + NVal cb(env, funcArg[cbIdx]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_STREAM_READ_NAME, cbExec, cbCompl).val_; + } +} + +napi_value StreamNExporter::Close(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto streamEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!streamEntity || !streamEntity->fp) { + HILOGE("Stream may has been closed"); + NError(EIO).ThrowErr(env); + return nullptr; + } + + auto cbExec = [streamEntity]() -> NError { + auto filp = streamEntity->fp.release(); + if (!fclose(filp)) { + HILOGE("Failed to close file with filp"); + return NError(ERRNO_NOERR); + } else { + return NError(errno); + } + }; + + auto cbCompl = [arg = funcArg.GetThisVar()](napi_env env, NError err) -> NVal { + (void)NClass::RemoveEntityOfFinal(env, arg); + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return NVal::CreateUndefined(env); + } + }; + + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::ZERO) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_STREAM_CLOSE_NAME, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[NARG_POS::FIRST]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_STREAM_CLOSE_NAME, cbExec, cbCompl).val_; + } +} + +napi_value StreamNExporter::Constructor(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + unique_ptr streamEntity = make_unique(); + if (!NClass::SetEntityFor(env, funcArg.GetThisVar(), move(streamEntity))) { + HILOGE("INNER BUG. Failed to wrap entity for obj stream"); + NError(EIO).ThrowErr(env); + return nullptr; + } + return funcArg.GetThisVar(); +} + +bool StreamNExporter::Export() +{ + vector props = { + NVal::DeclareNapiFunction("writeSync", WriteSync), + NVal::DeclareNapiFunction("flush", Flush::Async), + NVal::DeclareNapiFunction("flushSync", Flush::Sync), + NVal::DeclareNapiFunction("readSync", ReadSync), + NVal::DeclareNapiFunction("closeSync", CloseSync), + NVal::DeclareNapiFunction("write", Write), + NVal::DeclareNapiFunction("read", Read), + NVal::DeclareNapiFunction("close", Close), + }; + + string className = GetClassName(); + bool succ = false; + napi_value cls = nullptr; + tie(succ, cls) = NClass::DefineClass(exports_.env_, className, StreamNExporter::Constructor, move(props)); + if (!succ) { + HILOGE("INNER BUG. Failed to define class"); + NError(EIO).ThrowErr(exports_.env_); + return false; + } + succ = NClass::SaveClass(exports_.env_, className, cls); + if (!succ) { + HILOGE("INNER BUG. Failed to save class"); + NError(EIO).ThrowErr(exports_.env_); + return false; + } + + return exports_.AddProp(className, cls); +} + +string StreamNExporter::GetClassName() +{ + return StreamNExporter::className_; +} + +StreamNExporter::StreamNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {} + +StreamNExporter::~StreamNExporter() {} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.h b/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.h new file mode 100644 index 0000000000000000000000000000000000000000..afb2579e6e5e80c65111c14017ea3797823a372b --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 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_STREAM_STREAM_N_EXPORTER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STREAM_STREAM_N_EXPORTER_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace OHOS::FileManagement::LibN; +class StreamNExporter final : public NExporter { +public: + inline static const std::string className_ = "FsStream"; + + bool Export() override; + std::string GetClassName() override; + + static napi_value Constructor(napi_env env, napi_callback_info cbinfo); + + static napi_value WriteSync(napi_env env, napi_callback_info cbinfo); + static napi_value ReadSync(napi_env env, napi_callback_info cbinfo); + static napi_value CloseSync(napi_env env, napi_callback_info cbinfo); + + static napi_value Write(napi_env env, napi_callback_info cbinfo); + static napi_value Read(napi_env env, napi_callback_info cbinfo); + static napi_value Close(napi_env env, napi_callback_info cbinfo); + + StreamNExporter(napi_env env, napi_value exports); + ~StreamNExporter() override; +}; + +struct AsyncReadArg { + size_t lenRead { 0 }; + NRef refReadBuf; + + explicit AsyncReadArg(NVal jsReadBuf) : refReadBuf(jsReadBuf) {} + ~AsyncReadArg() = default; +}; + +struct AsyncWrtieArg { + NRef refWriteArrayBuf; + std::unique_ptr guardWriteStr; + size_t actLen { 0 }; + + explicit AsyncWrtieArg(NVal refWriteArrayBuf) : refWriteArrayBuf(refWriteArrayBuf) {} + explicit AsyncWrtieArg(std::unique_ptr &&guardWriteStr) : guardWriteStr(std::move(guardWriteStr)) {} + ~AsyncWrtieArg() = default; +}; + +const std::string PROCEDURE_STREAM_WRITE_NAME = "FileIOStreamWrite"; +const std::string PROCEDURE_STREAM_READ_NAME = "FileIOStreamRead"; +const std::string PROCEDURE_STREAM_CLOSE_NAME = "FileIOStreamClose"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STREAM_STREAM_N_EXPORTER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/common_func.cpp b/interfaces/kits/js/src/mod_fs/common_func.cpp index b02dc3d6150fd9ec87c085db3c3940ed439efce8..0761373ded9d4f121c8e10a91fc495426a0dd506 100644 --- a/interfaces/kits/js/src/mod_fs/common_func.cpp +++ b/interfaces/kits/js/src/mod_fs/common_func.cpp @@ -122,6 +122,15 @@ int CommonFunc::ConvertJsFlags(int &flags) return flagsABI; } +void CommonFunc::fs_req_cleanup(uv_fs_t* req) +{ + uv_fs_req_cleanup(req); + if (req) { + delete req; + req = nullptr; + } +} + tuple, unique_ptr> CommonFunc::GetCopyPathArg(napi_env env, napi_value srcPath, napi_value dstPath) diff --git a/interfaces/kits/js/src/mod_fs/common_func.h b/interfaces/kits/js/src/mod_fs/common_func.h index 0fdd7ccd5416ba752d9c19b6fefacab85514cf45..9893205087bd56427d71bfdaa6d866b384a6eae8 100644 --- a/interfaces/kits/js/src/mod_fs/common_func.h +++ b/interfaces/kits/js/src/mod_fs/common_func.h @@ -18,6 +18,7 @@ #include "fd_guard.h" #include "n_val.h" +#include "uv.h" namespace OHOS { namespace FileManagement { @@ -54,6 +55,7 @@ struct CommonFunc { static std::tuple, std::unique_ptr> GetCopyPathArg(napi_env env, napi_value srcPath, napi_value dstPath); + static void fs_req_cleanup(uv_fs_t* req); }; } // namespace ModuleFileIO } // namespace FileManagement diff --git a/interfaces/kits/js/src/mod_fs/module.cpp b/interfaces/kits/js/src/mod_fs/module.cpp index 792cab62bf133b1953fca285e294a55aa896f39d..2b969d95f2fdbc6f42fa6489b059589efb5df816 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) 2022 Huawei Device Co., Ltd. + * Copyright (c) 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 @@ -20,6 +20,7 @@ #include "class_file/file_n_exporter.h" #include "class_stat/stat_n_exporter.h" +#include "class_stream/stream_n_exporter.h" #include "filemgmt_libhilog.h" #include "properties/prop_n_exporter.h" @@ -35,6 +36,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)); products.emplace_back(make_unique(env, exports)); + products.emplace_back(make_unique(env, exports)); for (auto &&product : products) { if (!product->Export()) { diff --git a/interfaces/kits/js/src/mod_fs/properties/close.cpp b/interfaces/kits/js/src/mod_fs/properties/close.cpp new file mode 100644 index 0000000000000000000000000000000000000000..195feb69da5d8f3bb4bdd4b46a19997a36e9a7c0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/close.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 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 "close.h" + +#include +#include +#include + +#include "common_func.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +static FileEntity *GetFileEntity(napi_env env, napi_value objFile) +{ + auto fileEntity = NClass::GetEntityOf(env, objFile); + if (!fileEntity) { + HILOGE("Failed to get file entity"); + return nullptr; + } + if (!fileEntity->fd_) { + HILOGE("The fd of rafEntity is not exist"); + return nullptr; + } + return fileEntity; +} + +static tuple ParseJsOperand(napi_env env, napi_value fdOrFileFromJsArg) +{ + auto [isFd, fd] = NVal(env, fdOrFileFromJsArg).ToInt32(); + if (isFd) { + return { true, FileStruct { true, fd, nullptr } }; + } + auto file = GetFileEntity(env, fdOrFileFromJsArg); + if (file) { + return { true, FileStruct { false, -1, file } }; + } + + return { false, FileStruct { false, -1, nullptr } }; +} + +napi_value Close::Sync(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 [resGetFirstArg, fileStruct] = ParseJsOperand(env, funcArg[NARG_POS::FIRST]); + if (!resGetFirstArg) { + HILOGI("Failed to parse fd or FileEntity from JS parameter"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + if (fileStruct.isFd) { + std::unique_ptr close_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!close_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_close(nullptr, close_req.get(), fileStruct.fd, nullptr); + if (ret < 0) { + HILOGE("Failed to close file with fd: %{public}d, ret: %{public}d", fileStruct.fd, ret); + NError(errno).ThrowErr(env); + return nullptr; + } + } else { + fileStruct.fileEntity->fd_.reset(); + } + (void)NClass::RemoveEntityOfFinal(env, funcArg.GetThisVar()); + + return NVal::CreateUndefined(env).val_; +} + +napi_value Close::Async(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetFirstArg, fileStruct] = ParseJsOperand(env, funcArg[NARG_POS::FIRST]); + if (!resGetFirstArg) { + HILOGI("Failed to parse JS operand"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto cbExec = [fileStruct = fileStruct]() -> NError { + if (fileStruct.isFd) { + std::unique_ptr close_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!close_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + int ret = uv_fs_close(nullptr, close_req.get(), fileStruct.fd, nullptr); + if (ret < 0) { + HILOGE("Failed to close file with ret: %{public}d", ret); + return NError(errno); + } + } else { + fileStruct.fileEntity->fd_.reset(); + } + return NError(ERRNO_NOERR); + }; + + auto cbComplete = [arg = funcArg.GetThisVar()](napi_env env, NError err) -> NVal { + (void)NClass::RemoveEntityOfFinal(env, arg); + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return NVal::CreateUndefined(env); + } + }; + + size_t argc = funcArg.GetArgc(); + NVal thisVar(env, funcArg.GetThisVar()); + if (argc == NARG_CNT::ONE) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_CLOSE_NAME, cbExec, cbComplete).val_; + } else { + NVal cb(env, funcArg[NARG_POS::SECOND]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_CLOSE_NAME, cbExec, cbComplete).val_; + } +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/close.h b/interfaces/kits/js/src/mod_fs/properties/close.h new file mode 100644 index 0000000000000000000000000000000000000000..8fa3bab4eec2d6ddde166f96980f4eefc8cb980e --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/close.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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_CLOSE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CLOSE_H + +#include "class_file/file_entity.h" +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class Close final { +public: + static napi_value Sync(napi_env env, napi_callback_info info); + static napi_value Async(napi_env env, napi_callback_info info); +}; + +struct FileStruct { + bool isFd = false; + int fd; + FileEntity *fileEntity; +}; + +const std::string PROCEDURE_CLOSE_NAME = "FileIOClose"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CLOSE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_file.cpp b/interfaces/kits/js/src/mod_fs/properties/copy_file.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5aae5da788372f5f083280d4bced5c154a30db8c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_file.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (c) 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 "copy_file.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "common_func.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +static NError IsAllPath(FileInfo& srcFile, FileInfo& destFile) +{ + std::unique_ptr copyfile_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!copyfile_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + 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 NError(errno); + } + return NError(ERRNO_NOERR); +} + +static NError SendFileCore(FileInfo& srcFile, FileInfo& destFile) +{ + if (srcFile.isPath) { + std::unique_ptr open_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!open_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + int ret = uv_fs_open(nullptr, open_req.get(), srcFile.path.get(), O_RDONLY, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, nullptr); + if (ret < 0) { + HILOGE("Failed to open srcFile with ret: %{public}d", ret); + return NError(errno); + } + srcFile.fdg.SetFD(ret, true); + } + + 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 NError(errno); + } + + if (destFile.isPath) { + std::unique_ptr open_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!open_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + int ret = uv_fs_open(nullptr, open_req.get(), destFile.path.get(), O_RDWR | O_CREAT, statbf.st_mode, nullptr); + if (ret < 0) { + HILOGE("Failed to open destFile with ret: %{public}d", ret); + return NError(errno); + } + destFile.fdg.SetFD(ret, true); + } + + std::unique_ptr sendfile_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!sendfile_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + int ret = uv_fs_sendfile(nullptr, sendfile_req.get(), srcFile.fdg.GetFD(), destFile.fdg.GetFD(), 0, + statbf.st_size, nullptr); + if (ret < 0) { + HILOGE("Failed to sendfile by ret : %{public}d", ret); + return NError(errno); + } + + return NError(ERRNO_NOERR); +} + +static tuple ParseJsModeAndProm(napi_env env, const NFuncArg& funcArg) +{ + bool promise = false; + bool hasMode = false; + int mode = 0; + if (funcArg.GetArgc() == NARG_CNT::THREE && NVal(env, funcArg[NARG_POS::THIRD]).TypeIs(napi_number)) { + promise = true; + hasMode = true; + } else if (funcArg.GetArgc() == NARG_CNT::FOUR) { + hasMode = true; + } + + if (hasMode) { + auto [succ, mode] = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32(); + if (!succ) { + return { false, mode, promise }; + } + } + + return { true, mode, promise }; +} + +static tuple ParseJsOperand(napi_env env, NVal pathOrFdFromJsArg) +{ + auto [isPath, path, ignore] = pathOrFdFromJsArg.ToUTF8String(); + if (isPath) { + return { true, FileInfo{ true, move(path), {} } }; + } + + auto [isFd, fd] = pathOrFdFromJsArg.ToInt32(); + if (isFd) { + return { true, FileInfo{ false, {}, { fd, false } }}; + } + + return { false, FileInfo{ false, {}, {} } }; +}; + +napi_value CopyFile::Sync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [succSrc, src] = ParseJsOperand(env, { env, funcArg[NARG_POS::FIRST] }); + auto [succDest, dest] = ParseJsOperand(env, { env, funcArg[NARG_POS::SECOND] }); + if (!succSrc || !succDest) { + HILOGE("The first/second argument requires filepath/fd"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [succMode, mode, unused] = ParseJsModeAndProm(env, funcArg); + if (!succMode) { + HILOGE("Failed to convert mode to int32"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + if (src.isPath && dest.isPath) { + auto err = IsAllPath(src, dest); + if (err) { + err.ThrowErr(env); + return nullptr; + } + } else { + auto err = SendFileCore(src, dest); + if (err) { + err.ThrowErr(env); + return nullptr; + } + } + return NVal::CreateUndefined(env).val_; +} + +napi_value CopyFile::Async(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::FOUR)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [succSrc, src] = ParseJsOperand(env, { env, funcArg[NARG_POS::FIRST] }); + auto [succDest, dest] = ParseJsOperand(env, { env, funcArg[NARG_POS::SECOND] }); + if (!succSrc || !succDest) { + HILOGE("The first/second argument requires filepath/fd"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [succMode, mode, promise] = ParseJsModeAndProm(env, funcArg); + if (!succMode) { + HILOGE("Failed to convert mode to int32"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto cbExec = [para = make_shared(move(src), move(dest))]() -> NError { + if (para->src_.isPath && para->dest_.isPath) { + return IsAllPath(para->src_, para->dest_); + } + return SendFileCore(para->src_, para->dest_); + }; + + auto cbCompl = [](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return { NVal::CreateUndefined(env) }; + }; + + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::TWO || promise) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_COPYFILE_NAME, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[((funcArg.GetArgc() == NARG_CNT::THREE) ? NARG_POS::THIRD : NARG_POS::FOURTH)]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_COPYFILE_NAME, cbExec, cbCompl).val_; + } +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_file.h b/interfaces/kits/js/src/mod_fs/properties/copy_file.h new file mode 100644 index 0000000000000000000000000000000000000000..cb6519d7dfc605390b76755fdbcfbf49ed0ea08a --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_file.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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_COPY_FILE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_FILE_H + +#include "common_func.h" +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +class CopyFile final { +public: + static napi_value Async(napi_env env, napi_callback_info info); + static napi_value Sync(napi_env env, napi_callback_info info); +}; + +class Para { +public: + FileInfo src_; + FileInfo dest_; + + Para(FileInfo src, FileInfo dest) : src_(move(src)), dest_(move(dest)){}; +}; + +const string PROCEDURE_COPYFILE_NAME = "FileIOCopyFile"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_FILE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/create_stream.cpp b/interfaces/kits/js/src/mod_fs/properties/create_stream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e63178df283257f0ea7fc0861927159fb3e1c7f5 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/create_stream.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 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 "create_stream.h" + +#include +#include + +#include "class_stream/stream_entity.h" +#include "class_stream/stream_n_exporter.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +static NVal InstantiateStream(napi_env env, unique_ptr fp) +{ + napi_value objStream = NClass::InstantiateClass(env, StreamNExporter::className_, {}); + if (!objStream) { + HILOGE("INNER BUG. Cannot instantiate stream"); + NError(EIO).ThrowErr(env); + return NVal(); + } + + auto streamEntity = NClass::GetEntityOf(env, objStream); + if (!streamEntity) { + HILOGE("Cannot instantiate stream because of void entity"); + NError(EIO).ThrowErr(env); + return NVal(); + } + + streamEntity->fp.swap(fp); + return { env, objStream }; +} + +static tuple GetCreateStreamArgs(napi_env env, const NFuncArg &funcArg) +{ + auto [resGetFirstArg, path, unused] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!resGetFirstArg) { + return { false, "", "" }; + } + + auto [resGetSecondArg, mode, useless] = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String(); + if (!resGetSecondArg) { + return { false, "", "" }; + } + + return { true, path.get(), mode.get() }; +} + +napi_value CreateStream::Sync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetCreateStreamArgs, argPath, argMode] = GetCreateStreamArgs(env, funcArg); + if (!resGetCreateStreamArgs) { + HILOGE("Arg path and mode are required to be type of string"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + unique_ptr fp = { fopen(argPath.c_str(), argMode.c_str()), fclose }; + if (!fp) { + HILOGE("Failed to fdopen file by path"); + NError(errno).ThrowErr(env); + return nullptr; + } + + return InstantiateStream(env, move(fp)).val_; +} + +napi_value CreateStream::Async(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetCreateStreamArgs, argPath, argMode] = GetCreateStreamArgs(env, funcArg); + if (!resGetCreateStreamArgs) { + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto arg = make_shared(); + if (arg == nullptr) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + auto cbExec = [arg, argPath = move(argPath), argMode = move(argMode)]() -> NError { + arg->fp = { fopen(argPath.c_str(), argMode.c_str()), fclose }; + if (!arg->fp) { + HILOGE("Failed to fdopen file by path"); + return NError(errno); + } + return NError(ERRNO_NOERR); + }; + + auto cbCompl = [arg](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return InstantiateStream(env, move(arg->fp)); + }; + + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::TWO) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_CREATESTREAM_NAME, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[NARG_POS::THIRD]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_CREATESTREAM_NAME, cbExec, cbCompl).val_; + } +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/create_stream.h b/interfaces/kits/js/src/mod_fs/properties/create_stream.h new file mode 100644 index 0000000000000000000000000000000000000000..9e7b01493dc6ff432791cd841773072dbdf40522 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/create_stream.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 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_CREATE_STREAM_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_STREAM_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class CreateStream final { +public: + static napi_value Async(napi_env env, napi_callback_info info); + static napi_value Sync(napi_env env, napi_callback_info info); +}; + +struct AsyncCreateStreamArg { + std::unique_ptr fp = { nullptr, fclose }; +}; + +const std::string PROCEDURE_CREATESTREAM_NAME = "FileIOCreateStream"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_STREAM_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/fdatasync.cpp b/interfaces/kits/js/src/mod_fs/properties/fdatasync.cpp index 8def7211140a3cfa1e23895b68f14eee1d235d1d..f5dbc0f4f24b670de0a610e7c6e71abd6fcaf3ee 100644 --- a/interfaces/kits/js/src/mod_fs/properties/fdatasync.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/fdatasync.cpp @@ -19,12 +19,10 @@ #include #include #include - #include +#include "common_func.h" #include "filemgmt_libhilog.h" -#include "uv.h" - namespace OHOS::FileManagement::ModuleFileIO { using namespace std; @@ -46,7 +44,13 @@ napi_value Fdatasync::Sync(napi_env env, napi_callback_info info) return nullptr; } - std::unique_ptr fdatasync_req = {new uv_fs_t, uv_fs_req_cleanup}; + std::unique_ptr fdatasync_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!fdatasync_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } int ret = uv_fs_fdatasync(nullptr, fdatasync_req.get(), fd, nullptr); if (ret < 0) { HILOGE("Failed to transfer data associated with file descriptor: %{public}d, ret:%{public}d", fd, ret); @@ -74,7 +78,12 @@ napi_value Fdatasync::Async(napi_env env, napi_callback_info info) } auto cbExec = [fd = fd]() -> NError { - std::unique_ptr fdatasync_req = {new uv_fs_t, uv_fs_req_cleanup}; + std::unique_ptr fdatasync_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!fdatasync_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } int ret = uv_fs_fdatasync(nullptr, fdatasync_req.get(), fd, nullptr); if (ret < 0) { HILOGE("Failed to transfer data associated with file descriptor: %{public}d", fd); diff --git a/interfaces/kits/js/src/mod_fs/properties/fdopen_stream.cpp b/interfaces/kits/js/src/mod_fs/properties/fdopen_stream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2fab9f21a5a9d230349632fca72a4705ecda6ad7 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/fdopen_stream.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 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 "fdopen_stream.h" + +#include +#include + +#include "class_stream/stream_entity.h" +#include "class_stream/stream_n_exporter.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +static NVal InstantiateStream(napi_env env, unique_ptr fp) +{ + napi_value objStream = NClass::InstantiateClass(env, StreamNExporter::className_, {}); + if (!objStream) { + HILOGE("INNER BUG. Cannot instantiate stream"); + NError(EIO).ThrowErr(env); + return NVal(); + } + + auto streamEntity = NClass::GetEntityOf(env, objStream); + if (!streamEntity) { + HILOGE("Cannot instantiate stream because of void entity"); + NError(EIO).ThrowErr(env); + return NVal(); + } + + streamEntity->fp.swap(fp); + return { env, objStream }; +} + +static tuple GetFdopenStreamArgs(napi_env env, const NFuncArg &funcArg) +{ + auto [resGetFirstArg, fd] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); + if (!resGetFirstArg) { + return { false, -1, "" }; + } + + auto [resGetSecondArg, mode, unused] = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String(); + if (!resGetSecondArg) { + return { false, -1, "" }; + } + + return { true, fd, mode.get() }; +} + +napi_value FdopenStream::Sync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetFdopenStreamArgs, fd, mode] = GetFdopenStreamArgs(env, funcArg); + if (!resGetFdopenStreamArgs) { + HILOGE("Invalid fd or mode from JS arugments"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + unique_ptr fp = { fdopen(fd, mode.c_str()), fclose }; + if (!fp) { + HILOGE("Failed to fdopen file by fd:%{public}d", fd); + NError(errno).ThrowErr(env); + return nullptr; + } + + return InstantiateStream(env, move(fp)).val_; +} + +napi_value FdopenStream::Async(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetFdopenStreamArgs, fd, mode] = GetFdopenStreamArgs(env, funcArg); + if (!resGetFdopenStreamArgs) { + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto arg = make_shared(); + if (arg == nullptr) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + auto cbExec = [arg, fd = fd, mode = mode]() -> NError { + arg->fp = { fdopen(fd, mode.c_str()), fclose }; + if (!arg->fp) { + HILOGE("Failed to fdopen file by fd:%{public}d", fd); + return NError(errno); + } + return NError(ERRNO_NOERR); + }; + + auto cbCompl = [arg](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return InstantiateStream(env, move(arg->fp)); + }; + + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::TWO) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_FDOPENSTREAM_NAME, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[NARG_POS::THIRD]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_FDOPENSTREAM_NAME, cbExec, cbCompl).val_; + } +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/fdopen_stream.h b/interfaces/kits/js/src/mod_fs/properties/fdopen_stream.h new file mode 100644 index 0000000000000000000000000000000000000000..ed43f3d3bd8b4a71499dfdaadbb997d42e7488f2 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/fdopen_stream.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 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_FDOPEN_STREAM_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDOPEN_STREAM_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class FdopenStream final { +public: + static napi_value Async(napi_env env, napi_callback_info info); + static napi_value Sync(napi_env env, napi_callback_info info); +}; + +struct AsyncFdopenStreamArg { + std::unique_ptr fp = { nullptr, fclose }; +}; + +const std::string PROCEDURE_FDOPENSTREAM_NAME = "FileIOFdopenStream"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDOPEN_STREAM_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/fsync.cpp b/interfaces/kits/js/src/mod_fs/properties/fsync.cpp index 85405dfe4a9b0041d776f621b4a4a4d591623530..422389c64e1cab3f7c12d5d6e159f38f3c49a20e 100644 --- a/interfaces/kits/js/src/mod_fs/properties/fsync.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/fsync.cpp @@ -19,8 +19,8 @@ #include #include +#include "common_func.h" #include "filemgmt_libhilog.h" -#include "uv.h" namespace OHOS::FileManagement::ModuleFileIO { using namespace std; @@ -42,7 +42,13 @@ napi_value Fsync::Sync(napi_env env, napi_callback_info info) return nullptr; } - std::unique_ptr fsync_req = {new uv_fs_t, uv_fs_req_cleanup}; + std::unique_ptr fsync_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!fsync_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } int ret = uv_fs_fsync(nullptr, fsync_req.get(), fd, nullptr); if (ret < 0) { HILOGE("Failed to transfer data associated with file descriptor: %{public}d", fd); @@ -69,7 +75,12 @@ napi_value Fsync::Async(napi_env env, napi_callback_info info) } auto cbExec = [fd = fd]() -> NError { - std::unique_ptr fsync_req = {new uv_fs_t, uv_fs_req_cleanup}; + std::unique_ptr fsync_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!fsync_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } int ret = uv_fs_fsync(nullptr, fsync_req.get(), fd, nullptr); if (ret < 0) { HILOGE("Failed to transfer data associated with file descriptor: %{public}d", fd); diff --git a/interfaces/kits/js/src/mod_fs/properties/mkdtemp.cpp b/interfaces/kits/js/src/mod_fs/properties/mkdtemp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..43ab54a2b316e8cb2b2b9309d38c9f3b86bc4da5 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/mkdtemp.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 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 "mkdtemp.h" + +#include "common_func.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +napi_value Mkdtemp::Sync(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 [resGetFirstArg, tmp, unused] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!resGetFirstArg) { + HILOGE("Invalid path"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + string path = tmp.get(); + std::unique_ptr mkdtemp_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!mkdtemp_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_mkdtemp(nullptr, mkdtemp_req.get(), const_cast(path.c_str()), nullptr); + if (ret < 0) { + HILOGE("Failed to create a temporary directory with path: %{public}s", path.c_str()); + NError(errno).ThrowErr(env); + return nullptr; + } + + return NVal::CreateUTF8String(env, mkdtemp_req->path).val_; +} + +napi_value Mkdtemp::Async(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetFirstArg, tmp, unused] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!resGetFirstArg) { + HILOGE("Invalid path"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto arg = make_shared(); + auto cbExec = [path = tmp.get(), arg]() -> NError { + std::unique_ptr mkdtemp_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!mkdtemp_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + int ret = uv_fs_mkdtemp(nullptr, mkdtemp_req.get(), const_cast(path), nullptr); + if (ret < 0) { + HILOGE("Failed to create a temporary directory with path: %{public}s", path); + return NError(errno); + } else { + *arg = mkdtemp_req->path; + return NError(ERRNO_NOERR); + } + }; + + auto cbComplete = [arg](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return NVal::CreateUTF8String(env, *arg); + } + }; + + const string procedureName = "FileIOmkdtemp"; + size_t argc = funcArg.GetArgc(); + NVal thisVar(env, funcArg.GetThisVar()); + if (argc == NARG_CNT::ONE) { + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_; + } else { + NVal cb(env, funcArg[NARG_POS::SECOND]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_; + } +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fs/properties/mkdtemp.h b/interfaces/kits/js/src/mod_fs/properties/mkdtemp.h new file mode 100644 index 0000000000000000000000000000000000000000..ac968c32e5ca7221a54cad2ae7fc13b399111f20 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/mkdtemp.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 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_MKDTEMP_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MKDTEMP_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace OHOS::FileManagement::LibN; + +class Mkdtemp final { +public: + static napi_value Sync(napi_env env, napi_callback_info info); + static napi_value Async(napi_env env, napi_callback_info info); +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MKDTEMP_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/open.cpp b/interfaces/kits/js/src/mod_fs/properties/open.cpp index ff16921a08348dd2286a5baf9bd805a918457ac6..bcd429fc8f3b2a3dfdfc0c4751466849d3001d61 100644 --- a/interfaces/kits/js/src/mod_fs/properties/open.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/open.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include "../common_func.h" #include "ability.h" @@ -122,15 +121,21 @@ napi_value Open::Sync(napi_env env, napi_callback_info info) NError(-1).ThrowErr(env); return nullptr; } - std::unique_ptr open_req = { new uv_fs_t, uv_fs_req_cleanup }; - int ret = uv_fs_open(uv_default_loop(), open_req.get(), path.get(), mode, S_IRUSR | - S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, NULL); + std::unique_ptr open_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!open_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_open(nullptr, open_req.get(), path.get(), mode, S_IRUSR | + S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, nullptr); if (ret < 0) { HILOGE("Failed to open file for libuv error %{public}d", ret); NError(errno).ThrowErr(env); return nullptr; } - auto file = InstantiateFile(env, open_req.get()->result, path.get(), false).val_; + auto file = InstantiateFile(env, ret, path.get(), false).val_; return file; } @@ -173,14 +178,19 @@ napi_value Open::Async(napi_env env, napi_callback_info info) HILOGE("Failed to open file by Datashare"); return NError(-1); } - std::unique_ptr open_req = { new uv_fs_t, uv_fs_req_cleanup }; - int ret = uv_fs_open(uv_default_loop(), open_req.get(), path.c_str(), mode, S_IRUSR | - S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, NULL); + std::unique_ptr open_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!open_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + int ret = uv_fs_open(nullptr, open_req.get(), path.c_str(), mode, S_IRUSR | + S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, nullptr); if (ret < 0) { HILOGE("Failed to open file for libuv error %{public}d", ret); return NError(errno); } - arg->fd = open_req.get()->result; + arg->fd = ret; arg->path = path; arg->uri = ""; return NError(ERRNO_NOERR); diff --git a/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.cpp b/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.cpp index 9f94a073645cf9dd4b1edeeff7296a2856518e33..ee2875685bec2b4001e644f158f0e790ac328eea 100644 --- a/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 @@ -21,14 +21,25 @@ #include #include #include -#include -#include "../common_func.h" +#include "common_func.h" #include "class_file/file_entity.h" #include "class_file/file_n_exporter.h" +#include "close.h" +#include "copy_file.h" +#include "create_stream.h" +#include "fdatasync.h" +#include "fdopen_stream.h" #include "filemgmt_libn.h" +#include "fsync.h" +#include "js_native_api.h" +#include "js_native_api_types.h" #include "lstat.h" +#include "mkdtemp.h" #include "open.h" +#include "read_text.h" +#include "rename.h" +#include "rmdirent.h" #include "stat.h" #include "symlink.h" #include "truncate.h" @@ -39,6 +50,254 @@ namespace ModuleFileIO { using namespace std; using namespace OHOS::FileManagement::LibN; +napi_value PropNExporter::AccessSync(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 [succ, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succ) { + HILOGE("Invalid path from JS first argument"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + bool isAccess = false; + std::unique_ptr access_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!access_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_access(nullptr, access_req.get(), path.get(), 0, nullptr); + if (ret < 0 && errno != ENOENT) { + HILOGE("Failed to access file by path"); + NError(errno).ThrowErr(env); + return nullptr; + } + if (ret == 0) { + isAccess = true; + } + return NVal::CreateBool(env, isAccess).val_; +} + +napi_value PropNExporter::Access(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [succ, tmp, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succ) { + HILOGE("Invalid path from JS first argument"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto result = make_shared(); + if (result == nullptr) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + auto cbExec = [path = string(tmp.get()), result]() -> NError { + std::unique_ptr access_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!access_req) { + HILOGE("Failed to request heap memory."); + return NError(ENOMEM); + } + int ret = uv_fs_access(nullptr, access_req.get(), path.c_str(), 0, nullptr); + if (ret == 0) { + result->isAccess = true; + } + return (ret < 0 && errno != ENOENT) ? NError(errno) : NError(ERRNO_NOERR); + }; + + auto cbComplete = [result](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return NVal::CreateBool(env, result->isAccess); + }; + + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::ONE) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_ACCESS_NAME, cbExec, cbComplete).val_; + } else { + NVal cb(env, funcArg[NARG_POS::SECOND]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_ACCESS_NAME, cbExec, cbComplete).val_; + } +} + +napi_value PropNExporter::Unlink(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) { + HILOGE("Number of Arguments Unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [succ, tmp, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succ) { + HILOGE("Invalid path from JS first argument"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto cbExec = [path = string(tmp.get())]() -> NError { + std::unique_ptr unlink_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!unlink_req) { + HILOGE("Failed to request heap memory."); + return NError(ENOMEM); + } + int ret = uv_fs_unlink(nullptr, unlink_req.get(), path.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to unlink with path"); + return NError(errno); + } + return NError(ERRNO_NOERR); + }; + + auto cbCompl = [](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return { NVal::CreateUndefined(env) }; + }; + + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::ONE) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_UNLINK_NAME, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[NARG_POS::SECOND]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_UNLINK_NAME, cbExec, cbCompl).val_; + } +} + +napi_value PropNExporter::UnlinkSync(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 [succ, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succ) { + HILOGE("Invalid path from JS first argument"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + std::unique_ptr unlink_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!unlink_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_unlink(nullptr, unlink_req.get(), path.get(), nullptr); + if (ret < 0) { + HILOGE("Failed to unlink with path"); + NError(errno).ThrowErr(env); + return nullptr; + } + + return NVal::CreateUndefined(env).val_; +} + +napi_value PropNExporter::Mkdir(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [succ, tmp, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succ) { + HILOGE("Invalid path from JS first argument"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto cbExec = [path = string(tmp.get())]() -> NError { + std::unique_ptr mkdir_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!mkdir_req) { + HILOGE("Failed to request heap memory."); + return NError(ENOMEM); + } + int ret = uv_fs_mkdir(nullptr, mkdir_req.get(), path.c_str(), DIR_DEFAULT_PERM, nullptr); + if (ret < 0) { + HILOGE("Failed to create directory"); + return NError(errno); + } + return NError(ERRNO_NOERR); + }; + + auto cbCompl = [](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return { NVal::CreateUndefined(env) }; + }; + + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::ONE) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_MKDIR_NAME, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[NARG_POS::SECOND]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_MKDIR_NAME, cbExec, cbCompl).val_; + } +} + +napi_value PropNExporter::MkdirSync(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 [succ, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succ) { + HILOGE("Invalid path from JS first argument"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + std::unique_ptr mkdir_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!mkdir_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_mkdir(nullptr, mkdir_req.get(), path.get(), DIR_DEFAULT_PERM, nullptr); + if (ret < 0) { + HILOGE("Failed to create directory"); + NError(errno).ThrowErr(env); + return nullptr; + } + + return NVal::CreateUndefined(env).val_; +} + napi_value PropNExporter::ReadSync(napi_env env, napi_callback_info info) { NFuncArg funcArg(env, info); @@ -49,16 +308,22 @@ napi_value PropNExporter::ReadSync(napi_env env, napi_callback_info info) return nullptr; } - auto [succ, fd] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); + bool succ = false; + int fd = 0; + tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); if (!succ) { - HILOGE("Invalid fd"); + HILOGE("Invalid fd from JS first argument"); NError(EINVAL).ThrowErr(env); return nullptr; } - auto [res, buf, len, hasPos, pos] = + void *buf = nullptr; + int64_t len = 0; + bool hasOffset = false; + int64_t offset = 0; + tie(succ, buf, len, hasOffset, offset) = CommonFunc::GetReadArg(env, funcArg[NARG_POS::SECOND], funcArg[NARG_POS::THIRD]); - if (!res) { + if (!succ) { HILOGE("Failed to resolve buf and options"); NError(EINVAL).ThrowErr(env); return nullptr; @@ -66,34 +331,38 @@ napi_value PropNExporter::ReadSync(napi_env env, napi_callback_info info) ssize_t actLen; uv_buf_t buffer = uv_buf_init(static_cast(buf), len); - uv_fs_t read_req; - int ret = uv_fs_read(nullptr, &read_req, fd, &buffer, 1, pos, nullptr); + std::unique_ptr read_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!read_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_read(nullptr, read_req.get(), fd, &buffer, 1, offset, nullptr); if (ret < 0) { HILOGE("Failed to read file for %{public}d", ret); NError(errno).ThrowErr(env); return nullptr; } - actLen = read_req.result; - uv_fs_req_cleanup(&read_req); - + actLen = ret; return NVal::CreateInt64(env, actLen).val_; } -struct AsyncIOReadArg { - ssize_t lenRead { 0 }; -}; - -static NError ReadExec(shared_ptr arg, void *buf, size_t len, int fd, size_t position) +static NError ReadExec(shared_ptr arg, void *buf, size_t len, int fd, size_t offset) { uv_buf_t buffer = uv_buf_init(static_cast(buf), len); - uv_fs_t read_req; - int ret = uv_fs_read(nullptr, &read_req, fd, &buffer, 1, static_cast(position), nullptr); + std::unique_ptr read_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!read_req) { + HILOGE("Failed to request heap memory."); + return NError(ENOMEM); + } + int ret = uv_fs_read(nullptr, read_req.get(), fd, &buffer, 1, static_cast(offset), nullptr); if (ret < 0) { HILOGE("Failed to read file for %{public}d", ret); return NError(errno); } - arg->lenRead = read_req.result; - uv_fs_req_cleanup(&read_req); + arg->lenRead = ret; return NError(ERRNO_NOERR); } @@ -106,24 +375,35 @@ napi_value PropNExporter::Read(napi_env env, napi_callback_info info) return nullptr; } - auto [succ, fd] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); + bool succ = false; + void *buf = nullptr; + int64_t len = 0; + int fd = 0; + bool hasOffset = false; + int64_t offset = 0; + tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); if (!succ) { - HILOGE("Invalid fd"); + HILOGE("Invalid fd from JS first argument"); NError(EINVAL).ThrowErr(env); return nullptr; } - auto [res, buf, len, hasPos, pos] = + tie(succ, buf, len, hasOffset, offset) = CommonFunc::GetReadArg(env, funcArg[NARG_POS::SECOND], funcArg[NARG_POS::THIRD]); - if (!res) { + if (!succ) { HILOGE("Failed to resolve buf and options"); NError(EINVAL).ThrowErr(env); return nullptr; } - auto arg = make_shared(); - auto cbExec = [arg, buf = buf, len = len, fd = fd, pos = pos, env = env]() -> NError { - return ReadExec(arg, buf, len, fd, pos); + auto arg = make_shared(NVal(env, funcArg[NARG_POS::SECOND])); + if (!arg) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + auto cbExec = [arg, buf = buf, len = len, fd = fd, offset = offset]() -> NError { + return ReadExec(arg, buf, len, fd, offset); }; auto cbCompl = [arg](napi_env env, NError err) -> NVal { @@ -137,32 +417,34 @@ napi_value PropNExporter::Read(napi_env env, napi_callback_info info) bool hasOp = false; if (funcArg.GetArgc() == NARG_CNT::THREE) { NVal op = NVal(env, funcArg[NARG_POS::THIRD]); - if (op.HasProp("offset") || op.HasProp("length")|| !op.TypeIs(napi_function)) { + if (op.HasProp("offset") || op.HasProp("length") || !op.TypeIs(napi_function)) { hasOp = true; } } if (funcArg.GetArgc() == NARG_CNT::TWO || (funcArg.GetArgc() == NARG_CNT::THREE && hasOp)) { - return NAsyncWorkPromise(env, thisVar).Schedule("FileIORead", cbExec, cbCompl).val_; + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_READ_NAME, cbExec, cbCompl).val_; } else { int cbIdx = ((funcArg.GetArgc() == NARG_CNT::THREE) ? NARG_POS::THIRD : NARG_POS::FOURTH); NVal cb(env, funcArg[cbIdx]); - return NAsyncWorkCallback(env, thisVar, cb).Schedule("FileIORead", cbExec, cbCompl).val_; + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_READ_NAME, cbExec, cbCompl).val_; } - - return NVal::CreateUndefined(env).val_; } -NError PropNExporter::WriteExec(shared_ptr arg, void *buf, size_t len, int fd, size_t position) +NError PropNExporter::WriteExec(shared_ptr arg, void *buf, size_t len, int fd, size_t offset) { uv_buf_t buffer = uv_buf_init(static_cast(buf), len); - uv_fs_t write_req; - int ret = uv_fs_write(nullptr, &write_req, fd, &buffer, 1, static_cast(position), nullptr); + std::unique_ptr write_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!write_req) { + HILOGE("Failed to request heap memory."); + return NError(ENOMEM); + } + int ret = uv_fs_write(nullptr, write_req.get(), fd, &buffer, 1, static_cast(offset), nullptr); if (ret < 0) { HILOGE("Failed to write file for %{public}d", ret); return NError(errno); } - arg->actLen = write_req.result; - uv_fs_req_cleanup(&write_req); + arg->actLen = ret; return NError(ERRNO_NOERR); } @@ -175,29 +457,36 @@ napi_value PropNExporter::Write(napi_env env, napi_callback_info info) return nullptr; } - auto [succ, fd] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); + bool succ = false; + int fd; + tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); if (!succ) { - HILOGE("Invalid fd"); + HILOGE("Invalid fd from JS first argument"); NError(EINVAL).ThrowErr(env); return nullptr; } - auto [res, bufGuard, buf, len, hasPos, position] = + unique_ptr bufGuard; + void *buf = nullptr; + size_t len = 0; + size_t offset = 0; + bool hasOffset = false; + tie(succ, bufGuard, buf, len, hasOffset, offset) = CommonFunc::GetWriteArg(env, funcArg[NARG_POS::SECOND], funcArg[NARG_POS::THIRD]); - if (!res) { + if (!succ) { HILOGE("Failed to resolve buf and options"); NError(EINVAL).ThrowErr(env); return nullptr; } - shared_ptr arg; - if (bufGuard) { - arg = make_shared(move(bufGuard)); - } else { - arg = make_shared(NVal(env, funcArg[NARG_POS::SECOND])); + auto arg = make_shared(move(bufGuard)); + if (!arg) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; } - auto cbExec = [arg, buf = buf, len = len, fd = fd, position = position, env = env]() -> NError { - return WriteExec(arg, buf, len, fd, position); + auto cbExec = [arg, buf = buf, len = len, fd = fd, offset = offset]() -> NError { + return WriteExec(arg, buf, len, fd, offset); }; auto cbCompl = [arg](napi_env env, NError err) -> NVal { @@ -212,21 +501,18 @@ napi_value PropNExporter::Write(napi_env env, napi_callback_info info) bool hasOp = false; if (funcArg.GetArgc() == NARG_CNT::THREE) { NVal op = NVal(env, funcArg[NARG_POS::THIRD]); - if (op.HasProp("offset") || op.HasProp("position") || op.HasProp("length") || - op.HasProp("encoding") || !op.TypeIs(napi_function)) { + if (op.HasProp("offset") || op.HasProp("length") || op.HasProp("encoding") || !op.TypeIs(napi_function)) { hasOp = true; } } if (funcArg.GetArgc() == NARG_CNT::TWO || (funcArg.GetArgc() == NARG_CNT::THREE && hasOp)) { - return NAsyncWorkPromise(env, thisVar).Schedule("FileIOWrite", cbExec, cbCompl).val_; + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_WRITE_NAME, cbExec, cbCompl).val_; } else { int cbIdx = ((funcArg.GetArgc() == NARG_CNT::THREE) ? NARG_POS::THIRD : NARG_POS::FOURTH); NVal cb(env, funcArg[cbIdx]); - return NAsyncWorkCallback(env, thisVar, cb).Schedule("FileIOWrite", cbExec, cbCompl).val_; + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_WRITE_NAME, cbExec, cbCompl).val_; } - - return NVal::CreateUndefined(env).val_; } napi_value PropNExporter::WriteSync(napi_env env, napi_callback_info info) @@ -238,50 +524,87 @@ napi_value PropNExporter::WriteSync(napi_env env, napi_callback_info info) return nullptr; } - auto [succ, fd] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); + bool succ = false; + int fd; + tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32(); if (!succ) { - HILOGE("Invalid fd"); + HILOGE("Invalid fd from JS first argument"); NError(EINVAL).ThrowErr(env); return nullptr; } - auto [res, bufGuard, buf, len, hasPos, position] = + void *buf = nullptr; + size_t len = 0; + size_t offset = 0; + unique_ptr bufGuard; + bool hasOffset = false; + tie(succ, bufGuard, buf, len, hasOffset, offset) = CommonFunc::GetWriteArg(env, funcArg[NARG_POS::SECOND], funcArg[NARG_POS::THIRD]); - if (!res) { + if (!succ) { HILOGE("Failed to resolve buf and options"); return nullptr; } ssize_t writeLen; uv_buf_t buffer = uv_buf_init(static_cast(buf), len); - uv_fs_t write_req; - int ret = uv_fs_write(nullptr, &write_req, fd, &buffer, 1, static_cast(position), nullptr); + std::unique_ptr write_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!write_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_write(nullptr, write_req.get(), fd, &buffer, 1, static_cast(offset), nullptr); if (ret < 0) { HILOGE("Failed to write file for %{public}d", ret); NError(errno).ThrowErr(env); return nullptr; } - writeLen = write_req.result; - uv_fs_req_cleanup(&write_req); - + writeLen = ret; return NVal::CreateInt64(env, writeLen).val_; } bool PropNExporter::Export() { return exports_.AddProp({ + NVal::DeclareNapiFunction("access", Access), + NVal::DeclareNapiFunction("accessSync", AccessSync), + NVal::DeclareNapiFunction("close", Close::Async), + NVal::DeclareNapiFunction("closeSync", Close::Sync), + NVal::DeclareNapiFunction("copyFile", CopyFile::Async), + NVal::DeclareNapiFunction("copyFileSync", CopyFile::Sync), + NVal::DeclareNapiFunction("createStream", CreateStream::Async), + NVal::DeclareNapiFunction("createStreamSync", CreateStream::Sync), + NVal::DeclareNapiFunction("fdatasync", Fdatasync::Async), + NVal::DeclareNapiFunction("fdatasyncSync", Fdatasync::Sync), + NVal::DeclareNapiFunction("fdopenStream", FdopenStream::Async), + NVal::DeclareNapiFunction("fdopenStreamSync", FdopenStream::Sync), + NVal::DeclareNapiFunction("fsync", Fsync::Async), + NVal::DeclareNapiFunction("fsyncSync", Fsync::Sync), NVal::DeclareNapiFunction("lstat", Lstat::Async), NVal::DeclareNapiFunction("lstatSync", Lstat::Sync), + NVal::DeclareNapiFunction("mkdir", Mkdir), + NVal::DeclareNapiFunction("mkdirSync", MkdirSync), + NVal::DeclareNapiFunction("mkdtemp", Mkdtemp::Async), + NVal::DeclareNapiFunction("mkdtempSync", Mkdtemp::Sync), NVal::DeclareNapiFunction("open", Open::Async), NVal::DeclareNapiFunction("openSync", Open::Sync), NVal::DeclareNapiFunction("read", Read), NVal::DeclareNapiFunction("readSync", ReadSync), + NVal::DeclareNapiFunction("readText", ReadText::Async), + NVal::DeclareNapiFunction("readTextSync", ReadText::Sync), + NVal::DeclareNapiFunction("rename", Rename::Async), + NVal::DeclareNapiFunction("renameSync", Rename::Sync), + NVal::DeclareNapiFunction("rmdir", Rmdirent::Async), + NVal::DeclareNapiFunction("rmdirSync", Rmdirent::Sync), NVal::DeclareNapiFunction("stat", Stat::Async), NVal::DeclareNapiFunction("statSync", Stat::Sync), NVal::DeclareNapiFunction("symlink", Symlink::Async), NVal::DeclareNapiFunction("symlinkSync", Symlink::Sync), NVal::DeclareNapiFunction("truncate", Truncate::Async), NVal::DeclareNapiFunction("truncateSync", Truncate::Sync), + NVal::DeclareNapiFunction("unlink", Unlink), + NVal::DeclareNapiFunction("unlinkSync", UnlinkSync), NVal::DeclareNapiFunction("write", Write), NVal::DeclareNapiFunction("writeSync", WriteSync), }); diff --git a/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.h b/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.h index 0e5bb66c8771c90c82a0223772c7b6658630f406..d9c335e8b111c57b9dc253796395c5fad1d0616d 100644 --- a/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.h +++ b/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 @@ -33,12 +33,30 @@ struct AsyncIOWrtieArg { ~AsyncIOWrtieArg() = default; }; +struct AsyncAccessArg { + bool isAccess = false; +}; + +struct AsyncIOReadArg { + ssize_t lenRead { 0 }; + NRef refReadBuf; + + explicit AsyncIOReadArg(NVal jsReadBuf) : refReadBuf(jsReadBuf) {} + ~AsyncIOReadArg() = default; +}; + class PropNExporter final : public NExporter { public: inline static const std::string className_ = "__properities__"; + static napi_value AccessSync(napi_env env, napi_callback_info info); + static napi_value MkdirSync(napi_env env, napi_callback_info info); static napi_value ReadSync(napi_env env, napi_callback_info info); + static napi_value UnlinkSync(napi_env env, napi_callback_info info); static napi_value WriteSync(napi_env env, napi_callback_info info); + static napi_value Access(napi_env env, napi_callback_info info); + static napi_value Unlink(napi_env env, napi_callback_info info); + static napi_value Mkdir(napi_env env, napi_callback_info info); static napi_value Read(napi_env env, napi_callback_info info); static napi_value Write(napi_env env, napi_callback_info info); static NError WriteExec(std::shared_ptr arg, void *buf, size_t len, int fd, size_t position); @@ -48,6 +66,13 @@ public: PropNExporter(napi_env env, napi_value exports); ~PropNExporter() override; }; + +constexpr int DIR_DEFAULT_PERM = 0770; +const std::string PROCEDURE_ACCESS_NAME = "FileIOAccess"; +const std::string PROCEDURE_UNLINK_NAME = "FileIOUnlink"; +const std::string PROCEDURE_MKDIR_NAME = "FileIOMkdir"; +const std::string PROCEDURE_READ_NAME = "FileIORead"; +const std::string PROCEDURE_WRITE_NAME = "FileIOWrite"; } // namespace ModuleFileIO } // namespace FileManagement } // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fs/properties/read_text.cpp b/interfaces/kits/js/src/mod_fs/properties/read_text.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0adbbf2f407e13b505df1cf30817861e8b782c09 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/read_text.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (c) 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 "read_text.h" + +#include +#include +#include +#include +#include + +#include "common_func.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +static tuple, bool> GetReadTextArg(napi_env env, napi_value argOption) +{ + NVal op(env, argOption); + ssize_t offset = 0; + ssize_t len = 0; + bool succ = false; + bool hasOp = false; + bool hasLen = false; + unique_ptr encoding; + + if (op.HasProp("offset")) { + tie(succ, offset) = op.GetProp("offset").ToInt32(); + if (!succ || offset < 0) { + HILOGE("Illegal option.offset parameter"); + return { false, offset, hasLen, len, nullptr, hasOp }; + } + hasOp = true; + } + + if (op.HasProp("length")) { + tie(succ, len) = op.GetProp("length").ToInt32(); + if (!succ || len < 0) { + HILOGE("Illegal option.length parameter"); + return { false, offset, hasLen, len, nullptr, hasOp }; + } + hasOp = true; + hasLen = true; + } + + if (op.HasProp("encoding")) { + auto [succ, encoding, unuse] = op.GetProp("encoding").ToUTF8String(); + if (!succ) { + HILOGE("Illegal option.encoding parameter"); + return { false, offset, hasLen, len, nullptr, hasOp }; + } + hasOp = true; + } + + if (!op.TypeIs(napi_function)) { + hasOp = true; + } + + return { true, offset, hasLen, len, move(encoding), hasOp }; +} + +static NError ReadTextAsync(const std::string path, std::shared_ptr arg, ssize_t offset, + bool hasLen, ssize_t len) +{ + OHOS::DistributedFS::FDGuard sfd; + struct stat statbf; + std::unique_ptr open_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!open_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + int ret = uv_fs_open(nullptr, open_req.get(), path.c_str(), O_RDONLY, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, nullptr); + if (ret < 0) { + HILOGE("Failed to open file, ret: %{public}d", ret); + return NError(errno); + } + + sfd.SetFD(ret); + if (sfd.GetFD() < 0) { + HILOGE("Failed to open file by path"); + return NError(errno); + } + if (fstat(sfd.GetFD(), &statbf) < 0) { + HILOGE("Failed to get stat of file by fd: %{public}d", sfd.GetFD()); + return NError(errno); + } + + if (offset > statbf.st_size) { + HILOGE("Invalid offset"); + return NError(EINVAL); + } + + len = (!hasLen || len > statbf.st_size) ? statbf.st_size : len; + string buffer(len, '\0'); + uv_buf_t readbuf = uv_buf_init(const_cast(buffer.c_str()), len); + std::unique_ptr read_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!read_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + arg->len = uv_fs_read(nullptr, read_req.get(), sfd.GetFD(), &readbuf, 1, offset, nullptr); + if (arg->len < 0) { + HILOGE("Failed to read file by fd: %{public}d", sfd.GetFD()); + return NError(errno); + } + arg->buffer = buffer; + return NError(ERRNO_NOERR); +} + +napi_value ReadText::Sync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetFirstArg, path, unused] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!resGetFirstArg) { + HILOGE("Invalid path"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetReadTextArg, offset, hasLen, len, encoding, useless] = GetReadTextArg(env, funcArg[NARG_POS::SECOND]); + if (!resGetReadTextArg) { + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + OHOS::DistributedFS::FDGuard sfd; + std::unique_ptr open_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!open_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_open(nullptr, open_req.get(), path.get(), O_RDONLY, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, nullptr); + if (ret < 0) { + HILOGE("Failed to open file by ret: %{public}d", ret); + NError(errno).ThrowErr(env); + return nullptr; + } + sfd.SetFD(ret); + struct stat statbf; + if ((!sfd) || (fstat(sfd.GetFD(), &statbf) < 0)) { + HILOGE("Failed to get stat of file by fd: %{public}d", sfd.GetFD()); + NError(errno).ThrowErr(env); + return nullptr; + } + + if (offset > statbf.st_size) { + HILOGE("Invalid offset: %{public}zd", offset); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + len = (!hasLen || len > statbf.st_size) ? statbf.st_size : len; + string buffer(len, '\0'); + uv_buf_t readbuf = uv_buf_init(const_cast(buffer.c_str()), len); + std::unique_ptr read_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!read_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + ret = uv_fs_read(nullptr, read_req.get(), sfd.GetFD(), &readbuf, 1, offset, nullptr); + if (ret < 0) { + HILOGE("Failed to read file by fd: %{public}d", sfd.GetFD()); + NError(errno).ThrowErr(env); + return nullptr; + } + + return NVal::CreateUTF8String(env, readbuf.base, ret).val_; +} + +napi_value ReadText::Async(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetFirstArg, path, unused] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!resGetFirstArg) { + HILOGE("Invalid path"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetSecondArg, offset, hasLen, len, encoding, hasOp] = GetReadTextArg(env, funcArg[NARG_POS::SECOND]); + if (!resGetSecondArg) { + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto arg = make_shared(NVal(env, funcArg.GetThisVar())); + auto cbExec = [path = string(path.get()), arg, offset = offset, hasLen = hasLen, len = len]() -> NError { + return ReadTextAsync(path, arg, offset, hasLen, len); + }; + + auto cbComplete = [arg](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return NVal::CreateUTF8String(env, arg->buffer.c_str(), arg->len); + } + }; + + size_t argc = funcArg.GetArgc(); + NVal thisVar(env, funcArg.GetThisVar()); + if (argc == NARG_CNT::ONE || (argc == NARG_CNT::TWO && hasOp)) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_READTEXT_NAME, cbExec, cbComplete).val_; + } else { + int cbIdx = !hasOp ? NARG_POS::SECOND : NARG_POS::THIRD; + NVal cb(env, funcArg[cbIdx]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_READTEXT_NAME, cbExec, cbComplete).val_; + } +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/read_text.h b/interfaces/kits/js/src/mod_fs/properties/read_text.h new file mode 100644 index 0000000000000000000000000000000000000000..71dac4eb666d3af85ff52e3414919ee438d91a02 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/read_text.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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_READ_TEXT_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_TEXT_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace OHOS::FileManagement::LibN; +class ReadText final { +public: + static napi_value Async(napi_env env, napi_callback_info info); + static napi_value Sync(napi_env env, napi_callback_info info); +}; + +struct AsyncReadTextArg { + NRef _refReadBuf; + std::string buffer; + ssize_t len = 0; + + explicit AsyncReadTextArg(NVal refReadBuf) : _refReadBuf(refReadBuf){}; + ~AsyncReadTextArg() = default; +}; + +const std::string PROCEDURE_READTEXT_NAME = "FileIOReadText"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_TEXT_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/rename.cpp b/interfaces/kits/js/src/mod_fs/properties/rename.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd05e02f83c4e233b216ab691ad3c31240ba6c2c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/rename.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 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 "rename.h" + +#include +#include +#include + +#include "common_func.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +napi_value Rename::Sync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetFirstArg, src, unused] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!resGetFirstArg) { + HILOGE("Invalid src"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetSecondArg, dest, useless] = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String(); + if (!resGetSecondArg) { + HILOGE("Invalid dest"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + std::unique_ptr rename_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!rename_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_rename(nullptr, rename_req.get(), src.get(), dest.get(), nullptr); + if (ret < 0) { + HILOGE("Failed to rename file with path"); + NError(errno).ThrowErr(env); + return nullptr; + } + + return NVal::CreateUndefined(env).val_; +} + +napi_value Rename::Async(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetFirstArg, src, unused] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!resGetFirstArg) { + HILOGE("Invalid src"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [resGetSecondArg, dest, useless] = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String(); + if (!resGetSecondArg) { + HILOGE("Invalid dest"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto cbExec = [opath = string(src.get()), npath = string(dest.get())]() -> NError { + std::unique_ptr rename_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!rename_req) { + HILOGE("Failed to request heap memory."); + return NError(ENOMEM); + } + int ret = uv_fs_rename(nullptr, rename_req.get(), opath.c_str(), npath.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to rename file with path"); + return NError(errno); + } + return NError(ERRNO_NOERR); + }; + + auto cbComplCallback = [](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return { NVal::CreateUndefined(env) }; + }; + + NVal thisVar(env, funcArg.GetThisVar()); + size_t argc = funcArg.GetArgc(); + if (argc == NARG_CNT::TWO) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_RENAME_NAME, cbExec, cbComplCallback).val_; + } else { + NVal cb(env, funcArg[NARG_POS::THIRD]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_RENAME_NAME, cbExec, cbComplCallback).val_; + } +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/rename.h b/interfaces/kits/js/src/mod_fs/properties/rename.h new file mode 100644 index 0000000000000000000000000000000000000000..32def34f2f630b6292f6f803547560ac2f782780 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/rename.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 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_RENAME_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_RENAME_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class Rename final { +public: + static napi_value Sync(napi_env env, napi_callback_info info); + static napi_value Async(napi_env env, napi_callback_info info); +}; +const std::string PROCEDURE_RENAME_NAME = "FileIORename"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_RENAME_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/rmdirent.cpp b/interfaces/kits/js/src/mod_fs/properties/rmdirent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c31c76a7bc615534b917bd95e5b67d852b1b701 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/rmdirent.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 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 "rmdirent.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +static NError RmDirent(const string &fpath) +{ + std::filesystem::path strToPath(fpath); + std::uintmax_t num = std::filesystem::remove_all(strToPath); + if (!num || std::filesystem::exists(strToPath)) { + HILOGE("Failed to remove file or directory by path"); + return NError(errno); + } + + return NError(ERRNO_NOERR); +} + +napi_value Rmdirent::Sync(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 [succ, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succ) { + HILOGE("Invalid path from JS first argument"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto err = RmDirent(string(path.get())); + if (err) { + err.ThrowErr(env); + return nullptr; + } + + return NVal::CreateUndefined(env).val_; +} + +napi_value Rmdirent::Async(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [succ, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succ) { + HILOGE("Invalid path from JS first argument"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto cbExec = [tmpPath = string(path.get())]() -> NError { + return RmDirent(tmpPath); + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return NVal::CreateUndefined(env); + } + }; + + NVal thisVar(env, funcArg.GetThisVar()); + size_t argc = funcArg.GetArgc(); + if (argc == NARG_CNT::ONE) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_RMDIRENT_NAME, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[NARG_POS::SECOND]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_RMDIRENT_NAME, cbExec, cbCompl).val_; + } +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/rmdirent.h b/interfaces/kits/js/src/mod_fs/properties/rmdirent.h new file mode 100644 index 0000000000000000000000000000000000000000..d78c5d4af55fbb386ffb056ced35d224b531a061 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/rmdirent.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 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_RMDIRENT_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_RMDIRENT_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class Rmdirent final { +public: + static napi_value Sync(napi_env env, napi_callback_info info); + static napi_value Async(napi_env env, napi_callback_info info); +}; +const std::string PROCEDURE_RMDIRENT_NAME = "FileIORmDirent"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_RMDIRENT_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/symlink.cpp b/interfaces/kits/js/src/mod_fs/properties/symlink.cpp index 9699168a4a3157115ff915ad24708368e2d0ba59..8ec7ab3a183dc725d3e089d05ac51480095442de 100644 --- a/interfaces/kits/js/src/mod_fs/properties/symlink.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/symlink.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 @@ -20,9 +20,12 @@ #include #include +#include "common_func.h" #include "filemgmt_libhilog.h" -namespace OHOS::FileManagement::ModuleFileIO { +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { using namespace std; using namespace OHOS::FileManagement::LibN; @@ -30,15 +33,11 @@ static tuple GetSymlinkArg(napi_env env, const NFuncArg &f { auto [resGetFirstArg, src, unused] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); if (!resGetFirstArg) { - HILOGE("Invalid src"); - NError(EINVAL).ThrowErr(env); return { false, "", "" }; } auto [resGetSecondArg, dest, useless] = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String(); if (!resGetSecondArg) { - HILOGE("Invalid dest"); - NError(EINVAL).ThrowErr(env); return { false, "", "" }; } @@ -56,12 +55,21 @@ napi_value Symlink::Sync(napi_env env, napi_callback_info info) auto [resGetSymlinkArg, oldPath, newPath] = GetSymlinkArg(env, funcArg); if (!resGetSymlinkArg) { + HILOGE("Failed to get symlink arguments"); NError(EINVAL).ThrowErr(env); return nullptr; } - if (symlink(oldPath.c_str(), newPath.c_str()) < 0) { - HILOGE("Failed to create a link for old path: %{public}s", oldPath.c_str()); + std::unique_ptr symlink_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!symlink_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_symlink(nullptr, symlink_req.get(), oldPath.c_str(), newPath.c_str(), 0, nullptr); + if (ret < 0) { + HILOGE("Failed to create a link for old path"); NError(errno).ThrowErr(env); return nullptr; } @@ -80,18 +88,24 @@ napi_value Symlink::Async(napi_env env, napi_callback_info info) auto [resGetSymlinkArg, oldPath, newPath] = GetSymlinkArg(env, funcArg); if (!resGetSymlinkArg) { + HILOGE("Failed to get symlink arguments"); NError(EINVAL).ThrowErr(env); return nullptr; } auto cbExec = [oldPath = move(oldPath), newPath = move(newPath)]() -> NError { - int ret = symlink(oldPath.c_str(), newPath.c_str()); + std::unique_ptr symlink_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!symlink_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + int ret = uv_fs_symlink(nullptr, symlink_req.get(), oldPath.c_str(), newPath.c_str(), 0, nullptr); if (ret < 0) { - HILOGE("Failed to create a link for old path: %{public}s, ret: %{public}d", oldPath.c_str(), ret); + HILOGE("Failed to create a link for old path"); return NError(errno); - } else { - return NError(ERRNO_NOERR); } + return NError(ERRNO_NOERR); }; auto cbComplCallback = [](napi_env env, NError err) -> NVal { @@ -101,14 +115,15 @@ napi_value Symlink::Async(napi_env env, napi_callback_info info) return { NVal::CreateUndefined(env) }; }; - const string procedureName = "FileIOSymLink"; NVal thisVar(env, funcArg.GetThisVar()); size_t argc = funcArg.GetArgc(); if (argc == NARG_CNT::TWO) { - return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplCallback).val_; + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_SYMLINK_NAME, cbExec, cbComplCallback).val_; } else { NVal cb(env, funcArg[NARG_POS::THIRD]); - return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplCallback).val_; + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_SYMLINK_NAME, cbExec, cbComplCallback).val_; } } -} // namespace OHOS::FileManagement::ModuleFileIO +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fs/properties/symlink.h b/interfaces/kits/js/src/mod_fs/properties/symlink.h index 0b14e8bec6259b8a39019db02047bce7a0c02c75..a9b7abeb1b8b0f7c72b8f0ef8a15ae05a8c1a785 100644 --- a/interfaces/kits/js/src/mod_fs/properties/symlink.h +++ b/interfaces/kits/js/src/mod_fs/properties/symlink.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 @@ -18,11 +18,17 @@ #include "filemgmt_libn.h" -namespace OHOS::FileManagement::ModuleFileIO { +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { class Symlink final { public: static napi_value Async(napi_env env, napi_callback_info info); static napi_value Sync(napi_env env, napi_callback_info info); }; -} // namespace OHOS::FileManagement::ModuleFileIO + +const std::string PROCEDURE_SYMLINK_NAME = "FileIOSymLink"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS #endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_SYMLINK_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/truncate.cpp b/interfaces/kits/js/src/mod_fs/properties/truncate.cpp index 0c0e9db88b19213b96c1ec9e78643484cd60fe3a..f6eb9e5600269176754e1ce03c77f4776015831f 100644 --- a/interfaces/kits/js/src/mod_fs/properties/truncate.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/truncate.cpp @@ -21,7 +21,6 @@ #include "../common_func.h" #include "filemgmt_libhilog.h" -#include "uv.h" namespace OHOS::FileManagement::ModuleFileIO { using namespace std; @@ -65,22 +64,40 @@ napi_value Truncate::Sync(napi_env env, napi_callback_info info) } } if (fileInfo.isPath) { - std::unique_ptr open_req = { new uv_fs_t, uv_fs_req_cleanup }; + std::unique_ptr open_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!open_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } int ret = uv_fs_open(nullptr, open_req.get(), fileInfo.path.get(), O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, nullptr); if (ret < 0) { NError(errno).ThrowErr(env); return nullptr; } - std::unique_ptr ftruncate_req = { new uv_fs_t, uv_fs_req_cleanup }; - ret = uv_fs_ftruncate(nullptr, ftruncate_req.get(), open_req.get()->result, truncateLen, nullptr); + std::unique_ptr ftruncate_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!ftruncate_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + ret = uv_fs_ftruncate(nullptr, ftruncate_req.get(), ret, truncateLen, nullptr); if (ret < 0) { HILOGE("Failed to truncate file by path"); NError(errno).ThrowErr(env); return nullptr; } } else { - std::unique_ptr ftruncate_req = { new uv_fs_t, uv_fs_req_cleanup }; + std::unique_ptr ftruncate_req = { + new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!ftruncate_req) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } int ret = uv_fs_ftruncate(nullptr, ftruncate_req.get(), fileInfo.fdg.GetFD(), truncateLen, nullptr); if (ret < 0) { HILOGE("Failed to truncate file by fd"); @@ -113,23 +130,35 @@ napi_value Truncate::Async(napi_env env, napi_callback_info info) } } auto cbExec = [fileInfo = make_shared(move(fileInfo)), truncateLen, env = env]() -> NError { - using uv_fs_unique_ptr_type = std::unique_ptr; + using uv_fs_unique_ptr_type = std::unique_ptr; if (fileInfo->isPath) { - uv_fs_unique_ptr_type open_req = { new uv_fs_t, uv_fs_req_cleanup }; - int ret = uv_fs_open(uv_default_loop(), open_req.get(), fileInfo->path.get(), O_RDWR, + uv_fs_unique_ptr_type open_req = { new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!open_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + int ret = uv_fs_open(nullptr, open_req.get(), fileInfo->path.get(), O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, nullptr); if (ret < 0) { return NError(errno); } - uv_fs_unique_ptr_type ftruncate_req = { new uv_fs_t, uv_fs_req_cleanup }; - ret = uv_fs_ftruncate(uv_default_loop(), ftruncate_req.get(), open_req.get()->result, truncateLen, nullptr); + uv_fs_unique_ptr_type ftruncate_req = { new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!ftruncate_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + ret = uv_fs_ftruncate(nullptr, ftruncate_req.get(), ret, truncateLen, nullptr); if (ret < 0) { HILOGE("Failed to truncate file by path"); return NError(errno); } } else { - uv_fs_unique_ptr_type ftruncate_req = { new uv_fs_t, uv_fs_req_cleanup }; - int ret = uv_fs_ftruncate(uv_default_loop(), ftruncate_req.get(), fileInfo->fdg.GetFD(), truncateLen, nullptr); + uv_fs_unique_ptr_type ftruncate_req = { new uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!ftruncate_req) { + HILOGE("Failed to request heap memory."); + return NError(ERRNO_NOERR); + } + int ret = uv_fs_ftruncate(nullptr, ftruncate_req.get(), fileInfo->fdg.GetFD(), truncateLen, nullptr); if (ret < 0) { HILOGE("Failed to truncate file by fd"); return NError(errno); diff --git a/utils/filemgmt_libn/include/n_class.h b/utils/filemgmt_libn/include/n_class.h index b4ec8c75a5cd791821e1abf213328ce8fe80e466..e82bffbe819a21157047b4cdce8aa230fc0e1640 100644 --- a/utils/filemgmt_libn/include/n_class.h +++ b/utils/filemgmt_libn/include/n_class.h @@ -68,6 +68,21 @@ public: return status == napi_ok; } + template static T *RemoveEntityOfFinal(napi_env env, napi_value objStat) + { + if (!env || !objStat) { + HILOGD("Empty input: env %d,obj %d", env == nullptr, objStat == nullptr); + return nullptr; + } + T *t = nullptr; + napi_status status = napi_remove_wrap(env, objStat, (void **)&t); + if (status != napi_ok) { + HILOGD("Cannot umwrap for pointer: %d", status); + return nullptr; + } + return t; + } + private: NClass() = default; ~NClass() = default;