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