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/FileSpec.h" 33 #include "lldb/Utility/Log.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 error.Clear(); 252 auto Perms = llvm::sys::fs::getPermissions(file_spec.GetPath()); 253 if (Perms) 254 return *Perms; 255 error = Error(Perms.getError()); 256 return 0; 257 } else 258 error.SetErrorString("empty file spec"); 259 return 0; 260 } 261 262 uint32_t File::GetPermissions(Error &error) const { 263 int fd = GetDescriptor(); 264 if (fd != kInvalidDescriptor) { 265 struct stat file_stats; 266 if (::fstat(fd, &file_stats) == -1) 267 error.SetErrorToErrno(); 268 else { 269 error.Clear(); 270 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 271 } 272 } else { 273 error.SetErrorString("invalid file descriptor"); 274 } 275 return 0; 276 } 277 278 Error File::Close() { 279 Error error; 280 if (StreamIsValid() && m_own_stream) { 281 if (::fclose(m_stream) == EOF) 282 error.SetErrorToErrno(); 283 } 284 285 if (DescriptorIsValid() && m_should_close_fd) { 286 if (::close(m_descriptor) != 0) 287 error.SetErrorToErrno(); 288 } 289 m_descriptor = kInvalidDescriptor; 290 m_stream = kInvalidStream; 291 m_options = 0; 292 m_own_stream = false; 293 m_should_close_fd = false; 294 m_is_interactive = eLazyBoolCalculate; 295 m_is_real_terminal = eLazyBoolCalculate; 296 return error; 297 } 298 299 void File::Clear() { 300 m_stream = nullptr; 301 m_descriptor = -1; 302 m_options = 0; 303 m_own_stream = false; 304 m_is_interactive = m_supports_colors = m_is_real_terminal = 305 eLazyBoolCalculate; 306 } 307 308 Error File::GetFileSpec(FileSpec &file_spec) const { 309 Error error; 310 #ifdef F_GETPATH 311 if (IsValid()) { 312 char path[PATH_MAX]; 313 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) 314 error.SetErrorToErrno(); 315 else 316 file_spec.SetFile(path, false); 317 } else { 318 error.SetErrorString("invalid file handle"); 319 } 320 #elif defined(__linux__) 321 char proc[64]; 322 char path[PATH_MAX]; 323 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) 324 error.SetErrorString("cannot resolve file descriptor"); 325 else { 326 ssize_t len; 327 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) 328 error.SetErrorToErrno(); 329 else { 330 path[len] = '\0'; 331 file_spec.SetFile(path, false); 332 } 333 } 334 #else 335 error.SetErrorString("File::GetFileSpec is not supported on this platform"); 336 #endif 337 338 if (error.Fail()) 339 file_spec.Clear(); 340 return error; 341 } 342 343 off_t File::SeekFromStart(off_t offset, Error *error_ptr) { 344 off_t result = 0; 345 if (DescriptorIsValid()) { 346 result = ::lseek(m_descriptor, offset, SEEK_SET); 347 348 if (error_ptr) { 349 if (result == -1) 350 error_ptr->SetErrorToErrno(); 351 else 352 error_ptr->Clear(); 353 } 354 } else if (StreamIsValid()) { 355 result = ::fseek(m_stream, offset, SEEK_SET); 356 357 if (error_ptr) { 358 if (result == -1) 359 error_ptr->SetErrorToErrno(); 360 else 361 error_ptr->Clear(); 362 } 363 } else if (error_ptr) { 364 error_ptr->SetErrorString("invalid file handle"); 365 } 366 return result; 367 } 368 369 off_t File::SeekFromCurrent(off_t offset, Error *error_ptr) { 370 off_t result = -1; 371 if (DescriptorIsValid()) { 372 result = ::lseek(m_descriptor, offset, SEEK_CUR); 373 374 if (error_ptr) { 375 if (result == -1) 376 error_ptr->SetErrorToErrno(); 377 else 378 error_ptr->Clear(); 379 } 380 } else if (StreamIsValid()) { 381 result = ::fseek(m_stream, offset, SEEK_CUR); 382 383 if (error_ptr) { 384 if (result == -1) 385 error_ptr->SetErrorToErrno(); 386 else 387 error_ptr->Clear(); 388 } 389 } else if (error_ptr) { 390 error_ptr->SetErrorString("invalid file handle"); 391 } 392 return result; 393 } 394 395 off_t File::SeekFromEnd(off_t offset, Error *error_ptr) { 396 off_t result = -1; 397 if (DescriptorIsValid()) { 398 result = ::lseek(m_descriptor, offset, SEEK_END); 399 400 if (error_ptr) { 401 if (result == -1) 402 error_ptr->SetErrorToErrno(); 403 else 404 error_ptr->Clear(); 405 } 406 } else if (StreamIsValid()) { 407 result = ::fseek(m_stream, offset, SEEK_END); 408 409 if (error_ptr) { 410 if (result == -1) 411 error_ptr->SetErrorToErrno(); 412 else 413 error_ptr->Clear(); 414 } 415 } else if (error_ptr) { 416 error_ptr->SetErrorString("invalid file handle"); 417 } 418 return result; 419 } 420 421 Error File::Flush() { 422 Error error; 423 if (StreamIsValid()) { 424 int err = 0; 425 do { 426 err = ::fflush(m_stream); 427 } while (err == EOF && errno == EINTR); 428 429 if (err == EOF) 430 error.SetErrorToErrno(); 431 } else if (!DescriptorIsValid()) { 432 error.SetErrorString("invalid file handle"); 433 } 434 return error; 435 } 436 437 Error File::Sync() { 438 Error error; 439 if (DescriptorIsValid()) { 440 #ifdef _WIN32 441 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); 442 if (err == 0) 443 error.SetErrorToGenericError(); 444 #else 445 int err = 0; 446 do { 447 err = ::fsync(m_descriptor); 448 } while (err == -1 && errno == EINTR); 449 450 if (err == -1) 451 error.SetErrorToErrno(); 452 #endif 453 } else { 454 error.SetErrorString("invalid file handle"); 455 } 456 return error; 457 } 458 459 #if defined(__APPLE__) 460 // Darwin kernels only can read/write <= INT_MAX bytes 461 #define MAX_READ_SIZE INT_MAX 462 #define MAX_WRITE_SIZE INT_MAX 463 #endif 464 465 Error File::Read(void *buf, size_t &num_bytes) { 466 Error error; 467 468 #if defined(MAX_READ_SIZE) 469 if (num_bytes > MAX_READ_SIZE) { 470 uint8_t *p = (uint8_t *)buf; 471 size_t bytes_left = num_bytes; 472 // Init the num_bytes read to zero 473 num_bytes = 0; 474 475 while (bytes_left > 0) { 476 size_t curr_num_bytes; 477 if (bytes_left > MAX_READ_SIZE) 478 curr_num_bytes = MAX_READ_SIZE; 479 else 480 curr_num_bytes = bytes_left; 481 482 error = Read(p + num_bytes, curr_num_bytes); 483 484 // Update how many bytes were read 485 num_bytes += curr_num_bytes; 486 if (bytes_left < curr_num_bytes) 487 bytes_left = 0; 488 else 489 bytes_left -= curr_num_bytes; 490 491 if (error.Fail()) 492 break; 493 } 494 return error; 495 } 496 #endif 497 498 ssize_t bytes_read = -1; 499 if (DescriptorIsValid()) { 500 do { 501 bytes_read = ::read(m_descriptor, buf, num_bytes); 502 } while (bytes_read < 0 && errno == EINTR); 503 504 if (bytes_read == -1) { 505 error.SetErrorToErrno(); 506 num_bytes = 0; 507 } else 508 num_bytes = bytes_read; 509 } else if (StreamIsValid()) { 510 bytes_read = ::fread(buf, 1, num_bytes, m_stream); 511 512 if (bytes_read == 0) { 513 if (::feof(m_stream)) 514 error.SetErrorString("feof"); 515 else if (::ferror(m_stream)) 516 error.SetErrorString("ferror"); 517 num_bytes = 0; 518 } else 519 num_bytes = bytes_read; 520 } else { 521 num_bytes = 0; 522 error.SetErrorString("invalid file handle"); 523 } 524 return error; 525 } 526 527 Error File::Write(const void *buf, size_t &num_bytes) { 528 Error error; 529 530 #if defined(MAX_WRITE_SIZE) 531 if (num_bytes > MAX_WRITE_SIZE) { 532 const uint8_t *p = (const uint8_t *)buf; 533 size_t bytes_left = num_bytes; 534 // Init the num_bytes written to zero 535 num_bytes = 0; 536 537 while (bytes_left > 0) { 538 size_t curr_num_bytes; 539 if (bytes_left > MAX_WRITE_SIZE) 540 curr_num_bytes = MAX_WRITE_SIZE; 541 else 542 curr_num_bytes = bytes_left; 543 544 error = Write(p + num_bytes, curr_num_bytes); 545 546 // Update how many bytes were read 547 num_bytes += curr_num_bytes; 548 if (bytes_left < curr_num_bytes) 549 bytes_left = 0; 550 else 551 bytes_left -= curr_num_bytes; 552 553 if (error.Fail()) 554 break; 555 } 556 return error; 557 } 558 #endif 559 560 ssize_t bytes_written = -1; 561 if (DescriptorIsValid()) { 562 do { 563 bytes_written = ::write(m_descriptor, buf, num_bytes); 564 } while (bytes_written < 0 && errno == EINTR); 565 566 if (bytes_written == -1) { 567 error.SetErrorToErrno(); 568 num_bytes = 0; 569 } else 570 num_bytes = bytes_written; 571 } else if (StreamIsValid()) { 572 bytes_written = ::fwrite(buf, 1, num_bytes, m_stream); 573 574 if (bytes_written == 0) { 575 if (::feof(m_stream)) 576 error.SetErrorString("feof"); 577 else if (::ferror(m_stream)) 578 error.SetErrorString("ferror"); 579 num_bytes = 0; 580 } else 581 num_bytes = bytes_written; 582 583 } else { 584 num_bytes = 0; 585 error.SetErrorString("invalid file handle"); 586 } 587 588 return error; 589 } 590 591 Error File::Read(void *buf, size_t &num_bytes, off_t &offset) { 592 Error error; 593 594 #if defined(MAX_READ_SIZE) 595 if (num_bytes > MAX_READ_SIZE) { 596 uint8_t *p = (uint8_t *)buf; 597 size_t bytes_left = num_bytes; 598 // Init the num_bytes read to zero 599 num_bytes = 0; 600 601 while (bytes_left > 0) { 602 size_t curr_num_bytes; 603 if (bytes_left > MAX_READ_SIZE) 604 curr_num_bytes = MAX_READ_SIZE; 605 else 606 curr_num_bytes = bytes_left; 607 608 error = Read(p + num_bytes, curr_num_bytes, offset); 609 610 // Update how many bytes were read 611 num_bytes += curr_num_bytes; 612 if (bytes_left < curr_num_bytes) 613 bytes_left = 0; 614 else 615 bytes_left -= curr_num_bytes; 616 617 if (error.Fail()) 618 break; 619 } 620 return error; 621 } 622 #endif 623 624 #ifndef _WIN32 625 int fd = GetDescriptor(); 626 if (fd != kInvalidDescriptor) { 627 ssize_t bytes_read = -1; 628 do { 629 bytes_read = ::pread(fd, buf, num_bytes, offset); 630 } while (bytes_read < 0 && errno == EINTR); 631 632 if (bytes_read < 0) { 633 num_bytes = 0; 634 error.SetErrorToErrno(); 635 } else { 636 offset += bytes_read; 637 num_bytes = bytes_read; 638 } 639 } else { 640 num_bytes = 0; 641 error.SetErrorString("invalid file handle"); 642 } 643 #else 644 long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 645 SeekFromStart(offset); 646 error = Read(buf, num_bytes); 647 if (!error.Fail()) 648 SeekFromStart(cur); 649 #endif 650 return error; 651 } 652 653 Error File::Read(size_t &num_bytes, off_t &offset, bool null_terminate, 654 DataBufferSP &data_buffer_sp) { 655 Error error; 656 657 if (num_bytes > 0) { 658 int fd = GetDescriptor(); 659 if (fd != kInvalidDescriptor) { 660 struct stat file_stats; 661 if (::fstat(fd, &file_stats) == 0) { 662 if (file_stats.st_size > offset) { 663 const size_t bytes_left = file_stats.st_size - offset; 664 if (num_bytes > bytes_left) 665 num_bytes = bytes_left; 666 667 size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); 668 std::unique_ptr<DataBufferHeap> data_heap_ap; 669 data_heap_ap.reset(new DataBufferHeap()); 670 data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 671 672 if (data_heap_ap.get()) { 673 error = Read(data_heap_ap->GetBytes(), num_bytes, offset); 674 if (error.Success()) { 675 // Make sure we read exactly what we asked for and if we got 676 // less, adjust the array 677 if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) 678 data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 679 data_buffer_sp.reset(data_heap_ap.release()); 680 return error; 681 } 682 } 683 } else 684 error.SetErrorString("file is empty"); 685 } else 686 error.SetErrorToErrno(); 687 } else 688 error.SetErrorString("invalid file handle"); 689 } else 690 error.SetErrorString("invalid file handle"); 691 692 num_bytes = 0; 693 data_buffer_sp.reset(); 694 return error; 695 } 696 697 Error File::Write(const void *buf, size_t &num_bytes, off_t &offset) { 698 Error error; 699 700 #if defined(MAX_WRITE_SIZE) 701 if (num_bytes > MAX_WRITE_SIZE) { 702 const uint8_t *p = (const uint8_t *)buf; 703 size_t bytes_left = num_bytes; 704 // Init the num_bytes written to zero 705 num_bytes = 0; 706 707 while (bytes_left > 0) { 708 size_t curr_num_bytes; 709 if (bytes_left > MAX_WRITE_SIZE) 710 curr_num_bytes = MAX_WRITE_SIZE; 711 else 712 curr_num_bytes = bytes_left; 713 714 error = Write(p + num_bytes, curr_num_bytes, offset); 715 716 // Update how many bytes were read 717 num_bytes += curr_num_bytes; 718 if (bytes_left < curr_num_bytes) 719 bytes_left = 0; 720 else 721 bytes_left -= curr_num_bytes; 722 723 if (error.Fail()) 724 break; 725 } 726 return error; 727 } 728 #endif 729 730 int fd = GetDescriptor(); 731 if (fd != kInvalidDescriptor) { 732 #ifndef _WIN32 733 ssize_t bytes_written = -1; 734 do { 735 bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset); 736 } while (bytes_written < 0 && errno == EINTR); 737 738 if (bytes_written < 0) { 739 num_bytes = 0; 740 error.SetErrorToErrno(); 741 } else { 742 offset += bytes_written; 743 num_bytes = bytes_written; 744 } 745 #else 746 long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 747 error = Write(buf, num_bytes); 748 long after = ::lseek(m_descriptor, 0, SEEK_CUR); 749 750 if (!error.Fail()) 751 SeekFromStart(cur); 752 753 offset = after; 754 #endif 755 } else { 756 num_bytes = 0; 757 error.SetErrorString("invalid file handle"); 758 } 759 return error; 760 } 761 762 //------------------------------------------------------------------ 763 // Print some formatted output to the stream. 764 //------------------------------------------------------------------ 765 size_t File::Printf(const char *format, ...) { 766 va_list args; 767 va_start(args, format); 768 size_t result = PrintfVarArg(format, args); 769 va_end(args); 770 return result; 771 } 772 773 //------------------------------------------------------------------ 774 // Print some formatted output to the stream. 775 //------------------------------------------------------------------ 776 size_t File::PrintfVarArg(const char *format, va_list args) { 777 size_t result = 0; 778 if (DescriptorIsValid()) { 779 char *s = NULL; 780 result = vasprintf(&s, format, args); 781 if (s != NULL) { 782 if (result > 0) { 783 size_t s_len = result; 784 Write(s, s_len); 785 result = s_len; 786 } 787 free(s); 788 } 789 } else if (StreamIsValid()) { 790 result = ::vfprintf(m_stream, format, args); 791 } 792 return result; 793 } 794 795 mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) { 796 mode_t mode = 0; 797 if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) 798 mode |= O_RDWR; 799 else if (open_options & eOpenOptionWrite) 800 mode |= O_WRONLY; 801 802 if (open_options & eOpenOptionAppend) 803 mode |= O_APPEND; 804 805 if (open_options & eOpenOptionTruncate) 806 mode |= O_TRUNC; 807 808 if (open_options & eOpenOptionNonBlocking) 809 mode |= O_NONBLOCK; 810 811 if (open_options & eOpenOptionCanCreateNewOnly) 812 mode |= O_CREAT | O_EXCL; 813 else if (open_options & eOpenOptionCanCreate) 814 mode |= O_CREAT; 815 816 return mode; 817 } 818 819 void File::CalculateInteractiveAndTerminal() { 820 const int fd = GetDescriptor(); 821 if (fd >= 0) { 822 m_is_interactive = eLazyBoolNo; 823 m_is_real_terminal = eLazyBoolNo; 824 #if defined(_WIN32) 825 if (_isatty(fd)) { 826 m_is_interactive = eLazyBoolYes; 827 m_is_real_terminal = eLazyBoolYes; 828 } 829 #else 830 if (isatty(fd)) { 831 m_is_interactive = eLazyBoolYes; 832 struct winsize window_size; 833 if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) { 834 if (window_size.ws_col > 0) { 835 m_is_real_terminal = eLazyBoolYes; 836 if (llvm::sys::Process::FileDescriptorHasColors(fd)) 837 m_supports_colors = eLazyBoolYes; 838 } 839 } 840 } 841 #endif 842 } 843 } 844 845 bool File::GetIsInteractive() { 846 if (m_is_interactive == eLazyBoolCalculate) 847 CalculateInteractiveAndTerminal(); 848 return m_is_interactive == eLazyBoolYes; 849 } 850 851 bool File::GetIsRealTerminal() { 852 if (m_is_real_terminal == eLazyBoolCalculate) 853 CalculateInteractiveAndTerminal(); 854 return m_is_real_terminal == eLazyBoolYes; 855 } 856 857 bool File::GetIsTerminalWithColors() { 858 if (m_supports_colors == eLazyBoolCalculate) 859 CalculateInteractiveAndTerminal(); 860 return m_supports_colors == eLazyBoolYes; 861 } 862