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