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 "std_filesystem.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#if defined(__has_include) 198bf80f4bSopenharmony_ci#if __has_include(<filesystem>) 208bf80f4bSopenharmony_ci#include <filesystem> 218bf80f4bSopenharmony_ci#endif 228bf80f4bSopenharmony_ci#endif // defined(__has_include) 238bf80f4bSopenharmony_ci 248bf80f4bSopenharmony_ci#if !defined(HAS_FILESYSTEM) 258bf80f4bSopenharmony_ci#include <sys/stat.h> 268bf80f4bSopenharmony_ci#include <unistd.h> 278bf80f4bSopenharmony_ci#endif 288bf80f4bSopenharmony_ci 298bf80f4bSopenharmony_ci#include <cstdint> 308bf80f4bSopenharmony_ci#include <cstdio> 318bf80f4bSopenharmony_ci 328bf80f4bSopenharmony_ci#include <base/containers/string.h> 338bf80f4bSopenharmony_ci#include <base/containers/string_view.h> 348bf80f4bSopenharmony_ci#include <base/containers/type_traits.h> 358bf80f4bSopenharmony_ci#include <base/containers/unique_ptr.h> 368bf80f4bSopenharmony_ci#include <base/containers/vector.h> 378bf80f4bSopenharmony_ci#include <base/namespace.h> 388bf80f4bSopenharmony_ci#include <core/io/intf_directory.h> 398bf80f4bSopenharmony_ci#include <core/io/intf_file.h> 408bf80f4bSopenharmony_ci#include <core/log.h> 418bf80f4bSopenharmony_ci#include <core/namespace.h> 428bf80f4bSopenharmony_ci 438bf80f4bSopenharmony_ci#include "io/path_tools.h" 448bf80f4bSopenharmony_ci#include "std_directory.h" 458bf80f4bSopenharmony_ci#include "std_file.h" 468bf80f4bSopenharmony_ci 478bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE() 488bf80f4bSopenharmony_ciusing BASE_NS::make_unique; 498bf80f4bSopenharmony_ciusing BASE_NS::string; 508bf80f4bSopenharmony_ciusing BASE_NS::string_view; 518bf80f4bSopenharmony_ciusing BASE_NS::vector; 528bf80f4bSopenharmony_ci 538bf80f4bSopenharmony_cinamespace { 548bf80f4bSopenharmony_ci#if defined(HAS_FILESYSTEM) 558bf80f4bSopenharmony_cistd::filesystem::path U8Path(string_view str) 568bf80f4bSopenharmony_ci{ 578bf80f4bSopenharmony_ci return std::filesystem::u8path(str.begin().ptr(), str.end().ptr()); 588bf80f4bSopenharmony_ci} 598bf80f4bSopenharmony_ci#endif 608bf80f4bSopenharmony_ci} // namespace 618bf80f4bSopenharmony_ci 628bf80f4bSopenharmony_cistring StdFilesystem::ValidatePath(const string_view pathIn) const 638bf80f4bSopenharmony_ci{ 648bf80f4bSopenharmony_ci auto path = NormalizePath(pathIn); 658bf80f4bSopenharmony_ci if (!path.empty()) { 668bf80f4bSopenharmony_ci if (!basePath_.empty()) { 678bf80f4bSopenharmony_ci // If basePath_ is set we are in a sandbox. so all paths are relative to basePath_ (after normalization) 688bf80f4bSopenharmony_ci path = basePath_ + path; 698bf80f4bSopenharmony_ci } 708bf80f4bSopenharmony_ci // path must be absolute. 718bf80f4bSopenharmony_ci if (path[0] != '/') { 728bf80f4bSopenharmony_ci CORE_LOG_V("Corrupted path in StdFilesystem::ValidatePath. not absolute"); 738bf80f4bSopenharmony_ci return ""; 748bf80f4bSopenharmony_ci } 758bf80f4bSopenharmony_ci#ifdef _WIN32 768bf80f4bSopenharmony_ci // path must have drive letter, otherwise it is NOT absolute. ie. must conform to "/C:/" style 778bf80f4bSopenharmony_ci if ((path.length() < 4) || (path[2] != ':') || (path[3] != '/')) { // 4: size limit; 2 3: index of ':' '/' 788bf80f4bSopenharmony_ci CORE_LOG_V("Corrupted path in StdFilesystem::ValidatePath. missing drive letter, or incorrect root"); 798bf80f4bSopenharmony_ci return ""; 808bf80f4bSopenharmony_ci } 818bf80f4bSopenharmony_ci // remove the '/' slash, which is not used in windows. 828bf80f4bSopenharmony_ci return string(path.substr(1)); 838bf80f4bSopenharmony_ci#endif 848bf80f4bSopenharmony_ci } 858bf80f4bSopenharmony_ci return path; 868bf80f4bSopenharmony_ci} 878bf80f4bSopenharmony_ci 888bf80f4bSopenharmony_ciIFile::Ptr StdFilesystem::OpenFile(const string_view pathIn) 898bf80f4bSopenharmony_ci{ 908bf80f4bSopenharmony_ci auto path = ValidatePath(pathIn); 918bf80f4bSopenharmony_ci if (!path.empty()) { 928bf80f4bSopenharmony_ci return StdFile::Open(path, IFile::Mode::READ_ONLY); 938bf80f4bSopenharmony_ci } 948bf80f4bSopenharmony_ci return IFile::Ptr(); 958bf80f4bSopenharmony_ci} 968bf80f4bSopenharmony_ci 978bf80f4bSopenharmony_ciIFile::Ptr StdFilesystem::CreateFile(const string_view pathIn) 988bf80f4bSopenharmony_ci{ 998bf80f4bSopenharmony_ci auto path = ValidatePath(pathIn); 1008bf80f4bSopenharmony_ci if (!path.empty()) { 1018bf80f4bSopenharmony_ci return StdFile::Create(path, IFile::Mode::READ_WRITE); 1028bf80f4bSopenharmony_ci } 1038bf80f4bSopenharmony_ci 1048bf80f4bSopenharmony_ci return IFile::Ptr(); 1058bf80f4bSopenharmony_ci} 1068bf80f4bSopenharmony_ci 1078bf80f4bSopenharmony_cibool StdFilesystem::DeleteFile(const string_view pathIn) 1088bf80f4bSopenharmony_ci{ 1098bf80f4bSopenharmony_ci auto path = ValidatePath(pathIn); 1108bf80f4bSopenharmony_ci if (path.empty()) { 1118bf80f4bSopenharmony_ci return false; 1128bf80f4bSopenharmony_ci } 1138bf80f4bSopenharmony_ci#if defined(HAS_FILESYSTEM) 1148bf80f4bSopenharmony_ci std::error_code ec; 1158bf80f4bSopenharmony_ci return std::filesystem::remove(U8Path(path), ec) && !ec; 1168bf80f4bSopenharmony_ci#else 1178bf80f4bSopenharmony_ci return std::remove(path.c_str()) == 0; 1188bf80f4bSopenharmony_ci#endif 1198bf80f4bSopenharmony_ci} 1208bf80f4bSopenharmony_ci 1218bf80f4bSopenharmony_ciIDirectory::Ptr StdFilesystem::OpenDirectory(const string_view pathIn) 1228bf80f4bSopenharmony_ci{ 1238bf80f4bSopenharmony_ci auto path = ValidatePath(pathIn); 1248bf80f4bSopenharmony_ci if (!path.empty()) { 1258bf80f4bSopenharmony_ci return IDirectory::Ptr { StdDirectory::Open(path).release() }; 1268bf80f4bSopenharmony_ci } 1278bf80f4bSopenharmony_ci 1288bf80f4bSopenharmony_ci return IDirectory::Ptr(); 1298bf80f4bSopenharmony_ci} 1308bf80f4bSopenharmony_ci 1318bf80f4bSopenharmony_ciIDirectory::Ptr StdFilesystem::CreateDirectory(const string_view pathIn) 1328bf80f4bSopenharmony_ci{ 1338bf80f4bSopenharmony_ci auto path = ValidatePath(pathIn); 1348bf80f4bSopenharmony_ci if (!path.empty()) { 1358bf80f4bSopenharmony_ci return IDirectory::Ptr { StdDirectory::Create(path).release() }; 1368bf80f4bSopenharmony_ci } 1378bf80f4bSopenharmony_ci 1388bf80f4bSopenharmony_ci return IDirectory::Ptr(); 1398bf80f4bSopenharmony_ci} 1408bf80f4bSopenharmony_ci 1418bf80f4bSopenharmony_cibool StdFilesystem::DeleteDirectory(const string_view pathIn) 1428bf80f4bSopenharmony_ci{ 1438bf80f4bSopenharmony_ci auto path = ValidatePath(pathIn); 1448bf80f4bSopenharmony_ci if (path.empty()) { 1458bf80f4bSopenharmony_ci return false; 1468bf80f4bSopenharmony_ci } 1478bf80f4bSopenharmony_ci#if defined(HAS_FILESYSTEM) 1488bf80f4bSopenharmony_ci std::error_code ec; 1498bf80f4bSopenharmony_ci return std::filesystem::remove(U8Path(path), ec) && !ec; 1508bf80f4bSopenharmony_ci#else 1518bf80f4bSopenharmony_ci return rmdir(string(path).c_str()) == 0; 1528bf80f4bSopenharmony_ci#endif 1538bf80f4bSopenharmony_ci} 1548bf80f4bSopenharmony_ci 1558bf80f4bSopenharmony_cibool StdFilesystem::Rename(const string_view fromPath, const string_view toPath) 1568bf80f4bSopenharmony_ci{ 1578bf80f4bSopenharmony_ci auto pathFrom = ValidatePath(fromPath); 1588bf80f4bSopenharmony_ci auto pathTo = ValidatePath(toPath); 1598bf80f4bSopenharmony_ci if (pathFrom.empty() || pathTo.empty()) { 1608bf80f4bSopenharmony_ci return false; 1618bf80f4bSopenharmony_ci } 1628bf80f4bSopenharmony_ci 1638bf80f4bSopenharmony_ci#if defined(HAS_FILESYSTEM) 1648bf80f4bSopenharmony_ci std::error_code ec; 1658bf80f4bSopenharmony_ci std::filesystem::rename(U8Path(pathFrom), U8Path(pathTo), ec); 1668bf80f4bSopenharmony_ci return !ec; 1678bf80f4bSopenharmony_ci#else 1688bf80f4bSopenharmony_ci return std::rename(pathFrom.c_str(), pathTo.c_str()) == 0; 1698bf80f4bSopenharmony_ci#endif 1708bf80f4bSopenharmony_ci} 1718bf80f4bSopenharmony_ci 1728bf80f4bSopenharmony_civector<string> StdFilesystem::GetUriPaths(const string_view) const 1738bf80f4bSopenharmony_ci{ 1748bf80f4bSopenharmony_ci return {}; 1758bf80f4bSopenharmony_ci} 1768bf80f4bSopenharmony_ci 1778bf80f4bSopenharmony_ciStdFilesystem::StdFilesystem(string_view basePath) : basePath_(basePath) 1788bf80f4bSopenharmony_ci{ 1798bf80f4bSopenharmony_ci // remove the extraneous slash 1808bf80f4bSopenharmony_ci if (basePath_.back() == '/') { 1818bf80f4bSopenharmony_ci basePath_.resize(basePath_.size() - 1); 1828bf80f4bSopenharmony_ci } 1838bf80f4bSopenharmony_ci} 1848bf80f4bSopenharmony_ci 1858bf80f4bSopenharmony_ciCORE_END_NAMESPACE() 1868bf80f4bSopenharmony_ci 1878bf80f4bSopenharmony_ci// the rest is here, due to shlwapi leaking windows CreateFile macro, and breaking build. 1888bf80f4bSopenharmony_ci#if !defined(HAS_FILESYSTEM) 1898bf80f4bSopenharmony_ci#include <climits> 1908bf80f4bSopenharmony_ci#define CORE_MAX_PATH PATH_MAX 1918bf80f4bSopenharmony_ci#endif 1928bf80f4bSopenharmony_ci 1938bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE() 1948bf80f4bSopenharmony_ciIDirectory::Entry StdFilesystem::GetEntry(const string_view uriIn) 1958bf80f4bSopenharmony_ci{ 1968bf80f4bSopenharmony_ci auto uri = ValidatePath(uriIn); 1978bf80f4bSopenharmony_ci if (!uri.empty()) { 1988bf80f4bSopenharmony_ci#if defined(HAS_FILESYSTEM) 1998bf80f4bSopenharmony_ci std::error_code ec; 2008bf80f4bSopenharmony_ci auto canonicalPath = std::filesystem::canonical(U8Path(uri), ec); 2018bf80f4bSopenharmony_ci if (ec) { 2028bf80f4bSopenharmony_ci return {}; 2038bf80f4bSopenharmony_ci } 2048bf80f4bSopenharmony_ci auto status = std::filesystem::status(canonicalPath, ec); 2058bf80f4bSopenharmony_ci if (ec) { 2068bf80f4bSopenharmony_ci return {}; 2078bf80f4bSopenharmony_ci } 2088bf80f4bSopenharmony_ci auto time = std::filesystem::last_write_time(canonicalPath, ec); 2098bf80f4bSopenharmony_ci if (ec) { 2108bf80f4bSopenharmony_ci return {}; 2118bf80f4bSopenharmony_ci } 2128bf80f4bSopenharmony_ci 2138bf80f4bSopenharmony_ci auto asString = canonicalPath.u8string(); 2148bf80f4bSopenharmony_ci if (std::filesystem::is_directory(status)) { 2158bf80f4bSopenharmony_ci return { IDirectory::Entry::DIRECTORY, string { asString.data(), asString.size() }, 2168bf80f4bSopenharmony_ci static_cast<uint64_t>(time.time_since_epoch().count()) }; 2178bf80f4bSopenharmony_ci } 2188bf80f4bSopenharmony_ci if (std::filesystem::is_regular_file(status)) { 2198bf80f4bSopenharmony_ci return { IDirectory::Entry::FILE, string { asString.data(), asString.size() }, 2208bf80f4bSopenharmony_ci static_cast<uint64_t>(time.time_since_epoch().count()) }; 2218bf80f4bSopenharmony_ci } 2228bf80f4bSopenharmony_ci#else 2238bf80f4bSopenharmony_ci auto path = string(uri); 2248bf80f4bSopenharmony_ci char canonicalPath[CORE_MAX_PATH] = { 0 }; 2258bf80f4bSopenharmony_ci 2268bf80f4bSopenharmony_ci if (realpath(path.c_str(), canonicalPath) == nullptr) { 2278bf80f4bSopenharmony_ci return {}; 2288bf80f4bSopenharmony_ci } 2298bf80f4bSopenharmony_ci struct stat ds {}; 2308bf80f4bSopenharmony_ci if (stat(canonicalPath, &ds) != 0) { 2318bf80f4bSopenharmony_ci return {}; 2328bf80f4bSopenharmony_ci } 2338bf80f4bSopenharmony_ci 2348bf80f4bSopenharmony_ci if ((ds.st_mode & S_IFDIR)) { 2358bf80f4bSopenharmony_ci return { IDirectory::Entry::DIRECTORY, canonicalPath, static_cast<uint64_t>(ds.st_mtime) }; 2368bf80f4bSopenharmony_ci } 2378bf80f4bSopenharmony_ci if ((ds.st_mode & S_IFREG)) { 2388bf80f4bSopenharmony_ci return { IDirectory::Entry::FILE, canonicalPath, static_cast<uint64_t>(ds.st_mtime) }; 2398bf80f4bSopenharmony_ci } 2408bf80f4bSopenharmony_ci#endif 2418bf80f4bSopenharmony_ci } 2428bf80f4bSopenharmony_ci return {}; 2438bf80f4bSopenharmony_ci} 2448bf80f4bSopenharmony_ci 2458bf80f4bSopenharmony_ciCORE_END_NAMESPACE() 246