27#include "lldb/Host/Config.h"
34#include "llvm/ADT/StringExtras.h"
35#include "llvm/Support/ConvertUTF.h"
36#include "llvm/Support/Errno.h"
37#include "llvm/Support/FileSystem.h"
38#include "llvm/Support/Process.h"
39#include "llvm/Support/raw_ostream.h"
76 return llvm::createStringError(
77 llvm::inconvertibleErrorCode(),
78 "invalid options, cannot convert to mode string");
83 llvm::StringSwitch<OpenOptions>(mode)
98 return llvm::createStringError(
99 llvm::inconvertibleErrorCode(),
100 "invalid mode, cannot convert to File::OpenOptions");
107 return std::error_code(ENOTSUP, std::system_category());
110 return std::error_code(ENOTSUP, std::system_category());
123 return std::error_code(ENOTSUP, std::system_category());
132 *error_ptr = std::error_code(ENOTSUP, std::system_category());
138 *error_ptr = std::error_code(ENOTSUP, std::system_category());
144 *error_ptr = std::error_code(ENOTSUP, std::system_category());
149 return std::error_code(ENOTSUP, std::system_category());
153 return std::error_code(ENOTSUP, std::system_category());
174#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
181 struct winsize window_size;
182 if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) {
183 if (window_size.ws_col > 0) {
185 if (llvm::sys::Process::FileDescriptorHasColors(fd))
213 va_start(args, format);
220 llvm::SmallString<0> s;
222 size_t written = s.size();
223 Write(s.data(), written);
230 return llvm::createStringError(
231 llvm::inconvertibleErrorCode(),
232 "GetOptions() not implemented for this File class");
238 error = std::error_code(ENOTSUP, std::system_category());
241 struct stat file_stats;
242 if (::fstat(fd, &file_stats) == -1) {
259 HANDLE h = INVALID_HANDLE_VALUE;
261 h = ::GetStdHandle(STD_INPUT_HANDLE);
262 else if (fh == stdout)
263 h = ::GetStdHandle(STD_OUTPUT_HANDLE);
264 else if (fh == stderr)
265 h = ::GetStdHandle(STD_ERROR_HANDLE);
267 h != INVALID_HANDLE_VALUE && ::GetFileType(h) == FILE_TYPE_CHAR;
274 int mode = fcntl(fd, F_GETFL);
281 (required_mode == O_RDWR && mode == O_RDWR) ||
282 (required_mode == O_RDONLY && (mode == O_RDWR || mode == O_RDONLY) ||
283 (required_mode == O_WRONLY &&
284 (mode == O_RDWR || mode == O_WRONLY))) &&
285 "invalid file access mode");
300 HANDLE h = INVALID_HANDLE_VALUE;
301 if (fd == STDIN_FILENO)
302 h = ::GetStdHandle(STD_INPUT_HANDLE);
303 else if (fd == STDOUT_FILENO)
304 h = ::GetStdHandle(STD_OUTPUT_HANDLE);
305 else if (fd == STDERR_FILENO)
306 h = ::GetStdHandle(STD_ERROR_HANDLE);
308 h != INVALID_HANDLE_VALUE && ::GetFileType(h) == FILE_TYPE_CHAR;
354 llvm::consumeError(mode.takeError());
428 file_spec.
SetFile(path, FileSpec::Style::native);
432#elif defined(__linux__)
435 if (::snprintf(proc,
sizeof(proc),
"/proc/self/fd/%d",
GetDescriptor()) < 0)
439 if ((len = ::readlink(proc, path,
sizeof(path) - 1)) == -1)
443 file_spec.
SetFile(path, FileSpec::Style::native);
448 "NativeFile::GetFileSpec is not supported on this platform");
471 result = ::fseek(
m_stream, offset, SEEK_SET);
502 result = ::fseek(
m_stream, offset, SEEK_CUR);
533 result = ::fseek(
m_stream, offset, SEEK_END);
552 if (llvm::sys::RetryAfterSignal(EOF, ::fflush,
m_stream) == EOF)
559 if (!descriptor_guard)
573 if (llvm::sys::RetryAfterSignal(-1, ::fsync,
m_descriptor) == -1)
582#if defined(__APPLE__)
584#define MAX_READ_SIZE INT_MAX
585#define MAX_WRITE_SIZE INT_MAX
593 return Status(std::make_error_code(std::errc::bad_file_descriptor));
595#if defined(MAX_READ_SIZE)
596 if (num_bytes > MAX_READ_SIZE) {
597 uint8_t *p = (uint8_t *)buf;
598 size_t bytes_left = num_bytes;
602 while (bytes_left > 0) {
603 size_t curr_num_bytes;
604 if (bytes_left > MAX_READ_SIZE)
605 curr_num_bytes = MAX_READ_SIZE;
607 curr_num_bytes = bytes_left;
609 error =
Read(p + num_bytes, curr_num_bytes);
612 num_bytes += curr_num_bytes;
613 if (bytes_left < curr_num_bytes)
616 bytes_left -= curr_num_bytes;
625 ssize_t bytes_read = -1;
628 llvm::sys::RetryAfterSignal(-1, ::read,
m_descriptor, buf, num_bytes);
629 if (bytes_read == -1) {
633 num_bytes = bytes_read;
638 bytes_read = ::fread(buf, 1, num_bytes,
m_stream);
640 if (bytes_read == 0) {
647 num_bytes = bytes_read;
661 return Status(std::make_error_code(std::errc::bad_file_descriptor));
663#if defined(MAX_WRITE_SIZE)
664 if (num_bytes > MAX_WRITE_SIZE) {
665 const uint8_t *p = (
const uint8_t *)buf;
666 size_t bytes_left = num_bytes;
670 while (bytes_left > 0) {
671 size_t curr_num_bytes;
672 if (bytes_left > MAX_WRITE_SIZE)
673 curr_num_bytes = MAX_WRITE_SIZE;
675 curr_num_bytes = bytes_left;
680 num_bytes += curr_num_bytes;
681 if (bytes_left < curr_num_bytes)
684 bytes_left -= curr_num_bytes;
693 ssize_t bytes_written = -1;
696 llvm::sys::RetryAfterSignal(-1, ::write,
m_descriptor, buf, num_bytes);
697 if (bytes_written == -1) {
701 num_bytes = bytes_written;
708 llvm::raw_fd_ostream(_fileno(
m_stream),
false)
709 .write((
const char *)buf, num_bytes);
713 bytes_written = ::fwrite(buf, 1, num_bytes,
m_stream);
715 if (bytes_written == 0) {
722 num_bytes = bytes_written;
734#if defined(MAX_READ_SIZE)
735 if (num_bytes > MAX_READ_SIZE) {
736 uint8_t *p = (uint8_t *)buf;
737 size_t bytes_left = num_bytes;
741 while (bytes_left > 0) {
742 size_t curr_num_bytes;
743 if (bytes_left > MAX_READ_SIZE)
744 curr_num_bytes = MAX_READ_SIZE;
746 curr_num_bytes = bytes_left;
748 error =
Read(p + num_bytes, curr_num_bytes, offset);
751 num_bytes += curr_num_bytes;
752 if (bytes_left < curr_num_bytes)
755 bytes_left -= curr_num_bytes;
768 llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset);
769 if (bytes_read < 0) {
773 offset += bytes_read;
774 num_bytes = bytes_read;
794#if defined(MAX_WRITE_SIZE)
795 if (num_bytes > MAX_WRITE_SIZE) {
796 const uint8_t *p = (
const uint8_t *)buf;
797 size_t bytes_left = num_bytes;
801 while (bytes_left > 0) {
802 size_t curr_num_bytes;
803 if (bytes_left > MAX_WRITE_SIZE)
804 curr_num_bytes = MAX_WRITE_SIZE;
806 curr_num_bytes = bytes_left;
808 error =
Write(p + num_bytes, curr_num_bytes, offset);
811 num_bytes += curr_num_bytes;
812 if (bytes_left < curr_num_bytes)
815 bytes_left -= curr_num_bytes;
827 ssize_t bytes_written = llvm::sys::RetryAfterSignal(
829 if (bytes_written < 0) {
833 offset += bytes_written;
834 num_bytes = bytes_written;
857 return ::vfprintf(
m_stream, format, args);
885 mode |= O_CREAT | O_EXCL;
892llvm::Expected<SerialPort::Options>
895 for (llvm::StringRef x : llvm::split(urlqs,
'&')) {
896 if (x.consume_front(
"baud=")) {
897 unsigned int baud_rate;
898 if (!llvm::to_integer(x, baud_rate, 10))
899 return llvm::createStringError(llvm::inconvertibleErrorCode(),
900 "Invalid baud rate: %s",
902 serial_options.
BaudRate = baud_rate;
903 }
else if (x.consume_front(
"parity=")) {
905 llvm::StringSwitch<std::optional<Terminal::Parity>>(x)
911 .Default(std::nullopt);
912 if (!serial_options.
Parity)
913 return llvm::createStringError(
914 llvm::inconvertibleErrorCode(),
915 "Invalid parity (must be no, even, odd, mark or space): %s",
917 }
else if (x.consume_front(
"parity-check=")) {
919 llvm::StringSwitch<std::optional<Terminal::ParityCheck>>(x)
926 .Default(std::nullopt);
928 return llvm::createStringError(
929 llvm::inconvertibleErrorCode(),
930 "Invalid parity-check (must be no, replace, ignore or mark): %s",
932 }
else if (x.consume_front(
"stop-bits=")) {
933 unsigned int stop_bits;
934 if (!llvm::to_integer(x, stop_bits, 10) ||
935 (stop_bits != 1 && stop_bits != 2))
936 return llvm::createStringError(
937 llvm::inconvertibleErrorCode(),
938 "Invalid stop bit number (must be 1 or 2): %s", x.str().c_str());
939 serial_options.
StopBits = stop_bits;
941 return llvm::createStringError(llvm::inconvertibleErrorCode(),
942 "Unknown parameter: %s", x.str().c_str());
944 return serial_options;
947llvm::Expected<std::unique_ptr<SerialPort>>
949 bool transfer_ownership) {
950 std::unique_ptr<SerialPort> out{
951 new SerialPort(fd, options, serial_options, transfer_ownership)};
953 if (!out->GetIsInteractive())
954 return llvm::createStringError(llvm::inconvertibleErrorCode(),
955 "the specified file is not a teletype");
959 return std::move(
error);
962 return std::move(
error);
964 if (serial_options.
Parity) {
966 return std::move(
error);
970 return std::move(
error);
974 return std::move(
error);
977 return std::move(out);
982 bool transfer_ownership)
static llvm::raw_ostream & error(Stream &strm)
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
void Clear()
Clears the object state.
virtual llvm::Expected< OpenOptions > GetOptions() const
Return the OpenOptions for this file.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
WaitableHandle GetWaitableHandle() override
Get a handle that can be used for OS polling interfaces, such as WaitForMultipleObjects,...
bool GetIsRealTerminal()
Return true if this file from a real terminal.
static constexpr OpenOptions OpenOptionsModeMask
virtual FILE * GetStream()
Get the underlying libc stream for this file, or NULL.
Status Read(void *buf, size_t &num_bytes) override
Read bytes from a file from the current file position into buf.
virtual off_t SeekFromStart(off_t offset, Status *error_ptr=nullptr)
Seek to an offset relative to the beginning of the file.
static int kInvalidDescriptor
static FILE * kInvalidStream
virtual Status GetFileSpec(FileSpec &file_spec) const
Get the file specification for this file, if possible.
LazyBool m_is_real_terminal
virtual off_t SeekFromCurrent(off_t offset, Status *error_ptr=nullptr)
Seek to an offset relative to the current file position.
LazyBool m_is_interactive
static bool DescriptorIsValid(int descriptor)
static mode_t ConvertOpenOptionsForPOSIXOpen(OpenOptions open_options)
virtual int GetDescriptor() const
Get underlying OS file descriptor for this file, or kInvalidDescriptor.
static llvm::Expected< const char * > GetStreamOpenModeFromOptions(OpenOptions options)
bool GetIsTerminalWithColors()
Return true if this file is a terminal which supports colors.
Status Close() override
Flush any buffers and release any resources owned by the file.
Status Write(const void *buf, size_t &num_bytes) override
Write bytes from buf to a file at the current file position.
@ eOpenOptionCanCreateNewOnly
uint32_t GetPermissions(Status &error) const
Get the permissions for a this file.
bool IsValid() const override
IsValid.
virtual Status Flush()
Flush the current stream.
static llvm::Expected< OpenOptions > GetOptionsFromMode(llvm::StringRef mode)
size_t virtual size_t PrintfVarArg(const char *format, va_list args)
Output printf formatted output to the stream.
virtual Status Sync()
Sync to disk.
LazyBool m_supports_colors
bool GetIsInteractive()
Return true if this file is interactive.
void CalculateInteractiveAndTerminal()
virtual off_t SeekFromEnd(off_t offset, Status *error_ptr=nullptr)
Seek to an offset relative to the end of the file.
static const WaitableHandle kInvalidHandleValue
lldb::file_t WaitableHandle
bool DescriptorIsValidUnlocked() const
off_t SeekFromStart(off_t offset, Status *error_ptr=nullptr) override
Seek to an offset relative to the beginning of the file.
Status GetFileSpec(FileSpec &file_spec) const override
Get the file specification for this file, if possible.
FILE * GetStream() override
Get the underlying libc stream for this file, or NULL.
Status Sync() override
Sync to disk.
std::mutex offset_access_mutex
Status Close() override
Flush any buffers and release any resources owned by the file.
WaitableHandle GetWaitableHandle() override
Get a handle that can be used for OS polling interfaces, such as WaitForMultipleObjects,...
Status Flush() override
Flush the current stream.
bool StreamIsValidUnlocked() const
ValueGuard DescriptorIsValid() const
llvm::Expected< OpenOptions > GetOptions() const override
Return the OpenOptions for this file.
off_t SeekFromCurrent(off_t offset, Status *error_ptr=nullptr) override
Seek to an offset relative to the current file position.
size_t PrintfVarArg(const char *format, va_list args) override
Output printf formatted output to the stream.
Status Write(const void *buf, size_t &num_bytes) override
Write bytes from buf to a file at the current file position.
int GetDescriptor() const override
Get underlying OS file descriptor for this file, or kInvalidDescriptor.
Status Read(void *buf, size_t &num_bytes) override
Read bytes from a file from the current file position into buf.
bool IsValid() const override
IsValid.
std::mutex m_descriptor_mutex
std::mutex m_stream_mutex
ValueGuard StreamIsValid() const
off_t SeekFromEnd(off_t offset, Status *error_ptr=nullptr) override
Seek to an offset relative to the end of the file.
static llvm::Expected< std::unique_ptr< SerialPort > > Create(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
SerialPort(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
Status Close() override
Flush any buffers and release any resources owned by the file.
static llvm::Expected< Options > OptionsFromURL(llvm::StringRef urlqs)
void Clear()
Clear the object state.
static Status FromErrno()
Set the current error to errno.
static Status FromErrorString(const char *str)
llvm::Error SetParityCheck(ParityCheck parity_check)
llvm::Error SetBaudRate(unsigned int baud_rate)
llvm::Error SetParity(Parity parity)
llvm::Error SetStopBits(unsigned int stop_bits)
A class that represents a running process on the host machine.
bool VASprintf(llvm::SmallVectorImpl< char > &buf, const char *fmt, va_list args)
std::optional< Terminal::ParityCheck > ParityCheck
std::optional< unsigned int > StopBits
std::optional< Terminal::Parity > Parity
std::optional< unsigned int > BaudRate