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