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