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/Support/ConvertUTF.h"
35#include "llvm/Support/Errno.h"
36#include "llvm/Support/FileSystem.h"
37#include "llvm/Support/Process.h"
38
39using namespace lldb;
40using namespace lldb_private;
41using llvm::Expected;
42
43Expected<const char *>
48
49 if (options & File::eOpenOptionAppend) {
52 return "a+x";
53 else
54 return "a+";
55 } else if (rw == File::eOpenOptionWriteOnly) {
57 return "ax";
58 else
59 return "a";
60 }
61 } else if (rw == File::eOpenOptionReadWrite) {
62 if (options & File::eOpenOptionCanCreate) {
64 return "w+x";
65 else
66 return "w+";
67 } else
68 return "r+";
69 } else if (rw == File::eOpenOptionWriteOnly) {
70 return "w";
71 } else if (rw == File::eOpenOptionReadOnly) {
72 return "r";
73 }
74 return llvm::createStringError(
75 llvm::inconvertibleErrorCode(),
76 "invalid options, cannot convert to mode string");
77}
78
79Expected<File::OpenOptions> File::GetOptionsFromMode(llvm::StringRef mode) {
80 OpenOptions opts =
81 llvm::StringSwitch<OpenOptions>(mode)
82 .Cases("r", "rb", eOpenOptionReadOnly)
83 .Cases("w", "wb", eOpenOptionWriteOnly)
84 .Cases("a", "ab",
87 .Cases("r+", "rb+", "r+b", eOpenOptionReadWrite)
88 .Cases("w+", "wb+", "w+b",
91 .Cases("a+", "ab+", "a+b",
94 .Default(eOpenOptionInvalid);
95 if (opts != eOpenOptionInvalid)
96 return opts;
97 return llvm::createStringError(
98 llvm::inconvertibleErrorCode(),
99 "invalid mode, cannot convert to File::OpenOptions");
100}
101
103FILE *File::kInvalidStream = nullptr;
104
105Status File::Read(void *buf, size_t &num_bytes) {
106 return std::error_code(ENOTSUP, std::system_category());
107}
108Status File::Write(const void *buf, size_t &num_bytes) {
109 return std::error_code(ENOTSUP, std::system_category());
110}
111
112bool File::IsValid() const { return false; }
113
114Status File::Close() { return Flush(); }
115
118}
119
121 file_spec.Clear();
122 return std::error_code(ENOTSUP, std::system_category());
123}
124
126
127FILE *File::GetStream() { return nullptr; }
128
129off_t File::SeekFromStart(off_t offset, Status *error_ptr) {
130 if (error_ptr)
131 *error_ptr = std::error_code(ENOTSUP, std::system_category());
132 return -1;
133}
134
135off_t File::SeekFromCurrent(off_t offset, Status *error_ptr) {
136 if (error_ptr)
137 *error_ptr = std::error_code(ENOTSUP, std::system_category());
138 return -1;
139}
140
141off_t File::SeekFromEnd(off_t offset, Status *error_ptr) {
142 if (error_ptr)
143 *error_ptr = std::error_code(ENOTSUP, std::system_category());
144 return -1;
145}
146
147Status File::Read(void *dst, size_t &num_bytes, off_t &offset) {
148 return std::error_code(ENOTSUP, std::system_category());
149}
150
151Status File::Write(const void *src, size_t &num_bytes, off_t &offset) {
152 return std::error_code(ENOTSUP, std::system_category());
153}
154
155Status File::Flush() { return Status(); }
156
157Status File::Sync() { return Flush(); }
158
160 const int fd = GetDescriptor();
161 if (!DescriptorIsValid(fd)) {
165 return;
166 }
169#if defined(_WIN32)
170 if (_isatty(fd)) {
173#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
175#endif
176 }
177#else
178 if (isatty(fd)) {
180 struct winsize window_size;
181 if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) {
182 if (window_size.ws_col > 0) {
184 if (llvm::sys::Process::FileDescriptorHasColors(fd))
186 }
187 }
188 }
189#endif
190}
191
196}
197
202}
203
208}
209
210size_t File::Printf(const char *format, ...) {
211 va_list args;
212 va_start(args, format);
213 size_t result = PrintfVarArg(format, args);
214 va_end(args);
215 return result;
216}
217
218size_t File::PrintfVarArg(const char *format, va_list args) {
219 llvm::SmallString<0> s;
220 if (VASprintf(s, format, args)) {
221 size_t written = s.size();;
222 Write(s.data(), written);
223 return written;
224 }
225 return 0;
226}
227
228Expected<File::OpenOptions> File::GetOptions() const {
229 return llvm::createStringError(
230 llvm::inconvertibleErrorCode(),
231 "GetOptions() not implemented for this File class");
232}
233
235 int fd = GetDescriptor();
236 if (!DescriptorIsValid(fd)) {
237 error = std::error_code(ENOTSUP, std::system_category());
238 return 0;
239 }
240 struct stat file_stats;
241 if (::fstat(fd, &file_stats) == -1) {
242 error.SetErrorToErrno();
243 return 0;
244 }
245 error.Clear();
246 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
247}
248
249Expected<File::OpenOptions> NativeFile::GetOptions() const { return m_options; }
250
252 if (DescriptorIsValid())
253 return m_descriptor;
254
255 // Don't open the file descriptor if we don't need to, just get it from the
256 // stream if we have one.
257 if (StreamIsValid()) {
258#if defined(_WIN32)
259 return _fileno(m_stream);
260#else
261 return fileno(m_stream);
262#endif
263 }
264
265 // Invalid descriptor and invalid stream, return invalid descriptor.
266 return kInvalidDescriptor;
267}
268
270 return GetDescriptor();
271}
272
274 if (!StreamIsValid()) {
275 if (DescriptorIsValid()) {
277 if (!mode)
278 llvm::consumeError(mode.takeError());
279 else {
280 if (!m_own_descriptor) {
281// We must duplicate the file descriptor if we don't own it because when you
282// call fdopen, the stream will own the fd
283#ifdef _WIN32
284 m_descriptor = ::_dup(GetDescriptor());
285#else
287#endif
288 m_own_descriptor = true;
289 }
290
291 m_stream = llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor,
292 mode.get());
293
294 // If we got a stream, then we own the stream and should no longer own
295 // the descriptor because fclose() will close it for us
296
297 if (m_stream) {
298 m_own_stream = true;
299 m_own_descriptor = false;
300 }
301 }
302 }
303 }
304 return m_stream;
305}
306
309 if (StreamIsValid()) {
310 if (m_own_stream) {
311 if (::fclose(m_stream) == EOF)
312 error.SetErrorToErrno();
313 } else {
317
318 if (rw == eOpenOptionWriteOnly || rw == eOpenOptionReadWrite) {
319 if (::fflush(m_stream) == EOF)
320 error.SetErrorToErrno();
321 }
322 }
323 }
325 if (::close(m_descriptor) != 0)
326 error.SetErrorToErrno();
327 }
331 m_own_stream = false;
332 m_own_descriptor = false;
335 return error;
336}
337
340#ifdef F_GETPATH
341 if (IsValid()) {
342 char path[PATH_MAX];
343 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
344 error.SetErrorToErrno();
345 else
346 file_spec.SetFile(path, FileSpec::Style::native);
347 } else {
348 error.SetErrorString("invalid file handle");
349 }
350#elif defined(__linux__)
351 char proc[64];
352 char path[PATH_MAX];
353 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0)
354 error.SetErrorString("cannot resolve file descriptor");
355 else {
356 ssize_t len;
357 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1)
358 error.SetErrorToErrno();
359 else {
360 path[len] = '\0';
361 file_spec.SetFile(path, FileSpec::Style::native);
362 }
363 }
364#else
365 error.SetErrorString(
366 "NativeFile::GetFileSpec is not supported on this platform");
367#endif
368
369 if (error.Fail())
370 file_spec.Clear();
371 return error;
372}
373
374off_t NativeFile::SeekFromStart(off_t offset, Status *error_ptr) {
375 off_t result = 0;
376 if (DescriptorIsValid()) {
377 result = ::lseek(m_descriptor, offset, SEEK_SET);
378
379 if (error_ptr) {
380 if (result == -1)
381 error_ptr->SetErrorToErrno();
382 else
383 error_ptr->Clear();
384 }
385 } else if (StreamIsValid()) {
386 result = ::fseek(m_stream, offset, SEEK_SET);
387
388 if (error_ptr) {
389 if (result == -1)
390 error_ptr->SetErrorToErrno();
391 else
392 error_ptr->Clear();
393 }
394 } else if (error_ptr) {
395 error_ptr->SetErrorString("invalid file handle");
396 }
397 return result;
398}
399
400off_t NativeFile::SeekFromCurrent(off_t offset, Status *error_ptr) {
401 off_t result = -1;
402 if (DescriptorIsValid()) {
403 result = ::lseek(m_descriptor, offset, SEEK_CUR);
404
405 if (error_ptr) {
406 if (result == -1)
407 error_ptr->SetErrorToErrno();
408 else
409 error_ptr->Clear();
410 }
411 } else if (StreamIsValid()) {
412 result = ::fseek(m_stream, offset, SEEK_CUR);
413
414 if (error_ptr) {
415 if (result == -1)
416 error_ptr->SetErrorToErrno();
417 else
418 error_ptr->Clear();
419 }
420 } else if (error_ptr) {
421 error_ptr->SetErrorString("invalid file handle");
422 }
423 return result;
424}
425
426off_t NativeFile::SeekFromEnd(off_t offset, Status *error_ptr) {
427 off_t result = -1;
428 if (DescriptorIsValid()) {
429 result = ::lseek(m_descriptor, offset, SEEK_END);
430
431 if (error_ptr) {
432 if (result == -1)
433 error_ptr->SetErrorToErrno();
434 else
435 error_ptr->Clear();
436 }
437 } else if (StreamIsValid()) {
438 result = ::fseek(m_stream, offset, SEEK_END);
439
440 if (error_ptr) {
441 if (result == -1)
442 error_ptr->SetErrorToErrno();
443 else
444 error_ptr->Clear();
445 }
446 } else if (error_ptr) {
447 error_ptr->SetErrorString("invalid file handle");
448 }
449 return result;
450}
451
454 if (StreamIsValid()) {
455 if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF)
456 error.SetErrorToErrno();
457 } else if (!DescriptorIsValid()) {
458 error.SetErrorString("invalid file handle");
459 }
460 return error;
461}
462
465 if (DescriptorIsValid()) {
466#ifdef _WIN32
467 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
468 if (err == 0)
469 error.SetErrorToGenericError();
470#else
471 if (llvm::sys::RetryAfterSignal(-1, ::fsync, m_descriptor) == -1)
472 error.SetErrorToErrno();
473#endif
474 } else {
475 error.SetErrorString("invalid file handle");
476 }
477 return error;
478}
479
480#if defined(__APPLE__)
481// Darwin kernels only can read/write <= INT_MAX bytes
482#define MAX_READ_SIZE INT_MAX
483#define MAX_WRITE_SIZE INT_MAX
484#endif
485
486Status NativeFile::Read(void *buf, size_t &num_bytes) {
488
489#if defined(MAX_READ_SIZE)
490 if (num_bytes > MAX_READ_SIZE) {
491 uint8_t *p = (uint8_t *)buf;
492 size_t bytes_left = num_bytes;
493 // Init the num_bytes read to zero
494 num_bytes = 0;
495
496 while (bytes_left > 0) {
497 size_t curr_num_bytes;
498 if (bytes_left > MAX_READ_SIZE)
499 curr_num_bytes = MAX_READ_SIZE;
500 else
501 curr_num_bytes = bytes_left;
502
503 error = Read(p + num_bytes, curr_num_bytes);
504
505 // Update how many bytes were read
506 num_bytes += curr_num_bytes;
507 if (bytes_left < curr_num_bytes)
508 bytes_left = 0;
509 else
510 bytes_left -= curr_num_bytes;
511
512 if (error.Fail())
513 break;
514 }
515 return error;
516 }
517#endif
518
519 ssize_t bytes_read = -1;
520 if (DescriptorIsValid()) {
521 bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes);
522 if (bytes_read == -1) {
523 error.SetErrorToErrno();
524 num_bytes = 0;
525 } else
526 num_bytes = bytes_read;
527 } else if (StreamIsValid()) {
528 bytes_read = ::fread(buf, 1, num_bytes, m_stream);
529
530 if (bytes_read == 0) {
531 if (::feof(m_stream))
532 error.SetErrorString("feof");
533 else if (::ferror(m_stream))
534 error.SetErrorString("ferror");
535 num_bytes = 0;
536 } else
537 num_bytes = bytes_read;
538 } else {
539 num_bytes = 0;
540 error.SetErrorString("invalid file handle");
541 }
542 return error;
543}
544
545Status NativeFile::Write(const void *buf, size_t &num_bytes) {
547
548#if defined(MAX_WRITE_SIZE)
549 if (num_bytes > MAX_WRITE_SIZE) {
550 const uint8_t *p = (const uint8_t *)buf;
551 size_t bytes_left = num_bytes;
552 // Init the num_bytes written to zero
553 num_bytes = 0;
554
555 while (bytes_left > 0) {
556 size_t curr_num_bytes;
557 if (bytes_left > MAX_WRITE_SIZE)
558 curr_num_bytes = MAX_WRITE_SIZE;
559 else
560 curr_num_bytes = bytes_left;
561
562 error = Write(p + num_bytes, curr_num_bytes);
563
564 // Update how many bytes were read
565 num_bytes += curr_num_bytes;
566 if (bytes_left < curr_num_bytes)
567 bytes_left = 0;
568 else
569 bytes_left -= curr_num_bytes;
570
571 if (error.Fail())
572 break;
573 }
574 return error;
575 }
576#endif
577
578 ssize_t bytes_written = -1;
579 if (DescriptorIsValid()) {
580 bytes_written =
581 llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes);
582 if (bytes_written == -1) {
583 error.SetErrorToErrno();
584 num_bytes = 0;
585 } else
586 num_bytes = bytes_written;
587 } else if (StreamIsValid()) {
588 bytes_written = ::fwrite(buf, 1, num_bytes, m_stream);
589
590 if (bytes_written == 0) {
591 if (::feof(m_stream))
592 error.SetErrorString("feof");
593 else if (::ferror(m_stream))
594 error.SetErrorString("ferror");
595 num_bytes = 0;
596 } else
597 num_bytes = bytes_written;
598
599 } else {
600 num_bytes = 0;
601 error.SetErrorString("invalid file handle");
602 }
603
604 return error;
605}
606
607Status NativeFile::Read(void *buf, size_t &num_bytes, off_t &offset) {
609
610#if defined(MAX_READ_SIZE)
611 if (num_bytes > MAX_READ_SIZE) {
612 uint8_t *p = (uint8_t *)buf;
613 size_t bytes_left = num_bytes;
614 // Init the num_bytes read to zero
615 num_bytes = 0;
616
617 while (bytes_left > 0) {
618 size_t curr_num_bytes;
619 if (bytes_left > MAX_READ_SIZE)
620 curr_num_bytes = MAX_READ_SIZE;
621 else
622 curr_num_bytes = bytes_left;
623
624 error = Read(p + num_bytes, curr_num_bytes, offset);
625
626 // Update how many bytes were read
627 num_bytes += curr_num_bytes;
628 if (bytes_left < curr_num_bytes)
629 bytes_left = 0;
630 else
631 bytes_left -= curr_num_bytes;
632
633 if (error.Fail())
634 break;
635 }
636 return error;
637 }
638#endif
639
640#ifndef _WIN32
641 int fd = GetDescriptor();
642 if (fd != kInvalidDescriptor) {
643 ssize_t bytes_read =
644 llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset);
645 if (bytes_read < 0) {
646 num_bytes = 0;
647 error.SetErrorToErrno();
648 } else {
649 offset += bytes_read;
650 num_bytes = bytes_read;
651 }
652 } else {
653 num_bytes = 0;
654 error.SetErrorString("invalid file handle");
655 }
656#else
657 std::lock_guard<std::mutex> guard(offset_access_mutex);
658 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
659 SeekFromStart(offset);
660 error = Read(buf, num_bytes);
661 if (!error.Fail())
662 SeekFromStart(cur);
663#endif
664 return error;
665}
666
667Status NativeFile::Write(const void *buf, size_t &num_bytes, off_t &offset) {
669
670#if defined(MAX_WRITE_SIZE)
671 if (num_bytes > MAX_WRITE_SIZE) {
672 const uint8_t *p = (const uint8_t *)buf;
673 size_t bytes_left = num_bytes;
674 // Init the num_bytes written to zero
675 num_bytes = 0;
676
677 while (bytes_left > 0) {
678 size_t curr_num_bytes;
679 if (bytes_left > MAX_WRITE_SIZE)
680 curr_num_bytes = MAX_WRITE_SIZE;
681 else
682 curr_num_bytes = bytes_left;
683
684 error = Write(p + num_bytes, curr_num_bytes, offset);
685
686 // Update how many bytes were read
687 num_bytes += curr_num_bytes;
688 if (bytes_left < curr_num_bytes)
689 bytes_left = 0;
690 else
691 bytes_left -= curr_num_bytes;
692
693 if (error.Fail())
694 break;
695 }
696 return error;
697 }
698#endif
699
700 int fd = GetDescriptor();
701 if (fd != kInvalidDescriptor) {
702#ifndef _WIN32
703 ssize_t bytes_written =
704 llvm::sys::RetryAfterSignal(-1, ::pwrite, m_descriptor, buf, num_bytes, offset);
705 if (bytes_written < 0) {
706 num_bytes = 0;
707 error.SetErrorToErrno();
708 } else {
709 offset += bytes_written;
710 num_bytes = bytes_written;
711 }
712#else
713 std::lock_guard<std::mutex> guard(offset_access_mutex);
714 long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
715 SeekFromStart(offset);
716 error = Write(buf, num_bytes);
717 long after = ::lseek(m_descriptor, 0, SEEK_CUR);
718
719 if (!error.Fail())
720 SeekFromStart(cur);
721
722 offset = after;
723#endif
724 } else {
725 num_bytes = 0;
726 error.SetErrorString("invalid file handle");
727 }
728 return error;
729}
730
731size_t NativeFile::PrintfVarArg(const char *format, va_list args) {
732 if (StreamIsValid()) {
733 return ::vfprintf(m_stream, format, args);
734 } else {
735 return File::PrintfVarArg(format, args);
736 }
737}
738
740 mode_t mode = 0;
744 if (rw == eOpenOptionReadWrite)
745 mode |= O_RDWR;
746 else if (rw == eOpenOptionWriteOnly)
747 mode |= O_WRONLY;
748 else if (rw == eOpenOptionReadOnly)
749 mode |= O_RDONLY;
750
751 if (open_options & eOpenOptionAppend)
752 mode |= O_APPEND;
753
754 if (open_options & eOpenOptionTruncate)
755 mode |= O_TRUNC;
756
757 if (open_options & eOpenOptionNonBlocking)
758 mode |= O_NONBLOCK;
759
760 if (open_options & eOpenOptionCanCreateNewOnly)
761 mode |= O_CREAT | O_EXCL;
762 else if (open_options & eOpenOptionCanCreate)
763 mode |= O_CREAT;
764
765 return mode;
766}
767
768llvm::Expected<SerialPort::Options>
769SerialPort::OptionsFromURL(llvm::StringRef urlqs) {
770 SerialPort::Options serial_options;
771 for (llvm::StringRef x : llvm::split(urlqs, '&')) {
772 if (x.consume_front("baud=")) {
773 unsigned int baud_rate;
774 if (!llvm::to_integer(x, baud_rate, 10))
775 return llvm::createStringError(llvm::inconvertibleErrorCode(),
776 "Invalid baud rate: %s",
777 x.str().c_str());
778 serial_options.BaudRate = baud_rate;
779 } else if (x.consume_front("parity=")) {
780 serial_options.Parity =
781 llvm::StringSwitch<std::optional<Terminal::Parity>>(x)
782 .Case("no", Terminal::Parity::No)
783 .Case("even", Terminal::Parity::Even)
784 .Case("odd", Terminal::Parity::Odd)
785 .Case("mark", Terminal::Parity::Mark)
786 .Case("space", Terminal::Parity::Space)
787 .Default(std::nullopt);
788 if (!serial_options.Parity)
789 return llvm::createStringError(
790 llvm::inconvertibleErrorCode(),
791 "Invalid parity (must be no, even, odd, mark or space): %s",
792 x.str().c_str());
793 } else if (x.consume_front("parity-check=")) {
794 serial_options.ParityCheck =
795 llvm::StringSwitch<std::optional<Terminal::ParityCheck>>(x)
796 .Case("no", Terminal::ParityCheck::No)
797 .Case("replace", Terminal::ParityCheck::ReplaceWithNUL)
798 .Case("ignore", Terminal::ParityCheck::Ignore)
799 // "mark" mode is not currently supported as it requires special
800 // input processing
801 // .Case("mark", Terminal::ParityCheck::Mark)
802 .Default(std::nullopt);
803 if (!serial_options.ParityCheck)
804 return llvm::createStringError(
805 llvm::inconvertibleErrorCode(),
806 "Invalid parity-check (must be no, replace, ignore or mark): %s",
807 x.str().c_str());
808 } else if (x.consume_front("stop-bits=")) {
809 unsigned int stop_bits;
810 if (!llvm::to_integer(x, stop_bits, 10) ||
811 (stop_bits != 1 && stop_bits != 2))
812 return llvm::createStringError(
813 llvm::inconvertibleErrorCode(),
814 "Invalid stop bit number (must be 1 or 2): %s", x.str().c_str());
815 serial_options.StopBits = stop_bits;
816 } else
817 return llvm::createStringError(llvm::inconvertibleErrorCode(),
818 "Unknown parameter: %s", x.str().c_str());
819 }
820 return serial_options;
821}
822
823llvm::Expected<std::unique_ptr<SerialPort>>
824SerialPort::Create(int fd, OpenOptions options, Options serial_options,
825 bool transfer_ownership) {
826 std::unique_ptr<SerialPort> out{
827 new SerialPort(fd, options, serial_options, transfer_ownership)};
828
829 if (!out->GetIsInteractive())
830 return llvm::createStringError(llvm::inconvertibleErrorCode(),
831 "the specified file is not a teletype");
832
833 Terminal term{fd};
834 if (llvm::Error error = term.SetRaw())
835 return std::move(error);
836 if (serial_options.BaudRate) {
837 if (llvm::Error error = term.SetBaudRate(*serial_options.BaudRate))
838 return std::move(error);
839 }
840 if (serial_options.Parity) {
841 if (llvm::Error error = term.SetParity(*serial_options.Parity))
842 return std::move(error);
843 }
844 if (serial_options.ParityCheck) {
845 if (llvm::Error error = term.SetParityCheck(*serial_options.ParityCheck))
846 return std::move(error);
847 }
848 if (serial_options.StopBits) {
849 if (llvm::Error error = term.SetStopBits(*serial_options.StopBits))
850 return std::move(error);
851 }
852
853 return std::move(out);
854}
855
857 SerialPort::Options serial_options,
858 bool transfer_ownership)
859 : NativeFile(fd, options, transfer_ownership), m_state(fd) {}
860
862 m_state.Restore();
863 return NativeFile::Close();
864}
865
866char File::ID = 0;
867char NativeFile::ID = 0;
868char 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:173
void Clear()
Clears the object state.
Definition: FileSpec.cpp:258
virtual llvm::Expected< OpenOptions > GetOptions() const
Return the OpenOptions for this file.
Definition: File.cpp:228
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: File.cpp:210
WaitableHandle GetWaitableHandle() override
Get a handle that can be used for OS polling interfaces, such as WaitForMultipleObjects,...
Definition: File.cpp:116
bool GetIsRealTerminal()
Return true if this file from a real terminal.
Definition: File.cpp:198
virtual FILE * GetStream()
Get the underlying libc stream for this file, or NULL.
Definition: File.cpp:127
Status Read(void *buf, size_t &num_bytes) override
Read bytes from a file from the current file position into buf.
Definition: File.cpp:105
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:129
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:120
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:135
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:739
virtual int GetDescriptor() const
Get underlying OS file descriptor for this file, or kInvalidDescriptor.
Definition: File.cpp:125
static llvm::Expected< const char * > GetStreamOpenModeFromOptions(OpenOptions options)
Definition: File.cpp:44
bool GetIsTerminalWithColors()
Return true if this file is a terminal which supports colors.
Definition: File.cpp:204
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition: File.cpp:114
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:108
@ 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:234
bool IsValid() const override
IsValid.
Definition: File.cpp:112
static char ID
Definition: File.h:362
virtual Status Flush()
Flush the current stream.
Definition: File.cpp:155
static llvm::Expected< OpenOptions > GetOptionsFromMode(llvm::StringRef mode)
Definition: File.cpp:79
size_t virtual size_t PrintfVarArg(const char *format, va_list args)
Output printf formatted output to the stream.
Definition: File.cpp:218
virtual Status Sync()
Sync to disk.
Definition: File.cpp:157
LazyBool m_supports_colors
Definition: File.h:369
bool GetIsInteractive()
Return true if this file is interactive.
Definition: File.cpp:192
void CalculateInteractiveAndTerminal()
Definition: File.cpp:159
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:141
static const WaitableHandle kInvalidHandleValue
Definition: IOObject.h:30
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:374
static char ID
Definition: File.h:413
Status GetFileSpec(FileSpec &file_spec) const override
Get the file specification for this file, if possible.
Definition: File.cpp:338
FILE * GetStream() override
Get the underlying libc stream for this file, or NULL.
Definition: File.cpp:273
bool StreamIsValid() const
Definition: File.h:423
Status Sync() override
Sync to disk.
Definition: File.cpp:463
std::mutex offset_access_mutex
Definition: File.h:431
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition: File.cpp:307
WaitableHandle GetWaitableHandle() override
Get a handle that can be used for OS polling interfaces, such as WaitForMultipleObjects,...
Definition: File.cpp:269
Status Flush() override
Flush the current stream.
Definition: File.cpp:452
bool DescriptorIsValid() const
Definition: File.h:420
llvm::Expected< OpenOptions > GetOptions() const override
Return the OpenOptions for this file.
Definition: File.cpp:249
OpenOptions m_options
Definition: File.h:429
off_t SeekFromCurrent(off_t offset, Status *error_ptr=nullptr) override
Seek to an offset relative to the current file position.
Definition: File.cpp:400
size_t PrintfVarArg(const char *format, va_list args) override
Output printf formatted output to the stream.
Definition: File.cpp:731
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:545
int GetDescriptor() const override
Get underlying OS file descriptor for this file, or kInvalidDescriptor.
Definition: File.cpp:251
Status Read(void *buf, size_t &num_bytes) override
Read bytes from a file from the current file position into buf.
Definition: File.cpp:486
bool IsValid() const override
IsValid.
Definition: File.h:392
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:426
static llvm::Expected< std::unique_ptr< SerialPort > > Create(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
Definition: File.cpp:824
TerminalState m_state
Definition: File.h:474
SerialPort(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
Definition: File.cpp:856
Status Close() override
Flush any buffers and release any resources owned by the file.
Definition: File.cpp:861
static char ID
Definition: File.h:461
static llvm::Expected< Options > OptionsFromURL(llvm::StringRef urlqs)
Definition: File.cpp:769
An error handling class.
Definition: Status.h:44
void Clear()
Clear the object state.
Definition: Status.cpp:167
void SetErrorToErrno()
Set the current error to errno.
Definition: Status.cpp:223
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
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:443
std::optional< unsigned int > StopBits
Definition: File.h:444
std::optional< Terminal::Parity > Parity
Definition: File.h:442
std::optional< unsigned int > BaudRate
Definition: File.h:441
#define S_IRWXG
#define O_NONBLOCK
#define S_IRWXO
#define PATH_MAX
#define S_IRWXU