diff --git a/interfaces/kits/js/src/file_manager_napi.cpp b/interfaces/kits/js/src/file_manager_napi.cpp index fd7acaa98efac2bbd0db80ec65cc02f6cd98ffa8..8e9b2e8af3d14be3bbbf50e034e8e1b55c138747 100644 --- a/interfaces/kits/js/src/file_manager_napi.cpp +++ b/interfaces/kits/js/src/file_manager_napi.cpp @@ -386,6 +386,172 @@ napi_value FileManagerNapi::ListFile(napi_env env, napi_callback_info info) } } +static bool GetScanFileFilter(const NVal &argv, FileFilter &filter) +{ + bool ret = false; + if (argv.HasProp("suffix")) { + vector filter_suffix; + tie(ret, filter_suffix, ignore) = argv.GetProp("suffix").ToStringArray(); + if (!ret) { + return false; + } + filter.SetSuffix(filter_suffix); + } + if (argv.HasProp("display_name")) { + vector display_name; + tie(ret, display_name, ignore) = argv.GetProp("display_name").ToStringArray(); + if (!ret) { + return false; + } + filter.SetDisplayName(display_name); + } + if (argv.HasProp("mime_type")) { + vector mime_type; + tie(ret, mime_type, ignore) = argv.GetProp("mime_type").ToStringArray(); + if (!ret) { + return false; + } + filter.SetDisplayName(mime_type); + } + if (argv.HasProp("file_size_over")) { + uint64_t file_size_over; + tie(ret, file_size_over, ignore) = argv.GetProp("file_size_over").ToUint64(); + if (!ret) { + return false; + } + filter.SetFileSizeOver(file_size_over); + } + if (argv.HasProp("last_modified_after")) { + double last_modified_after; + tie(ret, last_modified_after) = argv.GetProp("last_modified_after").ToDouble(); + if (!ret) { + return false; + } + filter.SetLastModifiedAfter(last_modified_after); + } + if (argv.HasProp("exclude_media")) { + bool exclude_media; + tie(ret, exclude_media) = argv.GetProp("exclude_media").ToBool(); + if (!ret) { + return false; + } + filter.SetExcludeMedia(exclude_media); + } + return true; +} + +static bool GetFilterOrOption(NVal Arg, FileFilter &filter, CmdOptions &option) +{ + if (Arg.HasProp("suffix")) { + filter.SetHasFilter(true); + if (!GetScanFileFilter(Arg, filter)) { + ERR_LOG("ScanFileArgs suffix fails"); + return false; + } + } else { + option.SetHasOpt(true); + if (!GetListFileOption(Arg, option)) { + ERR_LOG("ScanFileArgs option fails"); + return false; + } + } + return true; +} + +static tuple, CmdOptions> GetScanFileArg( + napi_env env, NFuncArg &funcArg) +{ + bool succ = false; + unique_ptr path; + vector suffix; + FileFilter filter(suffix); + CmdOptions option("local", "", 0, MAX_NUM, false); + tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succ) { + ERR_LOG("ScanFileArgs LF_PATH para fails"); + return {false, filter, nullptr, option}; + } + if (funcArg.GetArgc() == NARG_CNT::ONE) { + return {true, filter, move(path), option}; + } else if (funcArg.GetArgc() == NARG_CNT::TWO) { + if (!NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function)) { + NVal secondArg(env, funcArg[NARG_POS::SECOND]); + GetFilterOrOption(secondArg, filter, option); + } + return {true, filter, move(path), option}; + } else if (funcArg.GetArgc() == NARG_CNT::THREE) { + if (NVal(env, funcArg[NARG_POS::THIRD]).TypeIs(napi_function)) { + NVal secondArg(env, funcArg[NARG_POS::SECOND]); + GetFilterOrOption(secondArg, filter, option); + return {true, filter, move(path), option}; + } else { + NVal secondArg(env, funcArg[NARG_POS::SECOND]); + GetFilterOrOption(secondArg, filter, option); + NVal thirdArg(env, funcArg[NARG_POS::THIRD]); + GetFilterOrOption(thirdArg, filter, option); + return {true, filter, move(path), option}; + } + } else if (funcArg.GetArgc() == NARG_CNT::FOUR) { + NVal secondArg(env, funcArg[NARG_POS::SECOND]); + GetFilterOrOption(secondArg, filter, option); + NVal thirdArg(env, funcArg[NARG_POS::THIRD]); + GetFilterOrOption(thirdArg, filter, option); + return {true, filter, move(path), option}; + } + return {false, filter, nullptr, option}; +} + +napi_value FileManagerNapi::ScanFile(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::FOUR)) { + UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched"); + return nullptr; + } + bool succ = false; + FileFilter filter; + unique_ptr path; + CmdOptions option; + tie(succ, filter, path, option) = GetScanFileArg(env, funcArg); + if (!succ) { + UniError(EINVAL).ThrowErr(env, "Get arguments fail"); + return nullptr; + } + napi_value fileArr; + napi_create_array(env, &fileArr); + auto arg = make_shared(NVal(env, fileArr)); + auto cbExec = [filter, path = string(path.get()), option, arg](napi_env env) -> UniError { + IFmsClient* client = nullptr; + bool succ = false; + tie(succ, client) = GetFmsClient(); + if (!succ) { + return UniError(ESRCH); + } + int err = client->ScanFile(filter, path, option, arg->fileRes_); + return DealWithErrno(err); + }; + + auto cbComplete = [arg](napi_env env, UniError err) -> NVal { + if (!err && !CreateFileArray(env, arg)) { + err = UniError(ENOMEM); + } + if (err) { + return { env, err.GetNapiErr(env) }; + } else { + return NVal(env, arg->ref_.Deref(env).val_); + } + }; + size_t argc = funcArg.GetArgc(); + NVal thisVar(env, funcArg.GetThisVar()); + if (argc == NARG_CNT::ONE || (argc == NARG_CNT::TWO && (option.GetHasOpt() || filter.GetHasFilter())) || + (argc == NARG_CNT::THREE && !NVal(env, funcArg[NARG_POS::THIRD]).TypeIs(napi_function))) { + return NAsyncWorkPromise(env, thisVar).Schedule(scanFileprocedureName, cbExec, cbComplete).val_; + } else { + NVal cb(env, funcArg[argc - 1]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(scanFileprocedureName, cbExec, cbComplete).val_; + } +} + napi_value FileManagerNapi::Mkdir(napi_env env, napi_callback_info info) { return NVal::CreateUndefined(env).val_; @@ -395,6 +561,7 @@ bool FileManagerNapi::Export() { return exports_.AddProp( { NVal::DeclareNapiFunction("listFile", ListFile), + NVal::DeclareNapiFunction("scanFile", ScanFile), NVal::DeclareNapiFunction("createFile", CreateFile), NVal::DeclareNapiFunction("getRoot", GetRoot), }); diff --git a/interfaces/kits/js/src/file_manager_napi.h b/interfaces/kits/js/src/file_manager_napi.h index 8b06b57af5786ed8d4cf9c04eab819839b870ec9..5e3babb8d6366d581de56096039c87d4b967d7fb 100644 --- a/interfaces/kits/js/src/file_manager_napi.h +++ b/interfaces/kits/js/src/file_manager_napi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 @@ -24,6 +24,7 @@ class FileManagerNapi final : public DistributedFS::NExporter { public: static napi_value CreateFile(napi_env env, napi_callback_info info); static napi_value ListFile(napi_env env, napi_callback_info info); + static napi_value ScanFile(napi_env env, napi_callback_info info); static napi_value Mkdir(napi_env env, napi_callback_info info); static napi_value GetRoot(napi_env env, napi_callback_info info); bool Export() override; @@ -35,6 +36,7 @@ private: inline static const std::string className_ = "__properities__"; inline static IFmsClient* fmsClient_ = nullptr; }; +const std::string scanFileprocedureName = "ScanFile"; } // namespace FileManagerService } // namespace OHOS #endif // STORAGE_FILE_MANAGER_NAPI_H \ No newline at end of file diff --git a/services/BUILD.gn b/services/BUILD.gn index 3b17a7f4478bcf66748f41f85af5b6a909715d82..a08e2584ab4148e892aad6411b659a7643d63ed9 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# 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 @@ -41,6 +41,7 @@ ohos_shared_library("fms_server") { "$FMS_BASE_DIR/src/fileoper", "$FMS_BASE_DIR/include/fileoper", "//base/hiviewdfx/hilog/interfaces/native/innerkits/include/hilog", + "//foundation/distributeddatamgr/distributedfile/interfaces/kits/js/src/common", "//foundation/filemanagement/storage_service/services/storage_manager/include", "//foundation/filemanagement/storage_service/interfaces/innerkits/storage_manager/native", ] diff --git a/services/include/file_manager_service_def.h b/services/include/file_manager_service_def.h index 02b63dcfbde4e22d01dd8d6cc6edfd41c05730ff..7b428c4bc374231caad8f62ddf9733e32013452b 100644 --- a/services/include/file_manager_service_def.h +++ b/services/include/file_manager_service_def.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -27,6 +27,7 @@ enum Operation { GET_ROOT, MAKE_DIR, LIST_FILE, + SCAN_FILE, CREATE_FILE }; diff --git a/services/src/client/file_manager_proxy.cpp b/services/src/client/file_manager_proxy.cpp index 0c15b609f7cdeb7e79115a1c865568ade14a77d6..c57e2612f184e1c32d4fbe7efddcd829a3673597 100644 --- a/services/src/client/file_manager_proxy.cpp +++ b/services/src/client/file_manager_proxy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -144,6 +144,42 @@ int FileManagerProxy::ListFile(const std::string &type, const std::string &path, return err; } +int FileManagerProxy::ScanFile(const FileFilter &filefilter, const std::string &path, const CmdOptions &option, + std::vector> &fileRes) +{ + CmdOptions op(option); + std::string devName(op.GetDevInfo().GetName()); + std::string devPath(op.GetDevInfo().GetPath()); + int64_t offset = op.GetOffset(); + int64_t count = op.GetCount(); + MessageParcel data; + data.WriteInterfaceToken(GetDescriptor()); + data.WriteString(devName); + data.WriteString(devPath); + data.WriteParcelable(&filefilter); + data.WriteString(path); + data.WriteInt64(offset); + data.WriteInt64(count); + MessageParcel reply; + MessageOption messageOption; + uint32_t code = Operation::SCAN_FILE; + if (op.GetDevInfo().GetName() == "external_storage") { + code = (Equipment::EXTERNAL_STORAGE << EQUIPMENT_SHIFT) | Operation::SCAN_FILE; + } + int err = Remote()->SendRequest(code, data, reply, messageOption); + if (err != ERR_NONE) { + ERR_LOG("inner error send request fail, err = %{public}d", err); + return FAIL; + } + sptr cmdResponse; + err = GetCmdResponse(reply, cmdResponse); + if (err != ERR_NONE) { + return err; + } + fileRes = cmdResponse->GetFileInfoList(); + return err; +} + int FileManagerProxy::Mkdir(const string &name, const string &path) { MessageParcel data; diff --git a/services/src/client/file_manager_proxy.h b/services/src/client/file_manager_proxy.h index 494648ed26703f008083ec301e84e68a30329f74..971a2e32956f19a7c01ea36b381e7784ae866b64 100644 --- a/services/src/client/file_manager_proxy.h +++ b/services/src/client/file_manager_proxy.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -30,6 +30,8 @@ public: int Mkdir(const std::string &name, const std::string &path) override; int ListFile(const std::string &type, const std::string &path, const CmdOptions &option, std::vector> &fileRes) override; + int ScanFile(const FileFilter &filefilter, const std::string &path, const CmdOptions &option, + std::vector> &fileRes) override; int CreateFile(const std::string &path, const std::string &fileName, const CmdOptions &option, std::string &uri) override; int GetRoot(const CmdOptions &option, std::vector> &fileRes) override; diff --git a/services/src/client/ifms_client.h b/services/src/client/ifms_client.h index ba0ce14abfe063493042b82988963f0a168dee63..46cc848e03bbc2edd1990de549dd9df026732887 100644 --- a/services/src/client/ifms_client.h +++ b/services/src/client/ifms_client.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -15,16 +15,19 @@ #ifndef STORAGE_IFILE_MANAGER_CLIENT_H #define STORAGE_IFILE_MANAGER_CLIENT_H #include "cmd_options.h" +#include "file_filter.h" #include "file_info.h" namespace OHOS { namespace FileManagerService { -class IFmsClient { +class IFmsClient : public DistributedFS::FileFilter { public: virtual ~IFmsClient() {} static IFmsClient *GetFmsInstance(); virtual int Mkdir(const std::string &name, const std::string &path) = 0; virtual int ListFile(const std::string &type, const std::string &path, const CmdOptions &option, std::vector> &fileRes) = 0; + virtual int ScanFile(const FileFilter &filter, const std::string &path, const CmdOptions &option, + std::vector> &fileRes) = 0; virtual int GetRoot(const CmdOptions &option, std::vector> &fileRes) = 0; virtual int CreateFile(const std::string &path, const std::string &fileName, const CmdOptions &option, std::string &uri) = 0; diff --git a/services/src/fileoper/external_storage_oper.cpp b/services/src/fileoper/external_storage_oper.cpp index af9c01d6b7cfccf5c6863c56bf109a062866ca96..2ddf3c6c845343a91eae109a0e7ff776ffe59834 100644 --- a/services/src/fileoper/external_storage_oper.cpp +++ b/services/src/fileoper/external_storage_oper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -44,6 +44,17 @@ int ExternalStorageOper::OperProcess(uint32_t code, MessageParcel &data, Message errCode = this->ListFile(type, path, option, reply); break; } + case Operation::SCAN_FILE: { + std::string devName = data.ReadString(); + std::string devPath = data.ReadString(); + sptr filter = data.ReadParcelable(); + string path = data.ReadString(); + int64_t offset = data.ReadInt64(); + int64_t count = data.ReadInt64(); + CmdOptions option(devName, devPath, offset, count, true); + errCode = this->ScanFile(filter, path, option, reply); + break; + } case Operation::CREATE_FILE: { std::string name = data.ReadString(); std::string uri = data.ReadString(); @@ -104,5 +115,19 @@ int ExternalStorageOper::ListFile(const std::string &type, const std::string &ur } return ret; } + +int ExternalStorageOper::ScanFile(sptr filter, const std::string &uri, const CmdOptions &option, + MessageParcel &reply) const +{ + std::vector> fileList; + int ret = ExternalStorageUtils::DoScanFile(filter, uri, option, fileList); + CmdResponse cmdResponse; + cmdResponse.SetErr(ret); + cmdResponse.SetFileInfoList(fileList); + if (!reply.WriteParcelable(&cmdResponse)) { + ERR_LOG("reply write err parcel capacity:%{public}zu", reply.GetDataCapacity()); + } + return ret; +} } // namespace FileManagerService } // namespace OHOS diff --git a/services/src/fileoper/external_storage_oper.h b/services/src/fileoper/external_storage_oper.h index af5ee57a4d0c23f826e175370fbc8fcd06918b99..933675eb3fdbc2615b53c576e2dc3a207fa30ea6 100644 --- a/services/src/fileoper/external_storage_oper.h +++ b/services/src/fileoper/external_storage_oper.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -17,10 +17,11 @@ #include #include "cmd_options.h" +#include "file_filter.h" #include "file_oper.h" namespace OHOS { namespace FileManagerService { -class ExternalStorageOper : public FileOper { +class ExternalStorageOper : public FileOper, public DistributedFS::FileFilter { public: ExternalStorageOper() = default; virtual ~ExternalStorageOper() = default; @@ -29,6 +30,8 @@ private: int CreateFile(const std::string &uri, const std::string &name, MessageParcel &reply) const; int ListFile(const std::string &type, const std::string &uri, const CmdOptions &option, MessageParcel &reply) const; + int ScanFile(sptr filter, const std::string &uri, const CmdOptions &option, + MessageParcel &reply) const; int GetRoot(const std::string &name, const std::string &path, MessageParcel &reply) const; }; } // namespace FileManagerService diff --git a/services/src/fileoper/external_storage_utils.cpp b/services/src/fileoper/external_storage_utils.cpp index 1cff272a39f2eb3384b77be18c2e25cbe8afb438..ae2861cafacba3735cfea8bc1bab15806e937756 100644 --- a/services/src/fileoper/external_storage_utils.cpp +++ b/services/src/fileoper/external_storage_utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -32,6 +32,8 @@ using namespace std; using namespace OHOS::StorageManager; namespace OHOS { namespace FileManagerService { +static std::vector suffix; + static bool GetPathFromUri(const string &uri, string &path) { uint len = EXTERNAL_STORAGE_URI.size(); @@ -160,6 +162,100 @@ int ExternalStorageUtils::DoListFile(const std::string &type, const std::string return SUCCESS; } +int SuffixFilter(const struct dirent *pDir) +{ + std::string fileName = std::string(pDir->d_name); + if (fileName == "." || fileName == "..") { + return false; + } + if (suffix.empty()) { + return true; + } + for (size_t i = 0; i < suffix.size(); i++) { + string::size_type pos = fileName.find_last_of('.'); + if (pos != string::npos) { + if (fileName.substr(pos) != suffix[i]) { + return false; + } + } else { + return false; + } + } + return true; +} + +static int ScanFileCore(std::string path, int64_t &count, int64_t &offset, int64_t &idx, + std::vector> &fileList) +{ + if (count == 0) { + return SUCCESS; + } + struct dirent **namelist; + int n = scandir(path.c_str(), &namelist, SuffixFilter, alphasort); + if (n < 0) { + return errno; + } + for (int i = 0; i < n; i++) { + if (count == 0) { + return SUCCESS; + } + struct stat fileInformation; + std::string filePath = path + '/'; + filePath.insert(filePath.length(), namelist[i]->d_name); + if (stat(filePath.c_str(), &fileInformation) != 0) { + ERR_LOG("In external storage, stat fail"); + return errno; + } + if ((fileInformation.st_mode & S_IFMT) == S_IFDIR) { + int ret = ScanFileCore(filePath, count, offset, idx, fileList); + if (ret != SUCCESS) { + return ret; + } + } else { + if (idx < offset) { + idx++; + continue; + } + shared_ptr fileInfo = make_shared(); + if (!GetFileInfo(path, namelist[i]->d_name, fileInfo)) { + continue; + } + fileList.push_back(fileInfo); + idx++; + count--; + } + } + return SUCCESS; +} + +int ExternalStorageUtils::DoScanFile(sptr filter, const std::string &uri, const CmdOptions &option, + std::vector> &fileList) +{ + auto fileSuffix = filter->GetSuffix(); + suffix.swap(fileSuffix); + int64_t count = option.GetCount(); + int64_t offset = option.GetOffset(); + int64_t idx = 0; + if (count < 0 || count > MAX_NUM || offset < 0) { + ERR_LOG("invalid file count or offset."); + return E_INVALID_FILE_NUMBER; + } + DEBUG_LOG("limit %{public}lld, offset %{public}lld", (long long)count, (long long)offset); + std::string path; + if (!ConvertUriToAbsolutePath(uri, path)) { + ERR_LOG("invalid uri[%{private}s].", uri.c_str()); + return E_NOEXIST; + } + if (ScanFileCore(path, count, offset, idx, fileList) != SUCCESS) { + ERR_LOG("ScanFileCore fail"); + return errno; + } + if (option.GetCount() == MAX_NUM && count == 0) { + DEBUG_LOG("get files with MAX_NUM:[%{public}lld].", (long long)MAX_NUM); + } + return SUCCESS; +} + int ExternalStorageUtils::DoCreateFile(const std::string &uri, const std::string &name, std::string &resultUri) { std::string path; diff --git a/services/src/fileoper/external_storage_utils.h b/services/src/fileoper/external_storage_utils.h index a975ba179ed3c28989364afe8ce732ccc086b831..9d1197bb3cd2918b408b80ef965427fad6a38581 100644 --- a/services/src/fileoper/external_storage_utils.h +++ b/services/src/fileoper/external_storage_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -20,17 +20,20 @@ #include #include "cmd_options.h" +#include "file_filter.h" #include "file_info.h" #include "file_oper.h" namespace OHOS { namespace FileManagerService { -class ExternalStorageUtils { +class ExternalStorageUtils : public DistributedFS::FileFilter { public: ExternalStorageUtils(); ~ExternalStorageUtils(); static int DoListFile(const std::string &type, const std::string &uri, const CmdOptions &option, std::vector> &fileList); + static int DoScanFile(sptr filter, const std::string &uri, const CmdOptions &option, + std::vector> &fileList); static int DoCreateFile(const std::string &uri, const std::string &name, std::string &resultUri); static int DoGetRoot(const std::string &name, const std::string &path, std::vector> &fileList); diff --git a/services/src/fileoper/media_file_oper.cpp b/services/src/fileoper/media_file_oper.cpp index 118b6210939134ca836a3ac6c3fec940bd7844c3..44f023a9112229a413bd85d9a73760d368f53aba 100644 --- a/services/src/fileoper/media_file_oper.cpp +++ b/services/src/fileoper/media_file_oper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -63,6 +63,16 @@ int MediaFileOper::OperProcess(uint32_t code, MessageParcel &data, MessageParcel errCode = ListFile(type, path, off, count, reply); break; } + case Operation::SCAN_FILE: { + string devName = data.ReadString(); + string devPath = data.ReadString(); + sptr filter = data.ReadParcelable(); + string path = data.ReadString(); + int off = data.ReadInt64(); + int count = data.ReadInt64(); + errCode = ScanFile(filter, path, off, count, reply); + break; + } case Operation::CREATE_FILE: { string name = data.ReadString(); string path = data.ReadString(); @@ -123,6 +133,31 @@ int MediaFileOper::ListFile(const string &type, const string &path, int offset, return res; } +int MediaFileOper::ScanFile(sptr filter, const string &path, int offset, int count, + MessageParcel &reply) const +{ + shared_ptr result; + int res = MediaFileUtils::DoScanFile(filter, path, offset, count, result); + if (res != SUCCESS) { + ERR_LOG("DoScanFile fail, err = %{public}d", res); + CmdResponse cmdResponse; + cmdResponse.SetErr(res); + if (!reply.WriteParcelable(&cmdResponse)) { + ERR_LOG("reply write err parcel capacity:%{public}zu", reply.GetDataCapacity()); + } + return res; + } + std::vector> fileList; + res = MediaFileUtils::GetFileInfoFromResult(result, fileList); + CmdResponse cmdResponse; + cmdResponse.SetErr(res); + cmdResponse.SetFileInfoList(fileList); + if (!reply.WriteParcelable(&cmdResponse)) { + ERR_LOG("reply write err parcel capacity:%{public}zu", reply.GetDataCapacity()); + } + return res; +} + int MediaFileOper::Mkdir(const string &name, const string &path) const { (void)name; diff --git a/services/src/fileoper/media_file_oper.h b/services/src/fileoper/media_file_oper.h index bc4374b212fd9a7909a7bd1d2b5ab2e2c660b98d..97999cd7cedc936b7177a6429deac5da53c6c99f 100644 --- a/services/src/fileoper/media_file_oper.h +++ b/services/src/fileoper/media_file_oper.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -16,10 +16,11 @@ #define STORAGE_SERVICES_MEDIA_FILE_OPER_H #include +#include "file_filter.h" #include "file_oper.h" namespace OHOS { namespace FileManagerService { -class MediaFileOper : public FileOper { +class MediaFileOper : public FileOper, public DistributedFS::FileFilter { public: MediaFileOper() = default; virtual ~MediaFileOper() = default; @@ -27,6 +28,7 @@ public: private: int CreateFile(const std::string &name, const std::string &path, MessageParcel &reply) const; int ListFile(const std::string &type, const std::string &path, int offset, int count, MessageParcel &data) const; + int ScanFile(sptr filter, const std::string &path, int offset, int count, MessageParcel &data) const; int GetRoot(const std::string &name, const std::string &path, MessageParcel &reply) const; int Mkdir(const std::string &name, const std::string &path) const; }; diff --git a/services/src/fileoper/media_file_utils.cpp b/services/src/fileoper/media_file_utils.cpp index 78e84898b7451f8d1c44c5dfe64238d694bc5d70..49b49286816594392684fc5e7993c0f98a5f969b 100644 --- a/services/src/fileoper/media_file_utils.cpp +++ b/services/src/fileoper/media_file_utils.cpp @@ -296,6 +296,68 @@ int MediaFileUtils::DoListFile(const string &type, const string &path, int offse return SUCCESS; } +bool CheckFilterSuffix(const vector &filter_suffix) +{ + for (size_t i = 0; i < filter_suffix.size(); i++) { + if (filter_suffix[i][0] != '.') { + return false; + } + } + return true; +} + +int CreateSelectionAndArgs(sptr filter, const string &albumUri, string &selection, + vector &selectionArgs) +{ + // get the album path from the album uri + string albumPath; + if (IsFirstLevelUriPath(albumUri)) { + albumPath = RELATIVE_ROOT_PATH; + } else { + if (!GetPathFromAlbumPath(albumUri, albumPath)) { + ERR_LOG("path not exist"); + return E_NOEXIST; + } + } + if (!CheckFilterSuffix(filter->GetSuffix())) { + ERR_LOG("Invalid suffix"); + return E_NOEXIST; + } + selection = Media::MEDIA_DATA_DB_RELATIVE_PATH + " LIKE ? "; + selectionArgs.emplace_back(albumPath + "%"); + if (filter->GetSuffix().size() > 0) { + selection += "AND ( " + Media::MEDIA_DATA_DB_NAME + " LIKE ? "; + selectionArgs.emplace_back("%" + filter->GetSuffix()[0]); + } + for (size_t i = 1; i < filter->GetSuffix().size(); i++) { + selection += " OR " + Media::MEDIA_DATA_DB_NAME + " LIKE ? "; + selectionArgs.emplace_back("%" + filter->GetSuffix()[i]); + } + if (filter->GetSuffix().size() > 0) { + selection += ")"; + } + return SUCCESS; +} + +int MediaFileUtils::DoScanFile(sptr filter, const string &path, int offset, int count, + shared_ptr &result) +{ + string selection; + vector selectionArgs; + int err = CreateSelectionAndArgs(filter, path, selection, selectionArgs); + if (err) { + ERR_LOG("CreateSelectionAndArgs returns fail, err = %{public}d", err); + return err; + } + + result = DoQuery(selection, selectionArgs, offset, count); + if (result == nullptr) { + ERR_LOG("ScanFile folder is empty"); + return E_EMPTYFOLDER; + } + return SUCCESS; +} + shared_ptr MediaFileUtils::DoQuery(const string &selection, const vector &selectionArgs) { diff --git a/services/src/fileoper/media_file_utils.h b/services/src/fileoper/media_file_utils.h index 35d5245ff112b27acb872ecc1076d317362167e1..4a84391e9e3c1fd7884aa23beb7eb43f209dbaf7 100644 --- a/services/src/fileoper/media_file_utils.h +++ b/services/src/fileoper/media_file_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * 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 @@ -19,6 +19,7 @@ #include #include "datashare_abs_result_set.h" +#include "file_filter.h" #include "file_info.h" #include "file_oper.h" @@ -39,6 +40,8 @@ public: std::vector> &fileList); static int DoListFile(const std::string &type, const std::string &path, int offset, int count, std::shared_ptr &result); + static int DoScanFile(sptr filter, const std::string &path, int offset, + int count, std::shared_ptr &result); static std::shared_ptr DoQuery(const std::string &selection, const std::vector &selectionArgs); static std::shared_ptr DoQuery(const std::string &selection, diff --git a/services/test/BUILD.gn b/services/test/BUILD.gn index 1ab8e2a5367bb85dfb5f6bfe2120435e0a842abf..f6ff19937eeb59366c9a15cd4906ce6837032f32 100644 --- a/services/test/BUILD.gn +++ b/services/test/BUILD.gn @@ -26,6 +26,7 @@ ohos_unittest("file_manager_proxy_test") { "$FMS_BASE_DIR/src/server", "$FMS_BASE_DIR/src/fileoper", "//third_party/googletest/googlemock/include/gmock", + "//foundation/distributeddatamgr/distributedfile/interfaces/kits/js/src/common", "//foundation/multimedia/media_library/frameworks/utils/include", "//foundation/multimedia/media_library/interfaces/inner_api/media_library_helper/include", ] @@ -94,6 +95,7 @@ ohos_unittest("file_manager_service_test") { "$FMS_BASE_DIR/src/client", "$FMS_BASE_DIR/src/server", "$FMS_BASE_DIR/src/fileoper", + "//foundation/distributeddatamgr/distributedfile/interfaces/kits/js/src/common", "//foundation/multimedia/media_library/frameworks/utils/include", "//foundation/multimedia/media_library/interfaces/inner_api/media_library_helper/include", ] diff --git a/services/test/client/fms_manager_proxy_mock.h b/services/test/client/fms_manager_proxy_mock.h index 811807ed6f0d52ebdc692ea00dbe1545fb69ab72..0a5e16a37499646295756af52e133bdb34ccdae2 100644 --- a/services/test/client/fms_manager_proxy_mock.h +++ b/services/test/client/fms_manager_proxy_mock.h @@ -45,6 +45,11 @@ public: { return ERR_NONE; } + virtual int ScanFile(const FileFilter &filter, const std::string &path, const CmdOptions &option, + std::vector> &fileRes) override + { + return ERR_NONE; + } virtual int GetRoot(const CmdOptions &option, std::vector> &fileRes) override { return ERR_NONE;