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 45CORE_BEGIN_NAMESPACE(); 46namespace { 47using BASE_NS::string; 48using BASE_NS::string_view; 49using BASE_NS::Uid; 50using BASE_NS::vector; 51 52class FileMonitorImpl final : public IFileMonitor { 53public: 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; 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 74class FilesystemApi final : public IFileSystemApi { 75public: 76 string basePath_; 77 IFilesystem::Ptr rootFs_; 78 FilesystemApi() : basePath_(GetCurrentDirectory()), rootFs_(CreateStdFileSystem()) {} 79 80 const IInterface* GetInterface(const Uid& uid) const override 81 { 82 return const_cast<FilesystemApi*>(this)->GetInterface(uid); 83 } 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 } 91 void Ref() override {} 92 void Unref() override {} 93 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 105 IFileManager::Ptr CreateFilemanager() override 106 { 107 return IInterface::Ptr(new FileManager()); 108 } 109 IFileMonitor::Ptr CreateFilemonitor(IFileManager& manager) override 110 { 111 return IInterface::Ptr(new FileMonitorImpl(manager)); 112 } 113 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 169 IFilesystem::Ptr CreateStdFileSystem() override 170 { 171 return IFilesystem::Ptr(new StdFilesystem("/")); 172 } 173 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 } 193 IFilesystem::Ptr CreateMemFileSystem() override 194 { 195 return IFilesystem::Ptr(new MemoryFilesystem()); 196 } 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 204const 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 212IInterface* FileMonitorImpl::GetInterface(const Uid& uid) 213{ 214 if ((uid == IFileMonitor::UID) || (uid == IInterface::UID)) { 215 return this; 216 } 217 return nullptr; 218} 219 220void FileMonitorImpl::Ref() 221{ 222 refCount_++; 223} 224 225void FileMonitorImpl::Unref() 226{ 227 if (--refCount_ == 0) { 228 delete this; 229 } 230} 231 232void FileMonitorImpl::Initialize(IFileManager& manager) 233{ 234 fileMonitor_ = BASE_NS::make_unique<FileMonitor>(manager); 235} 236 237bool FileMonitorImpl::AddPath(const string_view path) 238{ 239 if (fileMonitor_) { 240 return fileMonitor_->AddPath(path); 241 } 242 return false; 243} 244 245bool FileMonitorImpl::RemovePath(const string_view path) 246{ 247 if (fileMonitor_) { 248 return fileMonitor_->RemovePath(path); 249 } 250 return false; 251} 252 253void 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 263IInterface* CreateFileMonitor(IClassFactory& /* registry */, PluginToken /* token */) 264{ 265 return new FileMonitorImpl(); 266} 267IInterface* GetFileApiFactory(IClassRegister& /* registry */, PluginToken /* token */) 268{ 269 static FilesystemApi fact; 270 return &fact; 271} 272CORE_END_NAMESPACE() 273