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