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;
};
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
/// \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.
///
///
/// \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.
///
///
/// \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.
///
///
/// \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.
///
/// \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.
///
/// \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.
///
/// 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
}
%#endif
using namespace lldb_private;
- File file($1, false);
+ NativeFile file($1, false);
PythonFile py_file(file, mode);
$result = py_file.release();
if (!$result)
void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) {
LLDB_RECORD_METHOD(void, SBDebugger, SetInputFileHandle, (FILE *, bool), fh,
transfer_ownership);
- SetInputFile(std::make_shared<File>(fh, transfer_ownership));
+ SetInputFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
}
// Shouldn't really be settable after initialization as this could cause lots
// 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<File>(fh, true);
+ file_sp = std::make_shared<NativeFile>(fh, true);
}
}
void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) {
LLDB_RECORD_METHOD(void, SBDebugger, SetOutputFileHandle, (FILE *, bool), fh,
transfer_ownership);
- SetOutputFile(std::make_shared<File>(fh, transfer_ownership));
+ SetOutputFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
}
SBError SBDebugger::SetOutputFile(SBFile file) {
void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) {
LLDB_RECORD_METHOD(void, SBDebugger, SetErrorFileHandle, (FILE *, bool), fh,
transfer_ownership);
- SetErrorFile(std::make_shared<File>(fh, transfer_ownership));
+ SetErrorFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
}
SBError SBDebugger::SetErrorFile(SBFile file) {
SBFile::SBFile() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFile); }
SBFile::SBFile(FILE *file, bool transfer_ownership) {
- m_opaque_sp = std::make_shared<File>(file, transfer_ownership);
+ m_opaque_sp = std::make_shared<NativeFile>(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<File>(fd, options, transfer_owndership);
+ m_opaque_sp = std::make_shared<NativeFile>(fd, options, transfer_owndership);
}
SBError SBFile::Read(uint8_t *buf, size_t num_bytes, size_t *bytes_read) {
Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
: UserID(g_unique_id++),
Properties(std::make_shared<OptionValueProperties>()),
- m_input_file_sp(std::make_shared<File>(stdin, false)),
+ m_input_file_sp(std::make_shared<NativeFile>(stdin, false)),
m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)),
m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)),
m_input_recorder(nullptr),
// If there is nothing, use stdin
if (!in)
- in = std::make_shared<File>(stdin, false);
+ in = std::make_shared<NativeFile>(stdin, false);
}
// If no STDOUT has been set, then set it appropriately
if (!out) {
StreamFile::StreamFile(int fd, bool transfer_ownership) : Stream() {
m_file_sp =
- std::make_shared<File>(fd, File::eOpenOptionWrite, transfer_ownership);
+ std::make_shared<NativeFile>(fd, File::eOpenOptionWrite, transfer_ownership);
}
StreamFile::StreamFile(FILE *fh, bool transfer_ownership) : Stream() {
- m_file_sp = std::make_shared<File>(fh, transfer_ownership);
+ m_file_sp = std::make_shared<NativeFile>(fh, transfer_ownership);
}
StreamFile::StreamFile(const char *path) : Stream() {
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;
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);
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) {
error.SetErrorToErrno();
}
}
-
if (DescriptorIsValid() && m_own_descriptor) {
if (::close(m_descriptor) != 0)
error.SetErrorToErrno();
return error;
}
-FILE *File::TakeStreamAndClear() {
+FILE *NativeFile::TakeStreamAndClear() {
FILE *stream = GetStream();
m_stream = NULL;
m_descriptor = kInvalidDescriptor;
return stream;
}
-Status File::GetFileSpec(FileSpec &file_spec) const {
+Status NativeFile::GetFileSpec(FileSpec &file_spec) const {
Status error;
#ifdef F_GETPATH
if (IsValid()) {
}
}
#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())
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);
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);
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);
return result;
}
-Status File::Flush() {
+Status NativeFile::Flush() {
Status error;
if (StreamIsValid()) {
if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF)
return error;
}
-Status File::Sync() {
+Status NativeFile::Sync() {
Status error;
if (DescriptorIsValid()) {
#ifdef _WIN32
#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)
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)
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)
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)
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) {
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;
-}
return llvm::errorCodeToError(
std::error_code(errno, std::system_category()));
- auto file = std::make_unique<File>(descriptor, options, should_close_fd);
+ auto file = std::unique_ptr<File>(
+ new NativeFile(descriptor, options, should_close_fd));
assert(file->IsValid());
return std::move(file);
}
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<File>(fd, File::eOpenOptionWrite, owns_fd);
- m_read_sp = std::make_shared<File>(fd, File::eOpenOptionRead, false);
+ m_write_sp = std::make_shared<NativeFile>(fd, File::eOpenOptionWrite, owns_fd);
+ m_read_sp = std::make_shared<NativeFile>(fd, File::eOpenOptionRead, false);
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION |
LIBLLDB_LOG_OBJECT));
m_write_sp = m_read_sp;
} else {
m_read_sp =
- std::make_shared<File>(fd, File::eOpenOptionRead, false);
+ std::make_shared<NativeFile>(fd, File::eOpenOptionRead, false);
m_write_sp =
- std::make_shared<File>(fd, File::eOpenOptionWrite, false);
+ std::make_shared<NativeFile>(fd, File::eOpenOptionWrite, false);
}
m_uri = *addr;
return eConnectionStatusSuccess;
::fcntl(fd, F_SETFL, flags);
}
}
- m_read_sp = std::make_shared<File>(fd, File::eOpenOptionRead, true);
- m_write_sp = std::make_shared<File>(fd, File::eOpenOptionWrite, false);
+ m_read_sp = std::make_shared<NativeFile>(fd, File::eOpenOptionRead, true);
+ m_write_sp = std::make_shared<NativeFile>(fd, File::eOpenOptionWrite, false);
return eConnectionStatusSuccess;
}
#endif
}
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()) {
file_options |= File::eOpenOptionRead;
if ((oflag & O_RDWR) || (oflag & O_RDONLY))
file_options |= File::eOpenOptionWrite;
- file = std::make_shared<File>(created_fd, file_options, true);
+ file = std::make_shared<NativeFile>(created_fd, file_options, true);
[options setValue:[NSNumber numberWithInteger:created_fd] forKey:key];
return error; // Success
} else {
// 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);
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();
}
std::string buffer(count, 0);
- File file(fd, File::eOpenOptionRead, false);
+ NativeFile file(fd, File::eOpenOptionRead, false);
Status error = file.Read(static_cast<void *>(&buffer[0]), count, offset);
const ssize_t bytes_read = error.Success() ? count : -1;
const int save_errno = error.GetError();
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<const void *>(&buffer[0]), count, offset);
// File object knows about that.
PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
auto options = File::GetOptionsFromMode(py_mode.GetString());
- auto file = std::make_unique<File>(PyObject_AsFileDescriptor(m_py_obj),
- options, false);
+ auto file = std::unique_ptr<File>(
+ new NativeFile(PyObject_AsFileDescriptor(m_py_obj), options, false));
if (!file->IsValid())
return nullptr;
return file;
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;
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<bool> m_is_running{false};
};
FILE *stream = fdopen(fd, "r");
ASSERT_TRUE(stream);
- File file(stream, true);
+ NativeFile file(stream, true);
EXPECT_EQ(file.GetWaitableHandle(), fd);
}
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();