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