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