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