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