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 = ::fcntl(GetDescriptor(), F_DUPFD); 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 = ::fcntl(rhs.GetDescriptor(), F_DUPFD); 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 403 Error 404 File::GetFileSpec (FileSpec &file_spec) const 405 { 406 Error error; 407 #ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED 408 if (IsValid ()) 409 { 410 char path[PATH_MAX]; 411 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) 412 error.SetErrorToErrno(); 413 else 414 file_spec.SetFile (path, false); 415 } 416 else 417 { 418 error.SetErrorString("invalid file handle"); 419 } 420 #elif defined(__linux__) 421 char proc[64]; 422 char path[PATH_MAX]; 423 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) 424 error.SetErrorString ("cannot resolve file descriptor"); 425 else 426 { 427 ssize_t len; 428 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) 429 error.SetErrorToErrno(); 430 else 431 { 432 path[len] = '\0'; 433 file_spec.SetFile (path, false); 434 } 435 } 436 #else 437 error.SetErrorString ("File::GetFileSpec is not supported on this platform"); 438 #endif 439 440 if (error.Fail()) 441 file_spec.Clear(); 442 return error; 443 } 444 445 off_t 446 File::SeekFromStart (off_t offset, Error *error_ptr) 447 { 448 off_t result = 0; 449 if (DescriptorIsValid()) 450 { 451 result = ::lseek (m_descriptor, offset, SEEK_SET); 452 453 if (error_ptr) 454 { 455 if (result == -1) 456 error_ptr->SetErrorToErrno(); 457 else 458 error_ptr->Clear(); 459 } 460 } 461 else if (StreamIsValid ()) 462 { 463 result = ::fseek(m_stream, offset, SEEK_SET); 464 465 if (error_ptr) 466 { 467 if (result == -1) 468 error_ptr->SetErrorToErrno(); 469 else 470 error_ptr->Clear(); 471 } 472 } 473 else if (error_ptr) 474 { 475 error_ptr->SetErrorString("invalid file handle"); 476 } 477 return result; 478 } 479 480 off_t 481 File::SeekFromCurrent (off_t offset, Error *error_ptr) 482 { 483 off_t result = -1; 484 if (DescriptorIsValid()) 485 { 486 result = ::lseek (m_descriptor, offset, SEEK_CUR); 487 488 if (error_ptr) 489 { 490 if (result == -1) 491 error_ptr->SetErrorToErrno(); 492 else 493 error_ptr->Clear(); 494 } 495 } 496 else if (StreamIsValid ()) 497 { 498 result = ::fseek(m_stream, offset, SEEK_CUR); 499 500 if (error_ptr) 501 { 502 if (result == -1) 503 error_ptr->SetErrorToErrno(); 504 else 505 error_ptr->Clear(); 506 } 507 } 508 else if (error_ptr) 509 { 510 error_ptr->SetErrorString("invalid file handle"); 511 } 512 return result; 513 } 514 515 off_t 516 File::SeekFromEnd (off_t offset, Error *error_ptr) 517 { 518 off_t result = -1; 519 if (DescriptorIsValid()) 520 { 521 result = ::lseek (m_descriptor, offset, SEEK_END); 522 523 if (error_ptr) 524 { 525 if (result == -1) 526 error_ptr->SetErrorToErrno(); 527 else 528 error_ptr->Clear(); 529 } 530 } 531 else if (StreamIsValid ()) 532 { 533 result = ::fseek(m_stream, offset, SEEK_END); 534 535 if (error_ptr) 536 { 537 if (result == -1) 538 error_ptr->SetErrorToErrno(); 539 else 540 error_ptr->Clear(); 541 } 542 } 543 else if (error_ptr) 544 { 545 error_ptr->SetErrorString("invalid file handle"); 546 } 547 return result; 548 } 549 550 Error 551 File::Flush () 552 { 553 Error error; 554 if (StreamIsValid()) 555 { 556 int err = 0; 557 do 558 { 559 err = ::fflush (m_stream); 560 } while (err == EOF && errno == EINTR); 561 562 if (err == EOF) 563 error.SetErrorToErrno(); 564 } 565 else if (!DescriptorIsValid()) 566 { 567 error.SetErrorString("invalid file handle"); 568 } 569 return error; 570 } 571 572 573 Error 574 File::Sync () 575 { 576 Error error; 577 if (DescriptorIsValid()) 578 { 579 #ifdef _WIN32 580 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); 581 if (err == 0) 582 error.SetErrorToGenericError(); 583 #else 584 int err = 0; 585 do 586 { 587 err = ::fsync (m_descriptor); 588 } while (err == -1 && errno == EINTR); 589 590 if (err == -1) 591 error.SetErrorToErrno(); 592 #endif 593 } 594 else 595 { 596 error.SetErrorString("invalid file handle"); 597 } 598 return error; 599 } 600 601 #if defined (__APPLE__) 602 // Darwin kernels only can read/write <= INT_MAX bytes 603 #define MAX_READ_SIZE INT_MAX 604 #define MAX_WRITE_SIZE INT_MAX 605 #endif 606 607 Error 608 File::Read (void *buf, size_t &num_bytes) 609 { 610 Error error; 611 612 #if defined (MAX_READ_SIZE) 613 if (num_bytes > MAX_READ_SIZE) 614 { 615 uint8_t *p = (uint8_t *)buf; 616 size_t bytes_left = num_bytes; 617 // Init the num_bytes read to zero 618 num_bytes = 0; 619 620 while (bytes_left > 0) 621 { 622 size_t curr_num_bytes; 623 if (bytes_left > MAX_READ_SIZE) 624 curr_num_bytes = MAX_READ_SIZE; 625 else 626 curr_num_bytes = bytes_left; 627 628 error = Read (p + num_bytes, curr_num_bytes); 629 630 // Update how many bytes were read 631 num_bytes += curr_num_bytes; 632 if (bytes_left < curr_num_bytes) 633 bytes_left = 0; 634 else 635 bytes_left -= curr_num_bytes; 636 637 if (error.Fail()) 638 break; 639 } 640 return error; 641 } 642 #endif 643 644 ssize_t bytes_read = -1; 645 if (DescriptorIsValid()) 646 { 647 do 648 { 649 bytes_read = ::read (m_descriptor, buf, num_bytes); 650 } while (bytes_read < 0 && errno == EINTR); 651 652 if (bytes_read == -1) 653 { 654 error.SetErrorToErrno(); 655 num_bytes = 0; 656 } 657 else 658 num_bytes = bytes_read; 659 } 660 else if (StreamIsValid()) 661 { 662 bytes_read = ::fread (buf, 1, num_bytes, m_stream); 663 664 if (bytes_read == 0) 665 { 666 if (::feof(m_stream)) 667 error.SetErrorString ("feof"); 668 else if (::ferror (m_stream)) 669 error.SetErrorString ("ferror"); 670 num_bytes = 0; 671 } 672 else 673 num_bytes = bytes_read; 674 } 675 else 676 { 677 num_bytes = 0; 678 error.SetErrorString("invalid file handle"); 679 } 680 return error; 681 } 682 683 Error 684 File::Write (const void *buf, size_t &num_bytes) 685 { 686 Error error; 687 688 #if defined (MAX_WRITE_SIZE) 689 if (num_bytes > MAX_WRITE_SIZE) 690 { 691 const uint8_t *p = (const uint8_t *)buf; 692 size_t bytes_left = num_bytes; 693 // Init the num_bytes written to zero 694 num_bytes = 0; 695 696 while (bytes_left > 0) 697 { 698 size_t curr_num_bytes; 699 if (bytes_left > MAX_WRITE_SIZE) 700 curr_num_bytes = MAX_WRITE_SIZE; 701 else 702 curr_num_bytes = bytes_left; 703 704 error = Write (p + num_bytes, curr_num_bytes); 705 706 // Update how many bytes were read 707 num_bytes += curr_num_bytes; 708 if (bytes_left < curr_num_bytes) 709 bytes_left = 0; 710 else 711 bytes_left -= curr_num_bytes; 712 713 if (error.Fail()) 714 break; 715 } 716 return error; 717 } 718 #endif 719 720 ssize_t bytes_written = -1; 721 if (DescriptorIsValid()) 722 { 723 do 724 { 725 bytes_written = ::write (m_descriptor, buf, num_bytes); 726 } while (bytes_written < 0 && errno == EINTR); 727 728 if (bytes_written == -1) 729 { 730 error.SetErrorToErrno(); 731 num_bytes = 0; 732 } 733 else 734 num_bytes = bytes_written; 735 } 736 else if (StreamIsValid()) 737 { 738 bytes_written = ::fwrite (buf, 1, num_bytes, m_stream); 739 740 if (bytes_written == 0) 741 { 742 if (::feof(m_stream)) 743 error.SetErrorString ("feof"); 744 else if (::ferror (m_stream)) 745 error.SetErrorString ("ferror"); 746 num_bytes = 0; 747 } 748 else 749 num_bytes = bytes_written; 750 751 } 752 else 753 { 754 num_bytes = 0; 755 error.SetErrorString("invalid file handle"); 756 } 757 758 return error; 759 } 760 761 762 Error 763 File::Read (void *buf, size_t &num_bytes, off_t &offset) 764 { 765 Error error; 766 767 #if defined (MAX_READ_SIZE) 768 if (num_bytes > MAX_READ_SIZE) 769 { 770 uint8_t *p = (uint8_t *)buf; 771 size_t bytes_left = num_bytes; 772 // Init the num_bytes read to zero 773 num_bytes = 0; 774 775 while (bytes_left > 0) 776 { 777 size_t curr_num_bytes; 778 if (bytes_left > MAX_READ_SIZE) 779 curr_num_bytes = MAX_READ_SIZE; 780 else 781 curr_num_bytes = bytes_left; 782 783 error = Read (p + num_bytes, curr_num_bytes, offset); 784 785 // Update how many bytes were read 786 num_bytes += curr_num_bytes; 787 if (bytes_left < curr_num_bytes) 788 bytes_left = 0; 789 else 790 bytes_left -= curr_num_bytes; 791 792 if (error.Fail()) 793 break; 794 } 795 return error; 796 } 797 #endif 798 799 #ifndef _WIN32 800 int fd = GetDescriptor(); 801 if (fd != kInvalidDescriptor) 802 { 803 ssize_t bytes_read = -1; 804 do 805 { 806 bytes_read = ::pread (fd, buf, num_bytes, offset); 807 } while (bytes_read < 0 && errno == EINTR); 808 809 if (bytes_read < 0) 810 { 811 num_bytes = 0; 812 error.SetErrorToErrno(); 813 } 814 else 815 { 816 offset += bytes_read; 817 num_bytes = bytes_read; 818 } 819 } 820 else 821 { 822 num_bytes = 0; 823 error.SetErrorString("invalid file handle"); 824 } 825 #else 826 long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 827 SeekFromStart(offset); 828 error = Read(buf, num_bytes); 829 if (!error.Fail()) 830 SeekFromStart(cur); 831 #endif 832 return error; 833 } 834 835 Error 836 File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp) 837 { 838 Error error; 839 840 if (num_bytes > 0) 841 { 842 int fd = GetDescriptor(); 843 if (fd != kInvalidDescriptor) 844 { 845 struct stat file_stats; 846 if (::fstat (fd, &file_stats) == 0) 847 { 848 if (file_stats.st_size > offset) 849 { 850 const size_t bytes_left = file_stats.st_size - offset; 851 if (num_bytes > bytes_left) 852 num_bytes = bytes_left; 853 854 size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); 855 std::unique_ptr<DataBufferHeap> data_heap_ap; 856 data_heap_ap.reset(new DataBufferHeap()); 857 data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 858 859 if (data_heap_ap.get()) 860 { 861 error = Read (data_heap_ap->GetBytes(), num_bytes, offset); 862 if (error.Success()) 863 { 864 // Make sure we read exactly what we asked for and if we got 865 // less, adjust the array 866 if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) 867 data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 868 data_buffer_sp.reset(data_heap_ap.release()); 869 return error; 870 } 871 } 872 } 873 else 874 error.SetErrorString("file is empty"); 875 } 876 else 877 error.SetErrorToErrno(); 878 } 879 else 880 error.SetErrorString("invalid file handle"); 881 } 882 else 883 error.SetErrorString("invalid file handle"); 884 885 num_bytes = 0; 886 data_buffer_sp.reset(); 887 return error; 888 } 889 890 Error 891 File::Write (const void *buf, size_t &num_bytes, off_t &offset) 892 { 893 Error error; 894 895 #if defined (MAX_WRITE_SIZE) 896 if (num_bytes > MAX_WRITE_SIZE) 897 { 898 const uint8_t *p = (const uint8_t *)buf; 899 size_t bytes_left = num_bytes; 900 // Init the num_bytes written to zero 901 num_bytes = 0; 902 903 while (bytes_left > 0) 904 { 905 size_t curr_num_bytes; 906 if (bytes_left > MAX_WRITE_SIZE) 907 curr_num_bytes = MAX_WRITE_SIZE; 908 else 909 curr_num_bytes = bytes_left; 910 911 error = Write (p + num_bytes, curr_num_bytes, offset); 912 913 // Update how many bytes were read 914 num_bytes += curr_num_bytes; 915 if (bytes_left < curr_num_bytes) 916 bytes_left = 0; 917 else 918 bytes_left -= curr_num_bytes; 919 920 if (error.Fail()) 921 break; 922 } 923 return error; 924 } 925 #endif 926 927 int fd = GetDescriptor(); 928 if (fd != kInvalidDescriptor) 929 { 930 #ifndef _WIN32 931 ssize_t bytes_written = -1; 932 do 933 { 934 bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset); 935 } while (bytes_written < 0 && errno == EINTR); 936 937 if (bytes_written < 0) 938 { 939 num_bytes = 0; 940 error.SetErrorToErrno(); 941 } 942 else 943 { 944 offset += bytes_written; 945 num_bytes = bytes_written; 946 } 947 #else 948 long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 949 error = Write(buf, num_bytes); 950 long after = ::lseek(m_descriptor, 0, SEEK_CUR); 951 952 if (!error.Fail()) 953 SeekFromStart(cur); 954 955 offset = after; 956 #endif 957 } 958 else 959 { 960 num_bytes = 0; 961 error.SetErrorString("invalid file handle"); 962 } 963 return error; 964 } 965 966 //------------------------------------------------------------------ 967 // Print some formatted output to the stream. 968 //------------------------------------------------------------------ 969 size_t 970 File::Printf (const char *format, ...) 971 { 972 va_list args; 973 va_start (args, format); 974 size_t result = PrintfVarArg (format, args); 975 va_end (args); 976 return result; 977 } 978 979 //------------------------------------------------------------------ 980 // Print some formatted output to the stream. 981 //------------------------------------------------------------------ 982 size_t 983 File::PrintfVarArg (const char *format, va_list args) 984 { 985 size_t result = 0; 986 if (DescriptorIsValid()) 987 { 988 char *s = NULL; 989 result = vasprintf(&s, format, args); 990 if (s != NULL) 991 { 992 if (result > 0) 993 { 994 size_t s_len = result; 995 Write (s, s_len); 996 result = s_len; 997 } 998 free (s); 999 } 1000 } 1001 else if (StreamIsValid()) 1002 { 1003 result = ::vfprintf (m_stream, format, args); 1004 } 1005 return result; 1006 } 1007 1008 mode_t 1009 File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options) 1010 { 1011 mode_t mode = 0; 1012 if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) 1013 mode |= O_RDWR; 1014 else if (open_options & eOpenOptionWrite) 1015 mode |= O_WRONLY; 1016 1017 if (open_options & eOpenOptionAppend) 1018 mode |= O_APPEND; 1019 1020 if (open_options & eOpenOptionTruncate) 1021 mode |= O_TRUNC; 1022 1023 if (open_options & eOpenOptionNonBlocking) 1024 mode |= O_NONBLOCK; 1025 1026 if (open_options & eOpenOptionCanCreateNewOnly) 1027 mode |= O_CREAT | O_EXCL; 1028 else if (open_options & eOpenOptionCanCreate) 1029 mode |= O_CREAT; 1030 1031 return mode; 1032 } 1033 1034 void 1035 File::CalculateInteractiveAndTerminal () 1036 { 1037 const int fd = GetDescriptor(); 1038 if (fd >= 0) 1039 { 1040 m_is_interactive = eLazyBoolNo; 1041 m_is_real_terminal = eLazyBoolNo; 1042 #if (defined(_WIN32) || defined(__ANDROID_NDK__)) 1043 if (_isatty(fd)) 1044 { 1045 m_is_interactive = eLazyBoolYes; 1046 m_is_real_terminal = eLazyBoolYes; 1047 } 1048 #else 1049 if (isatty(fd)) 1050 { 1051 m_is_interactive = eLazyBoolYes; 1052 struct winsize window_size; 1053 if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0) 1054 { 1055 if (window_size.ws_col > 0) 1056 { 1057 m_is_real_terminal = eLazyBoolYes; 1058 if (llvm::sys::Process::FileDescriptorHasColors(fd)) 1059 m_supports_colors = eLazyBoolYes; 1060 } 1061 } 1062 } 1063 #endif 1064 } 1065 } 1066 1067 bool 1068 File::GetIsInteractive () 1069 { 1070 if (m_is_interactive == eLazyBoolCalculate) 1071 CalculateInteractiveAndTerminal (); 1072 return m_is_interactive == eLazyBoolYes; 1073 } 1074 1075 bool 1076 File::GetIsRealTerminal () 1077 { 1078 if (m_is_real_terminal == eLazyBoolCalculate) 1079 CalculateInteractiveAndTerminal(); 1080 return m_is_real_terminal == eLazyBoolYes; 1081 } 1082 1083 bool 1084 File::GetIsTerminalWithColors () 1085 { 1086 if (m_supports_colors == eLazyBoolCalculate) 1087 CalculateInteractiveAndTerminal(); 1088 return m_supports_colors == eLazyBoolYes; 1089 } 1090 1091