18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#include "io/file_manager.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <algorithm>
198bf80f4bSopenharmony_ci#include <cstddef>
208bf80f4bSopenharmony_ci
218bf80f4bSopenharmony_ci#include <base/containers/iterator.h>
228bf80f4bSopenharmony_ci#include <base/containers/string.h>
238bf80f4bSopenharmony_ci#include <base/containers/string_view.h>
248bf80f4bSopenharmony_ci#include <base/containers/type_traits.h>
258bf80f4bSopenharmony_ci#include <base/containers/unique_ptr.h>
268bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h>
278bf80f4bSopenharmony_ci#include <base/containers/vector.h>
288bf80f4bSopenharmony_ci#include <base/namespace.h>
298bf80f4bSopenharmony_ci#include <base/util/uid.h>
308bf80f4bSopenharmony_ci#include <core/io/intf_directory.h>
318bf80f4bSopenharmony_ci#include <core/io/intf_file.h>
328bf80f4bSopenharmony_ci#include <core/io/intf_file_manager.h>
338bf80f4bSopenharmony_ci#include <core/io/intf_file_system.h>
348bf80f4bSopenharmony_ci#include <core/log.h>
358bf80f4bSopenharmony_ci#include <core/namespace.h>
368bf80f4bSopenharmony_ci#include <core/plugin/intf_interface.h>
378bf80f4bSopenharmony_ci
388bf80f4bSopenharmony_ci#include "io/path_tools.h"
398bf80f4bSopenharmony_ci#include "io/proxy_filesystem.h"
408bf80f4bSopenharmony_ci#include "io/rofs_filesystem.h"
418bf80f4bSopenharmony_ci#include "io/std_directory.h"
428bf80f4bSopenharmony_ci
438bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE()
448bf80f4bSopenharmony_ciusing BASE_NS::make_unique;
458bf80f4bSopenharmony_ciusing BASE_NS::string;
468bf80f4bSopenharmony_ciusing BASE_NS::string_view;
478bf80f4bSopenharmony_ciusing BASE_NS::Uid;
488bf80f4bSopenharmony_ciusing BASE_NS::vector;
498bf80f4bSopenharmony_ci
508bf80f4bSopenharmony_cistring FileManager::FixPath(string_view pathIn) const
518bf80f4bSopenharmony_ci{
528bf80f4bSopenharmony_ci    string_view protocol;
538bf80f4bSopenharmony_ci    string_view path;
548bf80f4bSopenharmony_ci    if (ParseUri(pathIn, protocol, path)) {
558bf80f4bSopenharmony_ci        // Try to identify relative "file" uris, and convert them to absolute.
568bf80f4bSopenharmony_ci        if (protocol == "file") {
578bf80f4bSopenharmony_ci            if (path.empty()) {
588bf80f4bSopenharmony_ci                // so it's the base path then? (empty relative path)
598bf80f4bSopenharmony_ci                return protocol + "://" + basePath_;
608bf80f4bSopenharmony_ci            }
618bf80f4bSopenharmony_ci#if _WIN32
628bf80f4bSopenharmony_ci            // Handle win32 specific drive letters.
638bf80f4bSopenharmony_ci            if (IsRelative(path)) {
648bf80f4bSopenharmony_ci                // might still be absolute (if it has drive letter)
658bf80f4bSopenharmony_ci                if ((path.size() > 1) && (path[1] == ':')) {
668bf80f4bSopenharmony_ci                    // seems to start with drive letter so, it must be absolute?
678bf80f4bSopenharmony_ci                    if (path.size() == 2) { // 2: path size
688bf80f4bSopenharmony_ci                        // has only drive letter? consider it as root of drive then
698bf80f4bSopenharmony_ci                        return protocol + ":///" + path + "/";
708bf80f4bSopenharmony_ci                    }
718bf80f4bSopenharmony_ci                    return protocol + ":///" + path;
728bf80f4bSopenharmony_ci                }
738bf80f4bSopenharmony_ci                // no drive letter so it's really relative.
748bf80f4bSopenharmony_ci                return protocol + "://" + NormalizePath(basePath_ + path);
758bf80f4bSopenharmony_ci            }
768bf80f4bSopenharmony_ci            // Even if it's "absolute" it might still be missing the drive letter.
778bf80f4bSopenharmony_ci            if ((path.size() < 3) || (path[2] != ':')) { // 3: path size limit; 2: the third letter
788bf80f4bSopenharmony_ci                // seems to be missing the drive letter.
798bf80f4bSopenharmony_ci                return protocol + "://" + NormalizePath(basePath_.substr(0, 3) + path); // 3: substring size
808bf80f4bSopenharmony_ci            }
818bf80f4bSopenharmony_ci            if (path.size() == 3) { // 3: path size
828bf80f4bSopenharmony_ci                // has only drive letter? consider it as root of drive then
838bf80f4bSopenharmony_ci                return protocol + "://" + path + "/";
848bf80f4bSopenharmony_ci            }
858bf80f4bSopenharmony_ci            return protocol + "://" + NormalizePath(path);
868bf80f4bSopenharmony_ci#else
878bf80f4bSopenharmony_ci            if (IsRelative(path)) {
888bf80f4bSopenharmony_ci                // normalize it with current path..
898bf80f4bSopenharmony_ci                return protocol + "://" + NormalizePath(basePath_ + path);
908bf80f4bSopenharmony_ci            }
918bf80f4bSopenharmony_ci            return protocol + "://" + NormalizePath(path);
928bf80f4bSopenharmony_ci#endif
938bf80f4bSopenharmony_ci        }
948bf80f4bSopenharmony_ci    }
958bf80f4bSopenharmony_ci    return string(pathIn);
968bf80f4bSopenharmony_ci}
978bf80f4bSopenharmony_ci
988bf80f4bSopenharmony_ciFileManager::FileManager() : basePath_(GetCurrentDirectory()) {}
998bf80f4bSopenharmony_ci
1008bf80f4bSopenharmony_ciconst IInterface* FileManager::GetInterface(const Uid& uid) const
1018bf80f4bSopenharmony_ci{
1028bf80f4bSopenharmony_ci    return const_cast<FileManager*>(this)->GetInterface(uid);
1038bf80f4bSopenharmony_ci}
1048bf80f4bSopenharmony_ci
1058bf80f4bSopenharmony_ciIInterface* FileManager::GetInterface(const Uid& uid)
1068bf80f4bSopenharmony_ci{
1078bf80f4bSopenharmony_ci    if ((uid == IInterface::UID) || (uid == IFileManager::UID)) {
1088bf80f4bSopenharmony_ci        return this;
1098bf80f4bSopenharmony_ci    }
1108bf80f4bSopenharmony_ci    return nullptr;
1118bf80f4bSopenharmony_ci}
1128bf80f4bSopenharmony_ci
1138bf80f4bSopenharmony_civoid FileManager::Ref()
1148bf80f4bSopenharmony_ci{
1158bf80f4bSopenharmony_ci    refCount_++;
1168bf80f4bSopenharmony_ci}
1178bf80f4bSopenharmony_ci
1188bf80f4bSopenharmony_civoid FileManager::Unref()
1198bf80f4bSopenharmony_ci{
1208bf80f4bSopenharmony_ci    if (--refCount_ == 0) {
1218bf80f4bSopenharmony_ci        delete this;
1228bf80f4bSopenharmony_ci    }
1238bf80f4bSopenharmony_ci}
1248bf80f4bSopenharmony_ci
1258bf80f4bSopenharmony_ciIFile::Ptr FileManager::OpenFile(const string_view uriIn)
1268bf80f4bSopenharmony_ci{
1278bf80f4bSopenharmony_ci    string_view protocol;
1288bf80f4bSopenharmony_ci    string_view path;
1298bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
1308bf80f4bSopenharmony_ci    if (ParseUri(uri, protocol, path)) {
1318bf80f4bSopenharmony_ci        IFilesystem* filesystem = GetFilesystem(protocol);
1328bf80f4bSopenharmony_ci        if (filesystem) {
1338bf80f4bSopenharmony_ci            return filesystem->OpenFile(path);
1348bf80f4bSopenharmony_ci        }
1358bf80f4bSopenharmony_ci        CORE_LOG_E("Failed to open file, no file system for uri: '%s'", string(uri).c_str());
1368bf80f4bSopenharmony_ci    } else {
1378bf80f4bSopenharmony_ci        CORE_LOG_E("Failed to open file, invalid uri: '%s'", string(uri).c_str());
1388bf80f4bSopenharmony_ci    }
1398bf80f4bSopenharmony_ci
1408bf80f4bSopenharmony_ci    return IFile::Ptr();
1418bf80f4bSopenharmony_ci}
1428bf80f4bSopenharmony_ci
1438bf80f4bSopenharmony_ciIFile::Ptr FileManager::CreateFile(const string_view uriIn)
1448bf80f4bSopenharmony_ci{
1458bf80f4bSopenharmony_ci    string_view protocol;
1468bf80f4bSopenharmony_ci    string_view path;
1478bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
1488bf80f4bSopenharmony_ci    if (ParseUri(uri, protocol, path)) {
1498bf80f4bSopenharmony_ci        IFilesystem* filesystem = GetFilesystem(protocol);
1508bf80f4bSopenharmony_ci        if (filesystem) {
1518bf80f4bSopenharmony_ci            return filesystem->CreateFile(path);
1528bf80f4bSopenharmony_ci        }
1538bf80f4bSopenharmony_ci        CORE_LOG_E("Failed to create file, no file system for uri: '%s'", string(uri).c_str());
1548bf80f4bSopenharmony_ci    } else {
1558bf80f4bSopenharmony_ci        CORE_LOG_E("Failed to create file, invalid uri: '%s'", string(uri).c_str());
1568bf80f4bSopenharmony_ci    }
1578bf80f4bSopenharmony_ci
1588bf80f4bSopenharmony_ci    return IFile::Ptr();
1598bf80f4bSopenharmony_ci}
1608bf80f4bSopenharmony_ci
1618bf80f4bSopenharmony_cibool FileManager::DeleteFile(const string_view uriIn)
1628bf80f4bSopenharmony_ci{
1638bf80f4bSopenharmony_ci    string_view protocol;
1648bf80f4bSopenharmony_ci    string_view path;
1658bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
1668bf80f4bSopenharmony_ci    if (ParseUri(uri, protocol, path)) {
1678bf80f4bSopenharmony_ci        IFilesystem* filesystem = GetFilesystem(protocol);
1688bf80f4bSopenharmony_ci        if (filesystem) {
1698bf80f4bSopenharmony_ci            return filesystem->DeleteFile(path);
1708bf80f4bSopenharmony_ci        }
1718bf80f4bSopenharmony_ci    }
1728bf80f4bSopenharmony_ci
1738bf80f4bSopenharmony_ci    return false;
1748bf80f4bSopenharmony_ci}
1758bf80f4bSopenharmony_ci
1768bf80f4bSopenharmony_cibool FileManager::Rename(const string_view fromUri, const string_view toUri)
1778bf80f4bSopenharmony_ci{
1788bf80f4bSopenharmony_ci    string_view fromProtocol;
1798bf80f4bSopenharmony_ci    string_view fromPath;
1808bf80f4bSopenharmony_ci    auto from = FixPath(fromUri);
1818bf80f4bSopenharmony_ci    if (ParseUri(from, fromProtocol, fromPath)) {
1828bf80f4bSopenharmony_ci        string_view toProtocol;
1838bf80f4bSopenharmony_ci        string_view toPath;
1848bf80f4bSopenharmony_ci        auto to = FixPath(toUri);
1858bf80f4bSopenharmony_ci        if (ParseUri(to, toProtocol, toPath)) {
1868bf80f4bSopenharmony_ci            if (fromProtocol == toProtocol) {
1878bf80f4bSopenharmony_ci                IFilesystem* filesystem = GetFilesystem(fromProtocol);
1888bf80f4bSopenharmony_ci                if (filesystem) {
1898bf80f4bSopenharmony_ci                    return filesystem->Rename(fromPath, toPath);
1908bf80f4bSopenharmony_ci                }
1918bf80f4bSopenharmony_ci            } else {
1928bf80f4bSopenharmony_ci                CORE_LOG_E("Rename requires both uris have same protocol");
1938bf80f4bSopenharmony_ci            }
1948bf80f4bSopenharmony_ci        }
1958bf80f4bSopenharmony_ci    }
1968bf80f4bSopenharmony_ci
1978bf80f4bSopenharmony_ci    return false;
1988bf80f4bSopenharmony_ci}
1998bf80f4bSopenharmony_ci
2008bf80f4bSopenharmony_ciIDirectory::Entry FileManager::GetEntry(const string_view uriIn)
2018bf80f4bSopenharmony_ci{
2028bf80f4bSopenharmony_ci    string_view protocol;
2038bf80f4bSopenharmony_ci    string_view path;
2048bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
2058bf80f4bSopenharmony_ci    if (ParseUri(uri, protocol, path)) {
2068bf80f4bSopenharmony_ci        IFilesystem* filesystem = GetFilesystem(protocol);
2078bf80f4bSopenharmony_ci        if (filesystem) {
2088bf80f4bSopenharmony_ci            return filesystem->GetEntry(path);
2098bf80f4bSopenharmony_ci        }
2108bf80f4bSopenharmony_ci        CORE_LOG_E("Failed to get entry for uri, no file system for uri: '%s'", string(uri).c_str());
2118bf80f4bSopenharmony_ci    } else {
2128bf80f4bSopenharmony_ci        CORE_LOG_E("Failed to get entry for uri, invalid uri: '%s'", string(uri).c_str());
2138bf80f4bSopenharmony_ci    }
2148bf80f4bSopenharmony_ci
2158bf80f4bSopenharmony_ci    return {};
2168bf80f4bSopenharmony_ci}
2178bf80f4bSopenharmony_ciIDirectory::Ptr FileManager::OpenDirectory(const string_view uriIn)
2188bf80f4bSopenharmony_ci{
2198bf80f4bSopenharmony_ci    string_view protocol;
2208bf80f4bSopenharmony_ci    string_view path;
2218bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
2228bf80f4bSopenharmony_ci    if (ParseUri(uri, protocol, path)) {
2238bf80f4bSopenharmony_ci        IFilesystem* filesystem = GetFilesystem(protocol);
2248bf80f4bSopenharmony_ci        if (filesystem) {
2258bf80f4bSopenharmony_ci            return filesystem->OpenDirectory(path);
2268bf80f4bSopenharmony_ci        }
2278bf80f4bSopenharmony_ci        CORE_LOG_E("Failed to open directory, no file system for uri: '%s'", string(uri).c_str());
2288bf80f4bSopenharmony_ci    } else {
2298bf80f4bSopenharmony_ci        CORE_LOG_E("Failed to open directory, invalid uri: '%s'", string(uri).c_str());
2308bf80f4bSopenharmony_ci    }
2318bf80f4bSopenharmony_ci
2328bf80f4bSopenharmony_ci    return IDirectory::Ptr();
2338bf80f4bSopenharmony_ci}
2348bf80f4bSopenharmony_ci
2358bf80f4bSopenharmony_ciIDirectory::Ptr FileManager::CreateDirectory(const string_view uriIn)
2368bf80f4bSopenharmony_ci{
2378bf80f4bSopenharmony_ci    string_view protocol;
2388bf80f4bSopenharmony_ci    string_view path;
2398bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
2408bf80f4bSopenharmony_ci    if (ParseUri(uri, protocol, path)) {
2418bf80f4bSopenharmony_ci        IFilesystem* filesystem = GetFilesystem(protocol);
2428bf80f4bSopenharmony_ci        if (filesystem) {
2438bf80f4bSopenharmony_ci            return filesystem->CreateDirectory(path);
2448bf80f4bSopenharmony_ci        }
2458bf80f4bSopenharmony_ci        CORE_LOG_E("Failed to create directory, no file system for uri: '%s'", string(uri).c_str());
2468bf80f4bSopenharmony_ci    } else {
2478bf80f4bSopenharmony_ci        CORE_LOG_E("Failed to create directory, invalid uri: '%s'", string(uri).c_str());
2488bf80f4bSopenharmony_ci    }
2498bf80f4bSopenharmony_ci
2508bf80f4bSopenharmony_ci    return IDirectory::Ptr();
2518bf80f4bSopenharmony_ci}
2528bf80f4bSopenharmony_ci
2538bf80f4bSopenharmony_cibool FileManager::DeleteDirectory(const string_view uriIn)
2548bf80f4bSopenharmony_ci{
2558bf80f4bSopenharmony_ci    string_view protocol;
2568bf80f4bSopenharmony_ci    string_view path;
2578bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
2588bf80f4bSopenharmony_ci    if (ParseUri(uri, protocol, path)) {
2598bf80f4bSopenharmony_ci        IFilesystem* filesystem = GetFilesystem(protocol);
2608bf80f4bSopenharmony_ci        if (filesystem) {
2618bf80f4bSopenharmony_ci            return filesystem->DeleteDirectory(path);
2628bf80f4bSopenharmony_ci        }
2638bf80f4bSopenharmony_ci    }
2648bf80f4bSopenharmony_ci
2658bf80f4bSopenharmony_ci    return false;
2668bf80f4bSopenharmony_ci}
2678bf80f4bSopenharmony_ci
2688bf80f4bSopenharmony_civoid FileManager::RegisterFilesystem(const string_view protocol, IFilesystem::Ptr filesystem)
2698bf80f4bSopenharmony_ci{
2708bf80f4bSopenharmony_ci    CORE_ASSERT_MSG(filesystems_.find(protocol) == filesystems_.cend(), "File system already registered");
2718bf80f4bSopenharmony_ci
2728bf80f4bSopenharmony_ci    filesystems_[protocol] = move(filesystem);
2738bf80f4bSopenharmony_ci}
2748bf80f4bSopenharmony_ci
2758bf80f4bSopenharmony_civoid FileManager::UnregisterFilesystem(const string_view protocol)
2768bf80f4bSopenharmony_ci{
2778bf80f4bSopenharmony_ci    const auto iterator = filesystems_.find(protocol);
2788bf80f4bSopenharmony_ci    if (iterator != filesystems_.end()) {
2798bf80f4bSopenharmony_ci        filesystems_.erase(iterator);
2808bf80f4bSopenharmony_ci    }
2818bf80f4bSopenharmony_ci}
2828bf80f4bSopenharmony_ci
2838bf80f4bSopenharmony_civoid FileManager::RegisterAssetPath(const string_view uriIn)
2848bf80f4bSopenharmony_ci{
2858bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
2868bf80f4bSopenharmony_ci    RegisterPath("assets", uri, false);
2878bf80f4bSopenharmony_ci}
2888bf80f4bSopenharmony_ci
2898bf80f4bSopenharmony_civoid FileManager::UnregisterAssetPath(const string_view uriIn)
2908bf80f4bSopenharmony_ci{
2918bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
2928bf80f4bSopenharmony_ci    UnregisterPath("assets", uri);
2938bf80f4bSopenharmony_ci}
2948bf80f4bSopenharmony_ci
2958bf80f4bSopenharmony_civector<string> FileManager::GetAbsolutePaths(const string_view uriIn) const
2968bf80f4bSopenharmony_ci{
2978bf80f4bSopenharmony_ci    vector<string> ret;
2988bf80f4bSopenharmony_ci    string_view protocol;
2998bf80f4bSopenharmony_ci    string_view path;
3008bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
3018bf80f4bSopenharmony_ci    if (ParseUri(uri, protocol, path)) {
3028bf80f4bSopenharmony_ci        const IFilesystem* filesystem = GetFilesystem(protocol);
3038bf80f4bSopenharmony_ci        if (filesystem) {
3048bf80f4bSopenharmony_ci            // a single URI path can be found in several paths in a proxy filesystem
3058bf80f4bSopenharmony_ci            auto uriPaths = filesystem->GetUriPaths(path);
3068bf80f4bSopenharmony_ci            for (auto& uriPath : uriPaths) {
3078bf80f4bSopenharmony_ci                if (uriPath.find("file://") == string::npos) {
3088bf80f4bSopenharmony_ci                    auto tmp = GetAbsolutePaths(uriPath);
3098bf80f4bSopenharmony_ci                    ret.insert(ret.cend(), tmp.cbegin(), tmp.cend());
3108bf80f4bSopenharmony_ci                } else {
3118bf80f4bSopenharmony_ci                    ret.push_back(move(uriPath));
3128bf80f4bSopenharmony_ci                }
3138bf80f4bSopenharmony_ci            }
3148bf80f4bSopenharmony_ci        }
3158bf80f4bSopenharmony_ci    }
3168bf80f4bSopenharmony_ci    std::transform(ret.begin(), ret.end(), ret.begin(), [](const string& uri) {
3178bf80f4bSopenharmony_ci        string_view protocol;
3188bf80f4bSopenharmony_ci        string_view path;
3198bf80f4bSopenharmony_ci        if (ParseUri(uri, protocol, path)) {
3208bf80f4bSopenharmony_ci            return StdDirectory::ResolveAbsolutePath(path, true);
3218bf80f4bSopenharmony_ci        }
3228bf80f4bSopenharmony_ci        return uri;
3238bf80f4bSopenharmony_ci    });
3248bf80f4bSopenharmony_ci
3258bf80f4bSopenharmony_ci    return ret;
3268bf80f4bSopenharmony_ci}
3278bf80f4bSopenharmony_ci
3288bf80f4bSopenharmony_cibool FileManager::RegisterPath(const string_view protocol, const string_view uriIn, bool prepend)
3298bf80f4bSopenharmony_ci{
3308bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
3318bf80f4bSopenharmony_ci    // Check if the proxy protocol exists already.
3328bf80f4bSopenharmony_ci    auto it = proxyFilesystems_.find(protocol);
3338bf80f4bSopenharmony_ci    if (it != proxyFilesystems_.end()) {
3348bf80f4bSopenharmony_ci        // Yes, add the new search path to it.
3358bf80f4bSopenharmony_ci        if (prepend) {
3368bf80f4bSopenharmony_ci            it->second->PrependSearchPath(uri);
3378bf80f4bSopenharmony_ci        } else {
3388bf80f4bSopenharmony_ci            it->second->AppendSearchPath(uri);
3398bf80f4bSopenharmony_ci        }
3408bf80f4bSopenharmony_ci        return true;
3418bf80f4bSopenharmony_ci    }
3428bf80f4bSopenharmony_ci
3438bf80f4bSopenharmony_ci    // Check if the protocol is already declared..
3448bf80f4bSopenharmony_ci    const auto itp = filesystems_.find(protocol);
3458bf80f4bSopenharmony_ci    if (itp != filesystems_.end()) {
3468bf80f4bSopenharmony_ci        // Okay there is a protocol handler already, we can't add paths to non-proxy protocols.
3478bf80f4bSopenharmony_ci        CORE_LOG_W("Tried to register a path to non-proxy filesystem. protocol [%s] uriIn [%s]",
3488bf80f4bSopenharmony_ci            string(protocol).c_str(), string(uriIn).c_str());
3498bf80f4bSopenharmony_ci        return false;
3508bf80f4bSopenharmony_ci    }
3518bf80f4bSopenharmony_ci
3528bf80f4bSopenharmony_ci    // Create new proxy protocol handler.
3538bf80f4bSopenharmony_ci    auto pfs = make_unique<ProxyFilesystem>(*this, uri);
3548bf80f4bSopenharmony_ci    proxyFilesystems_[protocol] = pfs.get();
3558bf80f4bSopenharmony_ci    RegisterFilesystem(protocol, IFilesystem::Ptr { pfs.release() });
3568bf80f4bSopenharmony_ci    return true;
3578bf80f4bSopenharmony_ci}
3588bf80f4bSopenharmony_ci
3598bf80f4bSopenharmony_civoid FileManager::UnregisterPath(const string_view protocol, const string_view uriIn)
3608bf80f4bSopenharmony_ci{
3618bf80f4bSopenharmony_ci    auto uri = FixPath(uriIn);
3628bf80f4bSopenharmony_ci    auto it = proxyFilesystems_.find(protocol);
3638bf80f4bSopenharmony_ci    if (it != proxyFilesystems_.end()) {
3648bf80f4bSopenharmony_ci        it->second->RemoveSearchPath(uri);
3658bf80f4bSopenharmony_ci    }
3668bf80f4bSopenharmony_ci}
3678bf80f4bSopenharmony_ci
3688bf80f4bSopenharmony_ciIFilesystem* FileManager::GetFilesystem(const string_view protocol) const
3698bf80f4bSopenharmony_ci{
3708bf80f4bSopenharmony_ci    const auto it = filesystems_.find(protocol);
3718bf80f4bSopenharmony_ci    if (it != filesystems_.end()) {
3728bf80f4bSopenharmony_ci        return it->second.get();
3738bf80f4bSopenharmony_ci    }
3748bf80f4bSopenharmony_ci
3758bf80f4bSopenharmony_ci    return nullptr;
3768bf80f4bSopenharmony_ci}
3778bf80f4bSopenharmony_ci
3788bf80f4bSopenharmony_ciIFilesystem::Ptr FileManager::CreateROFilesystem(const void* const data, uint64_t size)
3798bf80f4bSopenharmony_ci{
3808bf80f4bSopenharmony_ci    return IFilesystem::Ptr { new RoFileSystem(data, static_cast<size_t>(size)) };
3818bf80f4bSopenharmony_ci}
3828bf80f4bSopenharmony_ciCORE_END_NAMESPACE()
383