JDevlieghere created this revision.
JDevlieghere added reviewers: labath, zturner, jingham, clayborg.
JDevlieghere added a project: LLDB.

This patch modifies how we open `File` instances in LLDB. Rather than passing a 
path or FileSpec to the constructor, we now go through the virtual file system. 
This is needed in order to make things work with the VFS.

The current implementation doesn't use the VFS yet. The reason is that in LLDB 
we mostly use FILE pointers or file descriptors to manipulate files. This is 
currently not supported by the VFS and I haven't decided to address this yet. 
The two alternative I see are:

- Having the VFS translate paths. This will only work for virtual file systems 
where the files actually reside on disk. This would be sufficient for the 
reproducer use case but lacks generality.
- Having the VFS provide FILE pointers. Still we wouldn't be able to completely 
support in-memory vfses. I believe on POSIX there's a way to have a file point 
to memory, but I don't think you can do that for a file descriptor. Also not 
sure if that would work on Windows?

Both options are incomplete and I don't have the bandwidth to change how LLDB 
deals with files. I'm currently leaning towards the first alternative because 
LLVM doesn't provide `FILE*` APIs and I don't think we should start adding them 
now. Also I don't want to extend the VFS for just LLDB as that's going to be a 
pain to hook up and maintain. Anyway, I'm open to suggestions!


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D54020

Files:
  include/lldb/Host/File.h
  include/lldb/Host/FileSystem.h
  include/lldb/Utility/FileSpec.h
  source/API/SBStream.cpp
  source/Commands/CommandObjectBugreport.cpp
  source/Commands/CommandObjectMemory.cpp
  source/Core/StreamFile.cpp
  source/Expression/REPL.cpp
  source/Host/common/File.cpp
  source/Host/common/FileCache.cpp
  source/Host/common/FileSystem.cpp
  source/Host/posix/FileSystem.cpp
  source/Host/windows/FileSystem.cpp
  source/Interpreter/CommandInterpreter.cpp
  
source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
  source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
  source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
  source/Target/ModuleCache.cpp
  source/Target/Platform.cpp
  source/Utility/FileSpec.cpp

Index: source/Utility/FileSpec.cpp
===================================================================
--- source/Utility/FileSpec.cpp
+++ source/Utility/FileSpec.cpp
@@ -318,6 +318,8 @@
   m_filename.Clear();
 }
 
+bool FileSpec::Empty() const { return m_directory && m_filename; }
+
 //------------------------------------------------------------------
 // Compare two FileSpec objects. If "full" is true, then both the directory and
 // the filename must match. If "full" is false, then the directory names for
Index: source/Target/Platform.cpp
===================================================================
--- source/Target/Platform.cpp
+++ source/Target/Platform.cpp
@@ -1280,8 +1280,9 @@
   if (fs::is_symlink_file(source.GetPath()))
     source_open_options |= File::eOpenOptionDontFollowSymlinks;
 
-  File source_file(source, source_open_options, lldb::eFilePermissionsUserRW);
-  Status error;
+  File source_file;
+  Status error = FileSystem::Instance().OpenFile(
+      source_file, source, source_open_options, lldb::eFilePermissionsUserRW);
   uint32_t permissions = source_file.GetPermissions(error);
   if (permissions == 0)
     permissions = lldb::eFilePermissionsFileDefault;
Index: source/Target/ModuleCache.cpp
===================================================================
--- source/Target/ModuleCache.cpp
+++ source/Target/ModuleCache.cpp
@@ -159,9 +159,10 @@
     return;
 
   m_file_spec = JoinPath(lock_dir_spec, uuid.GetAsString().c_str());
-  m_file.Open(m_file_spec.GetCString(), File::eOpenOptionWrite |
-                                            File::eOpenOptionCanCreate |
-                                            File::eOpenOptionCloseOnExec);
+  FileSystem::Instance().OpenFile(m_file, m_file_spec,
+                                  File::eOpenOptionWrite |
+                                      File::eOpenOptionCanCreate |
+                                      File::eOpenOptionCloseOnExec);
   if (!m_file) {
     error.SetErrorToErrno();
     return;
Index: source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
===================================================================
--- source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -829,11 +829,15 @@
                                                  error_file_sp);
     } else {
       input_file_sp.reset(new StreamFile());
-      input_file_sp->GetFile().Open(FileSystem::DEV_NULL,
-                                    File::eOpenOptionRead);
+      FileSystem::Instance().OpenFile(input_file_sp->GetFile(),
+                                      FileSpec(FileSystem::DEV_NULL),
+                                      File::eOpenOptionRead);
+
       output_file_sp.reset(new StreamFile());
-      output_file_sp->GetFile().Open(FileSystem::DEV_NULL,
-                                     File::eOpenOptionWrite);
+      FileSystem::Instance().OpenFile(output_file_sp->GetFile(),
+                                      FileSpec(FileSystem::DEV_NULL),
+                                      File::eOpenOptionWrite);
+
       error_file_sp = output_file_sp;
     }
 
Index: source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
===================================================================
--- source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -939,7 +939,9 @@
 PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); }
 
 PythonFile::PythonFile(const char *path, const char *mode) {
-  lldb_private::File file(path, GetOptionsFromMode(mode));
+  lldb_private::File file;
+  FileSystem::Instance().OpenFile(file, FileSpec(path),
+                                  GetOptionsFromMode(mode));
   Reset(file, mode);
 }
 
Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -101,8 +101,9 @@
 // and get the packet history dumped to a file.
 void DumpProcessGDBRemotePacketHistory(void *p, const char *path) {
   StreamFile strm;
-  Status error(strm.GetFile().Open(path, File::eOpenOptionWrite |
-                                             File::eOpenOptionCanCreate));
+  Status error = FileSystem::Instance().OpenFile(
+      strm.GetFile(), FileSpec(path),
+      File::eOpenOptionWrite | File::eOpenOptionCanCreate);
   if (error.Success())
     ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm);
 }
Index: source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
===================================================================
--- source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -6324,10 +6324,10 @@
 
           File core_file;
           std::string core_file_path(outfile.GetPath());
-          error = core_file.Open(core_file_path.c_str(),
-                                 File::eOpenOptionWrite |
-                                     File::eOpenOptionTruncate |
-                                     File::eOpenOptionCanCreate);
+          error = FileSystem::Instance().OpenFile(
+              core_file, outfile,
+              File::eOpenOptionWrite | File::eOpenOptionTruncate |
+                  File::eOpenOptionCanCreate);
           if (error.Success()) {
             // Read 1 page at a time
             uint8_t bytes[0x1000];
Index: source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
===================================================================
--- source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -2756,8 +2756,12 @@
   // Check we can create writable file
   FileSpec file_spec(path);
   FileSystem::Instance().Resolve(file_spec);
-  File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate |
-                           File::eOpenOptionTruncate);
+  File file;
+  FileSystem::Instance().OpenFile(file, file_spec,
+                                  File::eOpenOptionWrite |
+                                      File::eOpenOptionCanCreate |
+                                      File::eOpenOptionTruncate);
+
   if (!file) {
     strm.Printf("Error: Failed to open '%s' for writing", path);
     strm.EOL();
@@ -4710,16 +4714,17 @@
         m_options.m_outfile; // Dump allocation to file instead
     if (outfile_spec) {
       // Open output file
-      char path[256];
-      outfile_spec.GetPath(path, sizeof(path));
-      if (outfile_stream.GetFile()
-              .Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate)
-              .Success()) {
+      std::string path = outfile_spec.GetPath();
+      auto error = FileSystem::Instance().OpenFile(
+          outfile_stream.GetFile(), outfile_spec,
+          File::eOpenOptionWrite | File::eOpenOptionCanCreate);
+      if (error.Success()) {
         output_strm = &outfile_stream;
-        result.GetOutputStream().Printf("Results written to '%s'", path);
+        result.GetOutputStream().Printf("Results written to '%s'",
+                                        path.c_str());
         result.GetOutputStream().EOL();
       } else {
-        result.AppendErrorWithFormat("Couldn't open file '%s'", path);
+        result.AppendErrorWithFormat("Couldn't open file '%s'", path.c_str());
         result.SetStatus(eReturnStatusFailed);
         return false;
       }
Index: source/Interpreter/CommandInterpreter.cpp
===================================================================
--- source/Interpreter/CommandInterpreter.cpp
+++ source/Interpreter/CommandInterpreter.cpp
@@ -430,7 +430,6 @@
     AddAlias("var", cmd_obj_sp);
     AddAlias("vo", cmd_obj_sp, "--object-description");
   }
-  
 }
 
 void CommandInterpreter::Clear() {
@@ -2357,9 +2356,8 @@
     StreamFileSP input_file_sp(new StreamFile());
 
     std::string cmd_file_path = cmd_file.GetPath();
-    Status error = input_file_sp->GetFile().Open(cmd_file_path.c_str(),
-                                                 File::eOpenOptionRead);
-
+    Status error = FileSystem::Instance().OpenFile(
+        input_file_sp->GetFile(), cmd_file, File::eOpenOptionRead);
     if (error.Success()) {
       Debugger &debugger = GetDebugger();
 
Index: source/Host/windows/FileSystem.cpp
===================================================================
--- source/Host/windows/FileSystem.cpp
+++ source/Host/windows/FileSystem.cpp
@@ -85,7 +85,7 @@
   return Status("ResolveSymbolicLink() isn't implemented on Windows");
 }
 
-FILE *FileSystem::Fopen(const char *path, const char *mode) {
+FILE *FileSystem::Fopen(const char *path, const char *mode) const {
   std::wstring wpath, wmode;
   if (!llvm::ConvertUTF8toWide(path, wpath))
     return nullptr;
@@ -97,7 +97,7 @@
   return file;
 }
 
-int FileSystem::Open(const char *path, int flags, int mode) {
+int FileSystem::Open(const char *path, int flags, int mode) const {
   std::wstring wpath;
   if (!llvm::ConvertUTF8toWide(path, wpath))
     return -1;
Index: source/Host/posix/FileSystem.cpp
===================================================================
--- source/Host/posix/FileSystem.cpp
+++ source/Host/posix/FileSystem.cpp
@@ -71,10 +71,10 @@
   return Status();
 }
 
-FILE *FileSystem::Fopen(const char *path, const char *mode) {
+FILE *FileSystem::Fopen(const char *path, const char *mode) const {
   return ::fopen(path, mode);
 }
 
-int FileSystem::Open(const char *path, int flags, int mode) {
+int FileSystem::Open(const char *path, int flags, int mode) const {
   return ::open(path, flags, mode);
 }
Index: source/Host/common/FileSystem.cpp
===================================================================
--- source/Host/common/FileSystem.cpp
+++ source/Host/common/FileSystem.cpp
@@ -12,11 +12,27 @@
 #include "lldb/Utility/LLDBAssert.h"
 #include "lldb/Utility/TildeExpressionResolver.h"
 
+#include "llvm/Support/Errno.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/Threading.h"
 
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#else
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <unistd.h>
+#endif
+
 #include <algorithm>
 #include <fstream>
 #include <vector>
@@ -227,3 +243,97 @@
   file_spec = result;
   return true;
 }
+
+static int OpenWithFS(const FileSystem &fs, const char *path, int flags,
+                      int mode) {
+  return fs.Open(path, flags, mode);
+}
+
+static int GetOpenFlags(uint32_t options) {
+  const bool read = options & File::OpenOptions::eOpenOptionRead;
+  const bool write = options & File::OpenOptions::eOpenOptionWrite;
+
+  int open_flags = 0;
+  if (write) {
+    if (read)
+      open_flags |= O_RDWR;
+    else
+      open_flags |= O_WRONLY;
+
+    if (options & File::OpenOptions::eOpenOptionAppend)
+      open_flags |= O_APPEND;
+
+    if (options & File::OpenOptions::eOpenOptionTruncate)
+      open_flags |= O_TRUNC;
+
+    if (options & File::OpenOptions::eOpenOptionCanCreate)
+      open_flags |= O_CREAT;
+
+    if (options & File::OpenOptions::eOpenOptionCanCreateNewOnly)
+      open_flags |= O_CREAT | O_EXCL;
+  } else if (read) {
+    open_flags |= O_RDONLY;
+
+#ifndef _WIN32
+    if (options & File::OpenOptions::eOpenOptionDontFollowSymlinks)
+      open_flags |= O_NOFOLLOW;
+#endif
+  }
+
+#ifndef _WIN32
+  if (options & File::OpenOptions::eOpenOptionNonBlocking)
+    open_flags |= O_NONBLOCK;
+  if (options & File::OpenOptions::eOpenOptionCloseOnExec)
+    open_flags |= O_CLOEXEC;
+#else
+  open_flags |= O_BINARY;
+#endif
+
+  return open_flags;
+}
+
+static mode_t GetOpenMode(uint32_t permissions) {
+  mode_t mode = 0;
+  if (permissions & lldb::eFilePermissionsUserRead)
+    mode |= S_IRUSR;
+  if (permissions & lldb::eFilePermissionsUserWrite)
+    mode |= S_IWUSR;
+  if (permissions & lldb::eFilePermissionsUserExecute)
+    mode |= S_IXUSR;
+  if (permissions & lldb::eFilePermissionsGroupRead)
+    mode |= S_IRGRP;
+  if (permissions & lldb::eFilePermissionsGroupWrite)
+    mode |= S_IWGRP;
+  if (permissions & lldb::eFilePermissionsGroupExecute)
+    mode |= S_IXGRP;
+  if (permissions & lldb::eFilePermissionsWorldRead)
+    mode |= S_IROTH;
+  if (permissions & lldb::eFilePermissionsWorldWrite)
+    mode |= S_IWOTH;
+  if (permissions & lldb::eFilePermissionsWorldExecute)
+    mode |= S_IXOTH;
+  return mode;
+}
+
+Status FileSystem::OpenFile(File &File, const FileSpec &file_spec,
+                            uint32_t options, uint32_t permissions) {
+  if (File.IsValid())
+    File.Close();
+
+  const int open_flags = GetOpenFlags(options);
+  const mode_t open_mode =
+      (open_flags & O_CREAT) ? GetOpenMode(permissions) : 0;
+  const std::string path = file_spec.GetPath();
+
+  int descriptor = llvm::sys::RetryAfterSignal(
+      -1, OpenWithFS, *this, path.c_str(), open_flags, open_mode);
+
+  Status error;
+  if (File::DescriptorIsValid(descriptor)) {
+    error.SetErrorToErrno();
+  } else {
+    File.SetDescriptor(descriptor, true);
+    File.SetOptions(options);
+  }
+  return error;
+}
Index: source/Host/common/FileCache.cpp
===================================================================
--- source/Host/common/FileCache.cpp
+++ source/Host/common/FileCache.cpp
@@ -10,6 +10,7 @@
 #include "lldb/Host/FileCache.h"
 
 #include "lldb/Host/File.h"
+#include "lldb/Host/FileSystem.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -25,13 +26,12 @@
 
 lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags,
                                     uint32_t mode, Status &error) {
-  std::string path(file_spec.GetPath());
-  if (path.empty()) {
+  if (file_spec.Empty()) {
     error.SetErrorString("empty path");
     return UINT64_MAX;
   }
   FileSP file_sp(new File());
-  error = file_sp->Open(path.c_str(), flags, mode);
+  error = FileSystem::Instance().OpenFile(*file_sp, file_spec, flags, mode);
   if (file_sp->IsValid() == false)
     return UINT64_MAX;
   lldb::user_id_t fd = file_sp->GetDescriptor();
Index: source/Host/common/File.cpp
===================================================================
--- source/Host/common/File.cpp
+++ source/Host/common/File.cpp
@@ -71,26 +71,6 @@
 int File::kInvalidDescriptor = -1;
 FILE *File::kInvalidStream = NULL;
 
-File::File(const char *path, uint32_t options, uint32_t permissions)
-    : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
-      m_stream(kInvalidStream), m_options(), m_own_stream(false),
-      m_is_interactive(eLazyBoolCalculate),
-      m_is_real_terminal(eLazyBoolCalculate) {
-  Open(path, options, permissions);
-}
-
-File::File(const FileSpec &filespec, uint32_t options, uint32_t permissions)
-    : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
-      m_stream(kInvalidStream), m_options(0), m_own_stream(false),
-      m_is_interactive(eLazyBoolCalculate),
-      m_is_real_terminal(eLazyBoolCalculate)
-
-{
-  if (filespec) {
-    Open(filespec.GetPath().c_str(), options, permissions);
-  }
-}
-
 File::~File() { Close(); }
 
 int File::GetDescriptor() const {
@@ -159,95 +139,6 @@
   m_own_stream = transfer_ownership;
 }
 
-static int DoOpen(const char *path, int flags, int mode) {
-#ifdef _MSC_VER
-  std::wstring wpath;
-  if (!llvm::ConvertUTF8toWide(path, wpath))
-    return -1;
-  int result;
-  ::_wsopen_s(&result, wpath.c_str(), flags, _SH_DENYNO, mode);
-  return result;
-#else
-  return ::open(path, flags, mode);
-#endif
-}
-
-Status File::Open(const char *path, uint32_t options, uint32_t permissions) {
-  Status error;
-  if (IsValid())
-    Close();
-
-  int oflag = 0;
-  const bool read = options & eOpenOptionRead;
-  const bool write = options & eOpenOptionWrite;
-  if (write) {
-    if (read)
-      oflag |= O_RDWR;
-    else
-      oflag |= O_WRONLY;
-
-    if (options & eOpenOptionAppend)
-      oflag |= O_APPEND;
-
-    if (options & eOpenOptionTruncate)
-      oflag |= O_TRUNC;
-
-    if (options & eOpenOptionCanCreate)
-      oflag |= O_CREAT;
-
-    if (options & eOpenOptionCanCreateNewOnly)
-      oflag |= O_CREAT | O_EXCL;
-  } else if (read) {
-    oflag |= O_RDONLY;
-
-#ifndef _WIN32
-    if (options & eOpenOptionDontFollowSymlinks)
-      oflag |= O_NOFOLLOW;
-#endif
-  }
-
-#ifndef _WIN32
-  if (options & eOpenOptionNonBlocking)
-    oflag |= O_NONBLOCK;
-  if (options & eOpenOptionCloseOnExec)
-    oflag |= O_CLOEXEC;
-#else
-  oflag |= O_BINARY;
-#endif
-
-  mode_t mode = 0;
-  if (oflag & O_CREAT) {
-    if (permissions & lldb::eFilePermissionsUserRead)
-      mode |= S_IRUSR;
-    if (permissions & lldb::eFilePermissionsUserWrite)
-      mode |= S_IWUSR;
-    if (permissions & lldb::eFilePermissionsUserExecute)
-      mode |= S_IXUSR;
-    if (permissions & lldb::eFilePermissionsGroupRead)
-      mode |= S_IRGRP;
-    if (permissions & lldb::eFilePermissionsGroupWrite)
-      mode |= S_IWGRP;
-    if (permissions & lldb::eFilePermissionsGroupExecute)
-      mode |= S_IXGRP;
-    if (permissions & lldb::eFilePermissionsWorldRead)
-      mode |= S_IROTH;
-    if (permissions & lldb::eFilePermissionsWorldWrite)
-      mode |= S_IWOTH;
-    if (permissions & lldb::eFilePermissionsWorldExecute)
-      mode |= S_IXOTH;
-  }
-
-  m_descriptor = llvm::sys::RetryAfterSignal(-1, DoOpen, path, oflag, mode);
-  if (!DescriptorIsValid())
-    error.SetErrorToErrno();
-  else {
-    m_should_close_fd = true;
-    m_options = options;
-  }
-
-  return error;
-}
-
 uint32_t File::GetPermissions(Status &error) const {
   int fd = GetDescriptor();
   if (fd != kInvalidDescriptor) {
Index: source/Expression/REPL.cpp
===================================================================
--- source/Expression/REPL.cpp
+++ source/Expression/REPL.cpp
@@ -416,11 +416,12 @@
 
           // Update our code on disk
           if (!m_repl_source_path.empty()) {
-            lldb_private::File file(m_repl_source_path.c_str(),
-                                    File::eOpenOptionWrite |
-                                        File::eOpenOptionTruncate |
-                                        File::eOpenOptionCanCreate,
-                                    lldb::eFilePermissionsFileDefault);
+            lldb_private::File file;
+            FileSystem::Instance().OpenFile(file, FileSpec(m_repl_source_path),
+                                            File::eOpenOptionWrite |
+                                                File::eOpenOptionTruncate |
+                                                File::eOpenOptionCanCreate,
+                                            lldb::eFilePermissionsFileDefault);
             std::string code(m_code.CopyList());
             code.append(1, '\n');
             size_t bytes_written = code.size();
Index: source/Core/StreamFile.cpp
===================================================================
--- source/Core/StreamFile.cpp
+++ source/Core/StreamFile.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Core/StreamFile.h"
+#include "lldb/Host/FileSystem.h"
 
 #include <stdio.h>
 
@@ -28,14 +29,18 @@
 StreamFile::StreamFile(FILE *fh, bool transfer_ownership)
     : Stream(), m_file(fh, transfer_ownership) {}
 
-StreamFile::StreamFile(const char *path)
-    : Stream(),
-      m_file(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate |
-                       File::eOpenOptionCloseOnExec,
-             lldb::eFilePermissionsFileDefault) {}
+StreamFile::StreamFile(const char *path) : Stream(), m_file() {
+  FileSystem::Instance().OpenFile(m_file, FileSpec(path),
+                                  File::eOpenOptionWrite |
+                                      File::eOpenOptionCanCreate |
+                                      File::eOpenOptionCloseOnExec);
+}
 
 StreamFile::StreamFile(const char *path, uint32_t options, uint32_t permissions)
-    : Stream(), m_file(path, options, permissions) {}
+    : Stream(), m_file() {
+
+  FileSystem::Instance().OpenFile(m_file, FileSpec(path), options, permissions);
+}
 
 StreamFile::~StreamFile() {}
 
Index: source/Commands/CommandObjectMemory.cpp
===================================================================
--- source/Commands/CommandObjectMemory.cpp
+++ source/Commands/CommandObjectMemory.cpp
@@ -762,29 +762,31 @@
     Stream *output_stream = nullptr;
     const FileSpec &outfile_spec =
         m_outfile_options.GetFile().GetCurrentValue();
+
+    std::string path = outfile_spec.GetPath();
     if (outfile_spec) {
-      char path[PATH_MAX];
-      outfile_spec.GetPath(path, sizeof(path));
 
       uint32_t open_options =
           File::eOpenOptionWrite | File::eOpenOptionCanCreate;
       const bool append = m_outfile_options.GetAppend().GetCurrentValue();
       if (append)
         open_options |= File::eOpenOptionAppend;
 
-      if (outfile_stream.GetFile().Open(path, open_options).Success()) {
+      Status error = FileSystem::Instance().OpenFile(
+          outfile_stream.GetFile(), outfile_spec, open_options);
+      if (error.Success()) {
         if (m_memory_options.m_output_as_binary) {
           const size_t bytes_written =
               outfile_stream.Write(data_sp->GetBytes(), bytes_read);
           if (bytes_written > 0) {
             result.GetOutputStream().Printf(
                 "%zi bytes %s to '%s'\n", bytes_written,
-                append ? "appended" : "written", path);
+                append ? "appended" : "written", path.c_str());
             return true;
           } else {
             result.AppendErrorWithFormat("Failed to write %" PRIu64
                                          " bytes to '%s'.\n",
-                                         (uint64_t)bytes_read, path);
+                                         (uint64_t)bytes_read, path.c_str());
             result.SetStatus(eReturnStatusFailed);
             return false;
           }
@@ -794,8 +796,8 @@
           output_stream = &outfile_stream;
         }
       } else {
-        result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path,
-                                     append ? "append" : "write");
+        result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n",
+                                     path.c_str(), append ? "append" : "write");
         result.SetStatus(eReturnStatusFailed);
         return false;
       }
Index: source/Commands/CommandObjectBugreport.cpp
===================================================================
--- source/Commands/CommandObjectBugreport.cpp
+++ source/Commands/CommandObjectBugreport.cpp
@@ -72,8 +72,6 @@
     const FileSpec &outfile_spec =
         m_outfile_options.GetFile().GetCurrentValue();
     if (outfile_spec) {
-      char path[PATH_MAX];
-      outfile_spec.GetPath(path, sizeof(path));
 
       uint32_t open_options =
           File::eOpenOptionWrite | File::eOpenOptionCanCreate |
@@ -84,10 +82,13 @@
         open_options |= File::eOpenOptionTruncate;
 
       StreamFileSP outfile_stream = std::make_shared<StreamFile>();
-      Status error = outfile_stream->GetFile().Open(path, open_options);
+      File &file = outfile_stream->GetFile();
+      Status error =
+          FileSystem::Instance().OpenFile(file, outfile_spec, open_options);
       if (error.Fail()) {
+        auto path = outfile_spec.GetPath();
         result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n",
-                                     path, append ? "append" : "write",
+                                     path.c_str(), append ? "append" : "write",
                                      error.AsCString());
         result.SetStatus(eReturnStatusFailed);
         return false;
Index: source/API/SBStream.cpp
===================================================================
--- source/API/SBStream.cpp
+++ source/API/SBStream.cpp
@@ -10,6 +10,7 @@
 #include "lldb/API/SBStream.h"
 
 #include "lldb/Core/StreamFile.h"
+#include "lldb/Host/FileSystem.h"
 #include "lldb/Utility/Status.h"
 #include "lldb/Utility/Stream.h"
 #include "lldb/Utility/StreamString.h"
@@ -70,9 +71,9 @@
     open_options |= File::eOpenOptionAppend;
   else
     open_options |= File::eOpenOptionTruncate;
-  stream_file->GetFile().Open(path, open_options,
-                              lldb::eFilePermissionsFileDefault);
 
+  FileSystem::Instance().OpenFile(stream_file->GetFile(), FileSpec(path),
+                                  open_options);
   m_opaque_ap.reset(stream_file);
 
   if (m_opaque_ap.get()) {
Index: include/lldb/Utility/FileSpec.h
===================================================================
--- include/lldb/Utility/FileSpec.h
+++ include/lldb/Utility/FileSpec.h
@@ -216,6 +216,8 @@
   //------------------------------------------------------------------
   void Clear();
 
+  bool Empty() const;
+
   //------------------------------------------------------------------
   /// Compare two FileSpec objects.
   ///
Index: include/lldb/Host/FileSystem.h
===================================================================
--- include/lldb/Host/FileSystem.h
+++ include/lldb/Host/FileSystem.h
@@ -10,6 +10,7 @@
 #ifndef liblldb_Host_FileSystem_h
 #define liblldb_Host_FileSystem_h
 
+#include "lldb/Host/File.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/Status.h"
 
@@ -45,8 +46,10 @@
 
   /// Wraps ::fopen in a platform-independent way. Once opened, FILEs can be
   /// manipulated and closed with the normal ::fread, ::fclose, etc. functions.
-  FILE *Fopen(const char *path, const char *mode);
-  int Open(const char *path, int flags, int mode);
+  FILE *Fopen(const char *path, const char *mode) const;
+
+  /// Wraps ::open in a platform-independent way.
+  int Open(const char *path, int flags, int mode) const;
 
   /// Returns the modification time of the given file.
   /// @{
@@ -123,6 +126,9 @@
   std::error_code GetRealPath(const llvm::Twine &path,
                               llvm::SmallVectorImpl<char> &output) const;
 
+  Status OpenFile(File &File, const FileSpec &file_spec, uint32_t options,
+                  uint32_t permissions = lldb::eFilePermissionsFileDefault);
+
 protected:
   void SetFileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs);
 
Index: include/lldb/Host/File.h
===================================================================
--- include/lldb/Host/File.h
+++ include/lldb/Host/File.h
@@ -64,50 +64,6 @@
         m_is_real_terminal(eLazyBoolCalculate),
         m_supports_colors(eLazyBoolCalculate) {}
 
-  //------------------------------------------------------------------
-  /// Constructor with path.
-  ///
-  /// Takes a path to a file which can be just a filename, or a full path. If
-  /// \a path is not nullptr or empty, this function will call File::Open
-  /// (const char *path, uint32_t options, uint32_t permissions).
-  ///
-  /// @param[in] path
-  ///     The full or partial path to a file.
-  ///
-  /// @param[in] options
-  ///     Options to use when opening (see File::OpenOptions)
-  ///
-  /// @param[in] permissions
-  ///     Options to use when opening (see File::Permissions)
-  ///
-  /// @see File::Open (const char *path, uint32_t options, uint32_t
-  /// permissions)
-  //------------------------------------------------------------------
-  File(const char *path, uint32_t options,
-       uint32_t permissions = lldb::eFilePermissionsFileDefault);
-
-  //------------------------------------------------------------------
-  /// Constructor with FileSpec.
-  ///
-  /// Takes a FileSpec pointing to a file which can be just a filename, or a
-  /// full path. If \a path is not nullptr or empty, this function will call
-  /// File::Open (const char *path, uint32_t options, uint32_t permissions).
-  ///
-  /// @param[in] filespec
-  ///     The FileSpec for this file.
-  ///
-  /// @param[in] options
-  ///     Options to use when opening (see File::OpenOptions)
-  ///
-  /// @param[in] permissions
-  ///     Options to use when opening (see File::Permissions)
-  ///
-  /// @see File::Open (const char *path, uint32_t options, uint32_t
-  /// permissions)
-  //------------------------------------------------------------------
-  File(const FileSpec &filespec, uint32_t options,
-       uint32_t permissions = lldb::eFilePermissionsFileDefault);
-
   File(int fd, bool transfer_ownership)
       : IOObject(eFDTypeFile, transfer_ownership), m_descriptor(fd),
         m_stream(kInvalidStream), m_options(0), m_own_stream(false),
@@ -169,23 +125,6 @@
   //------------------------------------------------------------------
   Status GetFileSpec(FileSpec &file_spec) const;
 
-  //------------------------------------------------------------------
-  /// Open a file for read/writing with the specified options.
-  ///
-  /// Takes a path to a file which can be just a filename, or a full path.
-  ///
-  /// @param[in] path
-  ///     The full or partial path to a file.
-  ///
-  /// @param[in] options
-  ///     Options to use when opening (see File::OpenOptions)
-  ///
-  /// @param[in] permissions
-  ///     Options to use when opening (see File::Permissions)
-  //------------------------------------------------------------------
-  Status Open(const char *path, uint32_t options,
-              uint32_t permissions = lldb::eFilePermissionsFileDefault);
-
   Status Close() override;
 
   void Clear();
@@ -461,8 +400,10 @@
 
   void SetOptions(uint32_t options) { m_options = options; }
 
+  static bool DescriptorIsValid(int descriptor) { return descriptor >= 0; };
+
 protected:
-  bool DescriptorIsValid() const { return m_descriptor >= 0; }
+  bool DescriptorIsValid() const { return DescriptorIsValid(m_descriptor); }
 
   bool StreamIsValid() const { return m_stream != kInvalidStream; }
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to