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/type_traits.h>
22 #include <base/containers/unique_ptr.h>
23 #include <base/containers/vector.h>
24 #include <base/namespace.h>
25 #include <base/util/uid.h>
26 #include <core/implementation_uids.h>
27 #include <core/io/intf_directory.h>
28 #include <core/io/intf_file_manager.h>
29 #include <core/io/intf_file_monitor.h>
30 #include <core/io/intf_file_system.h>
31 #include <core/io/intf_filesystem_api.h>
32 #include <core/namespace.h>
33 #include <core/plugin/intf_class_factory.h>
34 #include <core/plugin/intf_interface.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 #include "util/string_util.h"
44
45 CORE_BEGIN_NAMESPACE();
46 namespace {
47 using BASE_NS::string;
48 using BASE_NS::string_view;
49 using BASE_NS::Uid;
50 using BASE_NS::vector;
51
52 class FileMonitorImpl final : public IFileMonitor {
53 public:
54 const IInterface* GetInterface(const Uid& uid) const override;
55 IInterface* GetInterface(const Uid& uid) override;
56 void Ref() override;
57 void Unref() override;
58
59 void Initialize(IFileManager&) override;
60 bool AddPath(const string_view path) override;
61 bool RemovePath(const string_view path) override;
62 void ScanModifications(vector<string>& added, vector<string>& removed, vector<string>& modified) override;
63
64 FileMonitorImpl() = default;
FileMonitorImpl(IFileManager & manager)65 explicit FileMonitorImpl(IFileManager& manager)
66 {
67 Initialize(manager);
68 }
69
70 BASE_NS::unique_ptr<FileMonitor> fileMonitor_;
71 uint32_t refCount_ { 0 };
72 };
73
74 class FilesystemApi final : public IFileSystemApi {
75 public:
76 string basePath_;
77 IFilesystem::Ptr rootFs_;
FilesystemApi()78 FilesystemApi() : basePath_(GetCurrentDirectory()), rootFs_(CreateStdFileSystem()) {}
79
GetInterface(const Uid & uid) const80 const IInterface* GetInterface(const Uid& uid) const override
81 {
82 return const_cast<FilesystemApi*>(this)->GetInterface(uid);
83 }
GetInterface(const Uid & uid)84 IInterface* GetInterface(const Uid& uid) override
85 {
86 if ((uid == IFileSystemApi::UID) || (uid == IClassFactory::UID) || (uid == IInterface::UID)) {
87 return this;
88 }
89 return nullptr;
90 }
Ref()91 void Ref() override {}
Unref()92 void Unref() override {}
93
CreateInstance(const Uid & uid)94 IInterface::Ptr CreateInstance(const Uid& uid) override
95 {
96 if (uid == UID_FILE_MONITOR) {
97 return IInterface::Ptr(new FileMonitorImpl());
98 }
99 if (uid == UID_FILE_MANAGER) {
100 return IInterface::Ptr(new FileManager());
101 }
102 return IInterface::Ptr();
103 }
104
CreateFilemanager()105 IFileManager::Ptr CreateFilemanager() override
106 {
107 return IInterface::Ptr(new FileManager());
108 }
CreateFilemonitor(IFileManager & manager)109 IFileMonitor::Ptr CreateFilemonitor(IFileManager& manager) override
110 {
111 return IInterface::Ptr(new FileMonitorImpl(manager));
112 }
ResolvePath(string_view inPathRaw) const113 string ResolvePath(string_view inPathRaw) const
114 {
115 #if _WIN32
116 string_view curDrive;
117 string_view curPath;
118 string_view curFilename;
119 string_view curExt;
120 SplitPath(basePath_, curDrive, curPath, curFilename, curExt);
121
122 if (inPathRaw.empty()) {
123 return {};
124 }
125 // fix slashes. (just change \\ to /)
126 string_view pathIn = inPathRaw;
127 string tmp;
128 if (pathIn.find("\\") != string_view::npos) {
129 tmp = pathIn;
130 StringUtil::FindAndReplaceAll(tmp, "\\", "/");
131 pathIn = tmp;
132 }
133
134 string_view drive;
135 string_view path;
136 string_view filename;
137 string_view ext;
138 SplitPath(pathIn, drive, path, filename, ext);
139 string res = "/";
140 if (drive.empty()) {
141 // relative to current drive then
142 res += curDrive;
143 } else {
144 res += drive;
145 }
146 res += ":";
147 string normalizedPath;
148 if (path.empty()) {
149 return "";
150 }
151 if (path[0] != '/') {
152 // relative path.
153 normalizedPath = NormalizePath(curPath + path);
154 } else {
155 normalizedPath = NormalizePath(path);
156 }
157 if (normalizedPath.empty()) {
158 return "";
159 }
160 return res + normalizedPath;
161 #else
162 if (IsRelative(inPathRaw)) {
163 return NormalizePath(basePath_ + inPathRaw);
164 }
165 return NormalizePath(inPathRaw);
166 #endif
167 }
168
CreateStdFileSystem()169 IFilesystem::Ptr CreateStdFileSystem() override
170 {
171 return IFilesystem::Ptr(new StdFilesystem("/"));
172 }
173
CreateStdFileSystem(string_view rootPathIn)174 IFilesystem::Ptr CreateStdFileSystem(string_view rootPathIn) override
175 {
176 string_view protocol;
177 string_view path;
178 if (ParseUri(rootPathIn, protocol, path)) {
179 if (protocol != "file") {
180 return {};
181 }
182 rootPathIn = path;
183 }
184 auto rootPath = ResolvePath(rootPathIn);
185 if (!rootPath.empty()) {
186 auto entry = rootFs_->GetEntry(rootPath);
187 if (entry.type == IDirectory::Entry::DIRECTORY) {
188 return IFilesystem::Ptr(new StdFilesystem(rootPath));
189 }
190 }
191 return {};
192 }
CreateMemFileSystem()193 IFilesystem::Ptr CreateMemFileSystem() override
194 {
195 return IFilesystem::Ptr(new MemoryFilesystem());
196 }
CreateROFilesystem(const void * const data,uint64_t size)197 IFilesystem::Ptr CreateROFilesystem(const void* const data, uint64_t size) override
198 {
199 return IFilesystem::Ptr { new RoFileSystem(data, static_cast<size_t>(size)) };
200 }
201 };
202 } // namespace
203
GetInterface(const Uid & uid) const204 const IInterface* FileMonitorImpl::GetInterface(const Uid& uid) const
205 {
206 if ((uid == IFileMonitor::UID) || (uid == IInterface::UID)) {
207 return this;
208 }
209 return nullptr;
210 }
211
GetInterface(const Uid & uid)212 IInterface* FileMonitorImpl::GetInterface(const Uid& uid)
213 {
214 if ((uid == IFileMonitor::UID) || (uid == IInterface::UID)) {
215 return this;
216 }
217 return nullptr;
218 }
219
Ref()220 void FileMonitorImpl::Ref()
221 {
222 refCount_++;
223 }
224
Unref()225 void FileMonitorImpl::Unref()
226 {
227 if (--refCount_ == 0) {
228 delete this;
229 }
230 }
231
Initialize(IFileManager & manager)232 void FileMonitorImpl::Initialize(IFileManager& manager)
233 {
234 fileMonitor_ = BASE_NS::make_unique<FileMonitor>(manager);
235 }
236
AddPath(const string_view path)237 bool FileMonitorImpl::AddPath(const string_view path)
238 {
239 if (fileMonitor_) {
240 return fileMonitor_->AddPath(path);
241 }
242 return false;
243 }
244
RemovePath(const string_view path)245 bool FileMonitorImpl::RemovePath(const string_view path)
246 {
247 if (fileMonitor_) {
248 return fileMonitor_->RemovePath(path);
249 }
250 return false;
251 }
252
ScanModifications(vector<string> & added,vector<string> & removed,vector<string> & modified)253 void FileMonitorImpl::ScanModifications(vector<string>& added, vector<string>& removed, vector<string>& modified)
254 {
255 added.clear();
256 removed.clear();
257 modified.clear();
258 if (fileMonitor_) {
259 fileMonitor_->ScanModifications(added, removed, modified);
260 }
261 }
262
CreateFileMonitor(IClassFactory &,PluginToken)263 IInterface* CreateFileMonitor(IClassFactory& /* registry */, PluginToken /* token */)
264 {
265 return new FileMonitorImpl();
266 }
GetFileApiFactory(IClassRegister &,PluginToken)267 IInterface* GetFileApiFactory(IClassRegister& /* registry */, PluginToken /* token */)
268 {
269 static FilesystemApi fact;
270 return &fact;
271 }
272 CORE_END_NAMESPACE()
273