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