From c03b758f25afdcc8695767c91158c094898c0fcf Mon Sep 17 00:00:00 2001 From: futurezhou Date: Tue, 10 Jan 2023 21:29:19 +0800 Subject: [PATCH] Add listfile interfaces for mod_fs Signed-off-by: futurezhou --- interfaces/kits/js/BUILD.gn | 16 +- .../js/src/mod_fs/properties/listfile.cpp | 375 ++++++++++++++ .../kits/js/src/mod_fs/properties/listfile.h | 63 +++ .../src/mod_fs/properties/prop_n_exporter.cpp | 465 +++++++++++++++--- 4 files changed, 851 insertions(+), 68 deletions(-) create mode 100755 interfaces/kits/js/src/mod_fs/properties/listfile.cpp create mode 100755 interfaces/kits/js/src/mod_fs/properties/listfile.h diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index 4a67419f1..5f3a81959 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022 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 @@ -117,11 +117,25 @@ 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/listfile.cpp", "src/mod_fs/properties/lstat.cpp", + "src/mod_fs/properties/mkdtemp.cpp", + "src/mod_fs/properties/move.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/mod_fs/properties/listfile.cpp b/interfaces/kits/js/src/mod_fs/properties/listfile.cpp new file mode 100755 index 000000000..81bdf513f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/listfile.cpp @@ -0,0 +1,375 @@ +/* + * 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 "listfile.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +thread_local OptionArgs g_optionArgs; + +static bool CheckSuffix(vector suffixs) +{ + for (string suffix : suffixs) { + if (suffix.length() <= 1 || suffix.length() > MAX_SUFFIX_LENGTH) { + return false; + } + if (suffix[0] != '.') { + return false; + } + for (size_t i = 1; i < suffix.length(); i++) { + if (!isalnum(suffix[i])) { + return false; + } + } + } + return true; +} + +static bool GetFileFilterParam(const NVal &argv, OHOS::DistributedFS::FileFilter *filter) +{ + bool ret = false; + if (argv.HasProp("suffix")) { + vector suffixs; + tie(ret, suffixs, ignore) = argv.GetProp("suffix").ToStringArray(); + if (!ret) { + HILOGE("Failed to get suffix prop."); + return false; + } + if (!CheckSuffix(suffixs) || suffixs.size() == 0) { + HILOGE("Invalid suffix."); + return false; + } + filter->SetSuffix(suffixs); + } + if (argv.HasProp("displayName")) { + vector displayNames; + tie(ret, displayNames, ignore) = argv.GetProp("displayName").ToStringArray(); + if (!ret) { + HILOGE("Failed to get displayname prop."); + return false; + } + if (displayNames.size() == 0) { + HILOGE("Invalid displayName."); + return false; + } + filter->SetDisplayName(displayNames); + } + if (argv.HasProp("fileSizeOver")) { + int64_t fileSizeOver; + tie(ret, fileSizeOver) = argv.GetProp("fileSizeOver").ToInt64(); + if (!ret || fileSizeOver < 0) { + HILOGE("Failed to get fileSizeOver prop."); + return false; + } + filter->SetFileSizeOver(fileSizeOver); + } + if (argv.HasProp("lastModifiedAfter")) { + double lastModifiedAfter; + tie(ret, lastModifiedAfter) = argv.GetProp("lastModifiedAfter").ToDouble(); + if (!ret || lastModifiedAfter < 0) { + HILOGE("Failed to get lastModifiedAfter prop."); + return false; + } + filter->SetLastModifiedAfter(lastModifiedAfter); + } + return true; +} + +static bool GetOptionParam(const NVal &argv, OptionArgs *optionArgs) +{ + bool succ = false; + if (argv.HasProp("listNum")) { + tie(succ, optionArgs->listNum) = argv.GetProp("listNum").ToInt64(); + if (!succ) { + HILOGE("Failed to get listNum prop."); + return false; + } + } + + if (argv.HasProp("recursion")) { + tie(succ, optionArgs->recursion) = argv.GetProp("recursion").ToBool(); + if (!succ) { + HILOGE("Failed to get recursion prop."); + return false; + } + } + + if (argv.HasProp("filter")) { + NVal(filterProp) = argv.GetProp("filter"); + auto ret = GetFileFilterParam(NVal(filterProp), &optionArgs->filter); + if (!ret) { + HILOGE("Failed to get filter prop."); + return false; + } + } + return true; +} + +static bool GetOptionArg(napi_env env, const NFuncArg &funcArg, OptionArgs &optionArgs, const string &path) +{ + auto options = NVal(env, funcArg[NARG_POS::SECOND]); + if (funcArg.GetArgc() >= NARG_CNT::TWO && options.TypeIs(napi_object)) { + if (!GetOptionParam(options, &optionArgs)) { + HILOGE("Invalid options"); + return false; + } + } else if (funcArg.GetArgc() >= NARG_CNT::TWO && !options.TypeIs(napi_function)) { + HILOGE("Invalid options"); + return false; + } + optionArgs.path = path; + return true; +} + +static bool FilterSuffix(const vector& suffixs, const struct dirent& filename) +{ + for (auto iter = suffixs.begin(); iter != suffixs.end(); iter++) { + string_view sv1(*iter); + string_view sv2((string(filename.d_name)).substr((string(filename.d_name)).find('.'), + (string(filename.d_name)).length() - 1)); + if (sv1 != sv2) { + return true; + } + } + return false; +} + +static bool FilterDisplayname(const vector& displaynames, const struct dirent& filename) +{ + for (auto iter = displaynames.begin(); iter != displaynames.end(); iter++) { + int ret = fnmatch((*iter).c_str(), filename.d_name, FNM_PATHNAME | FNM_PERIOD); + if (ret == 0) { + return true; + } + } + return false; +} + +static bool FilterFilesizeOver(const int64_t fFileSizeOver, const struct dirent& filename) +{ + struct stat info; + string stPath = (g_optionArgs.path + '/' + string(filename.d_name)); + int32_t res = stat(stPath.c_str(), &info); + if (res != 0) { + HILOGE("Failed to stat file."); + return false; + } + if (fFileSizeOver > info.st_size) { + return false; + } + return true; +} + +static bool FilterLastModifyTime(const double lastModifiedAfter, const struct dirent& filename) +{ + struct stat info; + string stPath = g_optionArgs.path + '/' + string(filename.d_name); + int32_t res = stat(stPath.c_str(), &info); + if (res != 0) { + HILOGE("Failed to stat file."); + return false; + } + if (lastModifiedAfter >= time(&info.st_mtime)) { + return false; + } + return true; +} + +static bool FilterResult(const struct dirent &filename) +{ + vector fSuffixs = g_optionArgs.filter.GetSuffix(); + if (!FilterSuffix(fSuffixs, filename) && fSuffixs.size() > 0) { + return false; + } + vector fDisplaynames = g_optionArgs.filter.GetDisplayName(); + if (!FilterDisplayname(fDisplaynames, filename) && fDisplaynames.size() > 0) { + return false; + } + int64_t fFileSizeOver = g_optionArgs.filter.GetFileSizeOver(); + if (!FilterFilesizeOver(fFileSizeOver, filename) && fFileSizeOver > 0) { + return false; + } + double fLastModifiedAfter = g_optionArgs.filter.GetLastModifiedAfter(); + if (!FilterLastModifyTime(fLastModifiedAfter, filename) && fLastModifiedAfter > 0) { + return false; + } + g_optionArgs.countNum++; + return true; +} + +static int32_t FilterFunc(const struct dirent *filename) +{ + if (string_view(filename->d_name) == "." || string_view(filename->d_name) == "..") { + return FILTER_DISMATCH; + } + + if (filename->d_type == DT_REG) { + if (g_optionArgs.countNum < g_optionArgs.listNum || g_optionArgs.listNum == 0) { + if (FilterResult(*filename)) { + return FILTER_MATCH; + } + } + } else if (filename->d_type == DT_DIR) { + return FILTER_MATCH; + } + return FILTER_DISMATCH; +} + +static vector FileterFileRes(string path) +{ + struct dirent** namelist; + int num = scandir(path.c_str(), &(namelist), FilterFunc, alphasort); + vector dirents; + for (int i = 0; i < num; i++) { + dirents.push_back(*namelist[i]); + free(namelist[i]); + } + free(namelist); + return dirents; +} + +static void RecursiveFunc(string path, vector &dirents) +{ + struct dirent** namelist; + int num = scandir(path.c_str(), &(namelist), FilterFunc, alphasort); + for (int i = 0; i < num; i++) { + if ((*namelist[i]).d_type == DT_REG) { + dirents.push_back(*namelist[i]); + } else if ((*(namelist)[i]).d_type == DT_DIR) { + g_optionArgs.path += '/' + string((*namelist[i]).d_name); + RecursiveFunc(g_optionArgs.path, dirents); + } + free(namelist[i]); + } + free(namelist); +} + +static napi_value DoListFileVector2NV(napi_env env, vector dirents) +{ + vector strs; + for (size_t i = 0; i < dirents.size(); i++) { + strs.push_back(dirents[i].d_name); + } + return NVal::CreateArrayString(env, strs).val_; +} + +static NVal DoListFileCompile(napi_env env, NError err, shared_ptr arg) +{ + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return { env, DoListFileVector2NV(env, arg->dirents) }; + } +} + +napi_value ListFile::Sync(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 [succPath, path, unused] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succPath) { + HILOGE("Invalid path"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + if (!GetOptionArg(env, funcArg, g_optionArgs, string(path.get()))) { + NError(EINVAL).ThrowErr(env); + return nullptr; + } + vector direntsRes; + if (g_optionArgs.recursion) { + RecursiveFunc(path.get(), direntsRes); + } else { + direntsRes = FileterFileRes(path.get()); + } + g_optionArgs.Clear(); + return DoListFileVector2NV(env, direntsRes); +} + +napi_value ListFile::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 [succPath, path, unused] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succPath) { + HILOGE("Invalid path"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + OptionArgs optionArgsTmp = {}; + if (!GetOptionArg(env, funcArg, optionArgsTmp, string(path.get()))) { + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto arg = make_shared(); + if (!arg) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + + auto cbExec = [arg, optionArgsTmp]() -> NError { + g_optionArgs = optionArgsTmp; + if (g_optionArgs.recursion) { + RecursiveFunc(g_optionArgs.path, arg->dirents); + } else { + arg->dirents = FileterFileRes(g_optionArgs.path); + } + g_optionArgs.Clear(); + return NError(ERRNO_NOERR); + }; + + auto cbCompl = [arg](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return DoListFileCompile(env, err, arg); + }; + + NVal thisVar(env, funcArg.GetThisVar()); + + if (funcArg.GetArgc() == NARG_CNT::ONE || (funcArg.GetArgc() == NARG_CNT::TWO && + NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_object))) { + return NAsyncWorkPromise(env, thisVar).Schedule(LIST_FILE_PRODUCE_NAME, cbExec, cbCompl).val_; + } else { + int32_t cbIdx = (funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::THIRD; + NVal cb(env, funcArg[cbIdx]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(LIST_FILE_PRODUCE_NAME, cbExec, cbCompl).val_; + } +} +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/listfile.h b/interfaces/kits/js/src/mod_fs/properties/listfile.h new file mode 100755 index 000000000..d649bb913 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/listfile.h @@ -0,0 +1,63 @@ +/* + * 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_LISTFILE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_LISTFILE_H + +#include "filemgmt_libn.h" +#include "../../common/file_filter.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace OHOS::FileManagement::LibN; +class ListFile { +public: + static napi_value Sync(napi_env env, napi_callback_info info); + static napi_value Async(napi_env env, napi_callback_info info); +}; + +class ListFileArgs { +public: + std::vector dirents; + explicit ListFileArgs() + { + dirents = std::vector(); + } + ~ListFileArgs() = default; +}; + +struct OptionArgs { + OHOS::DistributedFS::FileFilter filter = { {}, {}, {}, 0, 0, false, false }; + int listNum = 0; + int countNum = 0; + bool recursion = false; + std::string path = ""; + void Clear() + { + filter = { {}, {}, {}, 0, 0, false, false }; + listNum = 0; + countNum = 0; + recursion = false; + path = ""; + } +}; + +constexpr int FILTER_MATCH = 1; +constexpr int FILTER_DISMATCH = 0; +const int32_t MAX_SUFFIX_LENGTH = 256; +const std::string LIST_FILE_PRODUCE_NAME = "FileIOListFile"; +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_LISTFILE_H \ No newline at end of file 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 62baa5206..badeb0d65 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,27 @@ #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 "listfile.h" #include "lstat.h" +#include "mkdtemp.h" +#include "move.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 +52,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) { + 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 +310,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 +333,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, char *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); + uv_buf_t buffer = uv_buf_init(buf, 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(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 +377,36 @@ 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, len, fd, offset]() -> NError { + return ReadExec(arg, static_cast(buf), len, fd, offset); }; auto cbCompl = [arg](napi_env env, NError err) -> NVal { @@ -137,32 +420,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) +static NError WriteExec(shared_ptr arg, char *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); + uv_buf_t buffer = uv_buf_init(buf, len); + 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 +460,37 @@ 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, len, fd, offset]() -> NError { + return WriteExec(arg, static_cast(buf), len, fd, offset); }; auto cbCompl = [arg](napi_env env, NError err) -> NVal { @@ -212,21 +505,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 +528,91 @@ 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("listFile", ListFile::Async), + NVal::DeclareNapiFunction("listFileSync", ListFile::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("moveFile", Move::Async), + NVal::DeclareNapiFunction("moveFileSync", Move::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), }); @@ -297,4 +628,4 @@ PropNExporter::PropNExporter(napi_env env, napi_value exports) : NExporter(env, PropNExporter::~PropNExporter() {} } // namespace ModuleFileIO } // namespace FileManagement -} // namespace OHOS +} // namespace OHOS \ No newline at end of file -- Gitee