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, OpenOptions options, bool transfer_ownership)
253 : m_stream(fh), m_options(options), 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#else
262#ifndef NDEBUG
263 int fd = fileno(fh);
264 if (fd != -1) {
265 int required_mode = ConvertOpenOptionsForPOSIXOpen(options) & O_ACCMODE;
266 int mode = fcntl(fd, F_GETFL);
267 if (mode != -1) {
268 mode &= O_ACCMODE;
269 // Check that the file is open with a valid subset of the requested file
270 // access mode, e.g. if we expected the file to be writable then ensure it
271 // was opened with O_WRONLY or O_RDWR.
272 assert(
273 (required_mode == O_RDWR && mode == O_RDWR) ||
274 (required_mode == O_RDONLY && (mode == O_RDWR || mode == O_RDONLY) ||
275 (required_mode == O_WRONLY &&
276 (mode == O_RDWR || mode == O_WRONLY))) &&
277 "invalid file access mode");
278 }
279 }
280#endif
281#endif
282}
283
284NativeFile::NativeFile(int fd, OpenOptions options, bool transfer_ownership)
285 : m_descriptor(fd), m_own_descriptor(transfer_ownership),
286 m_options(options) {
287#ifdef _WIN32
288 // In order to properly display non ASCII characters in Windows, we need to
289 // use Windows APIs to print to the console. This is only required if the
290 // file outputs to a console.
292 ::GetFileType((HANDLE)::_get_osfhandle(fd)) == FILE_TYPE_CHAR;
293#endif
294}
295
297 std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex,
300}
301
302Expected<File::OpenOptions> NativeFile::GetOptions() const { return m_options; }
303
305 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
306 return m_descriptor;
307 }
308
309 // Don't open the file descriptor if we don't need to, just get it from the
310 // stream if we have one.
311 if (ValueGuard stream_guard = StreamIsValid()) {
312#if defined(_WIN32)
313 return _fileno(m_stream);
314#else
315 return fileno(m_stream);
316#endif
317 }
318
319 // Invalid descriptor and invalid stream, return invalid descriptor.
320 return kInvalidDescriptor;
321}
322
324#ifdef _WIN32
325 return (HANDLE)_get_osfhandle(GetDescriptor());
326#else
327 return GetDescriptor();
328#endif
329}
330
332 ValueGuard stream_guard = StreamIsValid();
333 if (!stream_guard) {
334 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
336 if (!mode)
337 llvm::consumeError(mode.takeError());
338 else {
339 if (!m_own_descriptor) {
340// We must duplicate the file descriptor if we don't own it because when you
341// call fdopen, the stream will own the fd
342#ifdef _WIN32
343 m_descriptor = ::_dup(m_descriptor);
344#else
346#endif
347 m_own_descriptor = true;
348 }
349
350 m_stream = llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor,
351 mode.get());
352
353 // If we got a stream, then we own the stream and should no longer own
354 // the descriptor because fclose() will close it for us
355
356 if (m_stream) {
357 m_own_stream = true;
358 m_own_descriptor = false;
359 }
360 }
361 }
362 }
363 return m_stream;
364}
365
367 std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex,
369
371
372 if (StreamIsValidUnlocked()) {
373 if (m_own_stream) {
374 if (::fclose(m_stream) == EOF)
376 } else {
380
381 if (rw == eOpenOptionWriteOnly || rw == eOpenOptionReadWrite) {
382 if (::fflush(m_stream) == EOF)
384 }
385 }
386 }
387
389 if (::close(m_descriptor) != 0)
391 }
392
394 m_own_stream = false;
396 m_own_descriptor = false;
400 return error;
401}
402
405#ifdef F_GETPATH
406 if (IsValid()) {
407 char path[PATH_MAX];
408 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
410 else
411 file_spec.SetFile(path, FileSpec::Style::native);
412 } else {
413 error = Status::FromErrorString("invalid file handle");
414 }
415#elif defined(__linux__)
416 char proc[64];
417 char path[PATH_MAX];
418 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
419 error = Status::FromErrorString("cannot resolve file descriptor");
420 else {
421 ssize_t len;
422 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
424 else {
425 path[len] = '\0';
426 file_spec.SetFile(path, FileSpec::Style::native);
427 }
428 }
429#else
431 "NativeFile::GetFileSpec is not supported on this platform");
432#endif
433
434 if (error.Fail())
435 file_spec.Clear();
436 return error;
437}
438
439off_t NativeFile::SeekFromStart(off_t offset, Status *error_ptr) {
440 off_t result = 0;
441 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
442 result = ::lseek(m_descriptor, offset, SEEK_SET);
443
444 if (error_ptr) {
445 if (result == -1)
446 *error_ptr = Status::FromErrno();
447 else
448 error_ptr->Clear();
449 }
450 return result;
451 }
452
453 if (ValueGuard stream_guard = StreamIsValid()) {
454 result = ::fseek(m_stream, offset, SEEK_SET);
455
456 if (error_ptr) {
457 if (result == -1)
458 *error_ptr = Status::FromErrno();
459 else
460 error_ptr->Clear();
461 }
462 return result;
463 }
464
465 if (error_ptr)
466 *error_ptr = Status::FromErrorString("invalid file handle");
467 return result;
468}
469
470off_t NativeFile::SeekFromCurrent(off_t offset, Status *error_ptr) {
471 off_t result = -1;
472 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
473 result = ::lseek(m_descriptor, offset, SEEK_CUR);
474
475 if (error_ptr) {
476 if (result == -1)
477 *error_ptr = Status::FromErrno();
478 else
479 error_ptr->Clear();
480 }
481 return result;
482 }
483
484 if (ValueGuard stream_guard = StreamIsValid()) {
485 result = ::fseek(m_stream, offset, SEEK_CUR);
486
487 if (error_ptr) {
488 if (result == -1)
489 *error_ptr = Status::FromErrno();
490 else
491 error_ptr->Clear();
492 }
493 return result;
494 }
495
496 if (error_ptr)
497 *error_ptr = Status::FromErrorString("invalid file handle");
498 return result;
499}
500
501off_t NativeFile::SeekFromEnd(off_t offset, Status *error_ptr) {
502 off_t result = -1;
503 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
504 result = ::lseek(m_descriptor, offset, SEEK_END);
505
506 if (error_ptr) {
507 if (result == -1)
508 *error_ptr = Status::FromErrno();
509 else
510 error_ptr->Clear();
511 }
512 return result;
513 }
514
515 if (ValueGuard stream_guard = StreamIsValid()) {
516 result = ::fseek(m_stream, offset, SEEK_END);
517
518 if (error_ptr) {
519 if (result == -1)
520 *error_ptr = Status::FromErrno();
521 else
522 error_ptr->Clear();
523 }
524 return result;
525 }
526
527 if (error_ptr)
528 *error_ptr = Status::FromErrorString("invalid file handle");
529 return result;
530}
531
534 if (ValueGuard stream_guard = StreamIsValid()) {
535 if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF)
537 return error;
538 }
539
540 {
541 ValueGuard descriptor_guard = DescriptorIsValid();
542 if (!descriptor_guard)
543 error = Status::FromErrorString("invalid file handle");
544 }
545 return error;
546}
547
550 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
551#ifdef _WIN32
552 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
553 if (err == 0)
554 error = Status::FromErrorString("unknown error");
555#else
556 if (llvm::sys::RetryAfterSignal(-1, ::fsync, m_descriptor) == -1)
558#endif
559 } else {
560 error = Status::FromErrorString("invalid file handle");
561 }
562 return error;
563}
564
565#if defined(__APPLE__)
566// Darwin kernels only can read/write <= INT_MAX bytes
567#define MAX_READ_SIZE INT_MAX
568#define MAX_WRITE_SIZE INT_MAX
569#endif
570
571Status NativeFile::Read(void *buf, size_t &num_bytes) {
573
574 // Ensure the file is open for reading.
576 return Status(std::make_error_code(std::errc::bad_file_descriptor));
577
578#if defined(MAX_READ_SIZE)
579 if (num_bytes > MAX_READ_SIZE) {
580 uint8_t *p = (uint8_t *)buf;
581 size_t bytes_left = num_bytes;
582 // Init the num_bytes read to zero
583 num_bytes = 0;
584
585 while (bytes_left > 0) {
586 size_t curr_num_bytes;
587 if (bytes_left > MAX_READ_SIZE)
588 curr_num_bytes = MAX_READ_SIZE;
589 else
590 curr_num_bytes = bytes_left;
591
592 error = Read(p + num_bytes, curr_num_bytes);
593
594 // Update how many bytes were read
595 num_bytes += curr_num_bytes;
596 if (bytes_left < curr_num_bytes)
597 bytes_left = 0;
598 else
599 bytes_left -= curr_num_bytes;
600
601 if (error.Fail())
602 break;
603 }
604 return error;
605 }
606#endif
607
608 ssize_t bytes_read = -1;
609 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
610 bytes_read =
611 llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes);
612 if (bytes_read == -1) {
614 num_bytes = 0;
615 } else
616 num_bytes = bytes_read;
617 return error;
618 }
619
620 if (ValueGuard file_lock = StreamIsValid()) {
621 bytes_read = ::fread(buf, 1, num_bytes, m_stream);
622
623 if (bytes_read == 0) {
624 if (::feof(m_stream))
626 else if (::ferror(m_stream))
627 error = Status::FromErrorString("ferror");
628 num_bytes = 0;
629 } else
630 num_bytes = bytes_read;
631 return error;
632 }
633
634 num_bytes = 0;
635 error = Status::FromErrorString("invalid file handle");
636 return error;
637}
638
639Status NativeFile::Write(const void *buf, size_t &num_bytes) {
641
642 // Ensure the file is open for writing.
644 return Status(std::make_error_code(std::errc::bad_file_descriptor));
645
646#if defined(MAX_WRITE_SIZE)
647 if (num_bytes > MAX_WRITE_SIZE) {
648 const uint8_t *p = (const uint8_t *)buf;
649 size_t bytes_left = num_bytes;
650 // Init the num_bytes written to zero
651 num_bytes = 0;
652
653 while (bytes_left > 0) {
654 size_t curr_num_bytes;
655 if (bytes_left > MAX_WRITE_SIZE)
656 curr_num_bytes = MAX_WRITE_SIZE;
657 else
658 curr_num_bytes = bytes_left;
659
660 error = Write(p + num_bytes, curr_num_bytes);
661
662 // Update how many bytes were read
663 num_bytes += curr_num_bytes;
664 if (bytes_left < curr_num_bytes)
665 bytes_left = 0;
666 else
667 bytes_left -= curr_num_bytes;
668
669 if (error.Fail())
670 break;
671 }
672 return error;
673 }
674#endif
675
676 ssize_t bytes_written = -1;
677 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
678 bytes_written =
679 llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes);
680 if (bytes_written == -1) {
682 num_bytes = 0;
683 } else
684 num_bytes = bytes_written;
685 return error;
686 }
687
688 if (ValueGuard stream_guard = StreamIsValid()) {
689#ifdef _WIN32
690 if (is_windows_console) {
691 llvm::raw_fd_ostream(_fileno(m_stream), false)
692 .write((const char *)buf, num_bytes);
693 return error;
694 }
695#endif
696 bytes_written = ::fwrite(buf, 1, num_bytes, m_stream);
697
698 if (bytes_written == 0) {
699 if (::feof(m_stream))
701 else if (::ferror(m_stream))
702 error = Status::FromErrorString("ferror");
703 num_bytes = 0;
704 } else
705 num_bytes = bytes_written;
706 return error;
707 }
708
709 num_bytes = 0;
710 error = Status::FromErrorString("invalid file handle");
711 return error;
712}
713
714Status NativeFile::Read(void *buf, size_t &num_bytes, off_t &offset) {
716
717#if defined(MAX_READ_SIZE)
718 if (num_bytes > MAX_READ_SIZE) {
719 uint8_t *p = (uint8_t *)buf;
720 size_t bytes_left = num_bytes;
721 // Init the num_bytes read to zero
722 num_bytes = 0;
723
724 while (bytes_left > 0) {
725 size_t curr_num_bytes;
726 if (bytes_left > MAX_READ_SIZE)
727 curr_num_bytes = MAX_READ_SIZE;
728 else
729 curr_num_bytes = bytes_left;
730
731 error = Read(p + num_bytes, curr_num_bytes, offset);
732
733 // Update how many bytes were read
734 num_bytes += curr_num_bytes;
735 if (bytes_left < curr_num_bytes)
736 bytes_left = 0;
737 else
738 bytes_left -= curr_num_bytes;
739
740 if (error.Fail())
741 break;
742 }
743 return error;
744 }
745#endif
746
747#ifndef _WIN32
748 int fd = GetDescriptor();
749 if (fd != kInvalidDescriptor) {
750 ssize_t bytes_read =
751 llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset);
752 if (bytes_read < 0) {
753 num_bytes = 0;
755 } else {
756 offset += bytes_read;
757 num_bytes = bytes_read;
758 }
759 } else {
760 num_bytes = 0;
761 error = Status::FromErrorString("invalid file handle");
762 }
763#else
764 std::lock_guard<std::mutex> guard(offset_access_mutex);
765 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
766 SeekFromStart(offset);
767 error = Read(buf, num_bytes);
768 if (!error.Fail())
769 SeekFromStart(cur);
770#endif
771 return error;
772}
773
774Status NativeFile::Write(const void *buf, size_t &num_bytes, off_t &offset) {
776
777#if defined(MAX_WRITE_SIZE)
778 if (num_bytes > MAX_WRITE_SIZE) {
779 const uint8_t *p = (const uint8_t *)buf;
780 size_t bytes_left = num_bytes;
781 // Init the num_bytes written to zero
782 num_bytes = 0;
783
784 while (bytes_left > 0) {
785 size_t curr_num_bytes;
786 if (bytes_left > MAX_WRITE_SIZE)
787 curr_num_bytes = MAX_WRITE_SIZE;
788 else
789 curr_num_bytes = bytes_left;
790
791 error = Write(p + num_bytes, curr_num_bytes, offset);
792
793 // Update how many bytes were read
794 num_bytes += curr_num_bytes;
795 if (bytes_left < curr_num_bytes)
796 bytes_left = 0;
797 else
798 bytes_left -= curr_num_bytes;
799
800 if (error.Fail())
801 break;
802 }
803 return error;
804 }
805#endif
806
807 int fd = GetDescriptor();
808 if (fd != kInvalidDescriptor) {
809#ifndef _WIN32
810 ssize_t bytes_written = llvm::sys::RetryAfterSignal(
811 -1, ::pwrite, m_descriptor, buf, num_bytes, offset);
812 if (bytes_written < 0) {
813 num_bytes = 0;
815 } else {
816 offset += bytes_written;
817 num_bytes = bytes_written;
818 }
819#else
820 std::lock_guard<std::mutex> guard(offset_access_mutex);
821 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
822 SeekFromStart(offset);
823 error = Write(buf, num_bytes);
824 long after = ::lseek(m_descriptor, 0, SEEK_CUR);
825
826 if (!error.Fail())
827 SeekFromStart(cur);
828
829 offset = after;
830#endif
831 } else {
832 num_bytes = 0;
833 error = Status::FromErrorString("invalid file handle");
834 }
835 return error;
836}
837
838size_t NativeFile::PrintfVarArg(const char *format, va_list args) {
839 if (StreamIsValid()) {
840 return ::vfprintf(m_stream, format, args);
841 } else {
842 return File::PrintfVarArg(format, args);
843 }
844}
845
847 mode_t mode = 0;
851 if (rw == eOpenOptionReadWrite)
852 mode |= O_RDWR;
853 else if (rw == eOpenOptionWriteOnly)
854 mode |= O_WRONLY;
855 else if (rw == eOpenOptionReadOnly)
856 mode |= O_RDONLY;
857
858 if (open_options & eOpenOptionAppend)
859 mode |= O_APPEND;
860
861 if (open_options & eOpenOptionTruncate)
862 mode |= O_TRUNC;
863
864 if (open_options & eOpenOptionNonBlocking)
865 mode |= O_NONBLOCK;
866
867 if (open_options & eOpenOptionCanCreateNewOnly)
868 mode |= O_CREAT | O_EXCL;
869 else if (open_options & eOpenOptionCanCreate)
870 mode |= O_CREAT;
871
872 return mode;
873}
874
875llvm::Expected<SerialPort::Options>
876SerialPort::OptionsFromURL(llvm::StringRef urlqs) {
877 SerialPort::Options serial_options;
878 for (llvm::StringRef x : llvm::split(urlqs, '&')) {
879 if (x.consume_front("baud=")) {
880 unsigned int baud_rate;
881 if (!llvm::to_integer(x, baud_rate, 10))
882 return llvm::createStringError(llvm::inconvertibleErrorCode(),
883 "Invalid baud rate: %s",
884 x.str().c_str());
885 serial_options.BaudRate = baud_rate;
886 } else if (x.consume_front("parity=")) {
887 serial_options.Parity =
888 llvm::StringSwitch<std::optional<Terminal::Parity>>(x)
889 .Case("no", Terminal::Parity::No)
890 .Case("even", Terminal::Parity::Even)
891 .Case("odd", Terminal::Parity::Odd)
892 .Case("mark", Terminal::Parity::Mark)
893 .Case("space", Terminal::Parity::Space)
894 .Default(std::nullopt);
895 if (!serial_options.Parity)
896 return llvm::createStringError(
897 llvm::inconvertibleErrorCode(),
898 "Invalid parity (must be no, even, odd, mark or space): %s",
899 x.str().c_str());
900 } else if (x.consume_front("parity-check=")) {
901 serial_options.ParityCheck =
902 llvm::StringSwitch<std::optional<Terminal::ParityCheck>>(x)
903 .Case("no", Terminal::ParityCheck::No)
905 .Case("ignore", Terminal::ParityCheck::Ignore)
906 // "mark" mode is not currently supported as it requires special
907 // input processing
908 // .Case("mark", Terminal::ParityCheck::Mark)
909 .Default(std::nullopt);
910 if (!serial_options.ParityCheck)
911 return llvm::createStringError(
912 llvm::inconvertibleErrorCode(),
913 "Invalid parity-check (must be no, replace, ignore or mark): %s",
914 x.str().c_str());
915 } else if (x.consume_front("stop-bits=")) {
916 unsigned int stop_bits;
917 if (!llvm::to_integer(x, stop_bits, 10) ||
918 (stop_bits != 1 && stop_bits != 2))
919 return llvm::createStringError(
920 llvm::inconvertibleErrorCode(),
921 "Invalid stop bit number (must be 1 or 2): %s", x.str().c_str());
922 serial_options.StopBits = stop_bits;
923 } else
924 return llvm::createStringError(llvm::inconvertibleErrorCode(),
925 "Unknown parameter: %s", x.str().c_str());
926 }
927 return serial_options;
928}
929
930llvm::Expected<std::unique_ptr<SerialPort>>
931SerialPort::Create(int fd, OpenOptions options, Options serial_options,
932 bool transfer_ownership) {
933 std::unique_ptr<SerialPort> out{
934 new SerialPort(fd, options, serial_options, transfer_ownership)};
935
936 if (!out->GetIsInteractive())
937 return llvm::createStringError(llvm::inconvertibleErrorCode(),
938 "the specified file is not a teletype");
939
940 Terminal term{fd};
941 if (llvm::Error error = term.SetRaw())
942 return std::move(error);
943 if (serial_options.BaudRate) {
944 if (llvm::Error error = term.SetBaudRate(*serial_options.BaudRate))
945 return std::move(error);
946 }
947 if (serial_options.Parity) {
948 if (llvm::Error error = term.SetParity(*serial_options.Parity))
949 return std::move(error);
950 }
951 if (serial_options.ParityCheck) {
952 if (llvm::Error error = term.SetParityCheck(*serial_options.ParityCheck))
953 return std::move(error);
954 }
955 if (serial_options.StopBits) {
956 if (llvm::Error error = term.SetStopBits(*serial_options.StopBits))
957 return std::move(error);
958 }
959
960 return std::move(out);
961}
962
964 SerialPort::Options serial_options,
965 bool transfer_ownership)
966 : NativeFile(fd, options, transfer_ownership), m_state(fd) {}
967
969 m_state.Restore();
970 return NativeFile::Close();
971}
972
973char File::ID = 0;
974char NativeFile::ID = 0;
975char SerialPort::ID = 0;
static llvm::raw_ostream & error(Stream &strm)
void * HANDLE
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
static constexpr OpenOptions OpenOptionsModeMask
Definition File.h:69
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:371
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:370
static bool DescriptorIsValid(int descriptor)
Definition File.h:74
static mode_t ConvertOpenOptionsForPOSIXOpen(OpenOptions open_options)
Definition File.cpp:846
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:365
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:372
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:429
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:439
Status GetFileSpec(FileSpec &file_spec) const override
Get the file specification for this file, if possible.
Definition File.cpp:403
FILE * GetStream() override
Get the underlying libc stream for this file, or NULL.
Definition File.cpp:331
Status Sync() override
Sync to disk.
Definition File.cpp:548
std::mutex offset_access_mutex
Definition File.h:455
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition File.cpp:366
WaitableHandle GetWaitableHandle() override
Get a handle that can be used for OS polling interfaces, such as WaitForMultipleObjects,...
Definition File.cpp:323
Status Flush() override
Flush the current stream.
Definition File.cpp:532
bool StreamIsValidUnlocked() const
Definition File.h:434
ValueGuard DescriptorIsValid() const
Definition File.h:436
llvm::Expected< OpenOptions > GetOptions() const override
Return the OpenOptions for this file.
Definition File.cpp:302
OpenOptions m_options
Definition File.h:453
off_t SeekFromCurrent(off_t offset, Status *error_ptr=nullptr) override
Seek to an offset relative to the current file position.
Definition File.cpp:470
size_t PrintfVarArg(const char *format, va_list args) override
Output printf formatted output to the stream.
Definition File.cpp:838
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:639
int GetDescriptor() const override
Get underlying OS file descriptor for this file, or kInvalidDescriptor.
Definition File.cpp:304
Status Read(void *buf, size_t &num_bytes) override
Read bytes from a file from the current file position into buf.
Definition File.cpp:571
bool IsValid() const override
IsValid.
Definition File.cpp:296
std::mutex m_descriptor_mutex
Definition File.h:448
std::mutex m_stream_mutex
Definition File.h:451
ValueGuard StreamIsValid() const
Definition File.h:441
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:501
static llvm::Expected< std::unique_ptr< SerialPort > > Create(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
Definition File.cpp:931
TerminalState m_state
Definition File.h:500
SerialPort(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
Definition File.cpp:963
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition File.cpp:968
static llvm::Expected< Options > OptionsFromURL(llvm::StringRef urlqs)
Definition File.cpp:876
An error handling class.
Definition Status.h:118
void Clear()
Clear the object state.
Definition Status.cpp:214
static Status FromErrno()
Set the current error to errno.
Definition Status.cpp:299
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:469
std::optional< unsigned int > StopBits
Definition File.h:470
std::optional< Terminal::Parity > Parity
Definition File.h:468
std::optional< unsigned int > BaudRate
Definition File.h:467
#define S_IRWXG
#define O_NONBLOCK
#define S_IRWXO
#define PATH_MAX
#define S_IRWXU