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 }
525
526 if (error_ptr)
527 *error_ptr = Status::FromErrorString("invalid file handle");
528 return result;
529}
530
533 if (ValueGuard stream_guard = StreamIsValid()) {
534 if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF)
536 return error;
537 }
538
539 {
540 ValueGuard descriptor_guard = DescriptorIsValid();
541 if (!descriptor_guard)
542 error = Status::FromErrorString("invalid file handle");
543 }
544 return error;
545}
546
549 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
550#ifdef _WIN32
551 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
552 if (err == 0)
553 error = Status::FromErrorString("unknown error");
554#else
555 if (llvm::sys::RetryAfterSignal(-1, ::fsync, m_descriptor) == -1)
557#endif
558 } else {
559 error = Status::FromErrorString("invalid file handle");
560 }
561 return error;
562}
563
564#if defined(__APPLE__)
565// Darwin kernels only can read/write <= INT_MAX bytes
566#define MAX_READ_SIZE INT_MAX
567#define MAX_WRITE_SIZE INT_MAX
568#endif
569
570Status NativeFile::Read(void *buf, size_t &num_bytes) {
572
573 // Ensure the file is open for reading.
575 return Status(std::make_error_code(std::errc::bad_file_descriptor));
576
577#if defined(MAX_READ_SIZE)
578 if (num_bytes > MAX_READ_SIZE) {
579 uint8_t *p = (uint8_t *)buf;
580 size_t bytes_left = num_bytes;
581 // Init the num_bytes read to zero
582 num_bytes = 0;
583
584 while (bytes_left > 0) {
585 size_t curr_num_bytes;
586 if (bytes_left > MAX_READ_SIZE)
587 curr_num_bytes = MAX_READ_SIZE;
588 else
589 curr_num_bytes = bytes_left;
590
591 error = Read(p + num_bytes, curr_num_bytes);
592
593 // Update how many bytes were read
594 num_bytes += curr_num_bytes;
595 if (bytes_left < curr_num_bytes)
596 bytes_left = 0;
597 else
598 bytes_left -= curr_num_bytes;
599
600 if (error.Fail())
601 break;
602 }
603 return error;
604 }
605#endif
606
607 ssize_t bytes_read = -1;
608 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
609 bytes_read =
610 llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes);
611 if (bytes_read == -1) {
613 num_bytes = 0;
614 } else
615 num_bytes = bytes_read;
616 return error;
617 }
618
619 if (ValueGuard file_lock = StreamIsValid()) {
620 bytes_read = ::fread(buf, 1, num_bytes, m_stream);
621
622 if (bytes_read == 0) {
623 if (::feof(m_stream))
625 else if (::ferror(m_stream))
626 error = Status::FromErrorString("ferror");
627 num_bytes = 0;
628 } else
629 num_bytes = bytes_read;
630 return error;
631 }
632
633 num_bytes = 0;
634 error = Status::FromErrorString("invalid file handle");
635 return error;
636}
637
638Status NativeFile::Write(const void *buf, size_t &num_bytes) {
640
641 // Ensure the file is open for writing.
643 return Status(std::make_error_code(std::errc::bad_file_descriptor));
644
645#if defined(MAX_WRITE_SIZE)
646 if (num_bytes > MAX_WRITE_SIZE) {
647 const uint8_t *p = (const uint8_t *)buf;
648 size_t bytes_left = num_bytes;
649 // Init the num_bytes written to zero
650 num_bytes = 0;
651
652 while (bytes_left > 0) {
653 size_t curr_num_bytes;
654 if (bytes_left > MAX_WRITE_SIZE)
655 curr_num_bytes = MAX_WRITE_SIZE;
656 else
657 curr_num_bytes = bytes_left;
658
659 error = Write(p + num_bytes, curr_num_bytes);
660
661 // Update how many bytes were read
662 num_bytes += curr_num_bytes;
663 if (bytes_left < curr_num_bytes)
664 bytes_left = 0;
665 else
666 bytes_left -= curr_num_bytes;
667
668 if (error.Fail())
669 break;
670 }
671 return error;
672 }
673#endif
674
675 ssize_t bytes_written = -1;
676 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
677 bytes_written =
678 llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes);
679 if (bytes_written == -1) {
681 num_bytes = 0;
682 } else
683 num_bytes = bytes_written;
684 return error;
685 }
686
687 if (ValueGuard stream_guard = StreamIsValid()) {
688#ifdef _WIN32
689 if (is_windows_console) {
690 llvm::raw_fd_ostream(_fileno(m_stream), false)
691 .write((const char *)buf, num_bytes);
692 return error;
693 }
694#endif
695 bytes_written = ::fwrite(buf, 1, num_bytes, m_stream);
696
697 if (bytes_written == 0) {
698 if (::feof(m_stream))
700 else if (::ferror(m_stream))
701 error = Status::FromErrorString("ferror");
702 num_bytes = 0;
703 } else
704 num_bytes = bytes_written;
705 return error;
706 }
707
708 num_bytes = 0;
709 error = Status::FromErrorString("invalid file handle");
710 return error;
711}
712
713Status NativeFile::Read(void *buf, size_t &num_bytes, off_t &offset) {
715
716#if defined(MAX_READ_SIZE)
717 if (num_bytes > MAX_READ_SIZE) {
718 uint8_t *p = (uint8_t *)buf;
719 size_t bytes_left = num_bytes;
720 // Init the num_bytes read to zero
721 num_bytes = 0;
722
723 while (bytes_left > 0) {
724 size_t curr_num_bytes;
725 if (bytes_left > MAX_READ_SIZE)
726 curr_num_bytes = MAX_READ_SIZE;
727 else
728 curr_num_bytes = bytes_left;
729
730 error = Read(p + num_bytes, curr_num_bytes, offset);
731
732 // Update how many bytes were read
733 num_bytes += curr_num_bytes;
734 if (bytes_left < curr_num_bytes)
735 bytes_left = 0;
736 else
737 bytes_left -= curr_num_bytes;
738
739 if (error.Fail())
740 break;
741 }
742 return error;
743 }
744#endif
745
746#ifndef _WIN32
747 int fd = GetDescriptor();
748 if (fd != kInvalidDescriptor) {
749 ssize_t bytes_read =
750 llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset);
751 if (bytes_read < 0) {
752 num_bytes = 0;
754 } else {
755 offset += bytes_read;
756 num_bytes = bytes_read;
757 }
758 } else {
759 num_bytes = 0;
760 error = Status::FromErrorString("invalid file handle");
761 }
762#else
763 std::lock_guard<std::mutex> guard(offset_access_mutex);
764 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
765 SeekFromStart(offset);
766 error = Read(buf, num_bytes);
767 if (!error.Fail())
768 SeekFromStart(cur);
769#endif
770 return error;
771}
772
773Status NativeFile::Write(const void *buf, size_t &num_bytes, off_t &offset) {
775
776#if defined(MAX_WRITE_SIZE)
777 if (num_bytes > MAX_WRITE_SIZE) {
778 const uint8_t *p = (const uint8_t *)buf;
779 size_t bytes_left = num_bytes;
780 // Init the num_bytes written to zero
781 num_bytes = 0;
782
783 while (bytes_left > 0) {
784 size_t curr_num_bytes;
785 if (bytes_left > MAX_WRITE_SIZE)
786 curr_num_bytes = MAX_WRITE_SIZE;
787 else
788 curr_num_bytes = bytes_left;
789
790 error = Write(p + num_bytes, curr_num_bytes, offset);
791
792 // Update how many bytes were read
793 num_bytes += curr_num_bytes;
794 if (bytes_left < curr_num_bytes)
795 bytes_left = 0;
796 else
797 bytes_left -= curr_num_bytes;
798
799 if (error.Fail())
800 break;
801 }
802 return error;
803 }
804#endif
805
806 int fd = GetDescriptor();
807 if (fd != kInvalidDescriptor) {
808#ifndef _WIN32
809 ssize_t bytes_written = llvm::sys::RetryAfterSignal(
810 -1, ::pwrite, m_descriptor, buf, num_bytes, offset);
811 if (bytes_written < 0) {
812 num_bytes = 0;
814 } else {
815 offset += bytes_written;
816 num_bytes = bytes_written;
817 }
818#else
819 std::lock_guard<std::mutex> guard(offset_access_mutex);
820 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
821 SeekFromStart(offset);
822 error = Write(buf, num_bytes);
823 long after = ::lseek(m_descriptor, 0, SEEK_CUR);
824
825 if (!error.Fail())
826 SeekFromStart(cur);
827
828 offset = after;
829#endif
830 } else {
831 num_bytes = 0;
832 error = Status::FromErrorString("invalid file handle");
833 }
834 return error;
835}
836
837size_t NativeFile::PrintfVarArg(const char *format, va_list args) {
838 if (StreamIsValid()) {
839 return ::vfprintf(m_stream, format, args);
840 } else {
841 return File::PrintfVarArg(format, args);
842 }
843}
844
846 mode_t mode = 0;
850 if (rw == eOpenOptionReadWrite)
851 mode |= O_RDWR;
852 else if (rw == eOpenOptionWriteOnly)
853 mode |= O_WRONLY;
854 else if (rw == eOpenOptionReadOnly)
855 mode |= O_RDONLY;
856
857 if (open_options & eOpenOptionAppend)
858 mode |= O_APPEND;
859
860 if (open_options & eOpenOptionTruncate)
861 mode |= O_TRUNC;
862
863 if (open_options & eOpenOptionNonBlocking)
864 mode |= O_NONBLOCK;
865
866 if (open_options & eOpenOptionCanCreateNewOnly)
867 mode |= O_CREAT | O_EXCL;
868 else if (open_options & eOpenOptionCanCreate)
869 mode |= O_CREAT;
870
871 return mode;
872}
873
874llvm::Expected<SerialPort::Options>
875SerialPort::OptionsFromURL(llvm::StringRef urlqs) {
876 SerialPort::Options serial_options;
877 for (llvm::StringRef x : llvm::split(urlqs, '&')) {
878 if (x.consume_front("baud=")) {
879 unsigned int baud_rate;
880 if (!llvm::to_integer(x, baud_rate, 10))
881 return llvm::createStringError(llvm::inconvertibleErrorCode(),
882 "Invalid baud rate: %s",
883 x.str().c_str());
884 serial_options.BaudRate = baud_rate;
885 } else if (x.consume_front("parity=")) {
886 serial_options.Parity =
887 llvm::StringSwitch<std::optional<Terminal::Parity>>(x)
888 .Case("no", Terminal::Parity::No)
889 .Case("even", Terminal::Parity::Even)
890 .Case("odd", Terminal::Parity::Odd)
891 .Case("mark", Terminal::Parity::Mark)
892 .Case("space", Terminal::Parity::Space)
893 .Default(std::nullopt);
894 if (!serial_options.Parity)
895 return llvm::createStringError(
896 llvm::inconvertibleErrorCode(),
897 "Invalid parity (must be no, even, odd, mark or space): %s",
898 x.str().c_str());
899 } else if (x.consume_front("parity-check=")) {
900 serial_options.ParityCheck =
901 llvm::StringSwitch<std::optional<Terminal::ParityCheck>>(x)
902 .Case("no", Terminal::ParityCheck::No)
904 .Case("ignore", Terminal::ParityCheck::Ignore)
905 // "mark" mode is not currently supported as it requires special
906 // input processing
907 // .Case("mark", Terminal::ParityCheck::Mark)
908 .Default(std::nullopt);
909 if (!serial_options.ParityCheck)
910 return llvm::createStringError(
911 llvm::inconvertibleErrorCode(),
912 "Invalid parity-check (must be no, replace, ignore or mark): %s",
913 x.str().c_str());
914 } else if (x.consume_front("stop-bits=")) {
915 unsigned int stop_bits;
916 if (!llvm::to_integer(x, stop_bits, 10) ||
917 (stop_bits != 1 && stop_bits != 2))
918 return llvm::createStringError(
919 llvm::inconvertibleErrorCode(),
920 "Invalid stop bit number (must be 1 or 2): %s", x.str().c_str());
921 serial_options.StopBits = stop_bits;
922 } else
923 return llvm::createStringError(llvm::inconvertibleErrorCode(),
924 "Unknown parameter: %s", x.str().c_str());
925 }
926 return serial_options;
927}
928
929llvm::Expected<std::unique_ptr<SerialPort>>
930SerialPort::Create(int fd, OpenOptions options, Options serial_options,
931 bool transfer_ownership) {
932 std::unique_ptr<SerialPort> out{
933 new SerialPort(fd, options, serial_options, transfer_ownership)};
934
935 if (!out->GetIsInteractive())
936 return llvm::createStringError(llvm::inconvertibleErrorCode(),
937 "the specified file is not a teletype");
938
939 Terminal term{fd};
940 if (llvm::Error error = term.SetRaw())
941 return std::move(error);
942 if (serial_options.BaudRate) {
943 if (llvm::Error error = term.SetBaudRate(*serial_options.BaudRate))
944 return std::move(error);
945 }
946 if (serial_options.Parity) {
947 if (llvm::Error error = term.SetParity(*serial_options.Parity))
948 return std::move(error);
949 }
950 if (serial_options.ParityCheck) {
951 if (llvm::Error error = term.SetParityCheck(*serial_options.ParityCheck))
952 return std::move(error);
953 }
954 if (serial_options.StopBits) {
955 if (llvm::Error error = term.SetStopBits(*serial_options.StopBits))
956 return std::move(error);
957 }
958
959 return std::move(out);
960}
961
963 SerialPort::Options serial_options,
964 bool transfer_ownership)
965 : NativeFile(fd, options, transfer_ownership), m_state(fd) {}
966
968 m_state.Restore();
969 return NativeFile::Close();
970}
971
972char File::ID = 0;
973char NativeFile::ID = 0;
974char 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
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:845
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:547
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:531
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:837
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:638
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:570
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:930
TerminalState m_state
Definition File.h:500
SerialPort(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
Definition File.cpp:962
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition File.cpp:967
static llvm::Expected< Options > OptionsFromURL(llvm::StringRef urlqs)
Definition File.cpp:875
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: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