aboutsummaryrefslogtreecommitdiffstats
path: root/source/Host/common/File.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Host/common/File.cpp')
-rw-r--r--source/Host/common/File.cpp410
1 files changed, 223 insertions, 187 deletions
diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp
index c8c8d7a0d496..9dae24d766f6 100644
--- a/source/Host/common/File.cpp
+++ b/source/Host/common/File.cpp
@@ -37,8 +37,10 @@
using namespace lldb;
using namespace lldb_private;
+using llvm::Expected;
-static const char *GetStreamOpenModeFromOptions(uint32_t options) {
+Expected<const char *>
+File::GetStreamOpenModeFromOptions(File::OpenOptions options) {
if (options & File::eOpenOptionAppend) {
if (options & File::eOpenOptionRead) {
if (options & File::eOpenOptionCanCreateNewOnly)
@@ -65,15 +67,188 @@ static const char *GetStreamOpenModeFromOptions(uint32_t options) {
} else if (options & File::eOpenOptionWrite) {
return "w";
}
- return nullptr;
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "invalid options, cannot convert to mode string");
+}
+
+Expected<File::OpenOptions> File::GetOptionsFromMode(llvm::StringRef mode) {
+ OpenOptions opts =
+ llvm::StringSwitch<OpenOptions>(mode)
+ .Cases("r", "rb", eOpenOptionRead)
+ .Cases("w", "wb", eOpenOptionWrite)
+ .Cases("a", "ab",
+ eOpenOptionWrite | eOpenOptionAppend | eOpenOptionCanCreate)
+ .Cases("r+", "rb+", "r+b", eOpenOptionRead | eOpenOptionWrite)
+ .Cases("w+", "wb+", "w+b",
+ eOpenOptionRead | eOpenOptionWrite | eOpenOptionCanCreate |
+ eOpenOptionTruncate)
+ .Cases("a+", "ab+", "a+b",
+ eOpenOptionRead | eOpenOptionWrite | eOpenOptionAppend |
+ eOpenOptionCanCreate)
+ .Default(OpenOptions());
+ if (opts)
+ return opts;
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "invalid mode, cannot convert to File::OpenOptions");
}
int File::kInvalidDescriptor = -1;
FILE *File::kInvalidStream = nullptr;
-File::~File() { Close(); }
+Status File::Read(void *buf, size_t &num_bytes) {
+ return std::error_code(ENOTSUP, std::system_category());
+}
+Status File::Write(const void *buf, size_t &num_bytes) {
+ return std::error_code(ENOTSUP, std::system_category());
+}
+
+bool File::IsValid() const { return false; }
+
+Status File::Close() { return Flush(); }
+
+IOObject::WaitableHandle File::GetWaitableHandle() {
+ return IOObject::kInvalidHandleValue;
+}
-int File::GetDescriptor() const {
+Status File::GetFileSpec(FileSpec &file_spec) const {
+ file_spec.Clear();
+ return std::error_code(ENOTSUP, std::system_category());
+}
+
+int File::GetDescriptor() const { return kInvalidDescriptor; }
+
+FILE *File::GetStream() { return nullptr; }
+
+off_t File::SeekFromStart(off_t offset, Status *error_ptr) {
+ if (error_ptr)
+ *error_ptr = std::error_code(ENOTSUP, std::system_category());
+ return -1;
+}
+
+off_t File::SeekFromCurrent(off_t offset, Status *error_ptr) {
+ if (error_ptr)
+ *error_ptr = std::error_code(ENOTSUP, std::system_category());
+ return -1;
+}
+
+off_t File::SeekFromEnd(off_t offset, Status *error_ptr) {
+ if (error_ptr)
+ *error_ptr = std::error_code(ENOTSUP, std::system_category());
+ return -1;
+}
+
+Status File::Read(void *dst, size_t &num_bytes, off_t &offset) {
+ return std::error_code(ENOTSUP, std::system_category());
+}
+
+Status File::Write(const void *src, size_t &num_bytes, off_t &offset) {
+ return std::error_code(ENOTSUP, std::system_category());
+}
+
+Status File::Flush() { return Status(); }
+
+Status File::Sync() { return Flush(); }
+
+void File::CalculateInteractiveAndTerminal() {
+ const int fd = GetDescriptor();
+ if (!DescriptorIsValid(fd)) {
+ m_is_interactive = eLazyBoolNo;
+ m_is_real_terminal = eLazyBoolNo;
+ m_supports_colors = eLazyBoolNo;
+ return;
+ }
+ m_is_interactive = eLazyBoolNo;
+ m_is_real_terminal = eLazyBoolNo;
+#if defined(_WIN32)
+ if (_isatty(fd)) {
+ m_is_interactive = eLazyBoolYes;
+ m_is_real_terminal = eLazyBoolYes;
+#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+ m_supports_colors = eLazyBoolYes;
+#endif
+ }
+#else
+ if (isatty(fd)) {
+ m_is_interactive = eLazyBoolYes;
+ struct winsize window_size;
+ if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) {
+ if (window_size.ws_col > 0) {
+ m_is_real_terminal = eLazyBoolYes;
+ if (llvm::sys::Process::FileDescriptorHasColors(fd))
+ m_supports_colors = eLazyBoolYes;
+ }
+ }
+ }
+#endif
+}
+
+bool File::GetIsInteractive() {
+ if (m_is_interactive == eLazyBoolCalculate)
+ CalculateInteractiveAndTerminal();
+ return m_is_interactive == eLazyBoolYes;
+}
+
+bool File::GetIsRealTerminal() {
+ if (m_is_real_terminal == eLazyBoolCalculate)
+ CalculateInteractiveAndTerminal();
+ return m_is_real_terminal == eLazyBoolYes;
+}
+
+bool File::GetIsTerminalWithColors() {
+ if (m_supports_colors == eLazyBoolCalculate)
+ CalculateInteractiveAndTerminal();
+ return m_supports_colors == eLazyBoolYes;
+}
+
+size_t File::Printf(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ size_t result = PrintfVarArg(format, args);
+ va_end(args);
+ return result;
+}
+
+size_t File::PrintfVarArg(const char *format, va_list args) {
+ size_t result = 0;
+ char *s = nullptr;
+ result = vasprintf(&s, format, args);
+ if (s != nullptr) {
+ if (result > 0) {
+ size_t s_len = result;
+ Write(s, s_len);
+ result = s_len;
+ }
+ free(s);
+ }
+ return result;
+}
+
+Expected<File::OpenOptions> File::GetOptions() const {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "GetOptions() not implemented for this File class");
+}
+
+uint32_t File::GetPermissions(Status &error) const {
+ int fd = GetDescriptor();
+ if (!DescriptorIsValid(fd)) {
+ error = std::error_code(ENOTSUP, std::system_category());
+ return 0;
+ }
+ struct stat file_stats;
+ if (::fstat(fd, &file_stats) == -1) {
+ error.SetErrorToErrno();
+ return 0;
+ }
+ error.Clear();
+ return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+}
+
+Expected<File::OpenOptions> NativeFile::GetOptions() const { return m_options; }
+
+int NativeFile::GetDescriptor() const {
if (DescriptorIsValid())
return m_descriptor;
@@ -91,21 +266,18 @@ int File::GetDescriptor() const {
return kInvalidDescriptor;
}
-IOObject::WaitableHandle File::GetWaitableHandle() { return m_descriptor; }
-
-void File::SetDescriptor(int fd, bool transfer_ownership) {
- if (IsValid())
- Close();
- m_descriptor = fd;
- m_should_close_fd = transfer_ownership;
+IOObject::WaitableHandle NativeFile::GetWaitableHandle() {
+ return GetDescriptor();
}
-FILE *File::GetStream() {
+FILE *NativeFile::GetStream() {
if (!StreamIsValid()) {
if (DescriptorIsValid()) {
- const char *mode = GetStreamOpenModeFromOptions(m_options);
- if (mode) {
- if (!m_should_close_fd) {
+ auto mode = GetStreamOpenModeFromOptions(m_options);
+ if (!mode)
+ llvm::consumeError(mode.takeError());
+ else {
+ if (!m_own_descriptor) {
// We must duplicate the file descriptor if we don't own it because when you
// call fdopen, the stream will own the fd
#ifdef _WIN32
@@ -113,18 +285,18 @@ FILE *File::GetStream() {
#else
m_descriptor = dup(GetDescriptor());
#endif
- m_should_close_fd = true;
+ m_own_descriptor = true;
}
- m_stream =
- llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor, mode);
+ m_stream = llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor,
+ mode.get());
// If we got a stream, then we own the stream and should no longer own
// the descriptor because fclose() will close it for us
if (m_stream) {
m_own_stream = true;
- m_should_close_fd = false;
+ m_own_descriptor = false;
}
}
}
@@ -132,60 +304,32 @@ FILE *File::GetStream() {
return m_stream;
}
-void File::SetStream(FILE *fh, bool transfer_ownership) {
- if (IsValid())
- Close();
- m_stream = fh;
- m_own_stream = transfer_ownership;
-}
-
-uint32_t File::GetPermissions(Status &error) const {
- int fd = GetDescriptor();
- if (fd != kInvalidDescriptor) {
- struct stat file_stats;
- if (::fstat(fd, &file_stats) == -1)
- error.SetErrorToErrno();
- else {
- error.Clear();
- return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
- }
- } else {
- error.SetErrorString("invalid file descriptor");
- }
- return 0;
-}
-
-Status File::Close() {
+Status NativeFile::Close() {
Status error;
- if (StreamIsValid() && m_own_stream) {
- if (::fclose(m_stream) == EOF)
- error.SetErrorToErrno();
+ if (StreamIsValid()) {
+ if (m_own_stream) {
+ if (::fclose(m_stream) == EOF)
+ error.SetErrorToErrno();
+ } else {
+ if (::fflush(m_stream) == EOF)
+ error.SetErrorToErrno();
+ }
}
-
- if (DescriptorIsValid() && m_should_close_fd) {
+ if (DescriptorIsValid() && m_own_descriptor) {
if (::close(m_descriptor) != 0)
error.SetErrorToErrno();
}
m_descriptor = kInvalidDescriptor;
m_stream = kInvalidStream;
- m_options = 0;
+ m_options = OpenOptions(0);
m_own_stream = false;
- m_should_close_fd = false;
+ m_own_descriptor = false;
m_is_interactive = eLazyBoolCalculate;
m_is_real_terminal = eLazyBoolCalculate;
return error;
}
-void File::Clear() {
- m_stream = nullptr;
- m_descriptor = kInvalidDescriptor;
- m_options = 0;
- m_own_stream = false;
- m_is_interactive = m_supports_colors = m_is_real_terminal =
- eLazyBoolCalculate;
-}
-
-Status File::GetFileSpec(FileSpec &file_spec) const {
+Status NativeFile::GetFileSpec(FileSpec &file_spec) const {
Status error;
#ifdef F_GETPATH
if (IsValid()) {
@@ -212,7 +356,8 @@ Status File::GetFileSpec(FileSpec &file_spec) const {
}
}
#else
- error.SetErrorString("File::GetFileSpec is not supported on this platform");
+ error.SetErrorString(
+ "NativeFile::GetFileSpec is not supported on this platform");
#endif
if (error.Fail())
@@ -220,7 +365,7 @@ Status File::GetFileSpec(FileSpec &file_spec) const {
return error;
}
-off_t File::SeekFromStart(off_t offset, Status *error_ptr) {
+off_t NativeFile::SeekFromStart(off_t offset, Status *error_ptr) {
off_t result = 0;
if (DescriptorIsValid()) {
result = ::lseek(m_descriptor, offset, SEEK_SET);
@@ -246,7 +391,7 @@ off_t File::SeekFromStart(off_t offset, Status *error_ptr) {
return result;
}
-off_t File::SeekFromCurrent(off_t offset, Status *error_ptr) {
+off_t NativeFile::SeekFromCurrent(off_t offset, Status *error_ptr) {
off_t result = -1;
if (DescriptorIsValid()) {
result = ::lseek(m_descriptor, offset, SEEK_CUR);
@@ -272,7 +417,7 @@ off_t File::SeekFromCurrent(off_t offset, Status *error_ptr) {
return result;
}
-off_t File::SeekFromEnd(off_t offset, Status *error_ptr) {
+off_t NativeFile::SeekFromEnd(off_t offset, Status *error_ptr) {
off_t result = -1;
if (DescriptorIsValid()) {
result = ::lseek(m_descriptor, offset, SEEK_END);
@@ -298,7 +443,7 @@ off_t File::SeekFromEnd(off_t offset, Status *error_ptr) {
return result;
}
-Status File::Flush() {
+Status NativeFile::Flush() {
Status error;
if (StreamIsValid()) {
if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF)
@@ -309,7 +454,7 @@ Status File::Flush() {
return error;
}
-Status File::Sync() {
+Status NativeFile::Sync() {
Status error;
if (DescriptorIsValid()) {
#ifdef _WIN32
@@ -332,7 +477,7 @@ Status File::Sync() {
#define MAX_WRITE_SIZE INT_MAX
#endif
-Status File::Read(void *buf, size_t &num_bytes) {
+Status NativeFile::Read(void *buf, size_t &num_bytes) {
Status error;
#if defined(MAX_READ_SIZE)
@@ -391,7 +536,7 @@ Status File::Read(void *buf, size_t &num_bytes) {
return error;
}
-Status File::Write(const void *buf, size_t &num_bytes) {
+Status NativeFile::Write(const void *buf, size_t &num_bytes) {
Status error;
#if defined(MAX_WRITE_SIZE)
@@ -453,7 +598,7 @@ Status File::Write(const void *buf, size_t &num_bytes) {
return error;
}
-Status File::Read(void *buf, size_t &num_bytes, off_t &offset) {
+Status NativeFile::Read(void *buf, size_t &num_bytes, off_t &offset) {
Status error;
#if defined(MAX_READ_SIZE)
@@ -513,51 +658,7 @@ Status File::Read(void *buf, size_t &num_bytes, off_t &offset) {
return error;
}
-Status File::Read(size_t &num_bytes, off_t &offset, bool null_terminate,
- DataBufferSP &data_buffer_sp) {
- Status error;
-
- if (num_bytes > 0) {
- int fd = GetDescriptor();
- if (fd != kInvalidDescriptor) {
- struct stat file_stats;
- if (::fstat(fd, &file_stats) == 0) {
- if (file_stats.st_size > offset) {
- const size_t bytes_left = file_stats.st_size - offset;
- if (num_bytes > bytes_left)
- num_bytes = bytes_left;
-
- size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0);
- std::unique_ptr<DataBufferHeap> data_heap_up;
- data_heap_up.reset(new DataBufferHeap());
- data_heap_up->SetByteSize(num_bytes_plus_nul_char);
-
- if (data_heap_up) {
- error = Read(data_heap_up->GetBytes(), num_bytes, offset);
- if (error.Success()) {
- // Make sure we read exactly what we asked for and if we got
- // less, adjust the array
- if (num_bytes_plus_nul_char < data_heap_up->GetByteSize())
- data_heap_up->SetByteSize(num_bytes_plus_nul_char);
- data_buffer_sp.reset(data_heap_up.release());
- return error;
- }
- }
- } else
- error.SetErrorString("file is empty");
- } else
- error.SetErrorToErrno();
- } else
- error.SetErrorString("invalid file handle");
- } else
- error.SetErrorString("invalid file handle");
-
- num_bytes = 0;
- data_buffer_sp.reset();
- return error;
-}
-
-Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) {
+Status NativeFile::Write(const void *buf, size_t &num_bytes, off_t &offset) {
Status error;
#if defined(MAX_WRITE_SIZE)
@@ -621,36 +722,15 @@ Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) {
return error;
}
-// Print some formatted output to the stream.
-size_t File::Printf(const char *format, ...) {
- va_list args;
- va_start(args, format);
- size_t result = PrintfVarArg(format, args);
- va_end(args);
- return result;
-}
-
-// Print some formatted output to the stream.
-size_t File::PrintfVarArg(const char *format, va_list args) {
- size_t result = 0;
- if (DescriptorIsValid()) {
- char *s = nullptr;
- result = vasprintf(&s, format, args);
- if (s != nullptr) {
- if (result > 0) {
- size_t s_len = result;
- Write(s, s_len);
- result = s_len;
- }
- free(s);
- }
- } else if (StreamIsValid()) {
- result = ::vfprintf(m_stream, format, args);
+size_t NativeFile::PrintfVarArg(const char *format, va_list args) {
+ if (StreamIsValid()) {
+ return ::vfprintf(m_stream, format, args);
+ } else {
+ return File::PrintfVarArg(format, args);
}
- return result;
}
-mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) {
+mode_t File::ConvertOpenOptionsForPOSIXOpen(OpenOptions open_options) {
mode_t mode = 0;
if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
mode |= O_RDWR;
@@ -674,49 +754,5 @@ mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) {
return mode;
}
-void File::CalculateInteractiveAndTerminal() {
- const int fd = GetDescriptor();
- if (fd >= 0) {
- m_is_interactive = eLazyBoolNo;
- m_is_real_terminal = eLazyBoolNo;
-#if defined(_WIN32)
- if (_isatty(fd)) {
- m_is_interactive = eLazyBoolYes;
- m_is_real_terminal = eLazyBoolYes;
-#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
- m_supports_colors = eLazyBoolYes;
-#endif
- }
-#else
- if (isatty(fd)) {
- m_is_interactive = eLazyBoolYes;
- struct winsize window_size;
- if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) {
- if (window_size.ws_col > 0) {
- m_is_real_terminal = eLazyBoolYes;
- if (llvm::sys::Process::FileDescriptorHasColors(fd))
- m_supports_colors = eLazyBoolYes;
- }
- }
- }
-#endif
- }
-}
-
-bool File::GetIsInteractive() {
- if (m_is_interactive == eLazyBoolCalculate)
- CalculateInteractiveAndTerminal();
- return m_is_interactive == eLazyBoolYes;
-}
-
-bool File::GetIsRealTerminal() {
- if (m_is_real_terminal == eLazyBoolCalculate)
- CalculateInteractiveAndTerminal();
- return m_is_real_terminal == eLazyBoolYes;
-}
-
-bool File::GetIsTerminalWithColors() {
- if (m_supports_colors == eLazyBoolCalculate)
- CalculateInteractiveAndTerminal();
- return m_supports_colors == eLazyBoolYes;
-}
+char File::ID = 0;
+char NativeFile::ID = 0;