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