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 <cstddef>
178bf80f4bSopenharmony_ci#include <cstdint>
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include <base/containers/string.h>
208bf80f4bSopenharmony_ci#include <base/containers/string_view.h>
218bf80f4bSopenharmony_ci#include <base/containers/type_traits.h>
228bf80f4bSopenharmony_ci#include <base/containers/unique_ptr.h>
238bf80f4bSopenharmony_ci#include <base/containers/vector.h>
248bf80f4bSopenharmony_ci#include <base/namespace.h>
258bf80f4bSopenharmony_ci#include <base/util/uid.h>
268bf80f4bSopenharmony_ci#include <core/implementation_uids.h>
278bf80f4bSopenharmony_ci#include <core/io/intf_directory.h>
288bf80f4bSopenharmony_ci#include <core/io/intf_file_manager.h>
298bf80f4bSopenharmony_ci#include <core/io/intf_file_monitor.h>
308bf80f4bSopenharmony_ci#include <core/io/intf_file_system.h>
318bf80f4bSopenharmony_ci#include <core/io/intf_filesystem_api.h>
328bf80f4bSopenharmony_ci#include <core/namespace.h>
338bf80f4bSopenharmony_ci#include <core/plugin/intf_class_factory.h>
348bf80f4bSopenharmony_ci#include <core/plugin/intf_interface.h>
358bf80f4bSopenharmony_ci#include <core/plugin/intf_plugin.h>
368bf80f4bSopenharmony_ci
378bf80f4bSopenharmony_ci#include "dev/file_monitor.h"
388bf80f4bSopenharmony_ci#include "io/file_manager.h"
398bf80f4bSopenharmony_ci#include "io/memory_filesystem.h"
408bf80f4bSopenharmony_ci#include "io/path_tools.h"
418bf80f4bSopenharmony_ci#include "io/rofs_filesystem.h"
428bf80f4bSopenharmony_ci#include "io/std_filesystem.h"
438bf80f4bSopenharmony_ci#include "util/string_util.h"
448bf80f4bSopenharmony_ci
458bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE();
468bf80f4bSopenharmony_cinamespace {
478bf80f4bSopenharmony_ciusing BASE_NS::string;
488bf80f4bSopenharmony_ciusing BASE_NS::string_view;
498bf80f4bSopenharmony_ciusing BASE_NS::Uid;
508bf80f4bSopenharmony_ciusing BASE_NS::vector;
518bf80f4bSopenharmony_ci
528bf80f4bSopenharmony_ciclass FileMonitorImpl final : public IFileMonitor {
538bf80f4bSopenharmony_cipublic:
548bf80f4bSopenharmony_ci    const IInterface* GetInterface(const Uid& uid) const override;
558bf80f4bSopenharmony_ci    IInterface* GetInterface(const Uid& uid) override;
568bf80f4bSopenharmony_ci    void Ref() override;
578bf80f4bSopenharmony_ci    void Unref() override;
588bf80f4bSopenharmony_ci
598bf80f4bSopenharmony_ci    void Initialize(IFileManager&) override;
608bf80f4bSopenharmony_ci    bool AddPath(const string_view path) override;
618bf80f4bSopenharmony_ci    bool RemovePath(const string_view path) override;
628bf80f4bSopenharmony_ci    void ScanModifications(vector<string>& added, vector<string>& removed, vector<string>& modified) override;
638bf80f4bSopenharmony_ci
648bf80f4bSopenharmony_ci    FileMonitorImpl() = default;
658bf80f4bSopenharmony_ci    explicit FileMonitorImpl(IFileManager& manager)
668bf80f4bSopenharmony_ci    {
678bf80f4bSopenharmony_ci        Initialize(manager);
688bf80f4bSopenharmony_ci    }
698bf80f4bSopenharmony_ci
708bf80f4bSopenharmony_ci    BASE_NS::unique_ptr<FileMonitor> fileMonitor_;
718bf80f4bSopenharmony_ci    uint32_t refCount_ { 0 };
728bf80f4bSopenharmony_ci};
738bf80f4bSopenharmony_ci
748bf80f4bSopenharmony_ciclass FilesystemApi final : public IFileSystemApi {
758bf80f4bSopenharmony_cipublic:
768bf80f4bSopenharmony_ci    string basePath_;
778bf80f4bSopenharmony_ci    IFilesystem::Ptr rootFs_;
788bf80f4bSopenharmony_ci    FilesystemApi() : basePath_(GetCurrentDirectory()), rootFs_(CreateStdFileSystem()) {}
798bf80f4bSopenharmony_ci
808bf80f4bSopenharmony_ci    const IInterface* GetInterface(const Uid& uid) const override
818bf80f4bSopenharmony_ci    {
828bf80f4bSopenharmony_ci        return const_cast<FilesystemApi*>(this)->GetInterface(uid);
838bf80f4bSopenharmony_ci    }
848bf80f4bSopenharmony_ci    IInterface* GetInterface(const Uid& uid) override
858bf80f4bSopenharmony_ci    {
868bf80f4bSopenharmony_ci        if ((uid == IFileSystemApi::UID) || (uid == IClassFactory::UID) || (uid == IInterface::UID)) {
878bf80f4bSopenharmony_ci            return this;
888bf80f4bSopenharmony_ci        }
898bf80f4bSopenharmony_ci        return nullptr;
908bf80f4bSopenharmony_ci    }
918bf80f4bSopenharmony_ci    void Ref() override {}
928bf80f4bSopenharmony_ci    void Unref() override {}
938bf80f4bSopenharmony_ci
948bf80f4bSopenharmony_ci    IInterface::Ptr CreateInstance(const Uid& uid) override
958bf80f4bSopenharmony_ci    {
968bf80f4bSopenharmony_ci        if (uid == UID_FILE_MONITOR) {
978bf80f4bSopenharmony_ci            return IInterface::Ptr(new FileMonitorImpl());
988bf80f4bSopenharmony_ci        }
998bf80f4bSopenharmony_ci        if (uid == UID_FILE_MANAGER) {
1008bf80f4bSopenharmony_ci            return IInterface::Ptr(new FileManager());
1018bf80f4bSopenharmony_ci        }
1028bf80f4bSopenharmony_ci        return IInterface::Ptr();
1038bf80f4bSopenharmony_ci    }
1048bf80f4bSopenharmony_ci
1058bf80f4bSopenharmony_ci    IFileManager::Ptr CreateFilemanager() override
1068bf80f4bSopenharmony_ci    {
1078bf80f4bSopenharmony_ci        return IInterface::Ptr(new FileManager());
1088bf80f4bSopenharmony_ci    }
1098bf80f4bSopenharmony_ci    IFileMonitor::Ptr CreateFilemonitor(IFileManager& manager) override
1108bf80f4bSopenharmony_ci    {
1118bf80f4bSopenharmony_ci        return IInterface::Ptr(new FileMonitorImpl(manager));
1128bf80f4bSopenharmony_ci    }
1138bf80f4bSopenharmony_ci    string ResolvePath(string_view inPathRaw) const
1148bf80f4bSopenharmony_ci    {
1158bf80f4bSopenharmony_ci#if _WIN32
1168bf80f4bSopenharmony_ci        string_view curDrive;
1178bf80f4bSopenharmony_ci        string_view curPath;
1188bf80f4bSopenharmony_ci        string_view curFilename;
1198bf80f4bSopenharmony_ci        string_view curExt;
1208bf80f4bSopenharmony_ci        SplitPath(basePath_, curDrive, curPath, curFilename, curExt);
1218bf80f4bSopenharmony_ci
1228bf80f4bSopenharmony_ci        if (inPathRaw.empty()) {
1238bf80f4bSopenharmony_ci            return {};
1248bf80f4bSopenharmony_ci        }
1258bf80f4bSopenharmony_ci        // fix slashes. (just change \\ to /)
1268bf80f4bSopenharmony_ci        string_view pathIn = inPathRaw;
1278bf80f4bSopenharmony_ci        string tmp;
1288bf80f4bSopenharmony_ci        if (pathIn.find("\\") != string_view::npos) {
1298bf80f4bSopenharmony_ci            tmp = pathIn;
1308bf80f4bSopenharmony_ci            StringUtil::FindAndReplaceAll(tmp, "\\", "/");
1318bf80f4bSopenharmony_ci            pathIn = tmp;
1328bf80f4bSopenharmony_ci        }
1338bf80f4bSopenharmony_ci
1348bf80f4bSopenharmony_ci        string_view drive;
1358bf80f4bSopenharmony_ci        string_view path;
1368bf80f4bSopenharmony_ci        string_view filename;
1378bf80f4bSopenharmony_ci        string_view ext;
1388bf80f4bSopenharmony_ci        SplitPath(pathIn, drive, path, filename, ext);
1398bf80f4bSopenharmony_ci        string res = "/";
1408bf80f4bSopenharmony_ci        if (drive.empty()) {
1418bf80f4bSopenharmony_ci            // relative to current drive then
1428bf80f4bSopenharmony_ci            res += curDrive;
1438bf80f4bSopenharmony_ci        } else {
1448bf80f4bSopenharmony_ci            res += drive;
1458bf80f4bSopenharmony_ci        }
1468bf80f4bSopenharmony_ci        res += ":";
1478bf80f4bSopenharmony_ci        string normalizedPath;
1488bf80f4bSopenharmony_ci        if (path.empty()) {
1498bf80f4bSopenharmony_ci            return "";
1508bf80f4bSopenharmony_ci        }
1518bf80f4bSopenharmony_ci        if (path[0] != '/') {
1528bf80f4bSopenharmony_ci            // relative path.
1538bf80f4bSopenharmony_ci            normalizedPath = NormalizePath(curPath + path);
1548bf80f4bSopenharmony_ci        } else {
1558bf80f4bSopenharmony_ci            normalizedPath = NormalizePath(path);
1568bf80f4bSopenharmony_ci        }
1578bf80f4bSopenharmony_ci        if (normalizedPath.empty()) {
1588bf80f4bSopenharmony_ci            return "";
1598bf80f4bSopenharmony_ci        }
1608bf80f4bSopenharmony_ci        return res + normalizedPath;
1618bf80f4bSopenharmony_ci#else
1628bf80f4bSopenharmony_ci        if (IsRelative(inPathRaw)) {
1638bf80f4bSopenharmony_ci            return NormalizePath(basePath_ + inPathRaw);
1648bf80f4bSopenharmony_ci        }
1658bf80f4bSopenharmony_ci        return NormalizePath(inPathRaw);
1668bf80f4bSopenharmony_ci#endif
1678bf80f4bSopenharmony_ci    }
1688bf80f4bSopenharmony_ci
1698bf80f4bSopenharmony_ci    IFilesystem::Ptr CreateStdFileSystem() override
1708bf80f4bSopenharmony_ci    {
1718bf80f4bSopenharmony_ci        return IFilesystem::Ptr(new StdFilesystem("/"));
1728bf80f4bSopenharmony_ci    }
1738bf80f4bSopenharmony_ci
1748bf80f4bSopenharmony_ci    IFilesystem::Ptr CreateStdFileSystem(string_view rootPathIn) override
1758bf80f4bSopenharmony_ci    {
1768bf80f4bSopenharmony_ci        string_view protocol;
1778bf80f4bSopenharmony_ci        string_view path;
1788bf80f4bSopenharmony_ci        if (ParseUri(rootPathIn, protocol, path)) {
1798bf80f4bSopenharmony_ci            if (protocol != "file") {
1808bf80f4bSopenharmony_ci                return {};
1818bf80f4bSopenharmony_ci            }
1828bf80f4bSopenharmony_ci            rootPathIn = path;
1838bf80f4bSopenharmony_ci        }
1848bf80f4bSopenharmony_ci        auto rootPath = ResolvePath(rootPathIn);
1858bf80f4bSopenharmony_ci        if (!rootPath.empty()) {
1868bf80f4bSopenharmony_ci            auto entry = rootFs_->GetEntry(rootPath);
1878bf80f4bSopenharmony_ci            if (entry.type == IDirectory::Entry::DIRECTORY) {
1888bf80f4bSopenharmony_ci                return IFilesystem::Ptr(new StdFilesystem(rootPath));
1898bf80f4bSopenharmony_ci            }
1908bf80f4bSopenharmony_ci        }
1918bf80f4bSopenharmony_ci        return {};
1928bf80f4bSopenharmony_ci    }
1938bf80f4bSopenharmony_ci    IFilesystem::Ptr CreateMemFileSystem() override
1948bf80f4bSopenharmony_ci    {
1958bf80f4bSopenharmony_ci        return IFilesystem::Ptr(new MemoryFilesystem());
1968bf80f4bSopenharmony_ci    }
1978bf80f4bSopenharmony_ci    IFilesystem::Ptr CreateROFilesystem(const void* const data, uint64_t size) override
1988bf80f4bSopenharmony_ci    {
1998bf80f4bSopenharmony_ci        return IFilesystem::Ptr { new RoFileSystem(data, static_cast<size_t>(size)) };
2008bf80f4bSopenharmony_ci    }
2018bf80f4bSopenharmony_ci};
2028bf80f4bSopenharmony_ci} // namespace
2038bf80f4bSopenharmony_ci
2048bf80f4bSopenharmony_ciconst IInterface* FileMonitorImpl::GetInterface(const Uid& uid) const
2058bf80f4bSopenharmony_ci{
2068bf80f4bSopenharmony_ci    if ((uid == IFileMonitor::UID) || (uid == IInterface::UID)) {
2078bf80f4bSopenharmony_ci        return this;
2088bf80f4bSopenharmony_ci    }
2098bf80f4bSopenharmony_ci    return nullptr;
2108bf80f4bSopenharmony_ci}
2118bf80f4bSopenharmony_ci
2128bf80f4bSopenharmony_ciIInterface* FileMonitorImpl::GetInterface(const Uid& uid)
2138bf80f4bSopenharmony_ci{
2148bf80f4bSopenharmony_ci    if ((uid == IFileMonitor::UID) || (uid == IInterface::UID)) {
2158bf80f4bSopenharmony_ci        return this;
2168bf80f4bSopenharmony_ci    }
2178bf80f4bSopenharmony_ci    return nullptr;
2188bf80f4bSopenharmony_ci}
2198bf80f4bSopenharmony_ci
2208bf80f4bSopenharmony_civoid FileMonitorImpl::Ref()
2218bf80f4bSopenharmony_ci{
2228bf80f4bSopenharmony_ci    refCount_++;
2238bf80f4bSopenharmony_ci}
2248bf80f4bSopenharmony_ci
2258bf80f4bSopenharmony_civoid FileMonitorImpl::Unref()
2268bf80f4bSopenharmony_ci{
2278bf80f4bSopenharmony_ci    if (--refCount_ == 0) {
2288bf80f4bSopenharmony_ci        delete this;
2298bf80f4bSopenharmony_ci    }
2308bf80f4bSopenharmony_ci}
2318bf80f4bSopenharmony_ci
2328bf80f4bSopenharmony_civoid FileMonitorImpl::Initialize(IFileManager& manager)
2338bf80f4bSopenharmony_ci{
2348bf80f4bSopenharmony_ci    fileMonitor_ = BASE_NS::make_unique<FileMonitor>(manager);
2358bf80f4bSopenharmony_ci}
2368bf80f4bSopenharmony_ci
2378bf80f4bSopenharmony_cibool FileMonitorImpl::AddPath(const string_view path)
2388bf80f4bSopenharmony_ci{
2398bf80f4bSopenharmony_ci    if (fileMonitor_) {
2408bf80f4bSopenharmony_ci        return fileMonitor_->AddPath(path);
2418bf80f4bSopenharmony_ci    }
2428bf80f4bSopenharmony_ci    return false;
2438bf80f4bSopenharmony_ci}
2448bf80f4bSopenharmony_ci
2458bf80f4bSopenharmony_cibool FileMonitorImpl::RemovePath(const string_view path)
2468bf80f4bSopenharmony_ci{
2478bf80f4bSopenharmony_ci    if (fileMonitor_) {
2488bf80f4bSopenharmony_ci        return fileMonitor_->RemovePath(path);
2498bf80f4bSopenharmony_ci    }
2508bf80f4bSopenharmony_ci    return false;
2518bf80f4bSopenharmony_ci}
2528bf80f4bSopenharmony_ci
2538bf80f4bSopenharmony_civoid FileMonitorImpl::ScanModifications(vector<string>& added, vector<string>& removed, vector<string>& modified)
2548bf80f4bSopenharmony_ci{
2558bf80f4bSopenharmony_ci    added.clear();
2568bf80f4bSopenharmony_ci    removed.clear();
2578bf80f4bSopenharmony_ci    modified.clear();
2588bf80f4bSopenharmony_ci    if (fileMonitor_) {
2598bf80f4bSopenharmony_ci        fileMonitor_->ScanModifications(added, removed, modified);
2608bf80f4bSopenharmony_ci    }
2618bf80f4bSopenharmony_ci}
2628bf80f4bSopenharmony_ci
2638bf80f4bSopenharmony_ciIInterface* CreateFileMonitor(IClassFactory& /* registry */, PluginToken /* token */)
2648bf80f4bSopenharmony_ci{
2658bf80f4bSopenharmony_ci    return new FileMonitorImpl();
2668bf80f4bSopenharmony_ci}
2678bf80f4bSopenharmony_ciIInterface* GetFileApiFactory(IClassRegister& /* registry */, PluginToken /* token */)
2688bf80f4bSopenharmony_ci{
2698bf80f4bSopenharmony_ci    static FilesystemApi fact;
2708bf80f4bSopenharmony_ci    return &fact;
2718bf80f4bSopenharmony_ci}
2728bf80f4bSopenharmony_ciCORE_END_NAMESPACE()
273