18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#include "rofs_filesystem.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <algorithm> 198bf80f4bSopenharmony_ci#include <cstdint> 208bf80f4bSopenharmony_ci 218bf80f4bSopenharmony_ci#include <base/containers/allocator.h> 228bf80f4bSopenharmony_ci#include <base/containers/array_view.h> 238bf80f4bSopenharmony_ci#include <base/containers/iterator.h> 248bf80f4bSopenharmony_ci#include <base/containers/string.h> 258bf80f4bSopenharmony_ci#include <base/containers/string_view.h> 268bf80f4bSopenharmony_ci#include <base/containers/type_traits.h> 278bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h> 288bf80f4bSopenharmony_ci#include <base/containers/vector.h> 298bf80f4bSopenharmony_ci#include <base/namespace.h> 308bf80f4bSopenharmony_ci#include <core/io/intf_directory.h> 318bf80f4bSopenharmony_ci#include <core/io/intf_file.h> 328bf80f4bSopenharmony_ci#include <core/log.h> 338bf80f4bSopenharmony_ci#include <core/namespace.h> 348bf80f4bSopenharmony_ci 358bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE() 368bf80f4bSopenharmony_cinamespace { 378bf80f4bSopenharmony_ciusing BASE_NS::array_view; 388bf80f4bSopenharmony_ciusing BASE_NS::CloneData; 398bf80f4bSopenharmony_ciusing BASE_NS::move; 408bf80f4bSopenharmony_ciusing BASE_NS::string; 418bf80f4bSopenharmony_ciusing BASE_NS::string_view; 428bf80f4bSopenharmony_ciusing BASE_NS::vector; 438bf80f4bSopenharmony_ci 448bf80f4bSopenharmony_cistruct FsEntry { 458bf80f4bSopenharmony_ci const char fname[256]; 468bf80f4bSopenharmony_ci const uint64_t offset; 478bf80f4bSopenharmony_ci const uint64_t size; 488bf80f4bSopenharmony_ci}; 498bf80f4bSopenharmony_ci 508bf80f4bSopenharmony_ci/** Read-only memory file. */ 518bf80f4bSopenharmony_ciclass ROFSMemoryFile final : public IFile { 528bf80f4bSopenharmony_cipublic: 538bf80f4bSopenharmony_ci ~ROFSMemoryFile() override = default; 548bf80f4bSopenharmony_ci ROFSMemoryFile(const uint8_t* const data, const size_t size) : data_(data), size_(size) {} 558bf80f4bSopenharmony_ci ROFSMemoryFile(const ROFSMemoryFile&) = delete; 568bf80f4bSopenharmony_ci ROFSMemoryFile(ROFSMemoryFile&&) = delete; 578bf80f4bSopenharmony_ci ROFSMemoryFile& operator=(const ROFSMemoryFile&) = delete; 588bf80f4bSopenharmony_ci ROFSMemoryFile& operator=(ROFSMemoryFile&&) = delete; 598bf80f4bSopenharmony_ci 608bf80f4bSopenharmony_ci Mode GetMode() const override 618bf80f4bSopenharmony_ci { 628bf80f4bSopenharmony_ci return IFile::Mode::READ_ONLY; 638bf80f4bSopenharmony_ci } 648bf80f4bSopenharmony_ci 658bf80f4bSopenharmony_ci void Close() override {} 668bf80f4bSopenharmony_ci 678bf80f4bSopenharmony_ci uint64_t Read(void* buffer, uint64_t count) override 688bf80f4bSopenharmony_ci { 698bf80f4bSopenharmony_ci uint64_t toRead = count; 708bf80f4bSopenharmony_ci if ((index_ + toRead) > size_) { 718bf80f4bSopenharmony_ci toRead = size_ - index_; 728bf80f4bSopenharmony_ci } 738bf80f4bSopenharmony_ci 748bf80f4bSopenharmony_ci if (toRead > 0) { 758bf80f4bSopenharmony_ci if (toRead <= SIZE_MAX) { 768bf80f4bSopenharmony_ci if (CloneData(buffer, static_cast<size_t>(count), data_ + index_, static_cast<size_t>(toRead))) { 778bf80f4bSopenharmony_ci index_ += toRead; 788bf80f4bSopenharmony_ci } 798bf80f4bSopenharmony_ci } else { 808bf80f4bSopenharmony_ci CORE_ASSERT_MSG(false, "Unable to read chunks bigger than (SIZE_MAX) bytes."); 818bf80f4bSopenharmony_ci toRead = 0; 828bf80f4bSopenharmony_ci } 838bf80f4bSopenharmony_ci } 848bf80f4bSopenharmony_ci 858bf80f4bSopenharmony_ci return toRead; 868bf80f4bSopenharmony_ci } 878bf80f4bSopenharmony_ci 888bf80f4bSopenharmony_ci uint64_t Write(const void* /* buffer */, uint64_t /* count */) override 898bf80f4bSopenharmony_ci { 908bf80f4bSopenharmony_ci return 0; 918bf80f4bSopenharmony_ci } 928bf80f4bSopenharmony_ci 938bf80f4bSopenharmony_ci uint64_t GetLength() const override 948bf80f4bSopenharmony_ci { 958bf80f4bSopenharmony_ci return size_; 968bf80f4bSopenharmony_ci } 978bf80f4bSopenharmony_ci 988bf80f4bSopenharmony_ci bool Seek(uint64_t offset) override 998bf80f4bSopenharmony_ci { 1008bf80f4bSopenharmony_ci if (offset < size_) { 1018bf80f4bSopenharmony_ci index_ = offset; 1028bf80f4bSopenharmony_ci return true; 1038bf80f4bSopenharmony_ci } 1048bf80f4bSopenharmony_ci 1058bf80f4bSopenharmony_ci return false; 1068bf80f4bSopenharmony_ci } 1078bf80f4bSopenharmony_ci 1088bf80f4bSopenharmony_ci uint64_t GetPosition() const override 1098bf80f4bSopenharmony_ci { 1108bf80f4bSopenharmony_ci return index_; 1118bf80f4bSopenharmony_ci } 1128bf80f4bSopenharmony_ci 1138bf80f4bSopenharmony_ciprotected: 1148bf80f4bSopenharmony_ci void Destroy() override 1158bf80f4bSopenharmony_ci { 1168bf80f4bSopenharmony_ci delete this; 1178bf80f4bSopenharmony_ci } 1188bf80f4bSopenharmony_ci 1198bf80f4bSopenharmony_ciprivate: 1208bf80f4bSopenharmony_ci uint64_t index_ { 0 }; 1218bf80f4bSopenharmony_ci const uint8_t* const data_; 1228bf80f4bSopenharmony_ci const size_t size_; 1238bf80f4bSopenharmony_ci}; 1248bf80f4bSopenharmony_ci 1258bf80f4bSopenharmony_ciclass ROFSMemoryDirectory final : public IDirectory { 1268bf80f4bSopenharmony_cipublic: 1278bf80f4bSopenharmony_ci ~ROFSMemoryDirectory() override = default; 1288bf80f4bSopenharmony_ci 1298bf80f4bSopenharmony_ci explicit ROFSMemoryDirectory(const vector<IDirectory::Entry>& contents) : contents_(contents) {} 1308bf80f4bSopenharmony_ci 1318bf80f4bSopenharmony_ci ROFSMemoryDirectory(const ROFSMemoryDirectory&) = delete; 1328bf80f4bSopenharmony_ci ROFSMemoryDirectory(ROFSMemoryDirectory&&) = delete; 1338bf80f4bSopenharmony_ci ROFSMemoryDirectory& operator=(const ROFSMemoryDirectory&) = delete; 1348bf80f4bSopenharmony_ci ROFSMemoryDirectory& operator=(ROFSMemoryDirectory&&) = delete; 1358bf80f4bSopenharmony_ci 1368bf80f4bSopenharmony_ci void Close() override {} 1378bf80f4bSopenharmony_ci 1388bf80f4bSopenharmony_ci vector<Entry> GetEntries() const override 1398bf80f4bSopenharmony_ci { 1408bf80f4bSopenharmony_ci return contents_; 1418bf80f4bSopenharmony_ci } 1428bf80f4bSopenharmony_ci 1438bf80f4bSopenharmony_ciprotected: 1448bf80f4bSopenharmony_ci void Destroy() override 1458bf80f4bSopenharmony_ci { 1468bf80f4bSopenharmony_ci delete this; 1478bf80f4bSopenharmony_ci } 1488bf80f4bSopenharmony_ci 1498bf80f4bSopenharmony_ciprivate: 1508bf80f4bSopenharmony_ci const vector<IDirectory::Entry>& contents_; 1518bf80f4bSopenharmony_ci}; 1528bf80f4bSopenharmony_ci 1538bf80f4bSopenharmony_cistring_view Trim(string_view path) 1548bf80f4bSopenharmony_ci{ 1558bf80f4bSopenharmony_ci // remove leading and trailing slash.. 1568bf80f4bSopenharmony_ci if (!path.empty()) { 1578bf80f4bSopenharmony_ci if (path.back() == '/') { 1588bf80f4bSopenharmony_ci path.remove_suffix(1U); 1598bf80f4bSopenharmony_ci } 1608bf80f4bSopenharmony_ci } 1618bf80f4bSopenharmony_ci if (!path.empty()) { 1628bf80f4bSopenharmony_ci if (path.front() == '/') { 1638bf80f4bSopenharmony_ci path.remove_prefix(1); 1648bf80f4bSopenharmony_ci } 1658bf80f4bSopenharmony_ci } 1668bf80f4bSopenharmony_ci return path; 1678bf80f4bSopenharmony_ci} 1688bf80f4bSopenharmony_ci} // namespace 1698bf80f4bSopenharmony_ci 1708bf80f4bSopenharmony_ciRoFileSystem::RoFileSystem(const void* const blob, size_t blobSize) 1718bf80f4bSopenharmony_ci{ 1728bf80f4bSopenharmony_ci for (size_t i = 0; i < blobSize; i++) { 1738bf80f4bSopenharmony_ci IDirectory::Entry entry; 1748bf80f4bSopenharmony_ci const auto& romEntry = (reinterpret_cast<const FsEntry*>(blob))[i]; 1758bf80f4bSopenharmony_ci if (romEntry.fname[0] == 0) { 1768bf80f4bSopenharmony_ci break; 1778bf80f4bSopenharmony_ci } 1788bf80f4bSopenharmony_ci const string_view tmp = romEntry.fname; 1798bf80f4bSopenharmony_ci size_t t = 0; 1808bf80f4bSopenharmony_ci string path; 1818bf80f4bSopenharmony_ci for (;;) { 1828bf80f4bSopenharmony_ci const size_t t2 = tmp.find_first_of('/', t); 1838bf80f4bSopenharmony_ci if (t2 == string::npos) { 1848bf80f4bSopenharmony_ci break; 1858bf80f4bSopenharmony_ci } 1868bf80f4bSopenharmony_ci t = t2; 1878bf80f4bSopenharmony_ci const auto pathLength = path.length(); 1888bf80f4bSopenharmony_ci entry.name = tmp.substr(pathLength, t - pathLength); 1898bf80f4bSopenharmony_ci path.reserve(pathLength + entry.name.length() + 1); 1908bf80f4bSopenharmony_ci path += entry.name; 1918bf80f4bSopenharmony_ci path += '/'; 1928bf80f4bSopenharmony_ci if (directories_.find(path) == directories_.end()) { 1938bf80f4bSopenharmony_ci // new directory seen 1948bf80f4bSopenharmony_ci entry.type = IDirectory::Entry::DIRECTORY; 1958bf80f4bSopenharmony_ci const auto& parentDir = Trim(path.substr(0, pathLength)); 1968bf80f4bSopenharmony_ci if (const auto pos = directories_.find(parentDir); pos != directories_.cend()) { 1978bf80f4bSopenharmony_ci // add each subdirectory only once 1988bf80f4bSopenharmony_ci if (std::none_of( 1998bf80f4bSopenharmony_ci pos->second.cbegin(), pos->second.cend(), [&entry](const IDirectory::Entry& child) { 2008bf80f4bSopenharmony_ci return child.type == entry.type && child.name == entry.name; 2018bf80f4bSopenharmony_ci })) { 2028bf80f4bSopenharmony_ci pos->second.push_back(move(entry)); 2038bf80f4bSopenharmony_ci } 2048bf80f4bSopenharmony_ci } else { 2058bf80f4bSopenharmony_ci directories_[string(parentDir)].push_back(move(entry)); 2068bf80f4bSopenharmony_ci } 2078bf80f4bSopenharmony_ci directories_[path.substr(0, path.length() - 1)].reserve(1); 2088bf80f4bSopenharmony_ci } 2098bf80f4bSopenharmony_ci t++; 2108bf80f4bSopenharmony_ci } 2118bf80f4bSopenharmony_ci // add the file entry.. 2128bf80f4bSopenharmony_ci entry.name = tmp.substr(t); 2138bf80f4bSopenharmony_ci entry.type = IDirectory::Entry::FILE; 2148bf80f4bSopenharmony_ci const auto pathLength = path.length(); 2158bf80f4bSopenharmony_ci path.reserve(pathLength + entry.name.length()); 2168bf80f4bSopenharmony_ci path += entry.name; 2178bf80f4bSopenharmony_ci directories_[Trim(path.substr(0, pathLength))].push_back(move(entry)); 2188bf80f4bSopenharmony_ci auto* data = reinterpret_cast<const uint8_t*>(blob) + romEntry.offset; 2198bf80f4bSopenharmony_ci files_[move(path)] = array_view(data, static_cast<size_t>(romEntry.size)); 2208bf80f4bSopenharmony_ci } 2218bf80f4bSopenharmony_ci} 2228bf80f4bSopenharmony_ci 2238bf80f4bSopenharmony_ciIDirectory::Entry RoFileSystem::GetEntry(const string_view uri) 2248bf80f4bSopenharmony_ci{ 2258bf80f4bSopenharmony_ci const string_view t = Trim(uri); 2268bf80f4bSopenharmony_ci // check if it's a file first... 2278bf80f4bSopenharmony_ci const auto it = files_.find(t); 2288bf80f4bSopenharmony_ci if (it != files_.end()) { 2298bf80f4bSopenharmony_ci return { IDirectory::Entry::FILE, string(uri), 0 }; 2308bf80f4bSopenharmony_ci } 2318bf80f4bSopenharmony_ci // is it a directory then 2328bf80f4bSopenharmony_ci const auto it2 = directories_.find(t); 2338bf80f4bSopenharmony_ci if (it2 != directories_.end()) { 2348bf80f4bSopenharmony_ci return { IDirectory::Entry::DIRECTORY, string(uri), 0 }; 2358bf80f4bSopenharmony_ci } 2368bf80f4bSopenharmony_ci // nope. does not exist. 2378bf80f4bSopenharmony_ci return {}; 2388bf80f4bSopenharmony_ci} 2398bf80f4bSopenharmony_ci 2408bf80f4bSopenharmony_ciIFile::Ptr RoFileSystem::OpenFile(const string_view path) 2418bf80f4bSopenharmony_ci{ 2428bf80f4bSopenharmony_ci auto it = files_.find(Trim(path)); 2438bf80f4bSopenharmony_ci if (it != files_.end()) { 2448bf80f4bSopenharmony_ci return IFile::Ptr { new ROFSMemoryFile(it->second.data(), it->second.size()) }; 2458bf80f4bSopenharmony_ci } 2468bf80f4bSopenharmony_ci return IFile::Ptr(); 2478bf80f4bSopenharmony_ci} 2488bf80f4bSopenharmony_ci 2498bf80f4bSopenharmony_ciIFile::Ptr RoFileSystem::CreateFile(const string_view /* path */) 2508bf80f4bSopenharmony_ci{ 2518bf80f4bSopenharmony_ci return IFile::Ptr(); 2528bf80f4bSopenharmony_ci} 2538bf80f4bSopenharmony_ci 2548bf80f4bSopenharmony_cibool RoFileSystem::DeleteFile(const string_view /* path */) 2558bf80f4bSopenharmony_ci{ 2568bf80f4bSopenharmony_ci return false; 2578bf80f4bSopenharmony_ci} 2588bf80f4bSopenharmony_ci 2598bf80f4bSopenharmony_ciIDirectory::Ptr RoFileSystem::OpenDirectory(const string_view path) 2608bf80f4bSopenharmony_ci{ 2618bf80f4bSopenharmony_ci const string_view t = Trim(path); 2628bf80f4bSopenharmony_ci auto it = directories_.find(t); 2638bf80f4bSopenharmony_ci if (it != directories_.end()) { 2648bf80f4bSopenharmony_ci return IDirectory::Ptr { new ROFSMemoryDirectory(it->second) }; 2658bf80f4bSopenharmony_ci } 2668bf80f4bSopenharmony_ci return IDirectory::Ptr(); 2678bf80f4bSopenharmony_ci} 2688bf80f4bSopenharmony_ci 2698bf80f4bSopenharmony_ciIDirectory::Ptr RoFileSystem::CreateDirectory(const string_view /* path */) 2708bf80f4bSopenharmony_ci{ 2718bf80f4bSopenharmony_ci return IDirectory::Ptr(); 2728bf80f4bSopenharmony_ci} 2738bf80f4bSopenharmony_ci 2748bf80f4bSopenharmony_cibool RoFileSystem::DeleteDirectory(const string_view /* path */) 2758bf80f4bSopenharmony_ci{ 2768bf80f4bSopenharmony_ci return false; 2778bf80f4bSopenharmony_ci} 2788bf80f4bSopenharmony_ci 2798bf80f4bSopenharmony_cibool RoFileSystem::Rename(const string_view /* fromPath */, const string_view /* toPath */) 2808bf80f4bSopenharmony_ci{ 2818bf80f4bSopenharmony_ci return false; 2828bf80f4bSopenharmony_ci} 2838bf80f4bSopenharmony_ci 2848bf80f4bSopenharmony_civector<string> RoFileSystem::GetUriPaths(const string_view) const 2858bf80f4bSopenharmony_ci{ 2868bf80f4bSopenharmony_ci return {}; 2878bf80f4bSopenharmony_ci} 2888bf80f4bSopenharmony_ciCORE_END_NAMESPACE() 289