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