From 789adafee2f3420fd2fd789dc60eaa41fdb63494 Mon Sep 17 00:00:00 2001 From: ningzuobin Date: Sat, 16 Jul 2022 18:25:03 +0800 Subject: [PATCH] =?UTF-8?q?file=5Fapi=E5=8A=9F=E8=83=BD=E4=BD=BF=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ningzuobin --- .../mod_fileio/class_watcher/watcher_entity.h | 53 +++++ .../class_watcher/watcher_n_exporter.cpp | 144 ++++++++++++ .../class_watcher/watcher_n_exporter.h | 41 ++++ .../kits/js/src/mod_fileio/common_func.cpp | 217 ++++++++++++++++++ .../kits/js/src/mod_fileio/common_func.h | 40 ++++ interfaces/kits/js/src/mod_fileio/module.cpp | 58 +++++ 6 files changed, 553 insertions(+) create mode 100644 interfaces/kits/js/src/mod_fileio/class_watcher/watcher_entity.h create mode 100644 interfaces/kits/js/src/mod_fileio/class_watcher/watcher_n_exporter.cpp create mode 100644 interfaces/kits/js/src/mod_fileio/class_watcher/watcher_n_exporter.h create mode 100644 interfaces/kits/js/src/mod_fileio/common_func.cpp create mode 100644 interfaces/kits/js/src/mod_fileio/common_func.h create mode 100644 interfaces/kits/js/src/mod_fileio/module.cpp diff --git a/interfaces/kits/js/src/mod_fileio/class_watcher/watcher_entity.h b/interfaces/kits/js/src/mod_fileio/class_watcher/watcher_entity.h new file mode 100644 index 000000000..ce604ee6b --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/class_watcher/watcher_entity.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 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_WATCHER_WATCHER_ENTITY_H +#define INTERFACES_KITS_JS_SRC_MOD_FILEIO_CLASS_WATCHER_WATCHER_ENTITY_H + +#include + +#include "../../common/napi/uni_header.h" + +namespace OHOS { +namespace DistributedFS { +namespace ModuleFileIO { +class WatcherHandleDeleter { +public: + void operator()(uv_fs_event_t *ptr) + { + if (ptr == nullptr) { + return; + } + + uv_fs_event_stop(ptr); + uv_handle_t *handle = reinterpret_cast(ptr); + uv_close(handle, [](uv_handle_t *handle) { delete handle; }); + } +}; + +struct WatcherInforArg { + int events = 0; + napi_env env = nullptr; + napi_ref ref = nullptr; +}; + +struct WatcherEntity { + std::unique_ptr data_; + std::unique_ptr fsEventReq_; +}; +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS +#endif diff --git a/interfaces/kits/js/src/mod_fileio/class_watcher/watcher_n_exporter.cpp b/interfaces/kits/js/src/mod_fileio/class_watcher/watcher_n_exporter.cpp new file mode 100644 index 000000000..f6c456ed1 --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/class_watcher/watcher_n_exporter.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2021 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 "watcher_n_exporter.h" + +#include +#include +#include +#include + +#include "../../common/log.h" +#include "../../common/napi/n_async/n_async_work_callback.h" +#include "../../common/napi/n_async/n_async_work_promise.h" +#include "../../common/napi/n_class.h" +#include "../../common/napi/n_func_arg.h" +#include "../../common/uni_error.h" +#include "securec.h" +#include "watcher_entity.h" + +namespace OHOS { +namespace DistributedFS { +namespace ModuleFileIO { +using namespace std; + +napi_value WatcherNExporter::Constructor(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched"); + return nullptr; + } + + unique_ptr watcherEntity = make_unique(); + if (!NClass::SetEntityFor(env, funcArg.GetThisVar(), move(watcherEntity))) { + UniError(EIO).ThrowErr(env, "INNER BUG. Failed to wrap entity for obj stat"); + return nullptr; + } + + return funcArg.GetThisVar(); +} + +napi_value WatcherNExporter::StopSync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched"); + return nullptr; + } + + auto watchEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!watchEntity) { + UniError(EINVAL).ThrowErr(env, "get watcherEntity fail"); + return nullptr; + } + + watchEntity->fsEventReq_.reset(); + return NVal::CreateUndefined(env).val_; +} + +napi_value WatcherNExporter::Stop(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) { + UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched"); + return nullptr; + } + + auto watchEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!watchEntity) { + UniError(EINVAL).ThrowErr(env, "get watcherEntity fail"); + return nullptr; + } + + auto cbExec = [watchEntity](napi_env env) -> UniError { + watchEntity->fsEventReq_.reset(); + return UniError(ERRNO_NOERR); + }; + + auto cbCompl = [](napi_env env, UniError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return { NVal::CreateUndefined(env) }; + }; + + const string procedureName = "FileIOCreaterWatcher"; + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::ZERO) { + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[NARG_POS::FIRST]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbCompl).val_; + } +} + +bool WatcherNExporter::Export() +{ + vector props = { + NVal::DeclareNapiFunction("stop", Stop), + NVal::DeclareNapiFunction("stopSync", StopSync), + }; + + string className = GetClassName(); + auto [resDefineClass, classValue) = NClass::DefineClass(exports_.env_, + className, + WatcherNExporter::Constructor, + std::move(props)); + if (!resDefineClass) { + UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to define class"); + return false; + } + + bool succ = NClass::SaveClass(exports_.env_, className, classValue); + if (!succ) { + UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to save class"); + return false; + } + + return exports_.AddProp(className, classValue); +} + +string WatcherNExporter::GetClassName() +{ + return WatcherNExporter::className_; +} + +WatcherNExporter::WatcherNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {} + +WatcherNExporter::~WatcherNExporter() {} +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fileio/class_watcher/watcher_n_exporter.h b/interfaces/kits/js/src/mod_fileio/class_watcher/watcher_n_exporter.h new file mode 100644 index 000000000..3d3502b7b --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/class_watcher/watcher_n_exporter.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 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_WATCHER_WATCHER_N_EXPORTER_H +#define INTERFACES_KITS_JS_SRC_MOD_FILEIO_CLASS_WATCHER_WATCHER_N_EXPORTER_H + +#include "../../common/napi/n_exporter.h" + +namespace OHOS { +namespace DistributedFS { +namespace ModuleFileIO { +class WatcherNExporter final : public NExporter { +public: + inline static const std::string className_ = "Watcher"; + + bool Export() override; + std::string GetClassName() override; + + static napi_value Constructor(napi_env env, napi_callback_info info); + static napi_value Stop(napi_env env, napi_callback_info info); + static napi_value StopSync(napi_env env, napi_callback_info info); + + WatcherNExporter(napi_env env, napi_value exports); + ~WatcherNExporter() override; +}; +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS +#endif diff --git a/interfaces/kits/js/src/mod_fileio/common_func.cpp b/interfaces/kits/js/src/mod_fileio/common_func.cpp new file mode 100644 index 000000000..d8d8e8577 --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/common_func.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_func.h" + +#include +#include +#include +#include +#include + +#include "../common/log.h" +#include "../common/napi/n_class.h" +#include "../common/napi/n_func_arg.h" +#include "../common/napi/n_val.h" +#include "../common/uni_error.h" + +namespace OHOS { +namespace DistributedFS { +namespace ModuleFileIO { +using namespace std; + +static tuple GetActualBuf(napi_env env, void *rawBuf, int64_t bufLen, NVal op) +{ + bool succ = false; + void *realBuf = nullptr; + int64_t opOffset = 0; + if (op.HasProp("offset")) { + tie(succ, opOffset) = op.GetProp("offset").ToInt64(); + if (!succ || opOffset < 0) { + UniError(EINVAL).ThrowErr(env, "Invalid option.offset, positive integer is desired"); + return { false, nullptr, opOffset }; + } else if (opOffset > bufLen) { + UniError(EINVAL).ThrowErr(env, "Invalid option.offset, buffer limit exceeded"); + return { false, nullptr, opOffset }; + } else { + realBuf = static_cast(rawBuf) + opOffset; + } + } else { + realBuf = rawBuf; + } + + return { true, realBuf, opOffset }; +} + +static tuple GetActualLen(napi_env env, int64_t bufLen, int64_t bufOff, NVal op) +{ + bool succ = false; + int64_t retLen; + if (op.HasProp("length")) { + int64_t opLength; + tie(succ, opLength) = op.GetProp("length").ToInt64(); + if (!succ) { + UniError(EINVAL).ThrowErr(env, "Invalid option.length, expect integer"); + return { false, 0 }; + } + + if (opLength < 0) { + retLen = (bufLen > bufOff) ? bufLen - bufOff : 0; + } else if ((bufLen > opLength) && (bufOff > bufLen - opLength)) { + UniError(EINVAL).ThrowErr(env, "Invalid option.length, buffer limit exceeded"); + return { false, 0 }; + } else { + retLen = opLength; + } + } else { + retLen = (bufLen > bufOff) ? bufLen - bufOff : 0; + } + + return { true, retLen }; +} + +tuple, unique_ptr> CommonFunc::GetCopyPathArg(napi_env env, + napi_value srcPath, + napi_value dstPath) +{ + auto [succ, src, unuse] = NVal(env, srcPath).ToUTF8String(); + if (!succ) { + return { false, nullptr, nullptr }; + } + + tie(res, dest, useless) = NVal(env, dstPath).ToUTF8String(); + if (!res) { + return { false, nullptr, nullptr }; + } + + return make_tuple(true, move(src), move(dest)); +} + +tuple CommonFunc::GetReadArg(napi_env env, + napi_value readBuf, + napi_value option) +{ + bool posAssigned = false; + int64_t position = 0; + NVal txt(env, readBuf); + auto [resToArraybuffer, buf, bufLen] = txt.ToArraybuffer(); + if (!resToArraybuffer) { + UniError(EINVAL).ThrowErr(env, "Invalid read buffer, expect arraybuffer"); + return { false, nullptr, 0, posAssigned, position, 0 }; + } + + NVal op = NVal(env, option); + auto [resGetActualBuf, retBuf, offset] = GetActualBuf(env, buf, bufLen, op); + if (!resGetActualBuf) { + return { false, nullptr, 0, posAssigned, position, 0 }; + } + + int64_t bufOff = static_cast(retBuf) - static_cast(buf); + auto [resGetActualLen, retLen] = GetActualLen(env, bufLen, bufOff, op); + if (!resGetActualLen) { + return { false, nullptr, 0, posAssigned, position, 0 }; + } + + if (op.HasProp("position")) { + auto [resGetProp, pos] = op.GetProp("position").ToInt64(); + if (resGetProp && pos >= 0) { + posAssigned = true; + position = pos; + } else { + UniError(EINVAL).ThrowErr(env, "option.position shall be positive number"); + return { false, nullptr, 0, posAssigned, position, 0 }; + } + } + + return { true, retBuf, retLen, posAssigned, position, offset }; +} + +static tuple, int64_t> DecodeString(napi_env env, NVal jsStr, NVal encoding) +{ + unique_ptr buf; + if (!jsStr.TypeIs(napi_string)) { + return { false, nullptr, 0 }; + } + + if (!encoding) { + return jsStr.ToUTF8String(); + } + + unique_ptr encodingBuf; + auto [resToUTF8String, encodingBuf, unuse] = encoding.ToUTF8String(); + if (!resToUTF8String) { + return { false, nullptr, 0 }; + } + + string encodingStr(encodingBuf.release()); + if (encodingStr == "utf-8") { + return jsStr.ToUTF8String(); + } else if (encodingStr == "utf-16") { + return jsStr.ToUTF16String(); + } else { + return { false, nullptr, 0 }; + } +} + +tuple, void *, int64_t, bool, int64_t> CommonFunc::GetWriteArg(napi_env env, + napi_value argWBuf, + napi_value argOption) +{ + bool hasPos = false; + int64_t retPos = 0; + bool succ = false; + void *buf = nullptr; + NVal op(env, argOption); + NVal jsBuffer(env, argWBuf); + auto [resDecodeString, bufferGuard, bufLen] = DecodeString(env, jsBuffer, op.GetProp("encoding")); + if (!resDecodeString) { + tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer(); + if (!succ) { + UniError(EINVAL).ThrowErr(env, "Illegal write buffer or encoding"); + return { false, nullptr, nullptr, 0, false, 0 }; + } + } else { + buf = bufferGuard.get(); + } + + auto [resGetActualBuf, retBuf, unused] = GetActualBuf(env, buf, bufLen, op); + if (!resGetActualBuf) { + return { false, nullptr, nullptr, 0, false, 0 }; + } + + int64_t bufOff = static_cast(retBuf) - static_cast(buf); + auto [resGetActualLen, retLen] = GetActualLen(env, bufLen, bufOff, op); + if (!resGetActualLen) { + return { false, nullptr, nullptr, 0, false, 0 }; + } + + /* To parse options - Where to begin writing */ + if (op.HasProp("position")) { + auto [resGetProp, position] = op.GetProp("position").ToInt32(); + if (!resGetProp || position < 0) { + UniError(EINVAL).ThrowErr(env, "option.position shall be positive number"); + return { false, nullptr, nullptr, 0, hasPos, retPos }; + } + hasPos = true; + retPos = position; + } else { + retPos = INVALID_POSITION; + } + + return { true, move(bufferGuard), retBuf, retLen, hasPos, retPos }; +} +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fileio/common_func.h b/interfaces/kits/js/src/mod_fileio/common_func.h new file mode 100644 index 000000000..f968bb40b --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/common_func.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 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_COMMON_FUNC_H +#define INTERFACES_KITS_JS_SRC_MOD_FILEIO_COMMON_FUNC_H + +#include "../common/napi/uni_header.h" + +namespace OHOS { +namespace DistributedFS { +namespace ModuleFileIO { +constexpr int64_t INVALID_POSITION = std::numeric_limits::max(); + +struct CommonFunc { + static std::tuple GetReadArg(napi_env env, + napi_value readBuf, + napi_value option); + static std::tuple, void *, int64_t, bool, int64_t> GetWriteArg(napi_env env, + napi_value argWBuf, + napi_value argOption); + static std::tuple, std::unique_ptr> GetCopyPathArg(napi_env env, + napi_value srcPath, + napi_value dstPath); +}; +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS +#endif \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fileio/module.cpp b/interfaces/kits/js/src/mod_fileio/module.cpp new file mode 100644 index 000000000..51bd91fd0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/module.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "../common/log.h" +#include "class_constants/constants.h" +#include "class_dir/dir_n_exporter.h" +#include "class_dirent/dirent_n_exporter.h" +#include "class_stat/stat_n_exporter.h" +#include "class_stream/stream_n_exporter.h" +#include "class_watcher/watcher_n_exporter.h" +#include "properties/prop_n_exporter.h" + +using namespace std; + +namespace OHOS { +namespace DistributedFS { +namespace ModuleFileIO { +static napi_value Export(napi_env env, napi_value exports) +{ + std::vector> products; + 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)); + 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()) { + HILOGE("INNER BUG. Failed to export class %{public}s for module fileio", product->GetClassName().c_str()); + return nullptr; + } else { + HILOGE("Class %{public}s for module fileio has been exported", product->GetClassName().c_str()); + } + } + return exports; +} + +NAPI_MODULE(fileio, Export) +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS \ No newline at end of file -- Gitee