• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cstddef>
17 #include <cstdint>
18 
19 #include <base/containers/string.h>
20 #include <base/containers/string_view.h>
21 #include <base/containers/unique_ptr.h>
22 #include <base/containers/vector.h>
23 #include <base/namespace.h>
24 #include <base/util/uid.h>
25 #include <core/implementation_uids.h>
26 #include <core/io/intf_directory.h>
27 #include <core/io/intf_file_manager.h>
28 #include <core/io/intf_file_monitor.h>
29 #include <core/io/intf_file_system.h>
30 #include <core/io/intf_filesystem_api.h>
31 #include <core/namespace.h>
32 #include <core/plugin/intf_class_factory.h>
33 #include <core/plugin/intf_interface.h>
34 #include <core/plugin/intf_interface_helper.h>
35 #include <core/plugin/intf_plugin.h>
36 
37 #include "dev/file_monitor.h"
38 #include "io/file_manager.h"
39 #include "io/memory_filesystem.h"
40 #include "io/path_tools.h"
41 #include "io/rofs_filesystem.h"
42 #include "io/std_filesystem.h"
43 #ifdef _WIN32
44 #include "util/string_util.h"
45 #endif // _WIN32
46 
47 CORE_BEGIN_NAMESPACE();
48 namespace {
49 using BASE_NS::string;
50 using BASE_NS::string_view;
51 using BASE_NS::Uid;
52 using BASE_NS::vector;
53 
54 class FileMonitorImpl final : public IInterfaceHelper<IFileMonitor> {
55 public:
56     void Initialize(IFileManager&) override;
57     bool AddPath(string_view path) override;
58     bool RemovePath(string_view path) override;
59     void ScanModifications(vector<string>& added, vector<string>& removed, vector<string>& modified) override;
60 
61     FileMonitorImpl() = default;
FileMonitorImpl(IFileManager & manager)62     explicit FileMonitorImpl(IFileManager& manager)
63     {
64         Initialize(manager);
65     }
66 
67     BASE_NS::unique_ptr<FileMonitor> fileMonitor_;
68 };
69 
70 class FilesystemApi final : public IFileSystemApi {
71 public:
72     string basePath_;
73     IFilesystem::Ptr rootFs_;
FilesystemApi()74     FilesystemApi() : basePath_(GetCurrentDirectory()), rootFs_(CreateStdFileSystem()) {}
75 
GetInterface(const Uid & uid) const76     const IInterface* GetInterface(const Uid& uid) const override
77     {
78         return const_cast<FilesystemApi*>(this)->GetInterface(uid);
79     }
GetInterface(const Uid & uid)80     IInterface* GetInterface(const Uid& uid) override
81     {
82         if ((uid == IFileSystemApi::UID) || (uid == IClassFactory::UID) || (uid == IInterface::UID)) {
83             return this;
84         }
85         return nullptr;
86     }
Ref()87     void Ref() override {}
Unref()88     void Unref() override {}
89 
CreateInstance(const Uid & uid)90     IInterface::Ptr CreateInstance(const Uid& uid) override
91     {
92         if (uid == UID_FILE_MONITOR) {
93             return IInterface::Ptr(new FileMonitorImpl());
94         }
95         if (uid == UID_FILE_MANAGER) {
96             return IInterface::Ptr(new FileManager());
97         }
98         return IInterface::Ptr();
99     }
100 
CreateFilemanager()101     IFileManager::Ptr CreateFilemanager() override
102     {
103         return IInterface::Ptr(new FileManager());
104     }
CreateFilemonitor(IFileManager & manager)105     IFileMonitor::Ptr CreateFilemonitor(IFileManager& manager) override
106     {
107         return IInterface::Ptr(new FileMonitorImpl(manager));
108     }
ResolvePath(string_view inPathRaw) const109     string ResolvePath(string_view inPathRaw) const
110     {
111 #if _WIN32
112         string_view curDrive;
113         string_view curPath;
114         string_view curFilename;
115         string_view curExt;
116         SplitPath(basePath_, curDrive, curPath, curFilename, curExt);
117 
118         if (inPathRaw.empty()) {
119             return {};
120         }
121         // fix slashes. (just change \\ to /)
122         string_view pathIn = inPathRaw;
123         string tmp;
124         if (pathIn.find("\\") != string_view::npos) {
125             tmp = pathIn;
126             StringUtil::FindAndReplaceAll(tmp, "\\", "/");
127             pathIn = tmp;
128         }
129 
130         string_view drive;
131         string_view path;
132         string_view filename;
133         string_view ext;
134         SplitPath(pathIn, drive, path, filename, ext);
135         string res = "/";
136         if (drive.empty()) {
137             // relative to current drive then
138             res += curDrive;
139         } else {
140             res += drive;
141         }
142         res += ":";
143         string normalizedPath;
144         if (path.empty()) {
145             return "";
146         }
147         if (path[0] != '/') {
148             // relative path.
149             normalizedPath = NormalizePath(curPath + path);
150         } else {
151             normalizedPath = NormalizePath(path);
152         }
153         if (normalizedPath.empty()) {
154             return "";
155         }
156         return res + normalizedPath;
157 #else
158         if (IsRelative(inPathRaw)) {
159             return NormalizePath(basePath_ + inPathRaw);
160         }
161         return NormalizePath(inPathRaw);
162 #endif
163     }
164 
CreateStdFileSystem()165     IFilesystem::Ptr CreateStdFileSystem() override
166     {
167         return IFilesystem::Ptr(new StdFilesystem("/"));
168     }
169 
CreateStdFileSystem(string_view rootPathIn)170     IFilesystem::Ptr CreateStdFileSystem(string_view rootPathIn) override
171     {
172         string_view protocol;
173         string_view path;
174         if (ParseUri(rootPathIn, protocol, path)) {
175             if (protocol != "file") {
176                 return {};
177             }
178             rootPathIn = path;
179         }
180         auto rootPath = ResolvePath(rootPathIn);
181         if (!rootPath.empty()) {
182             auto entry = rootFs_->GetEntry(rootPath);
183             if (entry.type == IDirectory::Entry::DIRECTORY) {
184                 return IFilesystem::Ptr(new StdFilesystem(rootPath));
185             }
186         }
187         return {};
188     }
CreateMemFileSystem()189     IFilesystem::Ptr CreateMemFileSystem() override
190     {
191         return IFilesystem::Ptr(new MemoryFilesystem());
192     }
CreateROFilesystem(const void * const data,uint64_t size)193     IFilesystem::Ptr CreateROFilesystem(const void* const data, uint64_t size) override
194     {
195         return IFilesystem::Ptr { new RoFileSystem(data, static_cast<size_t>(size)) };
196     }
197 };
198 } // namespace
199 
Initialize(IFileManager & manager)200 void FileMonitorImpl::Initialize(IFileManager& manager)
201 {
202     fileMonitor_ = BASE_NS::make_unique<FileMonitor>(manager);
203 }
204 
AddPath(const string_view path)205 bool FileMonitorImpl::AddPath(const string_view path)
206 {
207     if (fileMonitor_) {
208         return fileMonitor_->AddPath(path);
209     }
210     return false;
211 }
212 
RemovePath(const string_view path)213 bool FileMonitorImpl::RemovePath(const string_view path)
214 {
215     if (fileMonitor_) {
216         return fileMonitor_->RemovePath(path);
217     }
218     return false;
219 }
220 
ScanModifications(vector<string> & added,vector<string> & removed,vector<string> & modified)221 void FileMonitorImpl::ScanModifications(vector<string>& added, vector<string>& removed, vector<string>& modified)
222 {
223     added.clear();
224     removed.clear();
225     modified.clear();
226     if (fileMonitor_) {
227         fileMonitor_->ScanModifications(added, removed, modified);
228     }
229 }
230 
CreateFileMonitor(IClassFactory &,PluginToken)231 IInterface* CreateFileMonitor(IClassFactory& /* registry */, PluginToken /* token */)
232 {
233     return new FileMonitorImpl();
234 }
GetFileApiFactory(IClassRegister &,PluginToken)235 IInterface* GetFileApiFactory(IClassRegister& /* registry */, PluginToken /* token */)
236 {
237     static FilesystemApi fact;
238     return &fact;
239 }
240 CORE_END_NAMESPACE()
241