11c3bbb01SEd Maste //===-- FileSystem.cpp ------------------------------------------*- C++ -*-===//
21c3bbb01SEd Maste //
31c3bbb01SEd Maste // The LLVM Compiler Infrastructure
41c3bbb01SEd Maste //
51c3bbb01SEd Maste // This file is distributed under the University of Illinois Open Source
61c3bbb01SEd Maste // License. See LICENSE.TXT for details.
71c3bbb01SEd Maste //
81c3bbb01SEd Maste //===----------------------------------------------------------------------===//
91c3bbb01SEd Maste
101c3bbb01SEd Maste #include "lldb/Host/FileSystem.h"
111c3bbb01SEd Maste
12*b5893f02SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
13*b5893f02SDimitry Andric #include "lldb/Utility/TildeExpressionResolver.h"
14*b5893f02SDimitry Andric
15*b5893f02SDimitry Andric #include "llvm/Support/Errno.h"
16435933ddSDimitry Andric #include "llvm/Support/FileSystem.h"
17*b5893f02SDimitry Andric #include "llvm/Support/Path.h"
18*b5893f02SDimitry Andric #include "llvm/Support/Program.h"
19*b5893f02SDimitry Andric #include "llvm/Support/Threading.h"
20*b5893f02SDimitry Andric
21*b5893f02SDimitry Andric #include <errno.h>
22*b5893f02SDimitry Andric #include <fcntl.h>
23*b5893f02SDimitry Andric #include <limits.h>
24*b5893f02SDimitry Andric #include <stdarg.h>
25*b5893f02SDimitry Andric #include <stdio.h>
26*b5893f02SDimitry Andric
27*b5893f02SDimitry Andric #ifdef _WIN32
28*b5893f02SDimitry Andric #include "lldb/Host/windows/windows.h"
29*b5893f02SDimitry Andric #else
30*b5893f02SDimitry Andric #include <sys/ioctl.h>
31*b5893f02SDimitry Andric #include <sys/stat.h>
32*b5893f02SDimitry Andric #include <termios.h>
33*b5893f02SDimitry Andric #include <unistd.h>
34*b5893f02SDimitry Andric #endif
351c3bbb01SEd Maste
361c3bbb01SEd Maste #include <algorithm>
371c3bbb01SEd Maste #include <fstream>
381c3bbb01SEd Maste #include <vector>
391c3bbb01SEd Maste
401c3bbb01SEd Maste using namespace lldb;
411c3bbb01SEd Maste using namespace lldb_private;
42*b5893f02SDimitry Andric using namespace llvm;
431c3bbb01SEd Maste
Instance()44*b5893f02SDimitry Andric FileSystem &FileSystem::Instance() { return *InstanceImpl(); }
45*b5893f02SDimitry Andric
Initialize()46*b5893f02SDimitry Andric void FileSystem::Initialize() {
47*b5893f02SDimitry Andric lldbassert(!InstanceImpl() && "Already initialized.");
48*b5893f02SDimitry Andric InstanceImpl().emplace();
49*b5893f02SDimitry Andric }
50*b5893f02SDimitry Andric
Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs)51*b5893f02SDimitry Andric void FileSystem::Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs) {
52*b5893f02SDimitry Andric lldbassert(!InstanceImpl() && "Already initialized.");
53*b5893f02SDimitry Andric InstanceImpl().emplace(fs);
54*b5893f02SDimitry Andric }
55*b5893f02SDimitry Andric
Terminate()56*b5893f02SDimitry Andric void FileSystem::Terminate() {
57*b5893f02SDimitry Andric lldbassert(InstanceImpl() && "Already terminated.");
58*b5893f02SDimitry Andric InstanceImpl().reset();
59*b5893f02SDimitry Andric }
60*b5893f02SDimitry Andric
InstanceImpl()61*b5893f02SDimitry Andric Optional<FileSystem> &FileSystem::InstanceImpl() {
62*b5893f02SDimitry Andric static Optional<FileSystem> g_fs;
63*b5893f02SDimitry Andric return g_fs;
64*b5893f02SDimitry Andric }
65*b5893f02SDimitry Andric
DirBegin(const FileSpec & file_spec,std::error_code & ec)66*b5893f02SDimitry Andric vfs::directory_iterator FileSystem::DirBegin(const FileSpec &file_spec,
67*b5893f02SDimitry Andric std::error_code &ec) {
68*b5893f02SDimitry Andric return DirBegin(file_spec.GetPath(), ec);
69*b5893f02SDimitry Andric }
70*b5893f02SDimitry Andric
DirBegin(const Twine & dir,std::error_code & ec)71*b5893f02SDimitry Andric vfs::directory_iterator FileSystem::DirBegin(const Twine &dir,
72*b5893f02SDimitry Andric std::error_code &ec) {
73*b5893f02SDimitry Andric return m_fs->dir_begin(dir, ec);
74*b5893f02SDimitry Andric }
75*b5893f02SDimitry Andric
76*b5893f02SDimitry Andric llvm::ErrorOr<vfs::Status>
GetStatus(const FileSpec & file_spec) const77*b5893f02SDimitry Andric FileSystem::GetStatus(const FileSpec &file_spec) const {
78*b5893f02SDimitry Andric return GetStatus(file_spec.GetPath());
79*b5893f02SDimitry Andric }
80*b5893f02SDimitry Andric
GetStatus(const Twine & path) const81*b5893f02SDimitry Andric llvm::ErrorOr<vfs::Status> FileSystem::GetStatus(const Twine &path) const {
82*b5893f02SDimitry Andric return m_fs->status(path);
83*b5893f02SDimitry Andric }
84*b5893f02SDimitry Andric
85*b5893f02SDimitry Andric sys::TimePoint<>
GetModificationTime(const FileSpec & file_spec) const86*b5893f02SDimitry Andric FileSystem::GetModificationTime(const FileSpec &file_spec) const {
87*b5893f02SDimitry Andric return GetModificationTime(file_spec.GetPath());
88*b5893f02SDimitry Andric }
89*b5893f02SDimitry Andric
GetModificationTime(const Twine & path) const90*b5893f02SDimitry Andric sys::TimePoint<> FileSystem::GetModificationTime(const Twine &path) const {
91*b5893f02SDimitry Andric ErrorOr<vfs::Status> status = m_fs->status(path);
92*b5893f02SDimitry Andric if (!status)
93*b5893f02SDimitry Andric return sys::TimePoint<>();
94*b5893f02SDimitry Andric return status->getLastModificationTime();
95*b5893f02SDimitry Andric }
96*b5893f02SDimitry Andric
GetByteSize(const FileSpec & file_spec) const97*b5893f02SDimitry Andric uint64_t FileSystem::GetByteSize(const FileSpec &file_spec) const {
98*b5893f02SDimitry Andric return GetByteSize(file_spec.GetPath());
99*b5893f02SDimitry Andric }
100*b5893f02SDimitry Andric
GetByteSize(const Twine & path) const101*b5893f02SDimitry Andric uint64_t FileSystem::GetByteSize(const Twine &path) const {
102*b5893f02SDimitry Andric ErrorOr<vfs::Status> status = m_fs->status(path);
103*b5893f02SDimitry Andric if (!status)
104*b5893f02SDimitry Andric return 0;
105*b5893f02SDimitry Andric return status->getSize();
106*b5893f02SDimitry Andric }
107*b5893f02SDimitry Andric
GetPermissions(const FileSpec & file_spec) const108*b5893f02SDimitry Andric uint32_t FileSystem::GetPermissions(const FileSpec &file_spec) const {
109*b5893f02SDimitry Andric return GetPermissions(file_spec.GetPath());
110*b5893f02SDimitry Andric }
111*b5893f02SDimitry Andric
GetPermissions(const FileSpec & file_spec,std::error_code & ec) const112*b5893f02SDimitry Andric uint32_t FileSystem::GetPermissions(const FileSpec &file_spec,
113*b5893f02SDimitry Andric std::error_code &ec) const {
114*b5893f02SDimitry Andric return GetPermissions(file_spec.GetPath(), ec);
115*b5893f02SDimitry Andric }
116*b5893f02SDimitry Andric
GetPermissions(const Twine & path) const117*b5893f02SDimitry Andric uint32_t FileSystem::GetPermissions(const Twine &path) const {
118*b5893f02SDimitry Andric std::error_code ec;
119*b5893f02SDimitry Andric return GetPermissions(path, ec);
120*b5893f02SDimitry Andric }
121*b5893f02SDimitry Andric
GetPermissions(const Twine & path,std::error_code & ec) const122*b5893f02SDimitry Andric uint32_t FileSystem::GetPermissions(const Twine &path,
123*b5893f02SDimitry Andric std::error_code &ec) const {
124*b5893f02SDimitry Andric ErrorOr<vfs::Status> status = m_fs->status(path);
125*b5893f02SDimitry Andric if (!status) {
126*b5893f02SDimitry Andric ec = status.getError();
127*b5893f02SDimitry Andric return sys::fs::perms::perms_not_known;
128*b5893f02SDimitry Andric }
129*b5893f02SDimitry Andric return status->getPermissions();
130*b5893f02SDimitry Andric }
131*b5893f02SDimitry Andric
Exists(const Twine & path) const132*b5893f02SDimitry Andric bool FileSystem::Exists(const Twine &path) const { return m_fs->exists(path); }
133*b5893f02SDimitry Andric
Exists(const FileSpec & file_spec) const134*b5893f02SDimitry Andric bool FileSystem::Exists(const FileSpec &file_spec) const {
135*b5893f02SDimitry Andric return Exists(file_spec.GetPath());
136*b5893f02SDimitry Andric }
137*b5893f02SDimitry Andric
Readable(const Twine & path) const138*b5893f02SDimitry Andric bool FileSystem::Readable(const Twine &path) const {
139*b5893f02SDimitry Andric return GetPermissions(path) & sys::fs::perms::all_read;
140*b5893f02SDimitry Andric }
141*b5893f02SDimitry Andric
Readable(const FileSpec & file_spec) const142*b5893f02SDimitry Andric bool FileSystem::Readable(const FileSpec &file_spec) const {
143*b5893f02SDimitry Andric return Readable(file_spec.GetPath());
144*b5893f02SDimitry Andric }
145*b5893f02SDimitry Andric
IsDirectory(const Twine & path) const146*b5893f02SDimitry Andric bool FileSystem::IsDirectory(const Twine &path) const {
147*b5893f02SDimitry Andric ErrorOr<vfs::Status> status = m_fs->status(path);
148*b5893f02SDimitry Andric if (!status)
149*b5893f02SDimitry Andric return false;
150*b5893f02SDimitry Andric return status->isDirectory();
151*b5893f02SDimitry Andric }
152*b5893f02SDimitry Andric
IsDirectory(const FileSpec & file_spec) const153*b5893f02SDimitry Andric bool FileSystem::IsDirectory(const FileSpec &file_spec) const {
154*b5893f02SDimitry Andric return IsDirectory(file_spec.GetPath());
155*b5893f02SDimitry Andric }
156*b5893f02SDimitry Andric
IsLocal(const Twine & path) const157*b5893f02SDimitry Andric bool FileSystem::IsLocal(const Twine &path) const {
158*b5893f02SDimitry Andric bool b = false;
159*b5893f02SDimitry Andric m_fs->isLocal(path, b);
160*b5893f02SDimitry Andric return b;
161*b5893f02SDimitry Andric }
162*b5893f02SDimitry Andric
IsLocal(const FileSpec & file_spec) const163*b5893f02SDimitry Andric bool FileSystem::IsLocal(const FileSpec &file_spec) const {
164*b5893f02SDimitry Andric return IsLocal(file_spec.GetPath());
165*b5893f02SDimitry Andric }
166*b5893f02SDimitry Andric
EnumerateDirectory(Twine path,bool find_directories,bool find_files,bool find_other,EnumerateDirectoryCallbackType callback,void * callback_baton)167*b5893f02SDimitry Andric void FileSystem::EnumerateDirectory(Twine path, bool find_directories,
168*b5893f02SDimitry Andric bool find_files, bool find_other,
169*b5893f02SDimitry Andric EnumerateDirectoryCallbackType callback,
170*b5893f02SDimitry Andric void *callback_baton) {
171*b5893f02SDimitry Andric std::error_code EC;
172*b5893f02SDimitry Andric vfs::recursive_directory_iterator Iter(*m_fs, path, EC);
173*b5893f02SDimitry Andric vfs::recursive_directory_iterator End;
174*b5893f02SDimitry Andric for (; Iter != End && !EC; Iter.increment(EC)) {
175*b5893f02SDimitry Andric const auto &Item = *Iter;
176*b5893f02SDimitry Andric ErrorOr<vfs::Status> Status = m_fs->status(Item.path());
177*b5893f02SDimitry Andric if (!Status)
178*b5893f02SDimitry Andric break;
179*b5893f02SDimitry Andric if (!find_files && Status->isRegularFile())
180*b5893f02SDimitry Andric continue;
181*b5893f02SDimitry Andric if (!find_directories && Status->isDirectory())
182*b5893f02SDimitry Andric continue;
183*b5893f02SDimitry Andric if (!find_other && Status->isOther())
184*b5893f02SDimitry Andric continue;
185*b5893f02SDimitry Andric
186*b5893f02SDimitry Andric auto Result = callback(callback_baton, Status->getType(), Item.path());
187*b5893f02SDimitry Andric if (Result == eEnumerateDirectoryResultQuit)
188*b5893f02SDimitry Andric return;
189*b5893f02SDimitry Andric if (Result == eEnumerateDirectoryResultNext) {
190*b5893f02SDimitry Andric // Default behavior is to recurse. Opt out if the callback doesn't want
191*b5893f02SDimitry Andric // this behavior.
192*b5893f02SDimitry Andric Iter.no_push();
193*b5893f02SDimitry Andric }
194*b5893f02SDimitry Andric }
195*b5893f02SDimitry Andric }
196*b5893f02SDimitry Andric
MakeAbsolute(SmallVectorImpl<char> & path) const197*b5893f02SDimitry Andric std::error_code FileSystem::MakeAbsolute(SmallVectorImpl<char> &path) const {
198*b5893f02SDimitry Andric return m_fs->makeAbsolute(path);
199*b5893f02SDimitry Andric }
200*b5893f02SDimitry Andric
MakeAbsolute(FileSpec & file_spec) const201*b5893f02SDimitry Andric std::error_code FileSystem::MakeAbsolute(FileSpec &file_spec) const {
202*b5893f02SDimitry Andric SmallString<128> path;
203*b5893f02SDimitry Andric file_spec.GetPath(path, false);
204*b5893f02SDimitry Andric
205*b5893f02SDimitry Andric auto EC = MakeAbsolute(path);
206*b5893f02SDimitry Andric if (EC)
207*b5893f02SDimitry Andric return EC;
208*b5893f02SDimitry Andric
209*b5893f02SDimitry Andric FileSpec new_file_spec(path, file_spec.GetPathStyle());
210*b5893f02SDimitry Andric file_spec = new_file_spec;
211*b5893f02SDimitry Andric return {};
212*b5893f02SDimitry Andric }
213*b5893f02SDimitry Andric
GetRealPath(const Twine & path,SmallVectorImpl<char> & output) const214*b5893f02SDimitry Andric std::error_code FileSystem::GetRealPath(const Twine &path,
215*b5893f02SDimitry Andric SmallVectorImpl<char> &output) const {
216*b5893f02SDimitry Andric return m_fs->getRealPath(path, output);
217*b5893f02SDimitry Andric }
218*b5893f02SDimitry Andric
Resolve(SmallVectorImpl<char> & path)219*b5893f02SDimitry Andric void FileSystem::Resolve(SmallVectorImpl<char> &path) {
220*b5893f02SDimitry Andric if (path.empty())
221*b5893f02SDimitry Andric return;
222*b5893f02SDimitry Andric
223*b5893f02SDimitry Andric // Resolve tilde.
224*b5893f02SDimitry Andric SmallString<128> original_path(path.begin(), path.end());
225*b5893f02SDimitry Andric StandardTildeExpressionResolver Resolver;
226*b5893f02SDimitry Andric Resolver.ResolveFullPath(original_path, path);
227*b5893f02SDimitry Andric
228*b5893f02SDimitry Andric // Try making the path absolute if it exists.
229*b5893f02SDimitry Andric SmallString<128> absolute_path(path.begin(), path.end());
230*b5893f02SDimitry Andric MakeAbsolute(path);
231*b5893f02SDimitry Andric if (!Exists(path)) {
232*b5893f02SDimitry Andric path.clear();
233*b5893f02SDimitry Andric path.append(original_path.begin(), original_path.end());
234*b5893f02SDimitry Andric }
235*b5893f02SDimitry Andric }
236*b5893f02SDimitry Andric
Resolve(FileSpec & file_spec)237*b5893f02SDimitry Andric void FileSystem::Resolve(FileSpec &file_spec) {
238*b5893f02SDimitry Andric // Extract path from the FileSpec.
239*b5893f02SDimitry Andric SmallString<128> path;
240*b5893f02SDimitry Andric file_spec.GetPath(path);
241*b5893f02SDimitry Andric
242*b5893f02SDimitry Andric // Resolve the path.
243*b5893f02SDimitry Andric Resolve(path);
244*b5893f02SDimitry Andric
245*b5893f02SDimitry Andric // Update the FileSpec with the resolved path.
246*b5893f02SDimitry Andric file_spec.SetPath(path);
247*b5893f02SDimitry Andric file_spec.SetIsResolved(true);
248*b5893f02SDimitry Andric }
249*b5893f02SDimitry Andric
250*b5893f02SDimitry Andric std::shared_ptr<DataBufferLLVM>
CreateDataBuffer(const llvm::Twine & path,uint64_t size,uint64_t offset)251*b5893f02SDimitry Andric FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size,
252*b5893f02SDimitry Andric uint64_t offset) {
253*b5893f02SDimitry Andric const bool is_volatile = !IsLocal(path);
254*b5893f02SDimitry Andric
255*b5893f02SDimitry Andric std::unique_ptr<llvm::WritableMemoryBuffer> buffer;
256*b5893f02SDimitry Andric if (size == 0) {
257*b5893f02SDimitry Andric auto buffer_or_error =
258*b5893f02SDimitry Andric llvm::WritableMemoryBuffer::getFile(path, -1, is_volatile);
259*b5893f02SDimitry Andric if (!buffer_or_error)
260*b5893f02SDimitry Andric return nullptr;
261*b5893f02SDimitry Andric buffer = std::move(*buffer_or_error);
262*b5893f02SDimitry Andric } else {
263*b5893f02SDimitry Andric auto buffer_or_error = llvm::WritableMemoryBuffer::getFileSlice(
264*b5893f02SDimitry Andric path, size, offset, is_volatile);
265*b5893f02SDimitry Andric if (!buffer_or_error)
266*b5893f02SDimitry Andric return nullptr;
267*b5893f02SDimitry Andric buffer = std::move(*buffer_or_error);
268*b5893f02SDimitry Andric }
269*b5893f02SDimitry Andric return std::shared_ptr<DataBufferLLVM>(new DataBufferLLVM(std::move(buffer)));
270*b5893f02SDimitry Andric }
271*b5893f02SDimitry Andric
272*b5893f02SDimitry Andric std::shared_ptr<DataBufferLLVM>
CreateDataBuffer(const FileSpec & file_spec,uint64_t size,uint64_t offset)273*b5893f02SDimitry Andric FileSystem::CreateDataBuffer(const FileSpec &file_spec, uint64_t size,
274*b5893f02SDimitry Andric uint64_t offset) {
275*b5893f02SDimitry Andric return CreateDataBuffer(file_spec.GetPath(), size, offset);
276*b5893f02SDimitry Andric }
277*b5893f02SDimitry Andric
ResolveExecutableLocation(FileSpec & file_spec)278*b5893f02SDimitry Andric bool FileSystem::ResolveExecutableLocation(FileSpec &file_spec) {
279*b5893f02SDimitry Andric // If the directory is set there's nothing to do.
280*b5893f02SDimitry Andric const ConstString &directory = file_spec.GetDirectory();
281*b5893f02SDimitry Andric if (directory)
282*b5893f02SDimitry Andric return false;
283*b5893f02SDimitry Andric
284*b5893f02SDimitry Andric // We cannot look for a file if there's no file name.
285*b5893f02SDimitry Andric const ConstString &filename = file_spec.GetFilename();
286*b5893f02SDimitry Andric if (!filename)
287*b5893f02SDimitry Andric return false;
288*b5893f02SDimitry Andric
289*b5893f02SDimitry Andric // Search for the file on the host.
290*b5893f02SDimitry Andric const std::string filename_str(filename.GetCString());
291*b5893f02SDimitry Andric llvm::ErrorOr<std::string> error_or_path =
292*b5893f02SDimitry Andric llvm::sys::findProgramByName(filename_str);
293*b5893f02SDimitry Andric if (!error_or_path)
294*b5893f02SDimitry Andric return false;
295*b5893f02SDimitry Andric
296*b5893f02SDimitry Andric // findProgramByName returns "." if it can't find the file.
297*b5893f02SDimitry Andric llvm::StringRef path = *error_or_path;
298*b5893f02SDimitry Andric llvm::StringRef parent = llvm::sys::path::parent_path(path);
299*b5893f02SDimitry Andric if (parent.empty() || parent == ".")
300*b5893f02SDimitry Andric return false;
301*b5893f02SDimitry Andric
302*b5893f02SDimitry Andric // Make sure that the result exists.
303*b5893f02SDimitry Andric FileSpec result(*error_or_path);
304*b5893f02SDimitry Andric if (!Exists(result))
305*b5893f02SDimitry Andric return false;
306*b5893f02SDimitry Andric
307*b5893f02SDimitry Andric file_spec = result;
308*b5893f02SDimitry Andric return true;
309*b5893f02SDimitry Andric }
310*b5893f02SDimitry Andric
OpenWithFS(const FileSystem & fs,const char * path,int flags,int mode)311*b5893f02SDimitry Andric static int OpenWithFS(const FileSystem &fs, const char *path, int flags,
312*b5893f02SDimitry Andric int mode) {
313*b5893f02SDimitry Andric return const_cast<FileSystem &>(fs).Open(path, flags, mode);
314*b5893f02SDimitry Andric }
315*b5893f02SDimitry Andric
GetOpenFlags(uint32_t options)316*b5893f02SDimitry Andric static int GetOpenFlags(uint32_t options) {
317*b5893f02SDimitry Andric const bool read = options & File::eOpenOptionRead;
318*b5893f02SDimitry Andric const bool write = options & File::eOpenOptionWrite;
319*b5893f02SDimitry Andric
320*b5893f02SDimitry Andric int open_flags = 0;
321*b5893f02SDimitry Andric if (write) {
322*b5893f02SDimitry Andric if (read)
323*b5893f02SDimitry Andric open_flags |= O_RDWR;
324*b5893f02SDimitry Andric else
325*b5893f02SDimitry Andric open_flags |= O_WRONLY;
326*b5893f02SDimitry Andric
327*b5893f02SDimitry Andric if (options & File::eOpenOptionAppend)
328*b5893f02SDimitry Andric open_flags |= O_APPEND;
329*b5893f02SDimitry Andric
330*b5893f02SDimitry Andric if (options & File::eOpenOptionTruncate)
331*b5893f02SDimitry Andric open_flags |= O_TRUNC;
332*b5893f02SDimitry Andric
333*b5893f02SDimitry Andric if (options & File::eOpenOptionCanCreate)
334*b5893f02SDimitry Andric open_flags |= O_CREAT;
335*b5893f02SDimitry Andric
336*b5893f02SDimitry Andric if (options & File::eOpenOptionCanCreateNewOnly)
337*b5893f02SDimitry Andric open_flags |= O_CREAT | O_EXCL;
338*b5893f02SDimitry Andric } else if (read) {
339*b5893f02SDimitry Andric open_flags |= O_RDONLY;
340*b5893f02SDimitry Andric
341*b5893f02SDimitry Andric #ifndef _WIN32
342*b5893f02SDimitry Andric if (options & File::eOpenOptionDontFollowSymlinks)
343*b5893f02SDimitry Andric open_flags |= O_NOFOLLOW;
344*b5893f02SDimitry Andric #endif
345*b5893f02SDimitry Andric }
346*b5893f02SDimitry Andric
347*b5893f02SDimitry Andric #ifndef _WIN32
348*b5893f02SDimitry Andric if (options & File::eOpenOptionNonBlocking)
349*b5893f02SDimitry Andric open_flags |= O_NONBLOCK;
350*b5893f02SDimitry Andric if (options & File::eOpenOptionCloseOnExec)
351*b5893f02SDimitry Andric open_flags |= O_CLOEXEC;
352*b5893f02SDimitry Andric #else
353*b5893f02SDimitry Andric open_flags |= O_BINARY;
354*b5893f02SDimitry Andric #endif
355*b5893f02SDimitry Andric
356*b5893f02SDimitry Andric return open_flags;
357*b5893f02SDimitry Andric }
358*b5893f02SDimitry Andric
GetOpenMode(uint32_t permissions)359*b5893f02SDimitry Andric static mode_t GetOpenMode(uint32_t permissions) {
360*b5893f02SDimitry Andric mode_t mode = 0;
361*b5893f02SDimitry Andric if (permissions & lldb::eFilePermissionsUserRead)
362*b5893f02SDimitry Andric mode |= S_IRUSR;
363*b5893f02SDimitry Andric if (permissions & lldb::eFilePermissionsUserWrite)
364*b5893f02SDimitry Andric mode |= S_IWUSR;
365*b5893f02SDimitry Andric if (permissions & lldb::eFilePermissionsUserExecute)
366*b5893f02SDimitry Andric mode |= S_IXUSR;
367*b5893f02SDimitry Andric if (permissions & lldb::eFilePermissionsGroupRead)
368*b5893f02SDimitry Andric mode |= S_IRGRP;
369*b5893f02SDimitry Andric if (permissions & lldb::eFilePermissionsGroupWrite)
370*b5893f02SDimitry Andric mode |= S_IWGRP;
371*b5893f02SDimitry Andric if (permissions & lldb::eFilePermissionsGroupExecute)
372*b5893f02SDimitry Andric mode |= S_IXGRP;
373*b5893f02SDimitry Andric if (permissions & lldb::eFilePermissionsWorldRead)
374*b5893f02SDimitry Andric mode |= S_IROTH;
375*b5893f02SDimitry Andric if (permissions & lldb::eFilePermissionsWorldWrite)
376*b5893f02SDimitry Andric mode |= S_IWOTH;
377*b5893f02SDimitry Andric if (permissions & lldb::eFilePermissionsWorldExecute)
378*b5893f02SDimitry Andric mode |= S_IXOTH;
379*b5893f02SDimitry Andric return mode;
380*b5893f02SDimitry Andric }
381*b5893f02SDimitry Andric
Open(File & File,const FileSpec & file_spec,uint32_t options,uint32_t permissions)382*b5893f02SDimitry Andric Status FileSystem::Open(File &File, const FileSpec &file_spec, uint32_t options,
383*b5893f02SDimitry Andric uint32_t permissions) {
384*b5893f02SDimitry Andric if (File.IsValid())
385*b5893f02SDimitry Andric File.Close();
386*b5893f02SDimitry Andric
387*b5893f02SDimitry Andric const int open_flags = GetOpenFlags(options);
388*b5893f02SDimitry Andric const mode_t open_mode =
389*b5893f02SDimitry Andric (open_flags & O_CREAT) ? GetOpenMode(permissions) : 0;
390*b5893f02SDimitry Andric const std::string path = file_spec.GetPath();
391*b5893f02SDimitry Andric
392*b5893f02SDimitry Andric int descriptor = llvm::sys::RetryAfterSignal(
393*b5893f02SDimitry Andric -1, OpenWithFS, *this, path.c_str(), open_flags, open_mode);
394*b5893f02SDimitry Andric
395*b5893f02SDimitry Andric Status error;
396*b5893f02SDimitry Andric if (!File::DescriptorIsValid(descriptor)) {
397*b5893f02SDimitry Andric File.SetDescriptor(descriptor, false);
398*b5893f02SDimitry Andric error.SetErrorToErrno();
399*b5893f02SDimitry Andric } else {
400*b5893f02SDimitry Andric File.SetDescriptor(descriptor, true);
401*b5893f02SDimitry Andric File.SetOptions(options);
402*b5893f02SDimitry Andric }
403*b5893f02SDimitry Andric return error;
404435933ddSDimitry Andric }
405