15ffd83dbSDimitry Andric //===-- FileSystem.cpp ----------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h" 100b57cec5SDimitry Andric 1181ad6265SDimitry Andric #include "lldb/Utility/DataBufferLLVM.h" 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/Support/Errc.h" 140b57cec5SDimitry Andric #include "llvm/Support/Errno.h" 150b57cec5SDimitry Andric #include "llvm/Support/Error.h" 160b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 170b57cec5SDimitry Andric #include "llvm/Support/Path.h" 180b57cec5SDimitry Andric #include "llvm/Support/Program.h" 190b57cec5SDimitry Andric #include "llvm/Support/Threading.h" 200b57cec5SDimitry Andric 21fe6060f1SDimitry Andric #include <cerrno> 22fe6060f1SDimitry Andric #include <climits> 23fe6060f1SDimitry Andric #include <cstdarg> 24fe6060f1SDimitry Andric #include <cstdio> 250b57cec5SDimitry Andric #include <fcntl.h> 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric #ifdef _WIN32 280b57cec5SDimitry Andric #include "lldb/Host/windows/windows.h" 290b57cec5SDimitry Andric #else 300b57cec5SDimitry Andric #include <sys/ioctl.h> 310b57cec5SDimitry Andric #include <sys/stat.h> 320b57cec5SDimitry Andric #include <termios.h> 330b57cec5SDimitry Andric #include <unistd.h> 340b57cec5SDimitry Andric #endif 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric #include <algorithm> 370b57cec5SDimitry Andric #include <fstream> 38bdd1243dSDimitry Andric #include <optional> 390b57cec5SDimitry Andric #include <vector> 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric using namespace lldb; 420b57cec5SDimitry Andric using namespace lldb_private; 430b57cec5SDimitry Andric using namespace llvm; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric FileSystem &FileSystem::Instance() { return *InstanceImpl(); } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric void FileSystem::Terminate() { 480b57cec5SDimitry Andric lldbassert(InstanceImpl() && "Already terminated."); 490b57cec5SDimitry Andric InstanceImpl().reset(); 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 52bdd1243dSDimitry Andric std::optional<FileSystem> &FileSystem::InstanceImpl() { 53bdd1243dSDimitry Andric static std::optional<FileSystem> g_fs; 540b57cec5SDimitry Andric return g_fs; 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric vfs::directory_iterator FileSystem::DirBegin(const FileSpec &file_spec, 580b57cec5SDimitry Andric std::error_code &ec) { 595ffd83dbSDimitry Andric if (!file_spec) { 605ffd83dbSDimitry Andric ec = std::error_code(static_cast<int>(errc::no_such_file_or_directory), 615ffd83dbSDimitry Andric std::system_category()); 625ffd83dbSDimitry Andric return {}; 635ffd83dbSDimitry Andric } 640b57cec5SDimitry Andric return DirBegin(file_spec.GetPath(), ec); 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric vfs::directory_iterator FileSystem::DirBegin(const Twine &dir, 680b57cec5SDimitry Andric std::error_code &ec) { 690b57cec5SDimitry Andric return m_fs->dir_begin(dir, ec); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric llvm::ErrorOr<vfs::Status> 730b57cec5SDimitry Andric FileSystem::GetStatus(const FileSpec &file_spec) const { 745ffd83dbSDimitry Andric if (!file_spec) 755ffd83dbSDimitry Andric return std::error_code(static_cast<int>(errc::no_such_file_or_directory), 765ffd83dbSDimitry Andric std::system_category()); 770b57cec5SDimitry Andric return GetStatus(file_spec.GetPath()); 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric llvm::ErrorOr<vfs::Status> FileSystem::GetStatus(const Twine &path) const { 810b57cec5SDimitry Andric return m_fs->status(path); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric sys::TimePoint<> 850b57cec5SDimitry Andric FileSystem::GetModificationTime(const FileSpec &file_spec) const { 865ffd83dbSDimitry Andric if (!file_spec) 875ffd83dbSDimitry Andric return sys::TimePoint<>(); 880b57cec5SDimitry Andric return GetModificationTime(file_spec.GetPath()); 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric sys::TimePoint<> FileSystem::GetModificationTime(const Twine &path) const { 920b57cec5SDimitry Andric ErrorOr<vfs::Status> status = m_fs->status(path); 930b57cec5SDimitry Andric if (!status) 940b57cec5SDimitry Andric return sys::TimePoint<>(); 950b57cec5SDimitry Andric return status->getLastModificationTime(); 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric uint64_t FileSystem::GetByteSize(const FileSpec &file_spec) const { 995ffd83dbSDimitry Andric if (!file_spec) 1005ffd83dbSDimitry Andric return 0; 1010b57cec5SDimitry Andric return GetByteSize(file_spec.GetPath()); 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric uint64_t FileSystem::GetByteSize(const Twine &path) const { 1050b57cec5SDimitry Andric ErrorOr<vfs::Status> status = m_fs->status(path); 1060b57cec5SDimitry Andric if (!status) 1070b57cec5SDimitry Andric return 0; 1080b57cec5SDimitry Andric return status->getSize(); 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric uint32_t FileSystem::GetPermissions(const FileSpec &file_spec) const { 1120b57cec5SDimitry Andric return GetPermissions(file_spec.GetPath()); 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric uint32_t FileSystem::GetPermissions(const FileSpec &file_spec, 1160b57cec5SDimitry Andric std::error_code &ec) const { 1175ffd83dbSDimitry Andric if (!file_spec) 1185ffd83dbSDimitry Andric return sys::fs::perms::perms_not_known; 1190b57cec5SDimitry Andric return GetPermissions(file_spec.GetPath(), ec); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric uint32_t FileSystem::GetPermissions(const Twine &path) const { 1230b57cec5SDimitry Andric std::error_code ec; 1240b57cec5SDimitry Andric return GetPermissions(path, ec); 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric uint32_t FileSystem::GetPermissions(const Twine &path, 1280b57cec5SDimitry Andric std::error_code &ec) const { 1290b57cec5SDimitry Andric ErrorOr<vfs::Status> status = m_fs->status(path); 1300b57cec5SDimitry Andric if (!status) { 1310b57cec5SDimitry Andric ec = status.getError(); 1320b57cec5SDimitry Andric return sys::fs::perms::perms_not_known; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric return status->getPermissions(); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric bool FileSystem::Exists(const Twine &path) const { return m_fs->exists(path); } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric bool FileSystem::Exists(const FileSpec &file_spec) const { 1405ffd83dbSDimitry Andric return file_spec && Exists(file_spec.GetPath()); 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric bool FileSystem::Readable(const Twine &path) const { 1440b57cec5SDimitry Andric return GetPermissions(path) & sys::fs::perms::all_read; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric bool FileSystem::Readable(const FileSpec &file_spec) const { 1485ffd83dbSDimitry Andric return file_spec && Readable(file_spec.GetPath()); 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric bool FileSystem::IsDirectory(const Twine &path) const { 1520b57cec5SDimitry Andric ErrorOr<vfs::Status> status = m_fs->status(path); 1530b57cec5SDimitry Andric if (!status) 1540b57cec5SDimitry Andric return false; 1550b57cec5SDimitry Andric return status->isDirectory(); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric bool FileSystem::IsDirectory(const FileSpec &file_spec) const { 1595ffd83dbSDimitry Andric return file_spec && IsDirectory(file_spec.GetPath()); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric bool FileSystem::IsLocal(const Twine &path) const { 1630b57cec5SDimitry Andric bool b = false; 1640b57cec5SDimitry Andric m_fs->isLocal(path, b); 1650b57cec5SDimitry Andric return b; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric bool FileSystem::IsLocal(const FileSpec &file_spec) const { 1695ffd83dbSDimitry Andric return file_spec && IsLocal(file_spec.GetPath()); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric void FileSystem::EnumerateDirectory(Twine path, bool find_directories, 1730b57cec5SDimitry Andric bool find_files, bool find_other, 1740b57cec5SDimitry Andric EnumerateDirectoryCallbackType callback, 1750b57cec5SDimitry Andric void *callback_baton) { 1760b57cec5SDimitry Andric std::error_code EC; 1770b57cec5SDimitry Andric vfs::recursive_directory_iterator Iter(*m_fs, path, EC); 1780b57cec5SDimitry Andric vfs::recursive_directory_iterator End; 1790b57cec5SDimitry Andric for (; Iter != End && !EC; Iter.increment(EC)) { 1800b57cec5SDimitry Andric const auto &Item = *Iter; 1810b57cec5SDimitry Andric ErrorOr<vfs::Status> Status = m_fs->status(Item.path()); 1820b57cec5SDimitry Andric if (!Status) 183*fe013be4SDimitry Andric continue; 1840b57cec5SDimitry Andric if (!find_files && Status->isRegularFile()) 1850b57cec5SDimitry Andric continue; 1860b57cec5SDimitry Andric if (!find_directories && Status->isDirectory()) 1870b57cec5SDimitry Andric continue; 1880b57cec5SDimitry Andric if (!find_other && Status->isOther()) 1890b57cec5SDimitry Andric continue; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric auto Result = callback(callback_baton, Status->getType(), Item.path()); 1920b57cec5SDimitry Andric if (Result == eEnumerateDirectoryResultQuit) 1930b57cec5SDimitry Andric return; 1940b57cec5SDimitry Andric if (Result == eEnumerateDirectoryResultNext) { 1950b57cec5SDimitry Andric // Default behavior is to recurse. Opt out if the callback doesn't want 1960b57cec5SDimitry Andric // this behavior. 1970b57cec5SDimitry Andric Iter.no_push(); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric std::error_code FileSystem::MakeAbsolute(SmallVectorImpl<char> &path) const { 2030b57cec5SDimitry Andric return m_fs->makeAbsolute(path); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric std::error_code FileSystem::MakeAbsolute(FileSpec &file_spec) const { 2070b57cec5SDimitry Andric SmallString<128> path; 2080b57cec5SDimitry Andric file_spec.GetPath(path, false); 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric auto EC = MakeAbsolute(path); 2110b57cec5SDimitry Andric if (EC) 2120b57cec5SDimitry Andric return EC; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric FileSpec new_file_spec(path, file_spec.GetPathStyle()); 2150b57cec5SDimitry Andric file_spec = new_file_spec; 2160b57cec5SDimitry Andric return {}; 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric std::error_code FileSystem::GetRealPath(const Twine &path, 2200b57cec5SDimitry Andric SmallVectorImpl<char> &output) const { 2210b57cec5SDimitry Andric return m_fs->getRealPath(path, output); 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric void FileSystem::Resolve(SmallVectorImpl<char> &path) { 2250b57cec5SDimitry Andric if (path.empty()) 2260b57cec5SDimitry Andric return; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric // Resolve tilde in path. 2290b57cec5SDimitry Andric SmallString<128> resolved(path.begin(), path.end()); 230*fe013be4SDimitry Andric assert(m_tilde_resolver && "must initialize tilde resolver in constructor"); 231*fe013be4SDimitry Andric m_tilde_resolver->ResolveFullPath(llvm::StringRef(path.begin(), path.size()), 2320b57cec5SDimitry Andric resolved); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric // Try making the path absolute if it exists. 2350b57cec5SDimitry Andric SmallString<128> absolute(resolved.begin(), resolved.end()); 2360b57cec5SDimitry Andric MakeAbsolute(absolute); 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric path.clear(); 2390b57cec5SDimitry Andric if (Exists(absolute)) { 2400b57cec5SDimitry Andric path.append(absolute.begin(), absolute.end()); 2410b57cec5SDimitry Andric } else { 2420b57cec5SDimitry Andric path.append(resolved.begin(), resolved.end()); 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric void FileSystem::Resolve(FileSpec &file_spec) { 2475ffd83dbSDimitry Andric if (!file_spec) 2485ffd83dbSDimitry Andric return; 2495ffd83dbSDimitry Andric 2500b57cec5SDimitry Andric // Extract path from the FileSpec. 2510b57cec5SDimitry Andric SmallString<128> path; 2520b57cec5SDimitry Andric file_spec.GetPath(path); 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric // Resolve the path. 2550b57cec5SDimitry Andric Resolve(path); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric // Update the FileSpec with the resolved path. 2580b57cec5SDimitry Andric if (file_spec.GetFilename().IsEmpty()) 259bdd1243dSDimitry Andric file_spec.SetDirectory(path); 2600b57cec5SDimitry Andric else 2610b57cec5SDimitry Andric file_spec.SetPath(path); 2620b57cec5SDimitry Andric file_spec.SetIsResolved(true); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 26581ad6265SDimitry Andric template <typename T> 26681ad6265SDimitry Andric static std::unique_ptr<T> GetMemoryBuffer(const llvm::Twine &path, 26781ad6265SDimitry Andric uint64_t size, uint64_t offset, 26881ad6265SDimitry Andric bool is_volatile) { 26981ad6265SDimitry Andric std::unique_ptr<T> buffer; 2700b57cec5SDimitry Andric if (size == 0) { 27181ad6265SDimitry Andric auto buffer_or_error = T::getFile(path, is_volatile); 2720b57cec5SDimitry Andric if (!buffer_or_error) 2730b57cec5SDimitry Andric return nullptr; 2740b57cec5SDimitry Andric buffer = std::move(*buffer_or_error); 2750b57cec5SDimitry Andric } else { 27681ad6265SDimitry Andric auto buffer_or_error = T::getFileSlice(path, size, offset, is_volatile); 2770b57cec5SDimitry Andric if (!buffer_or_error) 2780b57cec5SDimitry Andric return nullptr; 2790b57cec5SDimitry Andric buffer = std::move(*buffer_or_error); 2800b57cec5SDimitry Andric } 28181ad6265SDimitry Andric return buffer; 28281ad6265SDimitry Andric } 28381ad6265SDimitry Andric 28481ad6265SDimitry Andric std::shared_ptr<WritableDataBuffer> 28581ad6265SDimitry Andric FileSystem::CreateWritableDataBuffer(const llvm::Twine &path, uint64_t size, 28681ad6265SDimitry Andric uint64_t offset) { 28781ad6265SDimitry Andric const bool is_volatile = !IsLocal(path); 28881ad6265SDimitry Andric auto buffer = GetMemoryBuffer<llvm::WritableMemoryBuffer>(path, size, offset, 28981ad6265SDimitry Andric is_volatile); 29081ad6265SDimitry Andric if (!buffer) 29181ad6265SDimitry Andric return {}; 29281ad6265SDimitry Andric return std::shared_ptr<WritableDataBufferLLVM>( 29381ad6265SDimitry Andric new WritableDataBufferLLVM(std::move(buffer))); 29481ad6265SDimitry Andric } 29581ad6265SDimitry Andric 29681ad6265SDimitry Andric std::shared_ptr<DataBuffer> 29781ad6265SDimitry Andric FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size, 29881ad6265SDimitry Andric uint64_t offset) { 29981ad6265SDimitry Andric const bool is_volatile = !IsLocal(path); 30081ad6265SDimitry Andric auto buffer = 30181ad6265SDimitry Andric GetMemoryBuffer<llvm::MemoryBuffer>(path, size, offset, is_volatile); 30281ad6265SDimitry Andric if (!buffer) 30381ad6265SDimitry Andric return {}; 3040b57cec5SDimitry Andric return std::shared_ptr<DataBufferLLVM>(new DataBufferLLVM(std::move(buffer))); 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric 30781ad6265SDimitry Andric std::shared_ptr<WritableDataBuffer> 30881ad6265SDimitry Andric FileSystem::CreateWritableDataBuffer(const FileSpec &file_spec, uint64_t size, 30981ad6265SDimitry Andric uint64_t offset) { 31081ad6265SDimitry Andric return CreateWritableDataBuffer(file_spec.GetPath(), size, offset); 31181ad6265SDimitry Andric } 31281ad6265SDimitry Andric 31381ad6265SDimitry Andric std::shared_ptr<DataBuffer> 3140b57cec5SDimitry Andric FileSystem::CreateDataBuffer(const FileSpec &file_spec, uint64_t size, 3150b57cec5SDimitry Andric uint64_t offset) { 3160b57cec5SDimitry Andric return CreateDataBuffer(file_spec.GetPath(), size, offset); 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric bool FileSystem::ResolveExecutableLocation(FileSpec &file_spec) { 3200b57cec5SDimitry Andric // If the directory is set there's nothing to do. 3210b57cec5SDimitry Andric ConstString directory = file_spec.GetDirectory(); 3220b57cec5SDimitry Andric if (directory) 3230b57cec5SDimitry Andric return false; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric // We cannot look for a file if there's no file name. 3260b57cec5SDimitry Andric ConstString filename = file_spec.GetFilename(); 3270b57cec5SDimitry Andric if (!filename) 3280b57cec5SDimitry Andric return false; 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric // Search for the file on the host. 3310b57cec5SDimitry Andric const std::string filename_str(filename.GetCString()); 3320b57cec5SDimitry Andric llvm::ErrorOr<std::string> error_or_path = 3330b57cec5SDimitry Andric llvm::sys::findProgramByName(filename_str); 3340b57cec5SDimitry Andric if (!error_or_path) 3350b57cec5SDimitry Andric return false; 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric // findProgramByName returns "." if it can't find the file. 3380b57cec5SDimitry Andric llvm::StringRef path = *error_or_path; 3390b57cec5SDimitry Andric llvm::StringRef parent = llvm::sys::path::parent_path(path); 3400b57cec5SDimitry Andric if (parent.empty() || parent == ".") 3410b57cec5SDimitry Andric return false; 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric // Make sure that the result exists. 3440b57cec5SDimitry Andric FileSpec result(*error_or_path); 3450b57cec5SDimitry Andric if (!Exists(result)) 3460b57cec5SDimitry Andric return false; 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric file_spec = result; 3490b57cec5SDimitry Andric return true; 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric 352e8d8bef9SDimitry Andric bool FileSystem::GetHomeDirectory(SmallVectorImpl<char> &path) const { 353e8d8bef9SDimitry Andric if (!m_home_directory.empty()) { 354e8d8bef9SDimitry Andric path.assign(m_home_directory.begin(), m_home_directory.end()); 355e8d8bef9SDimitry Andric return true; 356e8d8bef9SDimitry Andric } 357e8d8bef9SDimitry Andric return llvm::sys::path::home_directory(path); 358e8d8bef9SDimitry Andric } 359e8d8bef9SDimitry Andric 360e8d8bef9SDimitry Andric bool FileSystem::GetHomeDirectory(FileSpec &file_spec) const { 361e8d8bef9SDimitry Andric SmallString<128> home_dir; 362e8d8bef9SDimitry Andric if (!GetHomeDirectory(home_dir)) 363e8d8bef9SDimitry Andric return false; 364e8d8bef9SDimitry Andric file_spec.SetPath(home_dir); 365e8d8bef9SDimitry Andric return true; 366e8d8bef9SDimitry Andric } 367e8d8bef9SDimitry Andric 3680b57cec5SDimitry Andric static int OpenWithFS(const FileSystem &fs, const char *path, int flags, 3690b57cec5SDimitry Andric int mode) { 3700b57cec5SDimitry Andric return const_cast<FileSystem &>(fs).Open(path, flags, mode); 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 373349cc55cSDimitry Andric static int GetOpenFlags(File::OpenOptions options) { 3740b57cec5SDimitry Andric int open_flags = 0; 375349cc55cSDimitry Andric File::OpenOptions rw = 376349cc55cSDimitry Andric options & (File::eOpenOptionReadOnly | File::eOpenOptionWriteOnly | 377349cc55cSDimitry Andric File::eOpenOptionReadWrite); 378349cc55cSDimitry Andric if (rw == File::eOpenOptionWriteOnly || rw == File::eOpenOptionReadWrite) { 379349cc55cSDimitry Andric if (rw == File::eOpenOptionReadWrite) 3800b57cec5SDimitry Andric open_flags |= O_RDWR; 3810b57cec5SDimitry Andric else 3820b57cec5SDimitry Andric open_flags |= O_WRONLY; 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric if (options & File::eOpenOptionAppend) 3850b57cec5SDimitry Andric open_flags |= O_APPEND; 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric if (options & File::eOpenOptionTruncate) 3880b57cec5SDimitry Andric open_flags |= O_TRUNC; 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric if (options & File::eOpenOptionCanCreate) 3910b57cec5SDimitry Andric open_flags |= O_CREAT; 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric if (options & File::eOpenOptionCanCreateNewOnly) 3940b57cec5SDimitry Andric open_flags |= O_CREAT | O_EXCL; 395349cc55cSDimitry Andric } else if (rw == File::eOpenOptionReadOnly) { 3960b57cec5SDimitry Andric open_flags |= O_RDONLY; 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric #ifndef _WIN32 3990b57cec5SDimitry Andric if (options & File::eOpenOptionDontFollowSymlinks) 4000b57cec5SDimitry Andric open_flags |= O_NOFOLLOW; 4010b57cec5SDimitry Andric #endif 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric #ifndef _WIN32 4050b57cec5SDimitry Andric if (options & File::eOpenOptionNonBlocking) 4060b57cec5SDimitry Andric open_flags |= O_NONBLOCK; 4070b57cec5SDimitry Andric if (options & File::eOpenOptionCloseOnExec) 4080b57cec5SDimitry Andric open_flags |= O_CLOEXEC; 4090b57cec5SDimitry Andric #else 4100b57cec5SDimitry Andric open_flags |= O_BINARY; 4110b57cec5SDimitry Andric #endif 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric return open_flags; 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric static mode_t GetOpenMode(uint32_t permissions) { 4170b57cec5SDimitry Andric mode_t mode = 0; 4180b57cec5SDimitry Andric if (permissions & lldb::eFilePermissionsUserRead) 4190b57cec5SDimitry Andric mode |= S_IRUSR; 4200b57cec5SDimitry Andric if (permissions & lldb::eFilePermissionsUserWrite) 4210b57cec5SDimitry Andric mode |= S_IWUSR; 4220b57cec5SDimitry Andric if (permissions & lldb::eFilePermissionsUserExecute) 4230b57cec5SDimitry Andric mode |= S_IXUSR; 4240b57cec5SDimitry Andric if (permissions & lldb::eFilePermissionsGroupRead) 4250b57cec5SDimitry Andric mode |= S_IRGRP; 4260b57cec5SDimitry Andric if (permissions & lldb::eFilePermissionsGroupWrite) 4270b57cec5SDimitry Andric mode |= S_IWGRP; 4280b57cec5SDimitry Andric if (permissions & lldb::eFilePermissionsGroupExecute) 4290b57cec5SDimitry Andric mode |= S_IXGRP; 4300b57cec5SDimitry Andric if (permissions & lldb::eFilePermissionsWorldRead) 4310b57cec5SDimitry Andric mode |= S_IROTH; 4320b57cec5SDimitry Andric if (permissions & lldb::eFilePermissionsWorldWrite) 4330b57cec5SDimitry Andric mode |= S_IWOTH; 4340b57cec5SDimitry Andric if (permissions & lldb::eFilePermissionsWorldExecute) 4350b57cec5SDimitry Andric mode |= S_IXOTH; 4360b57cec5SDimitry Andric return mode; 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 4399dba64beSDimitry Andric Expected<FileUP> FileSystem::Open(const FileSpec &file_spec, 4409dba64beSDimitry Andric File::OpenOptions options, 4410b57cec5SDimitry Andric uint32_t permissions, bool should_close_fd) { 4420b57cec5SDimitry Andric const int open_flags = GetOpenFlags(options); 4430b57cec5SDimitry Andric const mode_t open_mode = 4440b57cec5SDimitry Andric (open_flags & O_CREAT) ? GetOpenMode(permissions) : 0; 4450b57cec5SDimitry Andric 44681ad6265SDimitry Andric auto path = file_spec.GetPath(); 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric int descriptor = llvm::sys::RetryAfterSignal( 44981ad6265SDimitry Andric -1, OpenWithFS, *this, path.c_str(), open_flags, open_mode); 4500b57cec5SDimitry Andric 4519dba64beSDimitry Andric if (!File::DescriptorIsValid(descriptor)) 4529dba64beSDimitry Andric return llvm::errorCodeToError( 4539dba64beSDimitry Andric std::error_code(errno, std::system_category())); 4549dba64beSDimitry Andric 4559dba64beSDimitry Andric auto file = std::unique_ptr<File>( 4569dba64beSDimitry Andric new NativeFile(descriptor, options, should_close_fd)); 4579dba64beSDimitry Andric assert(file->IsValid()); 4589dba64beSDimitry Andric return std::move(file); 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 461e8d8bef9SDimitry Andric void FileSystem::SetHomeDirectory(std::string home_directory) { 462e8d8bef9SDimitry Andric m_home_directory = std::move(home_directory); 463e8d8bef9SDimitry Andric } 4640eae32dcSDimitry Andric 4650eae32dcSDimitry Andric Status FileSystem::RemoveFile(const FileSpec &file_spec) { 4660eae32dcSDimitry Andric return RemoveFile(file_spec.GetPath()); 4670eae32dcSDimitry Andric } 4680eae32dcSDimitry Andric 4690eae32dcSDimitry Andric Status FileSystem::RemoveFile(const llvm::Twine &path) { 4700eae32dcSDimitry Andric return Status(llvm::sys::fs::remove(path)); 4710eae32dcSDimitry Andric } 472