27#include "lldb/Host/Config.h"
34#include "llvm/Support/ConvertUTF.h"
35#include "llvm/Support/Errno.h"
36#include "llvm/Support/FileSystem.h"
37#include "llvm/Support/Process.h"
74 return llvm::createStringError(
75 llvm::inconvertibleErrorCode(),
76 "invalid options, cannot convert to mode string");
81 llvm::StringSwitch<OpenOptions>(mode)
88 .Cases(
"w+",
"wb+",
"w+b",
91 .Cases(
"a+",
"ab+",
"a+b",
97 return llvm::createStringError(
98 llvm::inconvertibleErrorCode(),
99 "invalid mode, cannot convert to File::OpenOptions");
106 return std::error_code(ENOTSUP, std::system_category());
109 return std::error_code(ENOTSUP, std::system_category());
122 return std::error_code(ENOTSUP, std::system_category());
131 *error_ptr = std::error_code(ENOTSUP, std::system_category());
137 *error_ptr = std::error_code(ENOTSUP, std::system_category());
143 *error_ptr = std::error_code(ENOTSUP, std::system_category());
148 return std::error_code(ENOTSUP, std::system_category());
152 return std::error_code(ENOTSUP, std::system_category());
173#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
180 struct winsize window_size;
181 if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) {
182 if (window_size.ws_col > 0) {
184 if (llvm::sys::Process::FileDescriptorHasColors(fd))
212 va_start(args, format);
219 llvm::SmallString<0> s;
221 size_t written = s.size();;
222 Write(s.data(), written);
229 return llvm::createStringError(
230 llvm::inconvertibleErrorCode(),
231 "GetOptions() not implemented for this File class");
237 error = std::error_code(ENOTSUP, std::system_category());
240 struct stat file_stats;
241 if (::fstat(fd, &file_stats) == -1) {
242 error.SetErrorToErrno();
278 llvm::consumeError(mode.takeError());
312 error.SetErrorToErrno();
320 error.SetErrorToErrno();
326 error.SetErrorToErrno();
344 error.SetErrorToErrno();
346 file_spec.
SetFile(path, FileSpec::Style::native);
348 error.SetErrorString(
"invalid file handle");
350#elif defined(__linux__)
353 if (::snprintf(proc,
sizeof(proc),
"/proc/self/fd/%d",
GetDescriptor()) < 0)
354 error.SetErrorString(
"cannot resolve file descriptor");
357 if ((len = ::readlink(proc, path,
sizeof(path) - 1)) == -1)
358 error.SetErrorToErrno();
361 file_spec.
SetFile(path, FileSpec::Style::native);
365 error.SetErrorString(
366 "NativeFile::GetFileSpec is not supported on this platform");
386 result = ::fseek(
m_stream, offset, SEEK_SET);
394 }
else if (error_ptr) {
412 result = ::fseek(
m_stream, offset, SEEK_CUR);
420 }
else if (error_ptr) {
438 result = ::fseek(
m_stream, offset, SEEK_END);
446 }
else if (error_ptr) {
455 if (llvm::sys::RetryAfterSignal(EOF, ::fflush,
m_stream) == EOF)
456 error.SetErrorToErrno();
458 error.SetErrorString(
"invalid file handle");
467 int err = FlushFileBuffers((HANDLE)_get_osfhandle(
m_descriptor));
469 error.SetErrorToGenericError();
471 if (llvm::sys::RetryAfterSignal(-1, ::fsync,
m_descriptor) == -1)
472 error.SetErrorToErrno();
475 error.SetErrorString(
"invalid file handle");
480#if defined(__APPLE__)
482#define MAX_READ_SIZE INT_MAX
483#define MAX_WRITE_SIZE INT_MAX
489#if defined(MAX_READ_SIZE)
490 if (num_bytes > MAX_READ_SIZE) {
491 uint8_t *p = (uint8_t *)buf;
492 size_t bytes_left = num_bytes;
496 while (bytes_left > 0) {
497 size_t curr_num_bytes;
498 if (bytes_left > MAX_READ_SIZE)
499 curr_num_bytes = MAX_READ_SIZE;
501 curr_num_bytes = bytes_left;
503 error =
Read(p + num_bytes, curr_num_bytes);
506 num_bytes += curr_num_bytes;
507 if (bytes_left < curr_num_bytes)
510 bytes_left -= curr_num_bytes;
519 ssize_t bytes_read = -1;
521 bytes_read = llvm::sys::RetryAfterSignal(-1, ::read,
m_descriptor, buf, num_bytes);
522 if (bytes_read == -1) {
523 error.SetErrorToErrno();
526 num_bytes = bytes_read;
528 bytes_read = ::fread(buf, 1, num_bytes,
m_stream);
530 if (bytes_read == 0) {
532 error.SetErrorString(
"feof");
534 error.SetErrorString(
"ferror");
537 num_bytes = bytes_read;
540 error.SetErrorString(
"invalid file handle");
548#if defined(MAX_WRITE_SIZE)
549 if (num_bytes > MAX_WRITE_SIZE) {
550 const uint8_t *p = (
const uint8_t *)buf;
551 size_t bytes_left = num_bytes;
555 while (bytes_left > 0) {
556 size_t curr_num_bytes;
557 if (bytes_left > MAX_WRITE_SIZE)
558 curr_num_bytes = MAX_WRITE_SIZE;
560 curr_num_bytes = bytes_left;
565 num_bytes += curr_num_bytes;
566 if (bytes_left < curr_num_bytes)
569 bytes_left -= curr_num_bytes;
578 ssize_t bytes_written = -1;
581 llvm::sys::RetryAfterSignal(-1, ::write,
m_descriptor, buf, num_bytes);
582 if (bytes_written == -1) {
583 error.SetErrorToErrno();
586 num_bytes = bytes_written;
588 bytes_written = ::fwrite(buf, 1, num_bytes,
m_stream);
590 if (bytes_written == 0) {
592 error.SetErrorString(
"feof");
594 error.SetErrorString(
"ferror");
597 num_bytes = bytes_written;
601 error.SetErrorString(
"invalid file handle");
610#if defined(MAX_READ_SIZE)
611 if (num_bytes > MAX_READ_SIZE) {
612 uint8_t *p = (uint8_t *)buf;
613 size_t bytes_left = num_bytes;
617 while (bytes_left > 0) {
618 size_t curr_num_bytes;
619 if (bytes_left > MAX_READ_SIZE)
620 curr_num_bytes = MAX_READ_SIZE;
622 curr_num_bytes = bytes_left;
624 error =
Read(p + num_bytes, curr_num_bytes, offset);
627 num_bytes += curr_num_bytes;
628 if (bytes_left < curr_num_bytes)
631 bytes_left -= curr_num_bytes;
644 llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset);
645 if (bytes_read < 0) {
647 error.SetErrorToErrno();
649 offset += bytes_read;
650 num_bytes = bytes_read;
654 error.SetErrorString(
"invalid file handle");
670#if defined(MAX_WRITE_SIZE)
671 if (num_bytes > MAX_WRITE_SIZE) {
672 const uint8_t *p = (
const uint8_t *)buf;
673 size_t bytes_left = num_bytes;
677 while (bytes_left > 0) {
678 size_t curr_num_bytes;
679 if (bytes_left > MAX_WRITE_SIZE)
680 curr_num_bytes = MAX_WRITE_SIZE;
682 curr_num_bytes = bytes_left;
684 error =
Write(p + num_bytes, curr_num_bytes, offset);
687 num_bytes += curr_num_bytes;
688 if (bytes_left < curr_num_bytes)
691 bytes_left -= curr_num_bytes;
703 ssize_t bytes_written =
704 llvm::sys::RetryAfterSignal(-1, ::pwrite,
m_descriptor, buf, num_bytes, offset);
705 if (bytes_written < 0) {
707 error.SetErrorToErrno();
709 offset += bytes_written;
710 num_bytes = bytes_written;
726 error.SetErrorString(
"invalid file handle");
733 return ::vfprintf(
m_stream, format, args);
761 mode |= O_CREAT | O_EXCL;
768llvm::Expected<SerialPort::Options>
771 for (llvm::StringRef x : llvm::split(urlqs,
'&')) {
772 if (x.consume_front(
"baud=")) {
773 unsigned int baud_rate;
774 if (!llvm::to_integer(x, baud_rate, 10))
775 return llvm::createStringError(llvm::inconvertibleErrorCode(),
776 "Invalid baud rate: %s",
778 serial_options.
BaudRate = baud_rate;
779 }
else if (x.consume_front(
"parity=")) {
781 llvm::StringSwitch<std::optional<Terminal::Parity>>(x)
782 .Case(
"no", Terminal::Parity::No)
783 .Case(
"even", Terminal::Parity::Even)
784 .Case(
"odd", Terminal::Parity::Odd)
785 .Case(
"mark", Terminal::Parity::Mark)
786 .Case(
"space", Terminal::Parity::Space)
787 .Default(std::nullopt);
788 if (!serial_options.
Parity)
789 return llvm::createStringError(
790 llvm::inconvertibleErrorCode(),
791 "Invalid parity (must be no, even, odd, mark or space): %s",
793 }
else if (x.consume_front(
"parity-check=")) {
795 llvm::StringSwitch<std::optional<Terminal::ParityCheck>>(x)
796 .Case(
"no", Terminal::ParityCheck::No)
797 .Case(
"replace", Terminal::ParityCheck::ReplaceWithNUL)
798 .Case(
"ignore", Terminal::ParityCheck::Ignore)
802 .Default(std::nullopt);
804 return llvm::createStringError(
805 llvm::inconvertibleErrorCode(),
806 "Invalid parity-check (must be no, replace, ignore or mark): %s",
808 }
else if (x.consume_front(
"stop-bits=")) {
809 unsigned int stop_bits;
810 if (!llvm::to_integer(x, stop_bits, 10) ||
811 (stop_bits != 1 && stop_bits != 2))
812 return llvm::createStringError(
813 llvm::inconvertibleErrorCode(),
814 "Invalid stop bit number (must be 1 or 2): %s", x.str().c_str());
815 serial_options.
StopBits = stop_bits;
817 return llvm::createStringError(llvm::inconvertibleErrorCode(),
818 "Unknown parameter: %s", x.str().c_str());
820 return serial_options;
823llvm::Expected<std::unique_ptr<SerialPort>>
825 bool transfer_ownership) {
826 std::unique_ptr<SerialPort> out{
827 new SerialPort(fd, options, serial_options, transfer_ownership)};
829 if (!out->GetIsInteractive())
830 return llvm::createStringError(llvm::inconvertibleErrorCode(),
831 "the specified file is not a teletype");
834 if (llvm::Error
error = term.SetRaw())
835 return std::move(
error);
837 if (llvm::Error
error = term.SetBaudRate(*serial_options.
BaudRate))
838 return std::move(
error);
840 if (serial_options.
Parity) {
841 if (llvm::Error
error = term.SetParity(*serial_options.
Parity))
842 return std::move(
error);
846 return std::move(
error);
849 if (llvm::Error
error = term.SetStopBits(*serial_options.
StopBits))
850 return std::move(
error);
853 return std::move(out);
858 bool transfer_ownership)
859 :
NativeFile(fd, options, transfer_ownership), m_state(fd) {}
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.
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
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.
bool StreamIsValid() const
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 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.
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.
void SetErrorToErrno()
Set the current error to errno.
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
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