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