diff --git a/lldb/include/lldb/Host/File.h b/lldb/include/lldb/Host/File.h --- a/lldb/include/lldb/Host/File.h +++ b/lldb/include/lldb/Host/File.h @@ -22,10 +22,12 @@ namespace lldb_private { /// \class File File.h "lldb/Host/File.h" -/// A file class. +/// An abstract base class for files. /// -/// A file class that divides abstracts the LLDB core from host file -/// functionality. +/// Files will often be NativeFiles, which provides a wrapper +/// around host OS file functionality. But it +/// is also possible to subclass file to provide objects that have file +/// or stream functionality but are not backed by any host OS file. class File : public IOObject { public: static int kInvalidDescriptor; @@ -49,77 +51,80 @@ }; static mode_t ConvertOpenOptionsForPOSIXOpen(uint32_t open_options); + static uint32_t GetOptionsFromMode(llvm::StringRef mode); + static bool DescriptorIsValid(int descriptor) { return descriptor >= 0; }; File() - : IOObject(eFDTypeFile), m_descriptor(kInvalidDescriptor), - m_own_descriptor(false), m_stream(kInvalidStream), m_options(0), - m_own_stream(false), m_is_interactive(eLazyBoolCalculate), + : IOObject(eFDTypeFile), m_is_interactive(eLazyBoolCalculate), m_is_real_terminal(eLazyBoolCalculate), - m_supports_colors(eLazyBoolCalculate) {} - - File(FILE *fh, bool transfer_ownership) - : IOObject(eFDTypeFile), m_descriptor(kInvalidDescriptor), - m_own_descriptor(false), m_stream(fh), m_options(0), - m_own_stream(transfer_ownership), m_is_interactive(eLazyBoolCalculate), - m_is_real_terminal(eLazyBoolCalculate), - m_supports_colors(eLazyBoolCalculate) {} - - File(int fd, uint32_t options, bool transfer_ownership) - : IOObject(eFDTypeFile), m_descriptor(fd), - m_own_descriptor(transfer_ownership), m_stream(kInvalidStream), - m_options(options), m_own_stream(false), - m_is_interactive(eLazyBoolCalculate), - m_is_real_terminal(eLazyBoolCalculate) {} + m_supports_colors(eLazyBoolCalculate){}; - /// Destructor. + /// Read bytes from a file from the current file position into buf. /// - /// The destructor is virtual in case this class is subclassed. - ~File() override; - - bool IsValid() const override { - return DescriptorIsValid() || StreamIsValid(); - } - - /// Convert to pointer operator. + /// NOTE: This function is NOT thread safe. Use the read function + /// that takes an "off_t &offset" to ensure correct operation in multi- + /// threaded environments. /// - /// This allows code to check a File object to see if it contains anything - /// valid using code such as: + /// \param[out] buf /// - /// \code - /// File file(...); - /// if (file) - /// { ... - /// \endcode + /// \param[in,out] num_bytes. + /// Pass in the size of buf. Read will pass out the number + /// of bytes read. Zero bytes read with no error indicates + /// EOF. /// /// \return - /// A pointer to this object if either the directory or filename - /// is valid, nullptr otherwise. - operator bool() const { return DescriptorIsValid() || StreamIsValid(); } + /// success, ENOTSUP, or another error. + Status Read(void *buf, size_t &num_bytes) override; - /// Logical NOT operator. + /// Write bytes from buf to a file at the current file position. /// - /// This allows code to check a File object to see if it is invalid using - /// code such as: + /// NOTE: This function is NOT thread safe. Use the write function + /// that takes an "off_t &offset" to ensure correct operation in multi- + /// threaded environments. /// - /// \code - /// File file(...); - /// if (!file) - /// { ... - /// \endcode + /// \param[in] buf + /// + /// \param[in,out] num_bytes + /// Pass in the size of buf. Write will pass out the number + /// of bytes written. Write will attempt write the full number + /// of bytes and will not return early except on error. /// /// \return - /// Returns \b true if the object has an empty directory and - /// filename, \b false otherwise. - bool operator!() const { return !DescriptorIsValid() && !StreamIsValid(); } + /// success, ENOTSUP, or another error. + Status Write(const void *buf, size_t &num_bytes) override; - /// Get the file spec for this file. + /// IsValid /// /// \return - /// A reference to the file specification object. - Status GetFileSpec(FileSpec &file_spec) const; + /// true iff the file is valid. + bool IsValid() const override; + /// Flush any buffers and release any resources owned by the file. + /// After Close() the file will be invalid. + /// + /// \return + /// success or an error. Status Close() override; + /// Get a handle that can be used for OS polling interfaces, such + /// as WaitForMultipleObjects, select, or epoll. This may return + /// IOObject::kInvalidHandleValue if none is available. This will + /// generally be the same as the file descriptor, this function + /// is not interchangeable with GetDescriptor(). A WaitableHandle + /// must only be used for polling, not actual I/O. + /// + /// \return + /// a valid handle or IOObject::kInvalidHandleValue + WaitableHandle GetWaitableHandle() override; + + /// Get the file specification for this file, if possible. + /// + /// \param[out] file_spec + /// the file specification. + /// \return + /// ENOTSUP, success, or another error. + virtual Status GetFileSpec(FileSpec &file_spec) const; + /// DEPRECATED! Extract the underlying FILE* and reset this File without closing it. /// /// This is only here to support legacy SB interfaces that need to convert scripting @@ -132,52 +137,26 @@ /// \return /// The underlying FILE* stream from this File, if one exists and can be extracted, /// nullptr otherwise. - FILE *TakeStreamAndClear(); - - int GetDescriptor() const; - - static uint32_t GetOptionsFromMode(llvm::StringRef mode); + virtual FILE *TakeStreamAndClear(); - WaitableHandle GetWaitableHandle() override; - - FILE *GetStream(); - - /// Read bytes from a file from the current file position. - /// - /// NOTE: This function is NOT thread safe. Use the read function - /// that takes an "off_t &offset" to ensure correct operation in multi- - /// threaded environments. - /// - /// \param[in] buf - /// A buffer where to put the bytes that are read. - /// - /// \param[in,out] num_bytes - /// The number of bytes to read form the current file position - /// which gets modified with the number of bytes that were read. + /// Get underlying OS file descriptor for this file, or kInvalidDescriptor. + /// If the descriptor is valid, then it may be used directly for I/O + /// However, the File may also perform it's own buffering, so avoid using + /// this if it is not necessary, or use Flush() appropriately. /// /// \return - /// An error object that indicates success or the reason for - /// failure. - Status Read(void *buf, size_t &num_bytes) override; + /// a valid file descriptor for this file or kInvalidDescriptor + virtual int GetDescriptor() const; - /// Write bytes to a file at the current file position. - /// - /// NOTE: This function is NOT thread safe. Use the write function - /// that takes an "off_t &offset" to ensure correct operation in multi- - /// threaded environments. - /// - /// \param[in] buf - /// A buffer where to put the bytes that are read. + /// Get the underlying libc stream for this file, or NULL. /// - /// \param[in,out] num_bytes - /// The number of bytes to write to the current file position - /// which gets modified with the number of bytes that were - /// written. + /// Not all valid files will have a FILE* stream. This should only be + /// used if absolutely necessary, such as to interact with 3rd party + /// libraries that need FILE* streams. /// /// \return - /// An error object that indicates success or the reason for - /// failure. - Status Write(const void *buf, size_t &num_bytes) override; + /// a valid stream or NULL; + virtual FILE *GetStream(); /// Seek to an offset relative to the beginning of the file. /// @@ -197,7 +176,7 @@ /// /// \return /// The resulting seek offset, or -1 on error. - off_t SeekFromStart(off_t offset, Status *error_ptr = nullptr); + virtual off_t SeekFromStart(off_t offset, Status *error_ptr = nullptr); /// Seek to an offset relative to the current file position. /// @@ -217,7 +196,7 @@ /// /// \return /// The resulting seek offset, or -1 on error. - off_t SeekFromCurrent(off_t offset, Status *error_ptr = nullptr); + virtual off_t SeekFromCurrent(off_t offset, Status *error_ptr = nullptr); /// Seek to an offset relative to the end of the file. /// @@ -238,7 +217,7 @@ /// /// \return /// The resulting seek offset, or -1 on error. - off_t SeekFromEnd(off_t offset, Status *error_ptr = nullptr); + virtual off_t SeekFromEnd(off_t offset, Status *error_ptr = nullptr); /// Read bytes from a file from the specified file offset. /// @@ -261,7 +240,7 @@ /// \return /// An error object that indicates success or the reason for /// failure. - Status Read(void *dst, size_t &num_bytes, off_t &offset); + virtual Status Read(void *dst, size_t &num_bytes, off_t &offset); /// Write bytes to a file at the specified file offset. /// @@ -286,21 +265,48 @@ /// \return /// An error object that indicates success or the reason for /// failure. - Status Write(const void *src, size_t &num_bytes, off_t &offset); + virtual Status Write(const void *src, size_t &num_bytes, off_t &offset); /// Flush the current stream /// /// \return /// An error object that indicates success or the reason for /// failure. - Status Flush(); + virtual Status Flush(); /// Sync to disk. /// /// \return /// An error object that indicates success or the reason for /// failure. - Status Sync(); + virtual Status Sync(); + + /// Output printf formatted output to the stream. + /// + /// NOTE: this is not virtual, because it just calls the va_list + /// version of the function. + /// + /// Print some formatted output to the stream. + /// + /// \param[in] format + /// A printf style format string. + /// + /// \param[in] ... + /// Variable arguments that are needed for the printf style + /// format string \a format. + size_t Printf(const char *format, ...) __attribute__((format(printf, 2, 3))); + + /// Output printf formatted output to the stream. + /// + /// Print some formatted output to the stream. + /// + /// \param[in] format + /// A printf style format string. + /// + /// \param[in] args + /// Variable arguments that are needed for the printf style + /// format string \a format. + virtual size_t PrintfVarArg(const char *format, va_list args); /// Get the permissions for a this file. /// @@ -327,44 +333,80 @@ /// a non-zero width and height, false otherwise. bool GetIsRealTerminal(); + /// Return true if this file is a terminal which supports colors. + /// + /// \return + /// True iff this is a terminal and it supports colors. bool GetIsTerminalWithColors(); - /// Output printf formatted output to the stream. - /// - /// Print some formatted output to the stream. - /// - /// \param[in] format - /// A printf style format string. - /// - /// \param[in] ... - /// Variable arguments that are needed for the printf style - /// format string \a format. - size_t Printf(const char *format, ...) __attribute__((format(printf, 2, 3))); + operator bool() const { return IsValid(); }; - size_t PrintfVarArg(const char *format, va_list args); - - static bool DescriptorIsValid(int descriptor) { return descriptor >= 0; }; + bool operator!() const { return !IsValid(); }; protected: - bool DescriptorIsValid() const { return DescriptorIsValid(m_descriptor); } - - bool StreamIsValid() const { return m_stream != kInvalidStream; } + LazyBool m_is_interactive; + LazyBool m_is_real_terminal; + LazyBool m_supports_colors; void CalculateInteractiveAndTerminal(); +private: + DISALLOW_COPY_AND_ASSIGN(File); +}; + +class NativeFile : public File { +public: + NativeFile() + : m_descriptor(kInvalidDescriptor), m_own_descriptor(false), + m_stream(kInvalidStream), m_options(0), m_own_stream(false) {} + + NativeFile(FILE *fh, bool transfer_ownership) + : m_descriptor(kInvalidDescriptor), m_own_descriptor(false), m_stream(fh), + m_options(0), m_own_stream(transfer_ownership) {} + + NativeFile(int fd, uint32_t options, bool transfer_ownership) + : m_descriptor(fd), m_own_descriptor(transfer_ownership), + m_stream(kInvalidStream), m_options(options), m_own_stream(false) {} + + ~NativeFile() override { Close(); } + + bool IsValid() const override { + return DescriptorIsValid() || StreamIsValid(); + } + + Status Read(void *buf, size_t &num_bytes) override; + Status Write(const void *buf, size_t &num_bytes) override; + Status Close() override; + WaitableHandle GetWaitableHandle() override; + Status GetFileSpec(FileSpec &file_spec) const override; + FILE *TakeStreamAndClear() override; + int GetDescriptor() const override; + FILE *GetStream() override; + off_t SeekFromStart(off_t offset, Status *error_ptr = nullptr) override; + off_t SeekFromCurrent(off_t offset, Status *error_ptr = nullptr) override; + off_t SeekFromEnd(off_t offset, Status *error_ptr = nullptr) override; + Status Read(void *dst, size_t &num_bytes, off_t &offset) override; + Status Write(const void *src, size_t &num_bytes, off_t &offset) override; + Status Flush() override; + Status Sync() override; + size_t PrintfVarArg(const char *format, va_list args) override; + +protected: + bool DescriptorIsValid() const { + return File::DescriptorIsValid(m_descriptor); + } + bool StreamIsValid() const { return m_stream != kInvalidStream; } + // Member variables int m_descriptor; bool m_own_descriptor; FILE *m_stream; uint32_t m_options; bool m_own_stream; - LazyBool m_is_interactive; - LazyBool m_is_real_terminal; - LazyBool m_supports_colors; std::mutex offset_access_mutex; private: - DISALLOW_COPY_AND_ASSIGN(File); + DISALLOW_COPY_AND_ASSIGN(NativeFile); }; } // namespace lldb_private diff --git a/lldb/scripts/Python/python-typemaps.swig b/lldb/scripts/Python/python-typemaps.swig --- a/lldb/scripts/Python/python-typemaps.swig +++ b/lldb/scripts/Python/python-typemaps.swig @@ -422,7 +422,7 @@ } %#endif using namespace lldb_private; - File file($1, false); + NativeFile file($1, false); PythonFile py_file(file, mode); $result = py_file.release(); if (!$result) diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -289,7 +289,7 @@ void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) { LLDB_RECORD_METHOD(void, SBDebugger, SetInputFileHandle, (FILE *, bool), fh, transfer_ownership); - SetInputFile(std::make_shared(fh, transfer_ownership)); + SetInputFile((FileSP)std::make_shared(fh, transfer_ownership)); } // Shouldn't really be settable after initialization as this could cause lots @@ -319,7 +319,7 @@ // FIXME Jonas Devlieghere: shouldn't this error be propagated out to the // reproducer somehow if fh is NULL? if (fh) { - file_sp = std::make_shared(fh, true); + file_sp = std::make_shared(fh, true); } } @@ -335,7 +335,7 @@ void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) { LLDB_RECORD_METHOD(void, SBDebugger, SetOutputFileHandle, (FILE *, bool), fh, transfer_ownership); - SetOutputFile(std::make_shared(fh, transfer_ownership)); + SetOutputFile((FileSP)std::make_shared(fh, transfer_ownership)); } SBError SBDebugger::SetOutputFile(SBFile file) { @@ -356,7 +356,7 @@ void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) { LLDB_RECORD_METHOD(void, SBDebugger, SetErrorFileHandle, (FILE *, bool), fh, transfer_ownership); - SetErrorFile(std::make_shared(fh, transfer_ownership)); + SetErrorFile((FileSP)std::make_shared(fh, transfer_ownership)); } SBError SBDebugger::SetErrorFile(SBFile file) { diff --git a/lldb/source/API/SBFile.cpp b/lldb/source/API/SBFile.cpp --- a/lldb/source/API/SBFile.cpp +++ b/lldb/source/API/SBFile.cpp @@ -21,14 +21,14 @@ SBFile::SBFile() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFile); } SBFile::SBFile(FILE *file, bool transfer_ownership) { - m_opaque_sp = std::make_shared(file, transfer_ownership); + m_opaque_sp = std::make_shared(file, transfer_ownership); } SBFile::SBFile(int fd, const char *mode, bool transfer_owndership) { LLDB_RECORD_CONSTRUCTOR(SBFile, (int, const char *, bool), fd, mode, transfer_owndership); auto options = File::GetOptionsFromMode(mode); - m_opaque_sp = std::make_shared(fd, options, transfer_owndership); + m_opaque_sp = std::make_shared(fd, options, transfer_owndership); } SBError SBFile::Read(uint8_t *buf, size_t num_bytes, size_t *bytes_read) { diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -698,7 +698,7 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) : UserID(g_unique_id++), Properties(std::make_shared()), - m_input_file_sp(std::make_shared(stdin, false)), + m_input_file_sp(std::make_shared(stdin, false)), m_output_stream_sp(std::make_shared(stdout, false)), m_error_stream_sp(std::make_shared(stderr, false)), m_input_recorder(nullptr), @@ -981,7 +981,7 @@ // If there is nothing, use stdin if (!in) - in = std::make_shared(stdin, false); + in = std::make_shared(stdin, false); } // If no STDOUT has been set, then set it appropriately if (!out) { diff --git a/lldb/source/Core/StreamFile.cpp b/lldb/source/Core/StreamFile.cpp --- a/lldb/source/Core/StreamFile.cpp +++ b/lldb/source/Core/StreamFile.cpp @@ -25,11 +25,11 @@ StreamFile::StreamFile(int fd, bool transfer_ownership) : Stream() { m_file_sp = - std::make_shared(fd, File::eOpenOptionWrite, transfer_ownership); + std::make_shared(fd, File::eOpenOptionWrite, transfer_ownership); } StreamFile::StreamFile(FILE *fh, bool transfer_ownership) : Stream() { - m_file_sp = std::make_shared(fh, transfer_ownership); + m_file_sp = std::make_shared(fh, transfer_ownership); } StreamFile::StreamFile(const char *path) : Stream() { diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp --- a/lldb/source/Host/common/File.cpp +++ b/lldb/source/Host/common/File.cpp @@ -85,9 +85,152 @@ 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; +} + +Status File::GetFileSpec(FileSpec &file_spec) const { + file_spec.Clear(); + return std::error_code(ENOTSUP, std::system_category()); +} + +FILE *File::TakeStreamAndClear() { return nullptr; } + +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; +} + +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); +} -int File::GetDescriptor() const { +int NativeFile::GetDescriptor() const { if (DescriptorIsValid()) return m_descriptor; @@ -105,9 +248,11 @@ return kInvalidDescriptor; } -IOObject::WaitableHandle File::GetWaitableHandle() { return GetDescriptor(); } +IOObject::WaitableHandle NativeFile::GetWaitableHandle() { + return GetDescriptor(); +} -FILE *File::GetStream() { +FILE *NativeFile::GetStream() { if (!StreamIsValid()) { if (DescriptorIsValid()) { const char *mode = GetStreamOpenModeFromOptions(m_options); @@ -139,23 +284,7 @@ return m_stream; } -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()) { if (m_own_stream) { @@ -166,7 +295,6 @@ error.SetErrorToErrno(); } } - if (DescriptorIsValid() && m_own_descriptor) { if (::close(m_descriptor) != 0) error.SetErrorToErrno(); @@ -181,7 +309,7 @@ return error; } -FILE *File::TakeStreamAndClear() { +FILE *NativeFile::TakeStreamAndClear() { FILE *stream = GetStream(); m_stream = NULL; m_descriptor = kInvalidDescriptor; @@ -193,7 +321,7 @@ return stream; } -Status File::GetFileSpec(FileSpec &file_spec) const { +Status NativeFile::GetFileSpec(FileSpec &file_spec) const { Status error; #ifdef F_GETPATH if (IsValid()) { @@ -220,7 +348,8 @@ } } #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()) @@ -228,7 +357,7 @@ 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); @@ -254,7 +383,7 @@ 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); @@ -280,7 +409,7 @@ 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); @@ -306,7 +435,7 @@ return result; } -Status File::Flush() { +Status NativeFile::Flush() { Status error; if (StreamIsValid()) { if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF) @@ -317,7 +446,7 @@ return error; } -Status File::Sync() { +Status NativeFile::Sync() { Status error; if (DescriptorIsValid()) { #ifdef _WIN32 @@ -340,7 +469,7 @@ #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) @@ -399,7 +528,7 @@ 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) @@ -461,7 +590,7 @@ 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) @@ -521,7 +650,7 @@ 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) @@ -585,33 +714,12 @@ 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) { @@ -638,49 +746,3 @@ 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; -} diff --git a/lldb/source/Host/common/FileSystem.cpp b/lldb/source/Host/common/FileSystem.cpp --- a/lldb/source/Host/common/FileSystem.cpp +++ b/lldb/source/Host/common/FileSystem.cpp @@ -435,7 +435,8 @@ return llvm::errorCodeToError( std::error_code(errno, std::system_category())); - auto file = std::make_unique(descriptor, options, should_close_fd); + auto file = std::unique_ptr( + new NativeFile(descriptor, options, should_close_fd)); assert(file->IsValid()); return std::move(file); } diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -86,8 +86,8 @@ ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd) : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), m_waiting_for_accept(false), m_child_processes_inherit(false) { - m_write_sp = std::make_shared(fd, File::eOpenOptionWrite, owns_fd); - m_read_sp = std::make_shared(fd, File::eOpenOptionRead, false); + m_write_sp = std::make_shared(fd, File::eOpenOptionWrite, owns_fd); + m_read_sp = std::make_shared(fd, File::eOpenOptionRead, false); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); @@ -219,9 +219,9 @@ m_write_sp = m_read_sp; } else { m_read_sp = - std::make_shared(fd, File::eOpenOptionRead, false); + std::make_shared(fd, File::eOpenOptionRead, false); m_write_sp = - std::make_shared(fd, File::eOpenOptionWrite, false); + std::make_shared(fd, File::eOpenOptionWrite, false); } m_uri = *addr; return eConnectionStatusSuccess; @@ -270,8 +270,8 @@ ::fcntl(fd, F_SETFL, flags); } } - m_read_sp = std::make_shared(fd, File::eOpenOptionRead, true); - m_write_sp = std::make_shared(fd, File::eOpenOptionWrite, false); + m_read_sp = std::make_shared(fd, File::eOpenOptionRead, true); + m_write_sp = std::make_shared(fd, File::eOpenOptionWrite, false); return eConnectionStatusSuccess; } #endif diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -896,7 +896,7 @@ } if (temp_fd != -1) { - lldb_private::File file(temp_fd, File::eOpenOptionWrite, true); + lldb_private::NativeFile file(temp_fd, File::eOpenOptionWrite, true); const size_t expr_text_len = strlen(expr_text); size_t bytes_written = expr_text_len; if (file.Write(expr_text, bytes_written).Success()) { diff --git a/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm b/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm --- a/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm +++ b/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm @@ -434,7 +434,7 @@ file_options |= File::eOpenOptionRead; if ((oflag & O_RDWR) || (oflag & O_RDONLY)) file_options |= File::eOpenOptionWrite; - file = std::make_shared(created_fd, file_options, true); + file = std::make_shared(created_fd, file_options, true); [options setValue:[NSNumber numberWithInteger:created_fd] forKey:key]; return error; // Success } else { diff --git a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp --- a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp +++ b/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp @@ -881,8 +881,8 @@ // TODO make PipePOSIX derive from IOObject. This is goofy here. const bool transfer_ownership = false; - auto io_sp = IOObjectSP( - new File(m_waitpid_pipe.GetReadFileDescriptor(), transfer_ownership)); + auto io_sp = IOObjectSP(new NativeFile(m_waitpid_pipe.GetReadFileDescriptor(), + transfer_ownership)); m_waitpid_reader_handle = main_loop.RegisterReadObject( io_sp, [this](MainLoopBase &) { HandleWaitpidResult(); }, error); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -546,7 +546,7 @@ int err = -1; int save_errno = 0; if (fd >= 0) { - File file(fd, 0, true); + NativeFile file(fd, 0, true); Status error = file.Close(); err = 0; save_errno = error.GetError(); @@ -577,7 +577,7 @@ } std::string buffer(count, 0); - File file(fd, File::eOpenOptionRead, false); + NativeFile file(fd, File::eOpenOptionRead, false); Status error = file.Read(static_cast(&buffer[0]), count, offset); const ssize_t bytes_read = error.Success() ? count : -1; const int save_errno = error.GetError(); @@ -609,7 +609,7 @@ if (packet.GetChar() == ',') { std::string buffer; if (packet.GetEscapedBinaryData(buffer)) { - File file(fd, File::eOpenOptionWrite, false); + NativeFile file(fd, File::eOpenOptionWrite, false); size_t count = buffer.size(); Status error = file.Write(static_cast(&buffer[0]), count, offset); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -1024,8 +1024,8 @@ // File object knows about that. PythonString py_mode = GetAttributeValue("mode").AsType(); auto options = File::GetOptionsFromMode(py_mode.GetString()); - auto file = std::make_unique(PyObject_AsFileDescriptor(m_py_obj), - options, false); + auto file = std::unique_ptr( + new NativeFile(PyObject_AsFileDescriptor(m_py_obj), options, false)); if (!file->IsValid()) return nullptr; return file; diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -719,9 +719,9 @@ PythonDictionary &sys_module_dict = GetSysModuleDictionary(); if (sys_module_dict.IsValid()) { - File in_file(in, false); - File out_file(out, false); - File err_file(err, false); + NativeFile in_file(in, false); + NativeFile out_file(out, false); + NativeFile err_file(err, false); lldb::FileSP in_sp; lldb::StreamFileSP out_sp; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -4422,9 +4422,9 @@ protected: Process *m_process; - File m_read_file; // Read from this file (usually actual STDIN for LLDB - File m_write_file; // Write to this file (usually the master pty for getting - // io to debuggee) + NativeFile m_read_file; // Read from this file (usually actual STDIN for LLDB + NativeFile m_write_file; // Write to this file (usually the master pty for + // getting io to debuggee) Pipe m_pipe; std::atomic m_is_running{false}; }; diff --git a/lldb/unittests/Host/FileTest.cpp b/lldb/unittests/Host/FileTest.cpp --- a/lldb/unittests/Host/FileTest.cpp +++ b/lldb/unittests/Host/FileTest.cpp @@ -31,7 +31,7 @@ FILE *stream = fdopen(fd, "r"); ASSERT_TRUE(stream); - File file(stream, true); + NativeFile file(stream, true); EXPECT_EQ(file.GetWaitableHandle(), fd); } @@ -46,7 +46,7 @@ llvm::FileRemover remover(name); ASSERT_GE(fd, 0); - File file(fd, File::eOpenOptionWrite, true); + NativeFile file(fd, File::eOpenOptionWrite, true); ASSERT_TRUE(file.IsValid()); FILE *stream = file.GetStream();