15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/Errno.h"
17 #include "llvm/Support/Error.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Support/Program.h"
21 #include "llvm/Support/Threading.h"
32 #include <sys/ioctl.h>
46 FileSystem &FileSystem::Instance() {
return *InstanceImpl(); }
48 void FileSystem::Initialize() {
49 lldbassert(!InstanceImpl() &&
"Already initialized.");
50 InstanceImpl().emplace();
53 void FileSystem::Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs) {
54 lldbassert(!InstanceImpl() &&
"Already initialized.");
55 InstanceImpl().emplace(fs);
58 void FileSystem::Terminate() {
59 lldbassert(InstanceImpl() &&
"Already terminated.");
60 InstanceImpl().reset();
63 Optional<FileSystem> &FileSystem::InstanceImpl() {
64 static Optional<FileSystem> g_fs;
68 vfs::directory_iterator FileSystem::DirBegin(
const FileSpec &file_spec,
69 std::error_code &ec) {
71 ec = std::error_code(
static_cast<int>(errc::no_such_file_or_directory),
72 std::system_category());
75 return DirBegin(file_spec.
GetPath(), ec);
78 vfs::directory_iterator FileSystem::DirBegin(
const Twine &dir,
79 std::error_code &ec) {
80 return m_fs->dir_begin(dir, ec);
83 llvm::ErrorOr<vfs::Status>
84 FileSystem::GetStatus(
const FileSpec &file_spec)
const {
86 return std::error_code(
static_cast<int>(errc::no_such_file_or_directory),
87 std::system_category());
88 return GetStatus(file_spec.
GetPath());
91 llvm::ErrorOr<vfs::Status> FileSystem::GetStatus(
const Twine &path)
const {
92 return m_fs->status(path);
96 FileSystem::GetModificationTime(
const FileSpec &file_spec)
const {
98 return sys::TimePoint<>();
99 return GetModificationTime(file_spec.
GetPath());
102 sys::TimePoint<> FileSystem::GetModificationTime(
const Twine &path)
const {
103 ErrorOr<vfs::Status> status = m_fs->status(path);
105 return sys::TimePoint<>();
106 return status->getLastModificationTime();
109 uint64_t FileSystem::GetByteSize(
const FileSpec &file_spec)
const {
112 return GetByteSize(file_spec.
GetPath());
115 uint64_t FileSystem::GetByteSize(
const Twine &path)
const {
116 ErrorOr<vfs::Status> status = m_fs->status(path);
119 return status->getSize();
127 std::error_code &ec)
const {
129 return sys::fs::perms::perms_not_known;
139 std::error_code &ec)
const {
140 ErrorOr<vfs::Status> status = m_fs->status(path);
142 ec = status.getError();
143 return sys::fs::perms::perms_not_known;
145 return status->getPermissions();
148 bool FileSystem::Exists(
const Twine &path)
const {
return m_fs->exists(path); }
150 bool FileSystem::Exists(
const FileSpec &file_spec)
const {
151 return file_spec && Exists(file_spec.
GetPath());
154 bool FileSystem::Readable(
const Twine &path)
const {
158 bool FileSystem::Readable(
const FileSpec &file_spec)
const {
159 return file_spec && Readable(file_spec.
GetPath());
162 bool FileSystem::IsDirectory(
const Twine &path)
const {
163 ErrorOr<vfs::Status> status = m_fs->status(path);
166 return status->isDirectory();
169 bool FileSystem::IsDirectory(
const FileSpec &file_spec)
const {
170 return file_spec && IsDirectory(file_spec.
GetPath());
173 bool FileSystem::IsLocal(
const Twine &path)
const {
175 m_fs->isLocal(path, b);
179 bool FileSystem::IsLocal(
const FileSpec &file_spec)
const {
180 return file_spec && IsLocal(file_spec.
GetPath());
183 void FileSystem::EnumerateDirectory(Twine path,
bool find_directories,
184 bool find_files,
bool find_other,
185 EnumerateDirectoryCallbackType callback,
186 void *callback_baton) {
188 vfs::recursive_directory_iterator Iter(*m_fs, path, EC);
189 vfs::recursive_directory_iterator End;
190 for (; Iter != End && !EC; Iter.increment(EC)) {
191 const auto &Item = *Iter;
192 ErrorOr<vfs::Status>
Status = m_fs->status(Item.path());
195 if (!find_files &&
Status->isRegularFile())
197 if (!find_directories &&
Status->isDirectory())
199 if (!find_other &&
Status->isOther())
202 auto Result = callback(callback_baton,
Status->getType(), Item.path());
203 if (Result == eEnumerateDirectoryResultQuit)
205 if (Result == eEnumerateDirectoryResultNext) {
214 return m_fs->makeAbsolute(path);
218 SmallString<128> path;
219 file_spec.
GetPath(path,
false);
226 file_spec = new_file_spec;
230 std::error_code FileSystem::GetRealPath(
const Twine &path,
232 return m_fs->getRealPath(path, output);
240 SmallString<128> resolved(path.begin(), path.end());
246 SmallString<128> absolute(resolved.begin(), resolved.end());
250 if (Exists(absolute)) {
251 path.append(absolute.begin(), absolute.end());
253 path.append(resolved.begin(), resolved.end());
262 SmallString<128> path;
276 template <
typename T>
278 uint64_t size, uint64_t offset,
280 std::unique_ptr<T> buffer;
282 auto buffer_or_error = T::getFile(path, is_volatile);
283 if (!buffer_or_error)
285 buffer = std::move(*buffer_or_error);
287 auto buffer_or_error = T::getFileSlice(path, size, offset, is_volatile);
288 if (!buffer_or_error)
290 buffer = std::move(*buffer_or_error);
295 std::shared_ptr<WritableDataBuffer>
296 FileSystem::CreateWritableDataBuffer(
const llvm::Twine &path, uint64_t size,
298 const bool is_volatile = !IsLocal(path);
299 auto buffer = GetMemoryBuffer<llvm::WritableMemoryBuffer>(path, size, offset,
303 return std::shared_ptr<WritableDataBufferLLVM>(
307 std::shared_ptr<DataBuffer>
308 FileSystem::CreateDataBuffer(
const llvm::Twine &path, uint64_t size,
310 const bool is_volatile = !IsLocal(path);
312 GetMemoryBuffer<llvm::MemoryBuffer>(path, size, offset, is_volatile);
315 return std::shared_ptr<DataBufferLLVM>(
new DataBufferLLVM(std::move(buffer)));
318 std::shared_ptr<WritableDataBuffer>
319 FileSystem::CreateWritableDataBuffer(
const FileSpec &file_spec, uint64_t size,
321 return CreateWritableDataBuffer(file_spec.
GetPath(), size, offset);
324 std::shared_ptr<DataBuffer>
325 FileSystem::CreateDataBuffer(
const FileSpec &file_spec, uint64_t size,
327 return CreateDataBuffer(file_spec.
GetPath(), size, offset);
330 bool FileSystem::ResolveExecutableLocation(
FileSpec &file_spec) {
343 llvm::ErrorOr<std::string> error_or_path =
344 llvm::sys::findProgramByName(filename_str);
349 llvm::StringRef path = *error_or_path;
350 llvm::StringRef parent = llvm::sys::path::parent_path(path);
351 if (parent.empty() || parent ==
".")
364 if (!m_home_directory.empty()) {
365 path.assign(m_home_directory.begin(), m_home_directory.end());
368 return llvm::sys::path::home_directory(path);
371 bool FileSystem::GetHomeDirectory(
FileSpec &file_spec)
const {
372 SmallString<128> home_dir;
373 if (!GetHomeDirectory(home_dir))
381 return const_cast<FileSystem &
>(fs).Open(path, flags, mode);
387 options & (File::eOpenOptionReadOnly | File::eOpenOptionWriteOnly |
388 File::eOpenOptionReadWrite);
389 if (rw == File::eOpenOptionWriteOnly || rw == File::eOpenOptionReadWrite) {
390 if (rw == File::eOpenOptionReadWrite)
391 open_flags |= O_RDWR;
393 open_flags |= O_WRONLY;
395 if (options & File::eOpenOptionAppend)
396 open_flags |= O_APPEND;
398 if (options & File::eOpenOptionTruncate)
399 open_flags |= O_TRUNC;
401 if (options & File::eOpenOptionCanCreate)
402 open_flags |= O_CREAT;
404 if (options & File::eOpenOptionCanCreateNewOnly)
405 open_flags |= O_CREAT | O_EXCL;
406 }
else if (rw == File::eOpenOptionReadOnly) {
407 open_flags |= O_RDONLY;
410 if (options & File::eOpenOptionDontFollowSymlinks)
411 open_flags |= O_NOFOLLOW;
416 if (options & File::eOpenOptionNonBlocking)
418 if (options & File::eOpenOptionCloseOnExec)
419 open_flags |= O_CLOEXEC;
421 open_flags |= O_BINARY;
429 if (permissions & lldb::eFilePermissionsUserRead)
431 if (permissions & lldb::eFilePermissionsUserWrite)
433 if (permissions & lldb::eFilePermissionsUserExecute)
435 if (permissions & lldb::eFilePermissionsGroupRead)
437 if (permissions & lldb::eFilePermissionsGroupWrite)
439 if (permissions & lldb::eFilePermissionsGroupExecute)
441 if (permissions & lldb::eFilePermissionsWorldRead)
443 if (permissions & lldb::eFilePermissionsWorldWrite)
445 if (permissions & lldb::eFilePermissionsWorldExecute)
450 Expected<FileUP> FileSystem::Open(
const FileSpec &file_spec,
452 uint32_t permissions,
bool should_close_fd) {
454 const mode_t open_mode =
455 (open_flags & O_CREAT) ?
GetOpenMode(permissions) : 0;
457 auto path = file_spec.
GetPath();
459 int descriptor = llvm::sys::RetryAfterSignal(
460 -1,
OpenWithFS, *
this, path.c_str(), open_flags, open_mode);
462 if (!File::DescriptorIsValid(descriptor))
463 return llvm::errorCodeToError(
464 std::error_code(errno, std::system_category()));
466 auto file = std::unique_ptr<File>(
467 new NativeFile(descriptor, options, should_close_fd));
468 assert(file->IsValid());
469 return std::move(file);
473 m_home_directory = std::move(home_directory);
477 return RemoveFile(file_spec.
GetPath());
480 Status FileSystem::RemoveFile(
const llvm::Twine &path) {
481 return Status(llvm::sys::fs::remove(path));