xref: /openbsd-src/gnu/llvm/lldb/source/Host/common/FileSystem.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- FileSystem.cpp ----------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Host/FileSystem.h"
10061da546Spatrick 
11*f6aab3d8Srobert #include "lldb/Utility/DataBufferLLVM.h"
12061da546Spatrick #include "lldb/Utility/LLDBAssert.h"
13061da546Spatrick #include "lldb/Utility/TildeExpressionResolver.h"
14061da546Spatrick 
15061da546Spatrick #include "llvm/Support/Errc.h"
16061da546Spatrick #include "llvm/Support/Errno.h"
17061da546Spatrick #include "llvm/Support/Error.h"
18061da546Spatrick #include "llvm/Support/FileSystem.h"
19061da546Spatrick #include "llvm/Support/Path.h"
20061da546Spatrick #include "llvm/Support/Program.h"
21061da546Spatrick #include "llvm/Support/Threading.h"
22061da546Spatrick 
23be691f3bSpatrick #include <cerrno>
24be691f3bSpatrick #include <climits>
25be691f3bSpatrick #include <cstdarg>
26be691f3bSpatrick #include <cstdio>
27061da546Spatrick #include <fcntl.h>
28061da546Spatrick 
29061da546Spatrick #ifdef _WIN32
30061da546Spatrick #include "lldb/Host/windows/windows.h"
31061da546Spatrick #else
32061da546Spatrick #include <sys/ioctl.h>
33061da546Spatrick #include <sys/stat.h>
34061da546Spatrick #include <termios.h>
35061da546Spatrick #include <unistd.h>
36061da546Spatrick #endif
37061da546Spatrick 
38061da546Spatrick #include <algorithm>
39061da546Spatrick #include <fstream>
40*f6aab3d8Srobert #include <optional>
41061da546Spatrick #include <vector>
42061da546Spatrick 
43061da546Spatrick using namespace lldb;
44061da546Spatrick using namespace lldb_private;
45061da546Spatrick using namespace llvm;
46061da546Spatrick 
Instance()47061da546Spatrick FileSystem &FileSystem::Instance() { return *InstanceImpl(); }
48061da546Spatrick 
Initialize()49061da546Spatrick void FileSystem::Initialize() {
50061da546Spatrick   lldbassert(!InstanceImpl() && "Already initialized.");
51061da546Spatrick   InstanceImpl().emplace();
52061da546Spatrick }
53061da546Spatrick 
Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs)54061da546Spatrick void FileSystem::Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs) {
55061da546Spatrick   lldbassert(!InstanceImpl() && "Already initialized.");
56061da546Spatrick   InstanceImpl().emplace(fs);
57061da546Spatrick }
58061da546Spatrick 
Terminate()59061da546Spatrick void FileSystem::Terminate() {
60061da546Spatrick   lldbassert(InstanceImpl() && "Already terminated.");
61061da546Spatrick   InstanceImpl().reset();
62061da546Spatrick }
63061da546Spatrick 
InstanceImpl()64*f6aab3d8Srobert std::optional<FileSystem> &FileSystem::InstanceImpl() {
65*f6aab3d8Srobert   static std::optional<FileSystem> g_fs;
66061da546Spatrick   return g_fs;
67061da546Spatrick }
68061da546Spatrick 
DirBegin(const FileSpec & file_spec,std::error_code & ec)69061da546Spatrick vfs::directory_iterator FileSystem::DirBegin(const FileSpec &file_spec,
70061da546Spatrick                                              std::error_code &ec) {
71dda28197Spatrick   if (!file_spec) {
72dda28197Spatrick     ec = std::error_code(static_cast<int>(errc::no_such_file_or_directory),
73dda28197Spatrick                          std::system_category());
74dda28197Spatrick     return {};
75dda28197Spatrick   }
76061da546Spatrick   return DirBegin(file_spec.GetPath(), ec);
77061da546Spatrick }
78061da546Spatrick 
DirBegin(const Twine & dir,std::error_code & ec)79061da546Spatrick vfs::directory_iterator FileSystem::DirBegin(const Twine &dir,
80061da546Spatrick                                              std::error_code &ec) {
81061da546Spatrick   return m_fs->dir_begin(dir, ec);
82061da546Spatrick }
83061da546Spatrick 
84061da546Spatrick llvm::ErrorOr<vfs::Status>
GetStatus(const FileSpec & file_spec) const85061da546Spatrick FileSystem::GetStatus(const FileSpec &file_spec) const {
86dda28197Spatrick   if (!file_spec)
87dda28197Spatrick     return std::error_code(static_cast<int>(errc::no_such_file_or_directory),
88dda28197Spatrick                            std::system_category());
89061da546Spatrick   return GetStatus(file_spec.GetPath());
90061da546Spatrick }
91061da546Spatrick 
GetStatus(const Twine & path) const92061da546Spatrick llvm::ErrorOr<vfs::Status> FileSystem::GetStatus(const Twine &path) const {
93061da546Spatrick   return m_fs->status(path);
94061da546Spatrick }
95061da546Spatrick 
96061da546Spatrick sys::TimePoint<>
GetModificationTime(const FileSpec & file_spec) const97061da546Spatrick FileSystem::GetModificationTime(const FileSpec &file_spec) const {
98dda28197Spatrick   if (!file_spec)
99dda28197Spatrick     return sys::TimePoint<>();
100061da546Spatrick   return GetModificationTime(file_spec.GetPath());
101061da546Spatrick }
102061da546Spatrick 
GetModificationTime(const Twine & path) const103061da546Spatrick sys::TimePoint<> FileSystem::GetModificationTime(const Twine &path) const {
104061da546Spatrick   ErrorOr<vfs::Status> status = m_fs->status(path);
105061da546Spatrick   if (!status)
106061da546Spatrick     return sys::TimePoint<>();
107061da546Spatrick   return status->getLastModificationTime();
108061da546Spatrick }
109061da546Spatrick 
GetByteSize(const FileSpec & file_spec) const110061da546Spatrick uint64_t FileSystem::GetByteSize(const FileSpec &file_spec) const {
111dda28197Spatrick   if (!file_spec)
112dda28197Spatrick     return 0;
113061da546Spatrick   return GetByteSize(file_spec.GetPath());
114061da546Spatrick }
115061da546Spatrick 
GetByteSize(const Twine & path) const116061da546Spatrick uint64_t FileSystem::GetByteSize(const Twine &path) const {
117061da546Spatrick   ErrorOr<vfs::Status> status = m_fs->status(path);
118061da546Spatrick   if (!status)
119061da546Spatrick     return 0;
120061da546Spatrick   return status->getSize();
121061da546Spatrick }
122061da546Spatrick 
GetPermissions(const FileSpec & file_spec) const123061da546Spatrick uint32_t FileSystem::GetPermissions(const FileSpec &file_spec) const {
124061da546Spatrick   return GetPermissions(file_spec.GetPath());
125061da546Spatrick }
126061da546Spatrick 
GetPermissions(const FileSpec & file_spec,std::error_code & ec) const127061da546Spatrick uint32_t FileSystem::GetPermissions(const FileSpec &file_spec,
128061da546Spatrick                                     std::error_code &ec) const {
129dda28197Spatrick   if (!file_spec)
130dda28197Spatrick     return sys::fs::perms::perms_not_known;
131061da546Spatrick   return GetPermissions(file_spec.GetPath(), ec);
132061da546Spatrick }
133061da546Spatrick 
GetPermissions(const Twine & path) const134061da546Spatrick uint32_t FileSystem::GetPermissions(const Twine &path) const {
135061da546Spatrick   std::error_code ec;
136061da546Spatrick   return GetPermissions(path, ec);
137061da546Spatrick }
138061da546Spatrick 
GetPermissions(const Twine & path,std::error_code & ec) const139061da546Spatrick uint32_t FileSystem::GetPermissions(const Twine &path,
140061da546Spatrick                                     std::error_code &ec) const {
141061da546Spatrick   ErrorOr<vfs::Status> status = m_fs->status(path);
142061da546Spatrick   if (!status) {
143061da546Spatrick     ec = status.getError();
144061da546Spatrick     return sys::fs::perms::perms_not_known;
145061da546Spatrick   }
146061da546Spatrick   return status->getPermissions();
147061da546Spatrick }
148061da546Spatrick 
Exists(const Twine & path) const149061da546Spatrick bool FileSystem::Exists(const Twine &path) const { return m_fs->exists(path); }
150061da546Spatrick 
Exists(const FileSpec & file_spec) const151061da546Spatrick bool FileSystem::Exists(const FileSpec &file_spec) const {
152dda28197Spatrick   return file_spec && Exists(file_spec.GetPath());
153061da546Spatrick }
154061da546Spatrick 
Readable(const Twine & path) const155061da546Spatrick bool FileSystem::Readable(const Twine &path) const {
156061da546Spatrick   return GetPermissions(path) & sys::fs::perms::all_read;
157061da546Spatrick }
158061da546Spatrick 
Readable(const FileSpec & file_spec) const159061da546Spatrick bool FileSystem::Readable(const FileSpec &file_spec) const {
160dda28197Spatrick   return file_spec && Readable(file_spec.GetPath());
161061da546Spatrick }
162061da546Spatrick 
IsDirectory(const Twine & path) const163061da546Spatrick bool FileSystem::IsDirectory(const Twine &path) const {
164061da546Spatrick   ErrorOr<vfs::Status> status = m_fs->status(path);
165061da546Spatrick   if (!status)
166061da546Spatrick     return false;
167061da546Spatrick   return status->isDirectory();
168061da546Spatrick }
169061da546Spatrick 
IsDirectory(const FileSpec & file_spec) const170061da546Spatrick bool FileSystem::IsDirectory(const FileSpec &file_spec) const {
171dda28197Spatrick   return file_spec && IsDirectory(file_spec.GetPath());
172061da546Spatrick }
173061da546Spatrick 
IsLocal(const Twine & path) const174061da546Spatrick bool FileSystem::IsLocal(const Twine &path) const {
175061da546Spatrick   bool b = false;
176061da546Spatrick   m_fs->isLocal(path, b);
177061da546Spatrick   return b;
178061da546Spatrick }
179061da546Spatrick 
IsLocal(const FileSpec & file_spec) const180061da546Spatrick bool FileSystem::IsLocal(const FileSpec &file_spec) const {
181dda28197Spatrick   return file_spec && IsLocal(file_spec.GetPath());
182061da546Spatrick }
183061da546Spatrick 
EnumerateDirectory(Twine path,bool find_directories,bool find_files,bool find_other,EnumerateDirectoryCallbackType callback,void * callback_baton)184061da546Spatrick void FileSystem::EnumerateDirectory(Twine path, bool find_directories,
185061da546Spatrick                                     bool find_files, bool find_other,
186061da546Spatrick                                     EnumerateDirectoryCallbackType callback,
187061da546Spatrick                                     void *callback_baton) {
188061da546Spatrick   std::error_code EC;
189061da546Spatrick   vfs::recursive_directory_iterator Iter(*m_fs, path, EC);
190061da546Spatrick   vfs::recursive_directory_iterator End;
191061da546Spatrick   for (; Iter != End && !EC; Iter.increment(EC)) {
192061da546Spatrick     const auto &Item = *Iter;
193061da546Spatrick     ErrorOr<vfs::Status> Status = m_fs->status(Item.path());
194061da546Spatrick     if (!Status)
195061da546Spatrick       break;
196061da546Spatrick     if (!find_files && Status->isRegularFile())
197061da546Spatrick       continue;
198061da546Spatrick     if (!find_directories && Status->isDirectory())
199061da546Spatrick       continue;
200061da546Spatrick     if (!find_other && Status->isOther())
201061da546Spatrick       continue;
202061da546Spatrick 
203061da546Spatrick     auto Result = callback(callback_baton, Status->getType(), Item.path());
204061da546Spatrick     if (Result == eEnumerateDirectoryResultQuit)
205061da546Spatrick       return;
206061da546Spatrick     if (Result == eEnumerateDirectoryResultNext) {
207061da546Spatrick       // Default behavior is to recurse. Opt out if the callback doesn't want
208061da546Spatrick       // this behavior.
209061da546Spatrick       Iter.no_push();
210061da546Spatrick     }
211061da546Spatrick   }
212061da546Spatrick }
213061da546Spatrick 
MakeAbsolute(SmallVectorImpl<char> & path) const214061da546Spatrick std::error_code FileSystem::MakeAbsolute(SmallVectorImpl<char> &path) const {
215061da546Spatrick   return m_fs->makeAbsolute(path);
216061da546Spatrick }
217061da546Spatrick 
MakeAbsolute(FileSpec & file_spec) const218061da546Spatrick std::error_code FileSystem::MakeAbsolute(FileSpec &file_spec) const {
219061da546Spatrick   SmallString<128> path;
220061da546Spatrick   file_spec.GetPath(path, false);
221061da546Spatrick 
222061da546Spatrick   auto EC = MakeAbsolute(path);
223061da546Spatrick   if (EC)
224061da546Spatrick     return EC;
225061da546Spatrick 
226061da546Spatrick   FileSpec new_file_spec(path, file_spec.GetPathStyle());
227061da546Spatrick   file_spec = new_file_spec;
228061da546Spatrick   return {};
229061da546Spatrick }
230061da546Spatrick 
GetRealPath(const Twine & path,SmallVectorImpl<char> & output) const231061da546Spatrick std::error_code FileSystem::GetRealPath(const Twine &path,
232061da546Spatrick                                         SmallVectorImpl<char> &output) const {
233061da546Spatrick   return m_fs->getRealPath(path, output);
234061da546Spatrick }
235061da546Spatrick 
Resolve(SmallVectorImpl<char> & path)236061da546Spatrick void FileSystem::Resolve(SmallVectorImpl<char> &path) {
237061da546Spatrick   if (path.empty())
238061da546Spatrick     return;
239061da546Spatrick 
240061da546Spatrick   // Resolve tilde in path.
241061da546Spatrick   SmallString<128> resolved(path.begin(), path.end());
242061da546Spatrick   StandardTildeExpressionResolver Resolver;
243061da546Spatrick   Resolver.ResolveFullPath(llvm::StringRef(path.begin(), path.size()),
244061da546Spatrick                            resolved);
245061da546Spatrick 
246061da546Spatrick   // Try making the path absolute if it exists.
247061da546Spatrick   SmallString<128> absolute(resolved.begin(), resolved.end());
248061da546Spatrick   MakeAbsolute(absolute);
249061da546Spatrick 
250061da546Spatrick   path.clear();
251061da546Spatrick   if (Exists(absolute)) {
252061da546Spatrick     path.append(absolute.begin(), absolute.end());
253061da546Spatrick   } else {
254061da546Spatrick     path.append(resolved.begin(), resolved.end());
255061da546Spatrick   }
256061da546Spatrick }
257061da546Spatrick 
Resolve(FileSpec & file_spec)258061da546Spatrick void FileSystem::Resolve(FileSpec &file_spec) {
259dda28197Spatrick   if (!file_spec)
260dda28197Spatrick     return;
261dda28197Spatrick 
262061da546Spatrick   // Extract path from the FileSpec.
263061da546Spatrick   SmallString<128> path;
264061da546Spatrick   file_spec.GetPath(path);
265061da546Spatrick 
266061da546Spatrick   // Resolve the path.
267061da546Spatrick   Resolve(path);
268061da546Spatrick 
269061da546Spatrick   // Update the FileSpec with the resolved path.
270061da546Spatrick   if (file_spec.GetFilename().IsEmpty())
271*f6aab3d8Srobert     file_spec.SetDirectory(path);
272061da546Spatrick   else
273061da546Spatrick     file_spec.SetPath(path);
274061da546Spatrick   file_spec.SetIsResolved(true);
275061da546Spatrick }
276061da546Spatrick 
277*f6aab3d8Srobert template <typename T>
GetMemoryBuffer(const llvm::Twine & path,uint64_t size,uint64_t offset,bool is_volatile)278*f6aab3d8Srobert static std::unique_ptr<T> GetMemoryBuffer(const llvm::Twine &path,
279*f6aab3d8Srobert                                           uint64_t size, uint64_t offset,
280*f6aab3d8Srobert                                           bool is_volatile) {
281*f6aab3d8Srobert   std::unique_ptr<T> buffer;
282061da546Spatrick   if (size == 0) {
283*f6aab3d8Srobert     auto buffer_or_error = T::getFile(path, is_volatile);
284061da546Spatrick     if (!buffer_or_error)
285061da546Spatrick       return nullptr;
286061da546Spatrick     buffer = std::move(*buffer_or_error);
287061da546Spatrick   } else {
288*f6aab3d8Srobert     auto buffer_or_error = T::getFileSlice(path, size, offset, is_volatile);
289061da546Spatrick     if (!buffer_or_error)
290061da546Spatrick       return nullptr;
291061da546Spatrick     buffer = std::move(*buffer_or_error);
292061da546Spatrick   }
293*f6aab3d8Srobert   return buffer;
294*f6aab3d8Srobert }
295*f6aab3d8Srobert 
296*f6aab3d8Srobert std::shared_ptr<WritableDataBuffer>
CreateWritableDataBuffer(const llvm::Twine & path,uint64_t size,uint64_t offset)297*f6aab3d8Srobert FileSystem::CreateWritableDataBuffer(const llvm::Twine &path, uint64_t size,
298*f6aab3d8Srobert                                      uint64_t offset) {
299*f6aab3d8Srobert   const bool is_volatile = !IsLocal(path);
300*f6aab3d8Srobert   auto buffer = GetMemoryBuffer<llvm::WritableMemoryBuffer>(path, size, offset,
301*f6aab3d8Srobert                                                             is_volatile);
302*f6aab3d8Srobert   if (!buffer)
303*f6aab3d8Srobert     return {};
304*f6aab3d8Srobert   return std::shared_ptr<WritableDataBufferLLVM>(
305*f6aab3d8Srobert       new WritableDataBufferLLVM(std::move(buffer)));
306*f6aab3d8Srobert }
307*f6aab3d8Srobert 
308*f6aab3d8Srobert std::shared_ptr<DataBuffer>
CreateDataBuffer(const llvm::Twine & path,uint64_t size,uint64_t offset)309*f6aab3d8Srobert FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size,
310*f6aab3d8Srobert                              uint64_t offset) {
311*f6aab3d8Srobert   const bool is_volatile = !IsLocal(path);
312*f6aab3d8Srobert   auto buffer =
313*f6aab3d8Srobert       GetMemoryBuffer<llvm::MemoryBuffer>(path, size, offset, is_volatile);
314*f6aab3d8Srobert   if (!buffer)
315*f6aab3d8Srobert     return {};
316061da546Spatrick   return std::shared_ptr<DataBufferLLVM>(new DataBufferLLVM(std::move(buffer)));
317061da546Spatrick }
318061da546Spatrick 
319*f6aab3d8Srobert std::shared_ptr<WritableDataBuffer>
CreateWritableDataBuffer(const FileSpec & file_spec,uint64_t size,uint64_t offset)320*f6aab3d8Srobert FileSystem::CreateWritableDataBuffer(const FileSpec &file_spec, uint64_t size,
321*f6aab3d8Srobert                                      uint64_t offset) {
322*f6aab3d8Srobert   return CreateWritableDataBuffer(file_spec.GetPath(), size, offset);
323*f6aab3d8Srobert }
324*f6aab3d8Srobert 
325*f6aab3d8Srobert std::shared_ptr<DataBuffer>
CreateDataBuffer(const FileSpec & file_spec,uint64_t size,uint64_t offset)326061da546Spatrick FileSystem::CreateDataBuffer(const FileSpec &file_spec, uint64_t size,
327061da546Spatrick                              uint64_t offset) {
328061da546Spatrick   return CreateDataBuffer(file_spec.GetPath(), size, offset);
329061da546Spatrick }
330061da546Spatrick 
ResolveExecutableLocation(FileSpec & file_spec)331061da546Spatrick bool FileSystem::ResolveExecutableLocation(FileSpec &file_spec) {
332061da546Spatrick   // If the directory is set there's nothing to do.
333061da546Spatrick   ConstString directory = file_spec.GetDirectory();
334061da546Spatrick   if (directory)
335061da546Spatrick     return false;
336061da546Spatrick 
337061da546Spatrick   // We cannot look for a file if there's no file name.
338061da546Spatrick   ConstString filename = file_spec.GetFilename();
339061da546Spatrick   if (!filename)
340061da546Spatrick     return false;
341061da546Spatrick 
342061da546Spatrick   // Search for the file on the host.
343061da546Spatrick   const std::string filename_str(filename.GetCString());
344061da546Spatrick   llvm::ErrorOr<std::string> error_or_path =
345061da546Spatrick       llvm::sys::findProgramByName(filename_str);
346061da546Spatrick   if (!error_or_path)
347061da546Spatrick     return false;
348061da546Spatrick 
349061da546Spatrick   // findProgramByName returns "." if it can't find the file.
350061da546Spatrick   llvm::StringRef path = *error_or_path;
351061da546Spatrick   llvm::StringRef parent = llvm::sys::path::parent_path(path);
352061da546Spatrick   if (parent.empty() || parent == ".")
353061da546Spatrick     return false;
354061da546Spatrick 
355061da546Spatrick   // Make sure that the result exists.
356061da546Spatrick   FileSpec result(*error_or_path);
357061da546Spatrick   if (!Exists(result))
358061da546Spatrick     return false;
359061da546Spatrick 
360061da546Spatrick   file_spec = result;
361061da546Spatrick   return true;
362061da546Spatrick }
363061da546Spatrick 
GetHomeDirectory(SmallVectorImpl<char> & path) const364be691f3bSpatrick bool FileSystem::GetHomeDirectory(SmallVectorImpl<char> &path) const {
365be691f3bSpatrick   if (!m_home_directory.empty()) {
366be691f3bSpatrick     path.assign(m_home_directory.begin(), m_home_directory.end());
367be691f3bSpatrick     return true;
368be691f3bSpatrick   }
369be691f3bSpatrick   return llvm::sys::path::home_directory(path);
370be691f3bSpatrick }
371be691f3bSpatrick 
GetHomeDirectory(FileSpec & file_spec) const372be691f3bSpatrick bool FileSystem::GetHomeDirectory(FileSpec &file_spec) const {
373be691f3bSpatrick   SmallString<128> home_dir;
374be691f3bSpatrick   if (!GetHomeDirectory(home_dir))
375be691f3bSpatrick     return false;
376be691f3bSpatrick   file_spec.SetPath(home_dir);
377be691f3bSpatrick   return true;
378be691f3bSpatrick }
379be691f3bSpatrick 
OpenWithFS(const FileSystem & fs,const char * path,int flags,int mode)380061da546Spatrick static int OpenWithFS(const FileSystem &fs, const char *path, int flags,
381061da546Spatrick                       int mode) {
382061da546Spatrick   return const_cast<FileSystem &>(fs).Open(path, flags, mode);
383061da546Spatrick }
384061da546Spatrick 
GetOpenFlags(File::OpenOptions options)385*f6aab3d8Srobert static int GetOpenFlags(File::OpenOptions options) {
386061da546Spatrick   int open_flags = 0;
387*f6aab3d8Srobert   File::OpenOptions rw =
388*f6aab3d8Srobert       options & (File::eOpenOptionReadOnly | File::eOpenOptionWriteOnly |
389*f6aab3d8Srobert                  File::eOpenOptionReadWrite);
390*f6aab3d8Srobert   if (rw == File::eOpenOptionWriteOnly || rw == File::eOpenOptionReadWrite) {
391*f6aab3d8Srobert     if (rw == File::eOpenOptionReadWrite)
392061da546Spatrick       open_flags |= O_RDWR;
393061da546Spatrick     else
394061da546Spatrick       open_flags |= O_WRONLY;
395061da546Spatrick 
396061da546Spatrick     if (options & File::eOpenOptionAppend)
397061da546Spatrick       open_flags |= O_APPEND;
398061da546Spatrick 
399061da546Spatrick     if (options & File::eOpenOptionTruncate)
400061da546Spatrick       open_flags |= O_TRUNC;
401061da546Spatrick 
402061da546Spatrick     if (options & File::eOpenOptionCanCreate)
403061da546Spatrick       open_flags |= O_CREAT;
404061da546Spatrick 
405061da546Spatrick     if (options & File::eOpenOptionCanCreateNewOnly)
406061da546Spatrick       open_flags |= O_CREAT | O_EXCL;
407*f6aab3d8Srobert   } else if (rw == File::eOpenOptionReadOnly) {
408061da546Spatrick     open_flags |= O_RDONLY;
409061da546Spatrick 
410061da546Spatrick #ifndef _WIN32
411061da546Spatrick     if (options & File::eOpenOptionDontFollowSymlinks)
412061da546Spatrick       open_flags |= O_NOFOLLOW;
413061da546Spatrick #endif
414061da546Spatrick   }
415061da546Spatrick 
416061da546Spatrick #ifndef _WIN32
417061da546Spatrick   if (options & File::eOpenOptionNonBlocking)
418061da546Spatrick     open_flags |= O_NONBLOCK;
419061da546Spatrick   if (options & File::eOpenOptionCloseOnExec)
420061da546Spatrick     open_flags |= O_CLOEXEC;
421061da546Spatrick #else
422061da546Spatrick   open_flags |= O_BINARY;
423061da546Spatrick #endif
424061da546Spatrick 
425061da546Spatrick   return open_flags;
426061da546Spatrick }
427061da546Spatrick 
GetOpenMode(uint32_t permissions)428061da546Spatrick static mode_t GetOpenMode(uint32_t permissions) {
429061da546Spatrick   mode_t mode = 0;
430061da546Spatrick   if (permissions & lldb::eFilePermissionsUserRead)
431061da546Spatrick     mode |= S_IRUSR;
432061da546Spatrick   if (permissions & lldb::eFilePermissionsUserWrite)
433061da546Spatrick     mode |= S_IWUSR;
434061da546Spatrick   if (permissions & lldb::eFilePermissionsUserExecute)
435061da546Spatrick     mode |= S_IXUSR;
436061da546Spatrick   if (permissions & lldb::eFilePermissionsGroupRead)
437061da546Spatrick     mode |= S_IRGRP;
438061da546Spatrick   if (permissions & lldb::eFilePermissionsGroupWrite)
439061da546Spatrick     mode |= S_IWGRP;
440061da546Spatrick   if (permissions & lldb::eFilePermissionsGroupExecute)
441061da546Spatrick     mode |= S_IXGRP;
442061da546Spatrick   if (permissions & lldb::eFilePermissionsWorldRead)
443061da546Spatrick     mode |= S_IROTH;
444061da546Spatrick   if (permissions & lldb::eFilePermissionsWorldWrite)
445061da546Spatrick     mode |= S_IWOTH;
446061da546Spatrick   if (permissions & lldb::eFilePermissionsWorldExecute)
447061da546Spatrick     mode |= S_IXOTH;
448061da546Spatrick   return mode;
449061da546Spatrick }
450061da546Spatrick 
Open(const FileSpec & file_spec,File::OpenOptions options,uint32_t permissions,bool should_close_fd)451061da546Spatrick Expected<FileUP> FileSystem::Open(const FileSpec &file_spec,
452061da546Spatrick                                   File::OpenOptions options,
453061da546Spatrick                                   uint32_t permissions, bool should_close_fd) {
454061da546Spatrick   const int open_flags = GetOpenFlags(options);
455061da546Spatrick   const mode_t open_mode =
456061da546Spatrick       (open_flags & O_CREAT) ? GetOpenMode(permissions) : 0;
457061da546Spatrick 
458*f6aab3d8Srobert   auto path = file_spec.GetPath();
459061da546Spatrick 
460061da546Spatrick   int descriptor = llvm::sys::RetryAfterSignal(
461*f6aab3d8Srobert       -1, OpenWithFS, *this, path.c_str(), open_flags, open_mode);
462061da546Spatrick 
463061da546Spatrick   if (!File::DescriptorIsValid(descriptor))
464061da546Spatrick     return llvm::errorCodeToError(
465061da546Spatrick         std::error_code(errno, std::system_category()));
466061da546Spatrick 
467061da546Spatrick   auto file = std::unique_ptr<File>(
468061da546Spatrick       new NativeFile(descriptor, options, should_close_fd));
469061da546Spatrick   assert(file->IsValid());
470061da546Spatrick   return std::move(file);
471061da546Spatrick }
472061da546Spatrick 
SetHomeDirectory(std::string home_directory)473be691f3bSpatrick void FileSystem::SetHomeDirectory(std::string home_directory) {
474be691f3bSpatrick   m_home_directory = std::move(home_directory);
475be691f3bSpatrick }
476*f6aab3d8Srobert 
RemoveFile(const FileSpec & file_spec)477*f6aab3d8Srobert Status FileSystem::RemoveFile(const FileSpec &file_spec) {
478*f6aab3d8Srobert   return RemoveFile(file_spec.GetPath());
479*f6aab3d8Srobert }
480*f6aab3d8Srobert 
RemoveFile(const llvm::Twine & path)481*f6aab3d8Srobert Status FileSystem::RemoveFile(const llvm::Twine &path) {
482*f6aab3d8Srobert   return Status(llvm::sys::fs::remove(path));
483*f6aab3d8Srobert }
484