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
40using namespace lldb;
41using namespace lldb_private;
42using llvm::Expected;
43
44Expected<const char *>
49
50 if (options & File::eOpenOptionAppend) {
53 return "a+x";
54 else
55 return "a+";
56 } else if (rw == File::eOpenOptionWriteOnly) {
58 return "ax";
59 else
60 return "a";
61 }
62 } else if (rw == File::eOpenOptionReadWrite) {
63 if (options & File::eOpenOptionCanCreate) {
65 return "w+x";
66 else
67 return "w+";
68 } else
69 return "r+";
70 } else if (rw == File::eOpenOptionWriteOnly) {
71 return "w";
72 } else if (rw == File::eOpenOptionReadOnly) {
73 return "r";
74 }
75 return llvm::createStringError(
76 llvm::inconvertibleErrorCode(),
77 "invalid options, cannot convert to mode string");
78}
79
80Expected<File::OpenOptions> File::GetOptionsFromMode(llvm::StringRef mode) {
81 OpenOptions opts =
82 llvm::StringSwitch<OpenOptions>(mode)
83 .Cases("r", "rb", eOpenOptionReadOnly)
84 .Cases("w", "wb", eOpenOptionWriteOnly)
85 .Cases("a", "ab",
88 .Cases("r+", "rb+", "r+b", eOpenOptionReadWrite)
89 .Cases("w+", "wb+", "w+b",
92 .Cases("a+", "ab+", "a+b",
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
119}
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
197}
198
203}
204
209}
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) {
243 error.SetErrorToErrno();
244 return 0;
245 }
246 error.Clear();
247 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
248}
249
251 std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex, m_stream_mutex);
253}
254
255Expected<File::OpenOptions> NativeFile::GetOptions() const { return m_options; }
256
258 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
259 return m_descriptor;
260 }
261
262 // Don't open the file descriptor if we don't need to, just get it from the
263 // stream if we have one.
264 if (ValueGuard stream_guard = StreamIsValid()) {
265#if defined(_WIN32)
266 return _fileno(m_stream);
267#else
268 return fileno(m_stream);
269#endif
270 }
271
272 // Invalid descriptor and invalid stream, return invalid descriptor.
273 return kInvalidDescriptor;
274}
275
277 return GetDescriptor();
278}
279
281 ValueGuard stream_guard = StreamIsValid();
282 if (!stream_guard) {
283 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
285 if (!mode)
286 llvm::consumeError(mode.takeError());
287 else {
288 if (!m_own_descriptor) {
289// We must duplicate the file descriptor if we don't own it because when you
290// call fdopen, the stream will own the fd
291#ifdef _WIN32
292 m_descriptor = ::_dup(m_descriptor);
293#else
295#endif
296 m_own_descriptor = true;
297 }
298
299 m_stream = llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor,
300 mode.get());
301
302 // If we got a stream, then we own the stream and should no longer own
303 // the descriptor because fclose() will close it for us
304
305 if (m_stream) {
306 m_own_stream = true;
307 m_own_descriptor = false;
308 }
309 }
310 }
311 }
312 return m_stream;
313}
314
316 std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex, m_stream_mutex);
317
319
320 if (StreamIsValidUnlocked()) {
321 if (m_own_stream) {
322 if (::fclose(m_stream) == EOF)
323 error.SetErrorToErrno();
324 } else {
328
329 if (rw == eOpenOptionWriteOnly || rw == eOpenOptionReadWrite) {
330 if (::fflush(m_stream) == EOF)
331 error.SetErrorToErrno();
332 }
333 }
334 }
335
337 if (::close(m_descriptor) != 0)
338 error.SetErrorToErrno();
339 }
340
342 m_own_stream = false;
344 m_own_descriptor = false;
348 return error;
349}
350
353#ifdef F_GETPATH
354 if (IsValid()) {
355 char path[PATH_MAX];
356 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
357 error.SetErrorToErrno();
358 else
359 file_spec.SetFile(path, FileSpec::Style::native);
360 } else {
361 error.SetErrorString("invalid file handle");
362 }
363#elif defined(__linux__)
364 char proc[64];
365 char path[PATH_MAX];
366 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
367 error.SetErrorString("cannot resolve file descriptor");
368 else {
369 ssize_t len;
370 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
371 error.SetErrorToErrno();
372 else {
373 path[len] = '\0';
374 file_spec.SetFile(path, FileSpec::Style::native);
375 }
376 }
377#else
378 error.SetErrorString(
379 "NativeFile::GetFileSpec is not supported on this platform");
380#endif
381
382 if (error.Fail())
383 file_spec.Clear();
384 return error;
385}
386
387off_t NativeFile::SeekFromStart(off_t offset, Status *error_ptr) {
388 off_t result = 0;
389 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
390 result = ::lseek(m_descriptor, offset, SEEK_SET);
391
392 if (error_ptr) {
393 if (result == -1)
394 error_ptr->SetErrorToErrno();
395 else
396 error_ptr->Clear();
397 }
398 return result;
399 }
400
401 if (ValueGuard stream_guard = StreamIsValid()) {
402 result = ::fseek(m_stream, offset, SEEK_SET);
403
404 if (error_ptr) {
405 if (result == -1)
406 error_ptr->SetErrorToErrno();
407 else
408 error_ptr->Clear();
409 }
410 return result;
411 }
412
413 if (error_ptr)
414 error_ptr->SetErrorString("invalid file handle");
415 return result;
416}
417
418off_t NativeFile::SeekFromCurrent(off_t offset, Status *error_ptr) {
419 off_t result = -1;
420 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
421 result = ::lseek(m_descriptor, offset, SEEK_CUR);
422
423 if (error_ptr) {
424 if (result == -1)
425 error_ptr->SetErrorToErrno();
426 else
427 error_ptr->Clear();
428 }
429 return result;
430 }
431
432 if (ValueGuard stream_guard = StreamIsValid()) {
433 result = ::fseek(m_stream, offset, SEEK_CUR);
434
435 if (error_ptr) {
436 if (result == -1)
437 error_ptr->SetErrorToErrno();
438 else
439 error_ptr->Clear();
440 }
441 return result;
442 }
443
444 if (error_ptr)
445 error_ptr->SetErrorString("invalid file handle");
446 return result;
447}
448
449off_t NativeFile::SeekFromEnd(off_t offset, Status *error_ptr) {
450 off_t result = -1;
451 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
452 result = ::lseek(m_descriptor, offset, SEEK_END);
453
454 if (error_ptr) {
455 if (result == -1)
456 error_ptr->SetErrorToErrno();
457 else
458 error_ptr->Clear();
459 }
460 return result;
461 }
462
463 if (ValueGuard stream_guard = StreamIsValid()) {
464 result = ::fseek(m_stream, offset, SEEK_END);
465
466 if (error_ptr) {
467 if (result == -1)
468 error_ptr->SetErrorToErrno();
469 else
470 error_ptr->Clear();
471 }
472 }
473
474 if (error_ptr)
475 error_ptr->SetErrorString("invalid file handle");
476 return result;
477}
478
481 if (ValueGuard stream_guard = StreamIsValid()) {
482 if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF)
483 error.SetErrorToErrno();
484 return error;
485 }
486
487 {
488 ValueGuard descriptor_guard = DescriptorIsValid();
489 if (!descriptor_guard)
490 error.SetErrorString("invalid file handle");
491 }
492 return error;
493}
494
497 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
498#ifdef _WIN32
499 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
500 if (err == 0)
501 error.SetErrorToGenericError();
502#else
503 if (llvm::sys::RetryAfterSignal(-1, ::fsync, m_descriptor) == -1)
504 error.SetErrorToErrno();
505#endif
506 } else {
507 error.SetErrorString("invalid file handle");
508 }
509 return error;
510}
511
512#if defined(__APPLE__)
513// Darwin kernels only can read/write <= INT_MAX bytes
514#define MAX_READ_SIZE INT_MAX
515#define MAX_WRITE_SIZE INT_MAX
516#endif
517
518Status NativeFile::Read(void *buf, size_t &num_bytes) {
520
521#if defined(MAX_READ_SIZE)
522 if (num_bytes > MAX_READ_SIZE) {
523 uint8_t *p = (uint8_t *)buf;
524 size_t bytes_left = num_bytes;
525 // Init the num_bytes read to zero
526 num_bytes = 0;
527
528 while (bytes_left > 0) {
529 size_t curr_num_bytes;
530 if (bytes_left > MAX_READ_SIZE)
531 curr_num_bytes = MAX_READ_SIZE;
532 else
533 curr_num_bytes = bytes_left;
534
535 error = Read(p + num_bytes, curr_num_bytes);
536
537 // Update how many bytes were read
538 num_bytes += curr_num_bytes;
539 if (bytes_left < curr_num_bytes)
540 bytes_left = 0;
541 else
542 bytes_left -= curr_num_bytes;
543
544 if (error.Fail())
545 break;
546 }
547 return error;
548 }
549#endif
550
551 ssize_t bytes_read = -1;
552 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
553 bytes_read =
554 llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes);
555 if (bytes_read == -1) {
556 error.SetErrorToErrno();
557 num_bytes = 0;
558 } else
559 num_bytes = bytes_read;
560 return error;
561 }
562
563 if (ValueGuard file_lock = StreamIsValid()) {
564 bytes_read = ::fread(buf, 1, num_bytes, m_stream);
565
566 if (bytes_read == 0) {
567 if (::feof(m_stream))
568 error.SetErrorString("feof");
569 else if (::ferror(m_stream))
570 error.SetErrorString("ferror");
571 num_bytes = 0;
572 } else
573 num_bytes = bytes_read;
574 return error;
575 }
576
577 num_bytes = 0;
578 error.SetErrorString("invalid file handle");
579 return error;
580}
581
582Status NativeFile::Write(const void *buf, size_t &num_bytes) {
584
585#if defined(MAX_WRITE_SIZE)
586 if (num_bytes > MAX_WRITE_SIZE) {
587 const uint8_t *p = (const uint8_t *)buf;
588 size_t bytes_left = num_bytes;
589 // Init the num_bytes written to zero
590 num_bytes = 0;
591
592 while (bytes_left > 0) {
593 size_t curr_num_bytes;
594 if (bytes_left > MAX_WRITE_SIZE)
595 curr_num_bytes = MAX_WRITE_SIZE;
596 else
597 curr_num_bytes = bytes_left;
598
599 error = Write(p + num_bytes, curr_num_bytes);
600
601 // Update how many bytes were read
602 num_bytes += curr_num_bytes;
603 if (bytes_left < curr_num_bytes)
604 bytes_left = 0;
605 else
606 bytes_left -= curr_num_bytes;
607
608 if (error.Fail())
609 break;
610 }
611 return error;
612 }
613#endif
614
615 ssize_t bytes_written = -1;
616 if (ValueGuard descriptor_guard = DescriptorIsValid()) {
617 bytes_written =
618 llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes);
619 if (bytes_written == -1) {
620 error.SetErrorToErrno();
621 num_bytes = 0;
622 } else
623 num_bytes = bytes_written;
624 return error;
625 }
626
627 if (ValueGuard stream_guard = StreamIsValid()) {
628 bytes_written = ::fwrite(buf, 1, num_bytes, m_stream);
629
630 if (bytes_written == 0) {
631 if (::feof(m_stream))
632 error.SetErrorString("feof");
633 else if (::ferror(m_stream))
634 error.SetErrorString("ferror");
635 num_bytes = 0;
636 } else
637 num_bytes = bytes_written;
638 return error;
639 }
640
641 num_bytes = 0;
642 error.SetErrorString("invalid file handle");
643 return error;
644}
645
646Status NativeFile::Read(void *buf, size_t &num_bytes, off_t &offset) {
648
649#if defined(MAX_READ_SIZE)
650 if (num_bytes > MAX_READ_SIZE) {
651 uint8_t *p = (uint8_t *)buf;
652 size_t bytes_left = num_bytes;
653 // Init the num_bytes read to zero
654 num_bytes = 0;
655
656 while (bytes_left > 0) {
657 size_t curr_num_bytes;
658 if (bytes_left > MAX_READ_SIZE)
659 curr_num_bytes = MAX_READ_SIZE;
660 else
661 curr_num_bytes = bytes_left;
662
663 error = Read(p + num_bytes, curr_num_bytes, offset);
664
665 // Update how many bytes were read
666 num_bytes += curr_num_bytes;
667 if (bytes_left < curr_num_bytes)
668 bytes_left = 0;
669 else
670 bytes_left -= curr_num_bytes;
671
672 if (error.Fail())
673 break;
674 }
675 return error;
676 }
677#endif
678
679#ifndef _WIN32
680 int fd = GetDescriptor();
681 if (fd != kInvalidDescriptor) {
682 ssize_t bytes_read =
683 llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset);
684 if (bytes_read < 0) {
685 num_bytes = 0;
686 error.SetErrorToErrno();
687 } else {
688 offset += bytes_read;
689 num_bytes = bytes_read;
690 }
691 } else {
692 num_bytes = 0;
693 error.SetErrorString("invalid file handle");
694 }
695#else
696 std::lock_guard<std::mutex> guard(offset_access_mutex);
697 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
698 SeekFromStart(offset);
699 error = Read(buf, num_bytes);
700 if (!error.Fail())
701 SeekFromStart(cur);
702#endif
703 return error;
704}
705
706Status NativeFile::Write(const void *buf, size_t &num_bytes, off_t &offset) {
708
709#if defined(MAX_WRITE_SIZE)
710 if (num_bytes > MAX_WRITE_SIZE) {
711 const uint8_t *p = (const uint8_t *)buf;
712 size_t bytes_left = num_bytes;
713 // Init the num_bytes written to zero
714 num_bytes = 0;
715
716 while (bytes_left > 0) {
717 size_t curr_num_bytes;
718 if (bytes_left > MAX_WRITE_SIZE)
719 curr_num_bytes = MAX_WRITE_SIZE;
720 else
721 curr_num_bytes = bytes_left;
722
723 error = Write(p + num_bytes, curr_num_bytes, offset);
724
725 // Update how many bytes were read
726 num_bytes += curr_num_bytes;
727 if (bytes_left < curr_num_bytes)
728 bytes_left = 0;
729 else
730 bytes_left -= curr_num_bytes;
731
732 if (error.Fail())
733 break;
734 }
735 return error;
736 }
737#endif
738
739 int fd = GetDescriptor();
740 if (fd != kInvalidDescriptor) {
741#ifndef _WIN32
742 ssize_t bytes_written =
743 llvm::sys::RetryAfterSignal(-1, ::pwrite, m_descriptor, buf, num_bytes, offset);
744 if (bytes_written < 0) {
745 num_bytes = 0;
746 error.SetErrorToErrno();
747 } else {
748 offset += bytes_written;
749 num_bytes = bytes_written;
750 }
751#else
752 std::lock_guard<std::mutex> guard(offset_access_mutex);
753 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
754 SeekFromStart(offset);
755 error = Write(buf, num_bytes);
756 long after = ::lseek(m_descriptor, 0, SEEK_CUR);
757
758 if (!error.Fail())
759 SeekFromStart(cur);
760
761 offset = after;
762#endif
763 } else {
764 num_bytes = 0;
765 error.SetErrorString("invalid file handle");
766 }
767 return error;
768}
769
770size_t NativeFile::PrintfVarArg(const char *format, va_list args) {
771 if (StreamIsValid()) {
772 return ::vfprintf(m_stream, format, args);
773 } else {
774 return File::PrintfVarArg(format, args);
775 }
776}
777
779 mode_t mode = 0;
783 if (rw == eOpenOptionReadWrite)
784 mode |= O_RDWR;
785 else if (rw == eOpenOptionWriteOnly)
786 mode |= O_WRONLY;
787 else if (rw == eOpenOptionReadOnly)
788 mode |= O_RDONLY;
789
790 if (open_options & eOpenOptionAppend)
791 mode |= O_APPEND;
792
793 if (open_options & eOpenOptionTruncate)
794 mode |= O_TRUNC;
795
796 if (open_options & eOpenOptionNonBlocking)
797 mode |= O_NONBLOCK;
798
799 if (open_options & eOpenOptionCanCreateNewOnly)
800 mode |= O_CREAT | O_EXCL;
801 else if (open_options & eOpenOptionCanCreate)
802 mode |= O_CREAT;
803
804 return mode;
805}
806
807llvm::Expected<SerialPort::Options>
808SerialPort::OptionsFromURL(llvm::StringRef urlqs) {
809 SerialPort::Options serial_options;
810 for (llvm::StringRef x : llvm::split(urlqs, '&')) {
811 if (x.consume_front("baud=")) {
812 unsigned int baud_rate;
813 if (!llvm::to_integer(x, baud_rate, 10))
814 return llvm::createStringError(llvm::inconvertibleErrorCode(),
815 "Invalid baud rate: %s",
816 x.str().c_str());
817 serial_options.BaudRate = baud_rate;
818 } else if (x.consume_front("parity=")) {
819 serial_options.Parity =
820 llvm::StringSwitch<std::optional<Terminal::Parity>>(x)
821 .Case("no", Terminal::Parity::No)
822 .Case("even", Terminal::Parity::Even)
823 .Case("odd", Terminal::Parity::Odd)
824 .Case("mark", Terminal::Parity::Mark)
825 .Case("space", Terminal::Parity::Space)
826 .Default(std::nullopt);
827 if (!serial_options.Parity)
828 return llvm::createStringError(
829 llvm::inconvertibleErrorCode(),
830 "Invalid parity (must be no, even, odd, mark or space): %s",
831 x.str().c_str());
832 } else if (x.consume_front("parity-check=")) {
833 serial_options.ParityCheck =
834 llvm::StringSwitch<std::optional<Terminal::ParityCheck>>(x)
835 .Case("no", Terminal::ParityCheck::No)
837 .Case("ignore", Terminal::ParityCheck::Ignore)
838 // "mark" mode is not currently supported as it requires special
839 // input processing
840 // .Case("mark", Terminal::ParityCheck::Mark)
841 .Default(std::nullopt);
842 if (!serial_options.ParityCheck)
843 return llvm::createStringError(
844 llvm::inconvertibleErrorCode(),
845 "Invalid parity-check (must be no, replace, ignore or mark): %s",
846 x.str().c_str());
847 } else if (x.consume_front("stop-bits=")) {
848 unsigned int stop_bits;
849 if (!llvm::to_integer(x, stop_bits, 10) ||
850 (stop_bits != 1 && stop_bits != 2))
851 return llvm::createStringError(
852 llvm::inconvertibleErrorCode(),
853 "Invalid stop bit number (must be 1 or 2): %s", x.str().c_str());
854 serial_options.StopBits = stop_bits;
855 } else
856 return llvm::createStringError(llvm::inconvertibleErrorCode(),
857 "Unknown parameter: %s", x.str().c_str());
858 }
859 return serial_options;
860}
861
862llvm::Expected<std::unique_ptr<SerialPort>>
863SerialPort::Create(int fd, OpenOptions options, Options serial_options,
864 bool transfer_ownership) {
865 std::unique_ptr<SerialPort> out{
866 new SerialPort(fd, options, serial_options, transfer_ownership)};
867
868 if (!out->GetIsInteractive())
869 return llvm::createStringError(llvm::inconvertibleErrorCode(),
870 "the specified file is not a teletype");
871
872 Terminal term{fd};
873 if (llvm::Error error = term.SetRaw())
874 return std::move(error);
875 if (serial_options.BaudRate) {
876 if (llvm::Error error = term.SetBaudRate(*serial_options.BaudRate))
877 return std::move(error);
878 }
879 if (serial_options.Parity) {
880 if (llvm::Error error = term.SetParity(*serial_options.Parity))
881 return std::move(error);
882 }
883 if (serial_options.ParityCheck) {
884 if (llvm::Error error = term.SetParityCheck(*serial_options.ParityCheck))
885 return std::move(error);
886 }
887 if (serial_options.StopBits) {
888 if (llvm::Error error = term.SetStopBits(*serial_options.StopBits))
889 return std::move(error);
890 }
891
892 return std::move(out);
893}
894
896 SerialPort::Options serial_options,
897 bool transfer_ownership)
898 : NativeFile(fd, options, transfer_ownership), m_state(fd) {}
899
902 return NativeFile::Close();
903}
904
905char File::ID = 0;
906char NativeFile::ID = 0;
907char SerialPort::ID = 0;
static llvm::raw_ostream & error(Stream &strm)
A file utility class.
Definition: FileSpec.h:56
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:778
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:45
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
@ eOpenOptionInvalid
Definition: File.h:65
@ eOpenOptionReadWrite
Definition: File.h:53
@ eOpenOptionWriteOnly
Definition: File.h:52
@ eOpenOptionAppend
Definition: File.h:54
@ 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:80
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:30
bool DescriptorIsValidUnlocked() const
Definition: File.h:425
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:387
static char ID
Definition: File.h:411
Status GetFileSpec(FileSpec &file_spec) const override
Get the file specification for this file, if possible.
Definition: File.cpp:351
FILE * GetStream() override
Get the underlying libc stream for this file, or NULL.
Definition: File.cpp:280
Status Sync() override
Sync to disk.
Definition: File.cpp:495
std::mutex offset_access_mutex
Definition: File.h:451
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition: File.cpp:315
WaitableHandle GetWaitableHandle() override
Get a handle that can be used for OS polling interfaces, such as WaitForMultipleObjects,...
Definition: File.cpp:276
Status Flush() override
Flush the current stream.
Definition: File.cpp:479
bool StreamIsValidUnlocked() const
Definition: File.h:430
ValueGuard DescriptorIsValid() const
Definition: File.h:432
llvm::Expected< OpenOptions > GetOptions() const override
Return the OpenOptions for this file.
Definition: File.cpp:255
OpenOptions m_options
Definition: File.h:449
off_t SeekFromCurrent(off_t offset, Status *error_ptr=nullptr) override
Seek to an offset relative to the current file position.
Definition: File.cpp:418
size_t PrintfVarArg(const char *format, va_list args) override
Output printf formatted output to the stream.
Definition: File.cpp:770
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:582
int GetDescriptor() const override
Get underlying OS file descriptor for this file, or kInvalidDescriptor.
Definition: File.cpp:257
Status Read(void *buf, size_t &num_bytes) override
Read bytes from a file from the current file position into buf.
Definition: File.cpp:518
bool IsValid() const override
IsValid.
Definition: File.cpp:250
std::mutex m_descriptor_mutex
Definition: File.h:444
std::mutex m_stream_mutex
Definition: File.h:447
ValueGuard StreamIsValid() const
Definition: File.h:437
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:449
static llvm::Expected< std::unique_ptr< SerialPort > > Create(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
Definition: File.cpp:863
TerminalState m_state
Definition: File.h:494
SerialPort(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
Definition: File.cpp:895
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition: File.cpp:900
static char ID
Definition: File.h:481
static llvm::Expected< Options > OptionsFromURL(llvm::StringRef urlqs)
Definition: File.cpp:808
An error handling class.
Definition: Status.h:44
void Clear()
Clear the object state.
Definition: Status.cpp:166
void SetErrorToErrno()
Set the current error to errno.
Definition: Status.cpp:214
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:232
bool Restore() const
Restore the TTY state to the cached state.
Definition: Terminal.cpp:436
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
Definition: SBAddress.h:15
std::optional< Terminal::ParityCheck > ParityCheck
Definition: File.h:463
std::optional< unsigned int > StopBits
Definition: File.h:464
std::optional< Terminal::Parity > Parity
Definition: File.h:462
std::optional< unsigned int > BaudRate
Definition: File.h:461
#define S_IRWXG
#define O_NONBLOCK
#define S_IRWXO
#define PATH_MAX
#define S_IRWXU