LLDB mainline
File.cpp
Go to the documentation of this file.
1//===-- File.cpp ----------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Host/File.h"
10
11#include <cerrno>
12#include <climits>
13#include <cstdarg>
14#include <cstdio>
15#include <fcntl.h>
16#include <optional>
17
18#ifdef _WIN32
20#else
21#include <sys/ioctl.h>
22#include <sys/stat.h>
23#include <termios.h>
24#include <unistd.h>
25#endif
26
27#include "lldb/Host/Config.h"
29#include "lldb/Host/Host.h"
32#include "lldb/Utility/Log.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"
40
41using namespace lldb;
42using namespace lldb_private;
43using llvm::Expected;
44
45Expected<const char *>
50
51 if (options & File::eOpenOptionAppend) {
54 return "a+x";
55 else
56 return "a+";
57 } else if (rw == File::eOpenOptionWriteOnly) {
59 return "ax";
60 else
61 return "a";
62 }
63 } else if (rw == File::eOpenOptionReadWrite) {
64 if (options & File::eOpenOptionCanCreate) {
66 return "w+x";
67 else
68 return "w+";
69 } else
70 return "r+";
71 } else if (rw == File::eOpenOptionWriteOnly) {
72 return "w";
73 } else if (rw == File::eOpenOptionReadOnly) {
74 return "r";
75 }
76 return llvm::createStringError(
77 llvm::inconvertibleErrorCode(),
78 "invalid options, cannot convert to mode string");
79}
80
81Expected<File::OpenOptions> File::GetOptionsFromMode(llvm::StringRef mode) {
82 OpenOptions opts =
83 llvm::StringSwitch<OpenOptions>(mode)
84 .Cases("r", "rb", eOpenOptionReadOnly)
85 .Cases("w", "wb", eOpenOptionWriteOnly)
86 .Cases("a", "ab",
89 .Cases("r+", "rb+", "r+b", eOpenOptionReadWrite)
90 .Cases("w+", "wb+", "w+b",
93 .Cases("a+", "ab+", "a+b",
96 .Default(eOpenOptionInvalid);
97 if (opts != eOpenOptionInvalid)
98 return opts;
99 return llvm::createStringError(
100 llvm::inconvertibleErrorCode(),
101 "invalid mode, cannot convert to File::OpenOptions");
102}
103
105FILE *File::kInvalidStream = nullptr;
106
107Status File::Read(void *buf, size_t &num_bytes) {
108 return std::error_code(ENOTSUP, std::system_category());
109}
110Status File::Write(const void *buf, size_t &num_bytes) {
111 return std::error_code(ENOTSUP, std::system_category());
112}
113
114bool File::IsValid() const { return false; }
115
116Status File::Close() { return Flush(); }
117
121
123 file_spec.Clear();
124 return std::error_code(ENOTSUP, std::system_category());
125}
126
128
129FILE *File::GetStream() { return nullptr; }
130
131off_t File::SeekFromStart(off_t offset, Status *error_ptr) {
132 if (error_ptr)
133 *error_ptr = std::error_code(ENOTSUP, std::system_category());
134 return -1;
135}
136
137off_t File::SeekFromCurrent(off_t offset, Status *error_ptr) {
138 if (error_ptr)
139 *error_ptr = std::error_code(ENOTSUP, std::system_category());
140 return -1;
141}
142
143off_t File::SeekFromEnd(off_t offset, Status *error_ptr) {
144 if (error_ptr)
145 *error_ptr = std::error_code(ENOTSUP, std::system_category());
146 return -1;
147}
148
149Status File::Read(void *dst, size_t &num_bytes, off_t &offset) {
150 return std::error_code(ENOTSUP, std::system_category());
151}
152
153Status File::Write(const void *src, size_t &num_bytes, off_t &offset) {
154 return std::error_code(ENOTSUP, std::system_category());
155}
156
157Status File::Flush() { return Status(); }
158
159Status File::Sync() { return Flush(); }
160
162 const int fd = GetDescriptor();
163 if (!DescriptorIsValid(fd)) {
167 return;
168 }
171#if defined(_WIN32)
172 if (_isatty(fd)) {
175#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
177#endif
178 }
179#else
180 if (isatty(fd)) {
182 struct winsize window_size;
183 if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) {
184 if (window_size.ws_col > 0) {
186 if (llvm::sys::Process::FileDescriptorHasColors(fd))
188 }
189 }
190 }
191#endif
192}
193
199
205
211
212size_t File::Printf(const char *format, ...) {
213 va_list args;
214 va_start(args, format);
215 size_t result = PrintfVarArg(format, args);
216 va_end(args);
217 return result;
218}
219
220size_t File::PrintfVarArg(const char *format, va_list args) {
221 llvm::SmallString<0> s;
222 if (VASprintf(s, format, args)) {
223 size_t written = s.size();
224 Write(s.data(), written);
225 return written;
226 }
227 return 0;
228}
229
230Expected<File::OpenOptions> File::GetOptions() const {
231 return llvm::createStringError(
232 llvm::inconvertibleErrorCode(),
233 "GetOptions() not implemented for this File class");
234}
235
237 int fd = GetDescriptor();
238 if (!DescriptorIsValid(fd)) {
239 error = std::error_code(ENOTSUP, std::system_category());
240 return 0;
241 }
242 struct stat file_stats;
243 if (::fstat(fd, &file_stats) == -1) {
245 return 0;
246 }
247 error.Clear();
248 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
249}
250
251NativeFile::NativeFile() = default;
252
253NativeFile::NativeFile(FILE *fh, bool transfer_ownership)
254 : m_stream(fh), m_own_stream(transfer_ownership) {
255#ifdef _WIN32
256 // In order to properly display non ASCII characters in Windows, we need to
257 // use Windows APIs to print to the console. This is only required if the
258 // stream outputs to a console.
259 int fd = _fileno(fh);
261 ::GetFileType((HANDLE)::_get_osfhandle(fd)) == FILE_TYPE_CHAR;
262#endif
263}
264
265NativeFile::NativeFile(int fd, OpenOptions options, bool transfer_ownership)
266 : m_descriptor(fd), m_own_descriptor(transfer_ownership),
267 m_options(options) {
268#ifdef _WIN32
269 // In order to properly display non ASCII characters in Windows, we need to
270 // use Windows APIs to print to the console. This is only required if the
271 // file outputs to a console.
273 ::GetFileType((HANDLE)::_get_osfhandle(fd)) == FILE_TYPE_CHAR;
274#endif
275}
276
278 std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex, m_stream_mutex);
280}
281
282Expected<File::OpenOptions> NativeFile::GetOptions() const { return m_options; }
283
285 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
286 return m_descriptor;
287 }
288
289 // Don't open the file descriptor if we don't need to, just get it from the
290 // stream if we have one.
291 if (ValueGuard stream_guard = StreamIsValid()) {
292#if defined(_WIN32)
293 return _fileno(m_stream);
294#else
295 return fileno(m_stream);
296#endif
297 }
298
299 // Invalid descriptor and invalid stream, return invalid descriptor.
300 return kInvalidDescriptor;
301}
302
304#ifdef _WIN32
305 return (HANDLE)_get_osfhandle(GetDescriptor());
306#else
307 return GetDescriptor();
308#endif
309}
310
312 ValueGuard stream_guard = StreamIsValid();
313 if (!stream_guard) {
314 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
316 if (!mode)
317 llvm::consumeError(mode.takeError());
318 else {
319 if (!m_own_descriptor) {
320// We must duplicate the file descriptor if we don't own it because when you
321// call fdopen, the stream will own the fd
322#ifdef _WIN32
323 m_descriptor = ::_dup(m_descriptor);
324#else
326#endif
327 m_own_descriptor = true;
328 }
329
330 m_stream = llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor,
331 mode.get());
332
333 // If we got a stream, then we own the stream and should no longer own
334 // the descriptor because fclose() will close it for us
335
336 if (m_stream) {
337 m_own_stream = true;
338 m_own_descriptor = false;
339 }
340 }
341 }
342 }
343 return m_stream;
344}
345
347 std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex, m_stream_mutex);
348
350
351 if (StreamIsValidUnlocked()) {
352 if (m_own_stream) {
353 if (::fclose(m_stream) == EOF)
355 } else {
359
360 if (rw == eOpenOptionWriteOnly || rw == eOpenOptionReadWrite) {
361 if (::fflush(m_stream) == EOF)
363 }
364 }
365 }
366
368 if (::close(m_descriptor) != 0)
370 }
371
373 m_own_stream = false;
375 m_own_descriptor = false;
379 return error;
380}
381
384#ifdef F_GETPATH
385 if (IsValid()) {
386 char path[PATH_MAX];
387 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
389 else
390 file_spec.SetFile(path, FileSpec::Style::native);
391 } else {
392 error = Status::FromErrorString("invalid file handle");
393 }
394#elif defined(__linux__)
395 char proc[64];
396 char path[PATH_MAX];
397 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
398 error = Status::FromErrorString("cannot resolve file descriptor");
399 else {
400 ssize_t len;
401 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
403 else {
404 path[len] = '\0';
405 file_spec.SetFile(path, FileSpec::Style::native);
406 }
407 }
408#else
410 "NativeFile::GetFileSpec is not supported on this platform");
411#endif
412
413 if (error.Fail())
414 file_spec.Clear();
415 return error;
416}
417
418off_t NativeFile::SeekFromStart(off_t offset, Status *error_ptr) {
419 off_t result = 0;
420 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
421 result = ::lseek(m_descriptor, offset, SEEK_SET);
422
423 if (error_ptr) {
424 if (result == -1)
425 *error_ptr = Status::FromErrno();
426 else
427 error_ptr->Clear();
428 }
429 return result;
430 }
431
432 if (ValueGuard stream_guard = StreamIsValid()) {
433 result = ::fseek(m_stream, offset, SEEK_SET);
434
435 if (error_ptr) {
436 if (result == -1)
437 *error_ptr = Status::FromErrno();
438 else
439 error_ptr->Clear();
440 }
441 return result;
442 }
443
444 if (error_ptr)
445 *error_ptr = Status::FromErrorString("invalid file handle");
446 return result;
447}
448
449off_t NativeFile::SeekFromCurrent(off_t offset, Status *error_ptr) {
450 off_t result = -1;
451 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
452 result = ::lseek(m_descriptor, offset, SEEK_CUR);
453
454 if (error_ptr) {
455 if (result == -1)
456 *error_ptr = Status::FromErrno();
457 else
458 error_ptr->Clear();
459 }
460 return result;
461 }
462
463 if (ValueGuard stream_guard = StreamIsValid()) {
464 result = ::fseek(m_stream, offset, SEEK_CUR);
465
466 if (error_ptr) {
467 if (result == -1)
468 *error_ptr = Status::FromErrno();
469 else
470 error_ptr->Clear();
471 }
472 return result;
473 }
474
475 if (error_ptr)
476 *error_ptr = Status::FromErrorString("invalid file handle");
477 return result;
478}
479
480off_t NativeFile::SeekFromEnd(off_t offset, Status *error_ptr) {
481 off_t result = -1;
482 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
483 result = ::lseek(m_descriptor, offset, SEEK_END);
484
485 if (error_ptr) {
486 if (result == -1)
487 *error_ptr = Status::FromErrno();
488 else
489 error_ptr->Clear();
490 }
491 return result;
492 }
493
494 if (ValueGuard stream_guard = StreamIsValid()) {
495 result = ::fseek(m_stream, offset, SEEK_END);
496
497 if (error_ptr) {
498 if (result == -1)
499 *error_ptr = Status::FromErrno();
500 else
501 error_ptr->Clear();
502 }
503 }
504
505 if (error_ptr)
506 *error_ptr = Status::FromErrorString("invalid file handle");
507 return result;
508}
509
512 if (ValueGuard stream_guard = StreamIsValid()) {
513 if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF)
515 return error;
516 }
517
518 {
519 ValueGuard descriptor_guard = DescriptorIsValid();
520 if (!descriptor_guard)
521 error = Status::FromErrorString("invalid file handle");
522 }
523 return error;
524}
525
528 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
529#ifdef _WIN32
530 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
531 if (err == 0)
532 error = Status::FromErrorString("unknown error");
533#else
534 if (llvm::sys::RetryAfterSignal(-1, ::fsync, m_descriptor) == -1)
536#endif
537 } else {
538 error = Status::FromErrorString("invalid file handle");
539 }
540 return error;
541}
542
543#if defined(__APPLE__)
544// Darwin kernels only can read/write <= INT_MAX bytes
545#define MAX_READ_SIZE INT_MAX
546#define MAX_WRITE_SIZE INT_MAX
547#endif
548
549Status NativeFile::Read(void *buf, size_t &num_bytes) {
551
552#if defined(MAX_READ_SIZE)
553 if (num_bytes > MAX_READ_SIZE) {
554 uint8_t *p = (uint8_t *)buf;
555 size_t bytes_left = num_bytes;
556 // Init the num_bytes read to zero
557 num_bytes = 0;
558
559 while (bytes_left > 0) {
560 size_t curr_num_bytes;
561 if (bytes_left > MAX_READ_SIZE)
562 curr_num_bytes = MAX_READ_SIZE;
563 else
564 curr_num_bytes = bytes_left;
565
566 error = Read(p + num_bytes, curr_num_bytes);
567
568 // Update how many bytes were read
569 num_bytes += curr_num_bytes;
570 if (bytes_left < curr_num_bytes)
571 bytes_left = 0;
572 else
573 bytes_left -= curr_num_bytes;
574
575 if (error.Fail())
576 break;
577 }
578 return error;
579 }
580#endif
581
582 ssize_t bytes_read = -1;
583 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
584 bytes_read =
585 llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes);
586 if (bytes_read == -1) {
588 num_bytes = 0;
589 } else
590 num_bytes = bytes_read;
591 return error;
592 }
593
594 if (ValueGuard file_lock = StreamIsValid()) {
595 bytes_read = ::fread(buf, 1, num_bytes, m_stream);
596
597 if (bytes_read == 0) {
598 if (::feof(m_stream))
600 else if (::ferror(m_stream))
601 error = Status::FromErrorString("ferror");
602 num_bytes = 0;
603 } else
604 num_bytes = bytes_read;
605 return error;
606 }
607
608 num_bytes = 0;
609 error = Status::FromErrorString("invalid file handle");
610 return error;
611}
612
613Status NativeFile::Write(const void *buf, size_t &num_bytes) {
615
616#if defined(MAX_WRITE_SIZE)
617 if (num_bytes > MAX_WRITE_SIZE) {
618 const uint8_t *p = (const uint8_t *)buf;
619 size_t bytes_left = num_bytes;
620 // Init the num_bytes written to zero
621 num_bytes = 0;
622
623 while (bytes_left > 0) {
624 size_t curr_num_bytes;
625 if (bytes_left > MAX_WRITE_SIZE)
626 curr_num_bytes = MAX_WRITE_SIZE;
627 else
628 curr_num_bytes = bytes_left;
629
630 error = Write(p + num_bytes, curr_num_bytes);
631
632 // Update how many bytes were read
633 num_bytes += curr_num_bytes;
634 if (bytes_left < curr_num_bytes)
635 bytes_left = 0;
636 else
637 bytes_left -= curr_num_bytes;
638
639 if (error.Fail())
640 break;
641 }
642 return error;
643 }
644#endif
645
646 ssize_t bytes_written = -1;
647 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
648 bytes_written =
649 llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes);
650 if (bytes_written == -1) {
652 num_bytes = 0;
653 } else
654 num_bytes = bytes_written;
655 return error;
656 }
657
658 if (ValueGuard stream_guard = StreamIsValid()) {
659#ifdef _WIN32
660 if (is_windows_console) {
661 llvm::raw_fd_ostream(_fileno(m_stream), false)
662 .write((const char *)buf, num_bytes);
663 return error;
664 }
665#endif
666 bytes_written = ::fwrite(buf, 1, num_bytes, m_stream);
667
668 if (bytes_written == 0) {
669 if (::feof(m_stream))
671 else if (::ferror(m_stream))
672 error = Status::FromErrorString("ferror");
673 num_bytes = 0;
674 } else
675 num_bytes = bytes_written;
676 return error;
677 }
678
679 num_bytes = 0;
680 error = Status::FromErrorString("invalid file handle");
681 return error;
682}
683
684Status NativeFile::Read(void *buf, size_t &num_bytes, off_t &offset) {
686
687#if defined(MAX_READ_SIZE)
688 if (num_bytes > MAX_READ_SIZE) {
689 uint8_t *p = (uint8_t *)buf;
690 size_t bytes_left = num_bytes;
691 // Init the num_bytes read to zero
692 num_bytes = 0;
693
694 while (bytes_left > 0) {
695 size_t curr_num_bytes;
696 if (bytes_left > MAX_READ_SIZE)
697 curr_num_bytes = MAX_READ_SIZE;
698 else
699 curr_num_bytes = bytes_left;
700
701 error = Read(p + num_bytes, curr_num_bytes, offset);
702
703 // Update how many bytes were read
704 num_bytes += curr_num_bytes;
705 if (bytes_left < curr_num_bytes)
706 bytes_left = 0;
707 else
708 bytes_left -= curr_num_bytes;
709
710 if (error.Fail())
711 break;
712 }
713 return error;
714 }
715#endif
716
717#ifndef _WIN32
718 int fd = GetDescriptor();
719 if (fd != kInvalidDescriptor) {
720 ssize_t bytes_read =
721 llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset);
722 if (bytes_read < 0) {
723 num_bytes = 0;
725 } else {
726 offset += bytes_read;
727 num_bytes = bytes_read;
728 }
729 } else {
730 num_bytes = 0;
731 error = Status::FromErrorString("invalid file handle");
732 }
733#else
734 std::lock_guard<std::mutex> guard(offset_access_mutex);
735 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
736 SeekFromStart(offset);
737 error = Read(buf, num_bytes);
738 if (!error.Fail())
739 SeekFromStart(cur);
740#endif
741 return error;
742}
743
744Status NativeFile::Write(const void *buf, size_t &num_bytes, off_t &offset) {
746
747#if defined(MAX_WRITE_SIZE)
748 if (num_bytes > MAX_WRITE_SIZE) {
749 const uint8_t *p = (const uint8_t *)buf;
750 size_t bytes_left = num_bytes;
751 // Init the num_bytes written to zero
752 num_bytes = 0;
753
754 while (bytes_left > 0) {
755 size_t curr_num_bytes;
756 if (bytes_left > MAX_WRITE_SIZE)
757 curr_num_bytes = MAX_WRITE_SIZE;
758 else
759 curr_num_bytes = bytes_left;
760
761 error = Write(p + num_bytes, curr_num_bytes, offset);
762
763 // Update how many bytes were read
764 num_bytes += curr_num_bytes;
765 if (bytes_left < curr_num_bytes)
766 bytes_left = 0;
767 else
768 bytes_left -= curr_num_bytes;
769
770 if (error.Fail())
771 break;
772 }
773 return error;
774 }
775#endif
776
777 int fd = GetDescriptor();
778 if (fd != kInvalidDescriptor) {
779#ifndef _WIN32
780 ssize_t bytes_written =
781 llvm::sys::RetryAfterSignal(-1, ::pwrite, m_descriptor, buf, num_bytes, offset);
782 if (bytes_written < 0) {
783 num_bytes = 0;
785 } else {
786 offset += bytes_written;
787 num_bytes = bytes_written;
788 }
789#else
790 std::lock_guard<std::mutex> guard(offset_access_mutex);
791 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
792 SeekFromStart(offset);
793 error = Write(buf, num_bytes);
794 long after = ::lseek(m_descriptor, 0, SEEK_CUR);
795
796 if (!error.Fail())
797 SeekFromStart(cur);
798
799 offset = after;
800#endif
801 } else {
802 num_bytes = 0;
803 error = Status::FromErrorString("invalid file handle");
804 }
805 return error;
806}
807
808size_t NativeFile::PrintfVarArg(const char *format, va_list args) {
809 if (StreamIsValid()) {
810 return ::vfprintf(m_stream, format, args);
811 } else {
812 return File::PrintfVarArg(format, args);
813 }
814}
815
817 mode_t mode = 0;
821 if (rw == eOpenOptionReadWrite)
822 mode |= O_RDWR;
823 else if (rw == eOpenOptionWriteOnly)
824 mode |= O_WRONLY;
825 else if (rw == eOpenOptionReadOnly)
826 mode |= O_RDONLY;
827
828 if (open_options & eOpenOptionAppend)
829 mode |= O_APPEND;
830
831 if (open_options & eOpenOptionTruncate)
832 mode |= O_TRUNC;
833
834 if (open_options & eOpenOptionNonBlocking)
835 mode |= O_NONBLOCK;
836
837 if (open_options & eOpenOptionCanCreateNewOnly)
838 mode |= O_CREAT | O_EXCL;
839 else if (open_options & eOpenOptionCanCreate)
840 mode |= O_CREAT;
841
842 return mode;
843}
844
845llvm::Expected<SerialPort::Options>
846SerialPort::OptionsFromURL(llvm::StringRef urlqs) {
847 SerialPort::Options serial_options;
848 for (llvm::StringRef x : llvm::split(urlqs, '&')) {
849 if (x.consume_front("baud=")) {
850 unsigned int baud_rate;
851 if (!llvm::to_integer(x, baud_rate, 10))
852 return llvm::createStringError(llvm::inconvertibleErrorCode(),
853 "Invalid baud rate: %s",
854 x.str().c_str());
855 serial_options.BaudRate = baud_rate;
856 } else if (x.consume_front("parity=")) {
857 serial_options.Parity =
858 llvm::StringSwitch<std::optional<Terminal::Parity>>(x)
859 .Case("no", Terminal::Parity::No)
860 .Case("even", Terminal::Parity::Even)
861 .Case("odd", Terminal::Parity::Odd)
862 .Case("mark", Terminal::Parity::Mark)
863 .Case("space", Terminal::Parity::Space)
864 .Default(std::nullopt);
865 if (!serial_options.Parity)
866 return llvm::createStringError(
867 llvm::inconvertibleErrorCode(),
868 "Invalid parity (must be no, even, odd, mark or space): %s",
869 x.str().c_str());
870 } else if (x.consume_front("parity-check=")) {
871 serial_options.ParityCheck =
872 llvm::StringSwitch<std::optional<Terminal::ParityCheck>>(x)
873 .Case("no", Terminal::ParityCheck::No)
875 .Case("ignore", Terminal::ParityCheck::Ignore)
876 // "mark" mode is not currently supported as it requires special
877 // input processing
878 // .Case("mark", Terminal::ParityCheck::Mark)
879 .Default(std::nullopt);
880 if (!serial_options.ParityCheck)
881 return llvm::createStringError(
882 llvm::inconvertibleErrorCode(),
883 "Invalid parity-check (must be no, replace, ignore or mark): %s",
884 x.str().c_str());
885 } else if (x.consume_front("stop-bits=")) {
886 unsigned int stop_bits;
887 if (!llvm::to_integer(x, stop_bits, 10) ||
888 (stop_bits != 1 && stop_bits != 2))
889 return llvm::createStringError(
890 llvm::inconvertibleErrorCode(),
891 "Invalid stop bit number (must be 1 or 2): %s", x.str().c_str());
892 serial_options.StopBits = stop_bits;
893 } else
894 return llvm::createStringError(llvm::inconvertibleErrorCode(),
895 "Unknown parameter: %s", x.str().c_str());
896 }
897 return serial_options;
898}
899
900llvm::Expected<std::unique_ptr<SerialPort>>
901SerialPort::Create(int fd, OpenOptions options, Options serial_options,
902 bool transfer_ownership) {
903 std::unique_ptr<SerialPort> out{
904 new SerialPort(fd, options, serial_options, transfer_ownership)};
905
906 if (!out->GetIsInteractive())
907 return llvm::createStringError(llvm::inconvertibleErrorCode(),
908 "the specified file is not a teletype");
909
910 Terminal term{fd};
911 if (llvm::Error error = term.SetRaw())
912 return std::move(error);
913 if (serial_options.BaudRate) {
914 if (llvm::Error error = term.SetBaudRate(*serial_options.BaudRate))
915 return std::move(error);
916 }
917 if (serial_options.Parity) {
918 if (llvm::Error error = term.SetParity(*serial_options.Parity))
919 return std::move(error);
920 }
921 if (serial_options.ParityCheck) {
922 if (llvm::Error error = term.SetParityCheck(*serial_options.ParityCheck))
923 return std::move(error);
924 }
925 if (serial_options.StopBits) {
926 if (llvm::Error error = term.SetStopBits(*serial_options.StopBits))
927 return std::move(error);
928 }
929
930 return std::move(out);
931}
932
934 SerialPort::Options serial_options,
935 bool transfer_ownership)
936 : NativeFile(fd, options, transfer_ownership), m_state(fd) {}
937
939 m_state.Restore();
940 return NativeFile::Close();
941}
942
943char File::ID = 0;
944char NativeFile::ID = 0;
945char SerialPort::ID = 0;
static llvm::raw_ostream & error(Stream &strm)
A file utility class.
Definition FileSpec.h:57
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition FileSpec.cpp:174
void Clear()
Clears the object state.
Definition FileSpec.cpp:259
virtual llvm::Expected< OpenOptions > GetOptions() const
Return the OpenOptions for this file.
Definition File.cpp:230
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition File.cpp:212
WaitableHandle GetWaitableHandle() override
Get a handle that can be used for OS polling interfaces, such as WaitForMultipleObjects,...
Definition File.cpp:118
bool GetIsRealTerminal()
Return true if this file from a real terminal.
Definition File.cpp:200
virtual FILE * GetStream()
Get the underlying libc stream for this file, or NULL.
Definition File.cpp:129
Status Read(void *buf, size_t &num_bytes) override
Read bytes from a file from the current file position into buf.
Definition File.cpp:107
virtual off_t SeekFromStart(off_t offset, Status *error_ptr=nullptr)
Seek to an offset relative to the beginning of the file.
Definition File.cpp:131
static int kInvalidDescriptor
Definition File.h:38
static FILE * kInvalidStream
Definition File.h:39
virtual Status GetFileSpec(FileSpec &file_spec) const
Get the file specification for this file, if possible.
Definition File.cpp:122
LazyBool m_is_real_terminal
Definition File.h:368
virtual off_t SeekFromCurrent(off_t offset, Status *error_ptr=nullptr)
Seek to an offset relative to the current file position.
Definition File.cpp:137
LazyBool m_is_interactive
Definition File.h:367
static bool DescriptorIsValid(int descriptor)
Definition File.h:71
static mode_t ConvertOpenOptionsForPOSIXOpen(OpenOptions open_options)
Definition File.cpp:816
virtual int GetDescriptor() const
Get underlying OS file descriptor for this file, or kInvalidDescriptor.
Definition File.cpp:127
static llvm::Expected< const char * > GetStreamOpenModeFromOptions(OpenOptions options)
Definition File.cpp:46
bool GetIsTerminalWithColors()
Return true if this file is a terminal which supports colors.
Definition File.cpp:206
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition File.cpp:116
Status Write(const void *buf, size_t &num_bytes) override
Write bytes from buf to a file at the current file position.
Definition File.cpp:110
@ eOpenOptionReadOnly
Definition File.h:51
@ eOpenOptionCanCreateNewOnly
Definition File.h:58
@ eOpenOptionReadWrite
Definition File.h:53
@ eOpenOptionWriteOnly
Definition File.h:52
@ eOpenOptionCanCreate
Definition File.h:56
@ eOpenOptionTruncate
Definition File.h:57
@ eOpenOptionNonBlocking
Definition File.h:61
uint32_t GetPermissions(Status &error) const
Get the permissions for a this file.
Definition File.cpp:236
bool IsValid() const override
IsValid.
Definition File.cpp:114
static char ID
Definition File.h:362
virtual Status Flush()
Flush the current stream.
Definition File.cpp:157
static llvm::Expected< OpenOptions > GetOptionsFromMode(llvm::StringRef mode)
Definition File.cpp:81
size_t virtual size_t PrintfVarArg(const char *format, va_list args)
Output printf formatted output to the stream.
Definition File.cpp:220
virtual Status Sync()
Sync to disk.
Definition File.cpp:159
LazyBool m_supports_colors
Definition File.h:369
bool GetIsInteractive()
Return true if this file is interactive.
Definition File.cpp:194
void CalculateInteractiveAndTerminal()
Definition File.cpp:161
virtual off_t SeekFromEnd(off_t offset, Status *error_ptr=nullptr)
Seek to an offset relative to the end of the file.
Definition File.cpp:143
static const WaitableHandle kInvalidHandleValue
Definition IOObject.h:31
lldb::file_t WaitableHandle
Definition IOObject.h:29
bool DescriptorIsValidUnlocked() const
Definition File.h:426
off_t SeekFromStart(off_t offset, Status *error_ptr=nullptr) override
Seek to an offset relative to the beginning of the file.
Definition File.cpp:418
Status GetFileSpec(FileSpec &file_spec) const override
Get the file specification for this file, if possible.
Definition File.cpp:382
FILE * GetStream() override
Get the underlying libc stream for this file, or NULL.
Definition File.cpp:311
Status Sync() override
Sync to disk.
Definition File.cpp:526
std::mutex offset_access_mutex
Definition File.h:452
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition File.cpp:346
WaitableHandle GetWaitableHandle() override
Get a handle that can be used for OS polling interfaces, such as WaitForMultipleObjects,...
Definition File.cpp:303
Status Flush() override
Flush the current stream.
Definition File.cpp:510
bool StreamIsValidUnlocked() const
Definition File.h:431
ValueGuard DescriptorIsValid() const
Definition File.h:433
llvm::Expected< OpenOptions > GetOptions() const override
Return the OpenOptions for this file.
Definition File.cpp:282
OpenOptions m_options
Definition File.h:450
off_t SeekFromCurrent(off_t offset, Status *error_ptr=nullptr) override
Seek to an offset relative to the current file position.
Definition File.cpp:449
size_t PrintfVarArg(const char *format, va_list args) override
Output printf formatted output to the stream.
Definition File.cpp:808
Status Write(const void *buf, size_t &num_bytes) override
Write bytes from buf to a file at the current file position.
Definition File.cpp:613
int GetDescriptor() const override
Get underlying OS file descriptor for this file, or kInvalidDescriptor.
Definition File.cpp:284
Status Read(void *buf, size_t &num_bytes) override
Read bytes from a file from the current file position into buf.
Definition File.cpp:549
bool IsValid() const override
IsValid.
Definition File.cpp:277
std::mutex m_descriptor_mutex
Definition File.h:445
std::mutex m_stream_mutex
Definition File.h:448
ValueGuard StreamIsValid() const
Definition File.h:438
off_t SeekFromEnd(off_t offset, Status *error_ptr=nullptr) override
Seek to an offset relative to the end of the file.
Definition File.cpp:480
static llvm::Expected< std::unique_ptr< SerialPort > > Create(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
Definition File.cpp:901
TerminalState m_state
Definition File.h:497
SerialPort(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
Definition File.cpp:933
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition File.cpp:938
static llvm::Expected< Options > OptionsFromURL(llvm::StringRef urlqs)
Definition File.cpp:846
An error handling class.
Definition Status.h:118
void Clear()
Clear the object state.
Definition Status.cpp:215
static Status FromErrno()
Set the current error to errno.
Definition Status.cpp:300
static Status FromErrorString(const char *str)
Definition Status.h:141
llvm::Error SetRaw()
Definition Terminal.cpp:108
llvm::Error SetParityCheck(ParityCheck parity_check)
Definition Terminal.cpp:357
llvm::Error SetBaudRate(unsigned int baud_rate)
Definition Terminal.cpp:273
llvm::Error SetParity(Parity parity)
Definition Terminal.cpp:324
llvm::Error SetStopBits(unsigned int stop_bits)
Definition Terminal.cpp:299
A class that represents a running process on the host machine.
bool VASprintf(llvm::SmallVectorImpl< char > &buf, const char *fmt, va_list args)
Definition VASprintf.cpp:19
std::optional< Terminal::ParityCheck > ParityCheck
Definition File.h:466
std::optional< unsigned int > StopBits
Definition File.h:467
std::optional< Terminal::Parity > Parity
Definition File.h:465
std::optional< unsigned int > BaudRate
Definition File.h:464
#define S_IRWXG
#define O_NONBLOCK
#define S_IRWXO
#define PATH_MAX
#define S_IRWXU