1 //===-- File.cpp ------------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Host/File.h" 11 12 #include <errno.h> 13 #include <fcntl.h> 14 #include <limits.h> 15 #include <stdarg.h> 16 #include <stdio.h> 17 18 #ifdef _WIN32 19 #include "lldb/Host/windows/windows.h" 20 #else 21 #include <sys/ioctl.h> 22 #include <termios.h> 23 #endif 24 25 #include "llvm/Support/ConvertUTF.h" 26 #include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors() 27 28 #include "lldb/Core/DataBufferHeap.h" 29 #include "lldb/Core/Log.h" 30 #include "lldb/Host/Config.h" 31 #include "lldb/Host/FileSpec.h" 32 #include "lldb/Host/FileSystem.h" 33 #include "lldb/Utility/Error.h" 34 35 using namespace lldb; 36 using namespace lldb_private; 37 38 static const char *GetStreamOpenModeFromOptions(uint32_t options) { 39 if (options & File::eOpenOptionAppend) { 40 if (options & File::eOpenOptionRead) { 41 if (options & File::eOpenOptionCanCreateNewOnly) 42 return "a+x"; 43 else 44 return "a+"; 45 } else if (options & File::eOpenOptionWrite) { 46 if (options & File::eOpenOptionCanCreateNewOnly) 47 return "ax"; 48 else 49 return "a"; 50 } 51 } else if (options & File::eOpenOptionRead && 52 options & File::eOpenOptionWrite) { 53 if (options & File::eOpenOptionCanCreate) { 54 if (options & File::eOpenOptionCanCreateNewOnly) 55 return "w+x"; 56 else 57 return "w+"; 58 } else 59 return "r+"; 60 } else if (options & File::eOpenOptionRead) { 61 return "r"; 62 } else if (options & File::eOpenOptionWrite) { 63 return "w"; 64 } 65 return NULL; 66 } 67 68 int File::kInvalidDescriptor = -1; 69 FILE *File::kInvalidStream = NULL; 70 71 File::File(const char *path, uint32_t options, uint32_t permissions) 72 : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor), 73 m_stream(kInvalidStream), m_options(), m_own_stream(false), 74 m_is_interactive(eLazyBoolCalculate), 75 m_is_real_terminal(eLazyBoolCalculate) { 76 Open(path, options, permissions); 77 } 78 79 File::File(const FileSpec &filespec, uint32_t options, uint32_t permissions) 80 : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor), 81 m_stream(kInvalidStream), m_options(0), m_own_stream(false), 82 m_is_interactive(eLazyBoolCalculate), 83 m_is_real_terminal(eLazyBoolCalculate) 84 85 { 86 if (filespec) { 87 Open(filespec.GetPath().c_str(), options, permissions); 88 } 89 } 90 91 File::~File() { Close(); } 92 93 int File::GetDescriptor() const { 94 if (DescriptorIsValid()) 95 return m_descriptor; 96 97 // Don't open the file descriptor if we don't need to, just get it from the 98 // stream if we have one. 99 if (StreamIsValid()) { 100 #if defined(LLVM_ON_WIN32) 101 return _fileno(m_stream); 102 #else 103 return fileno(m_stream); 104 #endif 105 } 106 107 // Invalid descriptor and invalid stream, return invalid descriptor. 108 return kInvalidDescriptor; 109 } 110 111 IOObject::WaitableHandle File::GetWaitableHandle() { return m_descriptor; } 112 113 void File::SetDescriptor(int fd, bool transfer_ownership) { 114 if (IsValid()) 115 Close(); 116 m_descriptor = fd; 117 m_should_close_fd = transfer_ownership; 118 } 119 120 FILE *File::GetStream() { 121 if (!StreamIsValid()) { 122 if (DescriptorIsValid()) { 123 const char *mode = GetStreamOpenModeFromOptions(m_options); 124 if (mode) { 125 if (!m_should_close_fd) { 126 // We must duplicate the file descriptor if we don't own it because 127 // when you call fdopen, the stream will own the fd 128 #ifdef _WIN32 129 m_descriptor = ::_dup(GetDescriptor()); 130 #else 131 m_descriptor = dup(GetDescriptor()); 132 #endif 133 m_should_close_fd = true; 134 } 135 136 do { 137 m_stream = ::fdopen(m_descriptor, mode); 138 } while (m_stream == NULL && errno == EINTR); 139 140 // If we got a stream, then we own the stream and should no 141 // longer own the descriptor because fclose() will close it for us 142 143 if (m_stream) { 144 m_own_stream = true; 145 m_should_close_fd = false; 146 } 147 } 148 } 149 } 150 return m_stream; 151 } 152 153 void File::SetStream(FILE *fh, bool transfer_ownership) { 154 if (IsValid()) 155 Close(); 156 m_stream = fh; 157 m_own_stream = transfer_ownership; 158 } 159 160 Error File::Open(const char *path, uint32_t options, uint32_t permissions) { 161 Error error; 162 if (IsValid()) 163 Close(); 164 165 int oflag = 0; 166 const bool read = options & eOpenOptionRead; 167 const bool write = options & eOpenOptionWrite; 168 if (write) { 169 if (read) 170 oflag |= O_RDWR; 171 else 172 oflag |= O_WRONLY; 173 174 if (options & eOpenOptionAppend) 175 oflag |= O_APPEND; 176 177 if (options & eOpenOptionTruncate) 178 oflag |= O_TRUNC; 179 180 if (options & eOpenOptionCanCreate) 181 oflag |= O_CREAT; 182 183 if (options & eOpenOptionCanCreateNewOnly) 184 oflag |= O_CREAT | O_EXCL; 185 } else if (read) { 186 oflag |= O_RDONLY; 187 188 #ifndef _WIN32 189 if (options & eOpenOptionDontFollowSymlinks) 190 oflag |= O_NOFOLLOW; 191 #endif 192 } 193 194 #ifndef _WIN32 195 if (options & eOpenOptionNonBlocking) 196 oflag |= O_NONBLOCK; 197 if (options & eOpenOptionCloseOnExec) 198 oflag |= O_CLOEXEC; 199 #else 200 oflag |= O_BINARY; 201 #endif 202 203 mode_t mode = 0; 204 if (oflag & O_CREAT) { 205 if (permissions & lldb::eFilePermissionsUserRead) 206 mode |= S_IRUSR; 207 if (permissions & lldb::eFilePermissionsUserWrite) 208 mode |= S_IWUSR; 209 if (permissions & lldb::eFilePermissionsUserExecute) 210 mode |= S_IXUSR; 211 if (permissions & lldb::eFilePermissionsGroupRead) 212 mode |= S_IRGRP; 213 if (permissions & lldb::eFilePermissionsGroupWrite) 214 mode |= S_IWGRP; 215 if (permissions & lldb::eFilePermissionsGroupExecute) 216 mode |= S_IXGRP; 217 if (permissions & lldb::eFilePermissionsWorldRead) 218 mode |= S_IROTH; 219 if (permissions & lldb::eFilePermissionsWorldWrite) 220 mode |= S_IWOTH; 221 if (permissions & lldb::eFilePermissionsWorldExecute) 222 mode |= S_IXOTH; 223 } 224 225 do { 226 #ifdef _MSC_VER 227 std::wstring wpath; 228 if (!llvm::ConvertUTF8toWide(path, wpath)) { 229 m_descriptor = -1; 230 error.SetErrorString("Error converting path to UTF-16"); 231 return error; 232 } 233 ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode); 234 #else 235 m_descriptor = ::open(path, oflag, mode); 236 #endif 237 } while (m_descriptor < 0 && errno == EINTR); 238 239 if (!DescriptorIsValid()) 240 error.SetErrorToErrno(); 241 else { 242 m_should_close_fd = true; 243 m_options = options; 244 } 245 246 return error; 247 } 248 249 uint32_t File::GetPermissions(const FileSpec &file_spec, Error &error) { 250 if (file_spec) { 251 struct stat file_stats; 252 int stat_result = FileSystem::Stat(file_spec.GetCString(), &file_stats); 253 if (stat_result == -1) 254 error.SetErrorToErrno(); 255 else { 256 error.Clear(); 257 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 258 } 259 } else 260 error.SetErrorString("empty file spec"); 261 return 0; 262 } 263 264 uint32_t File::GetPermissions(Error &error) const { 265 int fd = GetDescriptor(); 266 if (fd != kInvalidDescriptor) { 267 struct stat file_stats; 268 if (::fstat(fd, &file_stats) == -1) 269 error.SetErrorToErrno(); 270 else { 271 error.Clear(); 272 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 273 } 274 } else { 275 error.SetErrorString("invalid file descriptor"); 276 } 277 return 0; 278 } 279 280 Error File::Close() { 281 Error error; 282 if (StreamIsValid() && m_own_stream) { 283 if (::fclose(m_stream) == EOF) 284 error.SetErrorToErrno(); 285 } 286 287 if (DescriptorIsValid() && m_should_close_fd) { 288 if (::close(m_descriptor) != 0) 289 error.SetErrorToErrno(); 290 } 291 m_descriptor = kInvalidDescriptor; 292 m_stream = kInvalidStream; 293 m_options = 0; 294 m_own_stream = false; 295 m_should_close_fd = false; 296 m_is_interactive = eLazyBoolCalculate; 297 m_is_real_terminal = eLazyBoolCalculate; 298 return error; 299 } 300 301 void File::Clear() { 302 m_stream = nullptr; 303 m_descriptor = -1; 304 m_options = 0; 305 m_own_stream = false; 306 m_is_interactive = m_supports_colors = m_is_real_terminal = 307 eLazyBoolCalculate; 308 } 309 310 Error File::GetFileSpec(FileSpec &file_spec) const { 311 Error error; 312 #ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED 313 if (IsValid()) { 314 char path[PATH_MAX]; 315 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) 316 error.SetErrorToErrno(); 317 else 318 file_spec.SetFile(path, false); 319 } else { 320 error.SetErrorString("invalid file handle"); 321 } 322 #elif defined(__linux__) 323 char proc[64]; 324 char path[PATH_MAX]; 325 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) 326 error.SetErrorString("cannot resolve file descriptor"); 327 else { 328 ssize_t len; 329 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) 330 error.SetErrorToErrno(); 331 else { 332 path[len] = '\0'; 333 file_spec.SetFile(path, false); 334 } 335 } 336 #else 337 error.SetErrorString("File::GetFileSpec is not supported on this platform"); 338 #endif 339 340 if (error.Fail()) 341 file_spec.Clear(); 342 return error; 343 } 344 345 off_t File::SeekFromStart(off_t offset, Error *error_ptr) { 346 off_t result = 0; 347 if (DescriptorIsValid()) { 348 result = ::lseek(m_descriptor, offset, SEEK_SET); 349 350 if (error_ptr) { 351 if (result == -1) 352 error_ptr->SetErrorToErrno(); 353 else 354 error_ptr->Clear(); 355 } 356 } else if (StreamIsValid()) { 357 result = ::fseek(m_stream, offset, SEEK_SET); 358 359 if (error_ptr) { 360 if (result == -1) 361 error_ptr->SetErrorToErrno(); 362 else 363 error_ptr->Clear(); 364 } 365 } else if (error_ptr) { 366 error_ptr->SetErrorString("invalid file handle"); 367 } 368 return result; 369 } 370 371 off_t File::SeekFromCurrent(off_t offset, Error *error_ptr) { 372 off_t result = -1; 373 if (DescriptorIsValid()) { 374 result = ::lseek(m_descriptor, offset, SEEK_CUR); 375 376 if (error_ptr) { 377 if (result == -1) 378 error_ptr->SetErrorToErrno(); 379 else 380 error_ptr->Clear(); 381 } 382 } else if (StreamIsValid()) { 383 result = ::fseek(m_stream, offset, SEEK_CUR); 384 385 if (error_ptr) { 386 if (result == -1) 387 error_ptr->SetErrorToErrno(); 388 else 389 error_ptr->Clear(); 390 } 391 } else if (error_ptr) { 392 error_ptr->SetErrorString("invalid file handle"); 393 } 394 return result; 395 } 396 397 off_t File::SeekFromEnd(off_t offset, Error *error_ptr) { 398 off_t result = -1; 399 if (DescriptorIsValid()) { 400 result = ::lseek(m_descriptor, offset, SEEK_END); 401 402 if (error_ptr) { 403 if (result == -1) 404 error_ptr->SetErrorToErrno(); 405 else 406 error_ptr->Clear(); 407 } 408 } else if (StreamIsValid()) { 409 result = ::fseek(m_stream, offset, SEEK_END); 410 411 if (error_ptr) { 412 if (result == -1) 413 error_ptr->SetErrorToErrno(); 414 else 415 error_ptr->Clear(); 416 } 417 } else if (error_ptr) { 418 error_ptr->SetErrorString("invalid file handle"); 419 } 420 return result; 421 } 422 423 Error File::Flush() { 424 Error error; 425 if (StreamIsValid()) { 426 int err = 0; 427 do { 428 err = ::fflush(m_stream); 429 } while (err == EOF && errno == EINTR); 430 431 if (err == EOF) 432 error.SetErrorToErrno(); 433 } else if (!DescriptorIsValid()) { 434 error.SetErrorString("invalid file handle"); 435 } 436 return error; 437 } 438 439 Error File::Sync() { 440 Error error; 441 if (DescriptorIsValid()) { 442 #ifdef _WIN32 443 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); 444 if (err == 0) 445 error.SetErrorToGenericError(); 446 #else 447 int err = 0; 448 do { 449 err = ::fsync(m_descriptor); 450 } while (err == -1 && errno == EINTR); 451 452 if (err == -1) 453 error.SetErrorToErrno(); 454 #endif 455 } else { 456 error.SetErrorString("invalid file handle"); 457 } 458 return error; 459 } 460 461 #if defined(__APPLE__) 462 // Darwin kernels only can read/write <= INT_MAX bytes 463 #define MAX_READ_SIZE INT_MAX 464 #define MAX_WRITE_SIZE INT_MAX 465 #endif 466 467 Error File::Read(void *buf, size_t &num_bytes) { 468 Error error; 469 470 #if defined(MAX_READ_SIZE) 471 if (num_bytes > MAX_READ_SIZE) { 472 uint8_t *p = (uint8_t *)buf; 473 size_t bytes_left = num_bytes; 474 // Init the num_bytes read to zero 475 num_bytes = 0; 476 477 while (bytes_left > 0) { 478 size_t curr_num_bytes; 479 if (bytes_left > MAX_READ_SIZE) 480 curr_num_bytes = MAX_READ_SIZE; 481 else 482 curr_num_bytes = bytes_left; 483 484 error = Read(p + num_bytes, curr_num_bytes); 485 486 // Update how many bytes were read 487 num_bytes += curr_num_bytes; 488 if (bytes_left < curr_num_bytes) 489 bytes_left = 0; 490 else 491 bytes_left -= curr_num_bytes; 492 493 if (error.Fail()) 494 break; 495 } 496 return error; 497 } 498 #endif 499 500 ssize_t bytes_read = -1; 501 if (DescriptorIsValid()) { 502 do { 503 bytes_read = ::read(m_descriptor, buf, num_bytes); 504 } while (bytes_read < 0 && errno == EINTR); 505 506 if (bytes_read == -1) { 507 error.SetErrorToErrno(); 508 num_bytes = 0; 509 } else 510 num_bytes = bytes_read; 511 } else if (StreamIsValid()) { 512 bytes_read = ::fread(buf, 1, num_bytes, m_stream); 513 514 if (bytes_read == 0) { 515 if (::feof(m_stream)) 516 error.SetErrorString("feof"); 517 else if (::ferror(m_stream)) 518 error.SetErrorString("ferror"); 519 num_bytes = 0; 520 } else 521 num_bytes = bytes_read; 522 } else { 523 num_bytes = 0; 524 error.SetErrorString("invalid file handle"); 525 } 526 return error; 527 } 528 529 Error File::Write(const void *buf, size_t &num_bytes) { 530 Error error; 531 532 #if defined(MAX_WRITE_SIZE) 533 if (num_bytes > MAX_WRITE_SIZE) { 534 const uint8_t *p = (const uint8_t *)buf; 535 size_t bytes_left = num_bytes; 536 // Init the num_bytes written to zero 537 num_bytes = 0; 538 539 while (bytes_left > 0) { 540 size_t curr_num_bytes; 541 if (bytes_left > MAX_WRITE_SIZE) 542 curr_num_bytes = MAX_WRITE_SIZE; 543 else 544 curr_num_bytes = bytes_left; 545 546 error = Write(p + num_bytes, curr_num_bytes); 547 548 // Update how many bytes were read 549 num_bytes += curr_num_bytes; 550 if (bytes_left < curr_num_bytes) 551 bytes_left = 0; 552 else 553 bytes_left -= curr_num_bytes; 554 555 if (error.Fail()) 556 break; 557 } 558 return error; 559 } 560 #endif 561 562 ssize_t bytes_written = -1; 563 if (DescriptorIsValid()) { 564 do { 565 bytes_written = ::write(m_descriptor, buf, num_bytes); 566 } while (bytes_written < 0 && errno == EINTR); 567 568 if (bytes_written == -1) { 569 error.SetErrorToErrno(); 570 num_bytes = 0; 571 } else 572 num_bytes = bytes_written; 573 } else if (StreamIsValid()) { 574 bytes_written = ::fwrite(buf, 1, num_bytes, m_stream); 575 576 if (bytes_written == 0) { 577 if (::feof(m_stream)) 578 error.SetErrorString("feof"); 579 else if (::ferror(m_stream)) 580 error.SetErrorString("ferror"); 581 num_bytes = 0; 582 } else 583 num_bytes = bytes_written; 584 585 } else { 586 num_bytes = 0; 587 error.SetErrorString("invalid file handle"); 588 } 589 590 return error; 591 } 592 593 Error File::Read(void *buf, size_t &num_bytes, off_t &offset) { 594 Error error; 595 596 #if defined(MAX_READ_SIZE) 597 if (num_bytes > MAX_READ_SIZE) { 598 uint8_t *p = (uint8_t *)buf; 599 size_t bytes_left = num_bytes; 600 // Init the num_bytes read to zero 601 num_bytes = 0; 602 603 while (bytes_left > 0) { 604 size_t curr_num_bytes; 605 if (bytes_left > MAX_READ_SIZE) 606 curr_num_bytes = MAX_READ_SIZE; 607 else 608 curr_num_bytes = bytes_left; 609 610 error = Read(p + num_bytes, curr_num_bytes, offset); 611 612 // Update how many bytes were read 613 num_bytes += curr_num_bytes; 614 if (bytes_left < curr_num_bytes) 615 bytes_left = 0; 616 else 617 bytes_left -= curr_num_bytes; 618 619 if (error.Fail()) 620 break; 621 } 622 return error; 623 } 624 #endif 625 626 #ifndef _WIN32 627 int fd = GetDescriptor(); 628 if (fd != kInvalidDescriptor) { 629 ssize_t bytes_read = -1; 630 do { 631 bytes_read = ::pread(fd, buf, num_bytes, offset); 632 } while (bytes_read < 0 && errno == EINTR); 633 634 if (bytes_read < 0) { 635 num_bytes = 0; 636 error.SetErrorToErrno(); 637 } else { 638 offset += bytes_read; 639 num_bytes = bytes_read; 640 } 641 } else { 642 num_bytes = 0; 643 error.SetErrorString("invalid file handle"); 644 } 645 #else 646 long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 647 SeekFromStart(offset); 648 error = Read(buf, num_bytes); 649 if (!error.Fail()) 650 SeekFromStart(cur); 651 #endif 652 return error; 653 } 654 655 Error File::Read(size_t &num_bytes, off_t &offset, bool null_terminate, 656 DataBufferSP &data_buffer_sp) { 657 Error error; 658 659 if (num_bytes > 0) { 660 int fd = GetDescriptor(); 661 if (fd != kInvalidDescriptor) { 662 struct stat file_stats; 663 if (::fstat(fd, &file_stats) == 0) { 664 if (file_stats.st_size > offset) { 665 const size_t bytes_left = file_stats.st_size - offset; 666 if (num_bytes > bytes_left) 667 num_bytes = bytes_left; 668 669 size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); 670 std::unique_ptr<DataBufferHeap> data_heap_ap; 671 data_heap_ap.reset(new DataBufferHeap()); 672 data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 673 674 if (data_heap_ap.get()) { 675 error = Read(data_heap_ap->GetBytes(), num_bytes, offset); 676 if (error.Success()) { 677 // Make sure we read exactly what we asked for and if we got 678 // less, adjust the array 679 if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) 680 data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 681 data_buffer_sp.reset(data_heap_ap.release()); 682 return error; 683 } 684 } 685 } else 686 error.SetErrorString("file is empty"); 687 } else 688 error.SetErrorToErrno(); 689 } else 690 error.SetErrorString("invalid file handle"); 691 } else 692 error.SetErrorString("invalid file handle"); 693 694 num_bytes = 0; 695 data_buffer_sp.reset(); 696 return error; 697 } 698 699 Error File::Write(const void *buf, size_t &num_bytes, off_t &offset) { 700 Error error; 701 702 #if defined(MAX_WRITE_SIZE) 703 if (num_bytes > MAX_WRITE_SIZE) { 704 const uint8_t *p = (const uint8_t *)buf; 705 size_t bytes_left = num_bytes; 706 // Init the num_bytes written to zero 707 num_bytes = 0; 708 709 while (bytes_left > 0) { 710 size_t curr_num_bytes; 711 if (bytes_left > MAX_WRITE_SIZE) 712 curr_num_bytes = MAX_WRITE_SIZE; 713 else 714 curr_num_bytes = bytes_left; 715 716 error = Write(p + num_bytes, curr_num_bytes, offset); 717 718 // Update how many bytes were read 719 num_bytes += curr_num_bytes; 720 if (bytes_left < curr_num_bytes) 721 bytes_left = 0; 722 else 723 bytes_left -= curr_num_bytes; 724 725 if (error.Fail()) 726 break; 727 } 728 return error; 729 } 730 #endif 731 732 int fd = GetDescriptor(); 733 if (fd != kInvalidDescriptor) { 734 #ifndef _WIN32 735 ssize_t bytes_written = -1; 736 do { 737 bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset); 738 } while (bytes_written < 0 && errno == EINTR); 739 740 if (bytes_written < 0) { 741 num_bytes = 0; 742 error.SetErrorToErrno(); 743 } else { 744 offset += bytes_written; 745 num_bytes = bytes_written; 746 } 747 #else 748 long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 749 error = Write(buf, num_bytes); 750 long after = ::lseek(m_descriptor, 0, SEEK_CUR); 751 752 if (!error.Fail()) 753 SeekFromStart(cur); 754 755 offset = after; 756 #endif 757 } else { 758 num_bytes = 0; 759 error.SetErrorString("invalid file handle"); 760 } 761 return error; 762 } 763 764 //------------------------------------------------------------------ 765 // Print some formatted output to the stream. 766 //------------------------------------------------------------------ 767 size_t File::Printf(const char *format, ...) { 768 va_list args; 769 va_start(args, format); 770 size_t result = PrintfVarArg(format, args); 771 va_end(args); 772 return result; 773 } 774 775 //------------------------------------------------------------------ 776 // Print some formatted output to the stream. 777 //------------------------------------------------------------------ 778 size_t File::PrintfVarArg(const char *format, va_list args) { 779 size_t result = 0; 780 if (DescriptorIsValid()) { 781 char *s = NULL; 782 result = vasprintf(&s, format, args); 783 if (s != NULL) { 784 if (result > 0) { 785 size_t s_len = result; 786 Write(s, s_len); 787 result = s_len; 788 } 789 free(s); 790 } 791 } else if (StreamIsValid()) { 792 result = ::vfprintf(m_stream, format, args); 793 } 794 return result; 795 } 796 797 mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) { 798 mode_t mode = 0; 799 if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) 800 mode |= O_RDWR; 801 else if (open_options & eOpenOptionWrite) 802 mode |= O_WRONLY; 803 804 if (open_options & eOpenOptionAppend) 805 mode |= O_APPEND; 806 807 if (open_options & eOpenOptionTruncate) 808 mode |= O_TRUNC; 809 810 if (open_options & eOpenOptionNonBlocking) 811 mode |= O_NONBLOCK; 812 813 if (open_options & eOpenOptionCanCreateNewOnly) 814 mode |= O_CREAT | O_EXCL; 815 else if (open_options & eOpenOptionCanCreate) 816 mode |= O_CREAT; 817 818 return mode; 819 } 820 821 void File::CalculateInteractiveAndTerminal() { 822 const int fd = GetDescriptor(); 823 if (fd >= 0) { 824 m_is_interactive = eLazyBoolNo; 825 m_is_real_terminal = eLazyBoolNo; 826 #if defined(_WIN32) 827 if (_isatty(fd)) { 828 m_is_interactive = eLazyBoolYes; 829 m_is_real_terminal = eLazyBoolYes; 830 } 831 #else 832 if (isatty(fd)) { 833 m_is_interactive = eLazyBoolYes; 834 struct winsize window_size; 835 if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) { 836 if (window_size.ws_col > 0) { 837 m_is_real_terminal = eLazyBoolYes; 838 if (llvm::sys::Process::FileDescriptorHasColors(fd)) 839 m_supports_colors = eLazyBoolYes; 840 } 841 } 842 } 843 #endif 844 } 845 } 846 847 bool File::GetIsInteractive() { 848 if (m_is_interactive == eLazyBoolCalculate) 849 CalculateInteractiveAndTerminal(); 850 return m_is_interactive == eLazyBoolYes; 851 } 852 853 bool File::GetIsRealTerminal() { 854 if (m_is_real_terminal == eLazyBoolCalculate) 855 CalculateInteractiveAndTerminal(); 856 return m_is_real_terminal == eLazyBoolYes; 857 } 858 859 bool File::GetIsTerminalWithColors() { 860 if (m_supports_colors == eLazyBoolCalculate) 861 CalculateInteractiveAndTerminal(); 862 return m_supports_colors == eLazyBoolYes; 863 } 864