File.cpp revision 296417
1254219Scy//===-- File.cpp ------------------------------------------------*- C++ -*-===// 2254219Scy// 3254219Scy// The LLVM Compiler Infrastructure 4254219Scy// 5254219Scy// This file is distributed under the University of Illinois Open Source 6254219Scy// License. See LICENSE.TXT for details. 7254219Scy// 8254219Scy//===----------------------------------------------------------------------===// 9254219Scy 10254219Scy#include "lldb/Host/File.h" 11254219Scy 12254219Scy#include <errno.h> 13254219Scy#include <fcntl.h> 14254219Scy#include <limits.h> 15254219Scy#include <stdarg.h> 16254219Scy#include <stdio.h> 17254219Scy#include <sys/stat.h> 18254219Scy 19254219Scy#ifdef _WIN32 20254219Scy#include "lldb/Host/windows/windows.h" 21254219Scy#else 22254219Scy#include <sys/ioctl.h> 23254219Scy#endif 24254219Scy 25254219Scy#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors() 26254219Scy 27254219Scy#include "lldb/Core/DataBufferHeap.h" 28254219Scy#include "lldb/Core/Error.h" 29254219Scy#include "lldb/Core/Log.h" 30254219Scy#include "lldb/Host/Config.h" 31254219Scy#include "lldb/Host/FileSpec.h" 32254219Scy 33254219Scyusing namespace lldb; 34254219Scyusing namespace lldb_private; 35254219Scy 36254219Scystatic const char * 37254219ScyGetStreamOpenModeFromOptions (uint32_t options) 38254219Scy{ 39254219Scy if (options & File::eOpenOptionAppend) 40254219Scy { 41254219Scy if (options & File::eOpenOptionRead) 42254219Scy { 43254219Scy if (options & File::eOpenOptionCanCreateNewOnly) 44254219Scy return "a+x"; 45254219Scy else 46254219Scy return "a+"; 47254219Scy } 48254219Scy else if (options & File::eOpenOptionWrite) 49254219Scy { 50254219Scy if (options & File::eOpenOptionCanCreateNewOnly) 51254219Scy return "ax"; 52254219Scy else 53254219Scy return "a"; 54254219Scy } 55254219Scy } 56254219Scy else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite) 57254219Scy { 58254219Scy if (options & File::eOpenOptionCanCreate) 59254219Scy { 60254219Scy if (options & File::eOpenOptionCanCreateNewOnly) 61254219Scy return "w+x"; 62254219Scy else 63254219Scy return "w+"; 64254219Scy } 65254219Scy else 66254219Scy return "r+"; 67254219Scy } 68254219Scy else if (options & File::eOpenOptionRead) 69254219Scy { 70254219Scy return "r"; 71254219Scy } 72254219Scy else if (options & File::eOpenOptionWrite) 73254219Scy { 74254219Scy return "w"; 75254219Scy } 76254219Scy return NULL; 77254219Scy} 78254219Scy 79254219Scyint File::kInvalidDescriptor = -1; 80254219ScyFILE * File::kInvalidStream = NULL; 81254219Scy 82254219ScyFile::File(const char *path, uint32_t options, uint32_t permissions) : 83254219Scy IOObject(eFDTypeFile, false), 84254219Scy m_descriptor (kInvalidDescriptor), 85254219Scy m_stream (kInvalidStream), 86254219Scy m_options (), 87254219Scy m_own_stream (false), 88254219Scy m_is_interactive (eLazyBoolCalculate), 89254219Scy m_is_real_terminal (eLazyBoolCalculate) 90254219Scy{ 91254219Scy Open (path, options, permissions); 92254219Scy} 93254219Scy 94254219ScyFile::File (const FileSpec& filespec, 95254219Scy uint32_t options, 96254219Scy uint32_t permissions) : 97254219Scy IOObject(eFDTypeFile, false), 98254219Scy m_descriptor (kInvalidDescriptor), 99254219Scy m_stream (kInvalidStream), 100254219Scy m_options (0), 101254219Scy m_own_stream (false), 102254219Scy m_is_interactive (eLazyBoolCalculate), 103254219Scy m_is_real_terminal (eLazyBoolCalculate) 104254219Scy 105254219Scy{ 106254219Scy if (filespec) 107254219Scy { 108254219Scy Open (filespec.GetPath().c_str(), options, permissions); 109254219Scy } 110254219Scy} 111254219Scy 112254219ScyFile::File (const File &rhs) : 113254219Scy IOObject(eFDTypeFile, false), 114254219Scy m_descriptor (kInvalidDescriptor), 115254219Scy m_stream (kInvalidStream), 116254219Scy m_options (0), 117254219Scy m_own_stream (false), 118254219Scy m_is_interactive (eLazyBoolCalculate), 119254219Scy m_is_real_terminal (eLazyBoolCalculate) 120254219Scy{ 121254219Scy Duplicate (rhs); 122254219Scy} 123254219Scy 124254219Scy 125254219ScyFile & 126254219ScyFile::operator = (const File &rhs) 127254219Scy{ 128254219Scy if (this != &rhs) 129254219Scy Duplicate (rhs); 130254219Scy return *this; 131254219Scy} 132254219Scy 133254219ScyFile::~File() 134254219Scy{ 135254219Scy Close (); 136254219Scy} 137254219Scy 138254219Scy 139254219Scyint 140254219ScyFile::GetDescriptor() const 141254219Scy{ 142254219Scy if (DescriptorIsValid()) 143254219Scy return m_descriptor; 144254219Scy 145254219Scy // Don't open the file descriptor if we don't need to, just get it from the 146254219Scy // stream if we have one. 147254219Scy if (StreamIsValid()) 148254219Scy { 149254219Scy#if defined(LLVM_ON_WIN32) 150254219Scy return _fileno(m_stream); 151254219Scy#else 152254219Scy return fileno(m_stream); 153254219Scy#endif 154254219Scy } 155254219Scy 156254219Scy // Invalid descriptor and invalid stream, return invalid descriptor. 157254219Scy return kInvalidDescriptor; 158254219Scy} 159254219Scy 160254219ScyIOObject::WaitableHandle 161254219ScyFile::GetWaitableHandle() 162254219Scy{ 163254219Scy return m_descriptor; 164254219Scy} 165254219Scy 166254219Scy 167254219Scyvoid 168254219ScyFile::SetDescriptor (int fd, bool transfer_ownership) 169254219Scy{ 170254219Scy if (IsValid()) 171254219Scy Close(); 172254219Scy m_descriptor = fd; 173254219Scy m_should_close_fd = transfer_ownership; 174254219Scy} 175254219Scy 176254219Scy 177254219ScyFILE * 178254219ScyFile::GetStream () 179254219Scy{ 180254219Scy if (!StreamIsValid()) 181254219Scy { 182254219Scy if (DescriptorIsValid()) 183254219Scy { 184254219Scy const char *mode = GetStreamOpenModeFromOptions (m_options); 185254219Scy if (mode) 186254219Scy { 187254219Scy if (!m_should_close_fd) 188254219Scy { 189254219Scy // We must duplicate the file descriptor if we don't own it because 190254219Scy // when you call fdopen, the stream will own the fd 191254219Scy#ifdef _WIN32 192254219Scy m_descriptor = ::_dup(GetDescriptor()); 193254219Scy#else 194254219Scy m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD); 195254219Scy#endif 196254219Scy m_should_close_fd = true; 197254219Scy } 198254219Scy 199254219Scy do 200254219Scy { 201254219Scy m_stream = ::fdopen (m_descriptor, mode); 202254219Scy } while (m_stream == NULL && errno == EINTR); 203254219Scy 204254219Scy // If we got a stream, then we own the stream and should no 205254219Scy // longer own the descriptor because fclose() will close it for us 206254219Scy 207254219Scy if (m_stream) 208254219Scy { 209254219Scy m_own_stream = true; 210254219Scy m_should_close_fd = false; 211254219Scy } 212254219Scy } 213254219Scy } 214254219Scy } 215254219Scy return m_stream; 216254219Scy} 217254219Scy 218254219Scy 219254219Scyvoid 220254219ScyFile::SetStream (FILE *fh, bool transfer_ownership) 221254219Scy{ 222254219Scy if (IsValid()) 223254219Scy Close(); 224254219Scy m_stream = fh; 225254219Scy m_own_stream = transfer_ownership; 226254219Scy} 227254219Scy 228254219ScyError 229254219ScyFile::Duplicate (const File &rhs) 230254219Scy{ 231254219Scy Error error; 232254219Scy if (IsValid ()) 233254219Scy Close(); 234254219Scy 235254219Scy if (rhs.DescriptorIsValid()) 236254219Scy { 237254219Scy#ifdef _WIN32 238254219Scy m_descriptor = ::_dup(rhs.GetDescriptor()); 239254219Scy#else 240254219Scy m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD); 241254219Scy#endif 242254219Scy if (!DescriptorIsValid()) 243254219Scy error.SetErrorToErrno(); 244254219Scy else 245254219Scy { 246254219Scy m_options = rhs.m_options; 247254219Scy m_should_close_fd = true; 248254219Scy } 249254219Scy } 250254219Scy else 251254219Scy { 252254219Scy error.SetErrorString ("invalid file to duplicate"); 253254219Scy } 254254219Scy return error; 255254219Scy} 256254219Scy 257254219ScyError 258254219ScyFile::Open (const char *path, uint32_t options, uint32_t permissions) 259254219Scy{ 260254219Scy Error error; 261254219Scy if (IsValid()) 262254219Scy Close (); 263254219Scy 264254219Scy int oflag = 0; 265254219Scy const bool read = options & eOpenOptionRead; 266254219Scy const bool write = options & eOpenOptionWrite; 267254219Scy if (write) 268254219Scy { 269254219Scy if (read) 270254219Scy oflag |= O_RDWR; 271254219Scy else 272254219Scy oflag |= O_WRONLY; 273254219Scy 274254219Scy if (options & eOpenOptionAppend) 275254219Scy oflag |= O_APPEND; 276254219Scy 277254219Scy if (options & eOpenOptionTruncate) 278254219Scy oflag |= O_TRUNC; 279254219Scy 280254219Scy if (options & eOpenOptionCanCreate) 281254219Scy oflag |= O_CREAT; 282254219Scy 283254219Scy if (options & eOpenOptionCanCreateNewOnly) 284 oflag |= O_CREAT | O_EXCL; 285 } 286 else if (read) 287 { 288 oflag |= O_RDONLY; 289 290#ifndef _WIN32 291 if (options & eOpenoptionDontFollowSymlinks) 292 oflag |= O_NOFOLLOW; 293#endif 294 } 295 296#ifndef _WIN32 297 if (options & eOpenOptionNonBlocking) 298 oflag |= O_NONBLOCK; 299 if (options & eOpenOptionCloseOnExec) 300 oflag |= O_CLOEXEC; 301#else 302 oflag |= O_BINARY; 303#endif 304 305 mode_t mode = 0; 306 if (oflag & O_CREAT) 307 { 308 if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR; 309 if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR; 310 if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR; 311 if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP; 312 if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP; 313 if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP; 314 if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH; 315 if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH; 316 if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH; 317 } 318 319 do 320 { 321 m_descriptor = ::open(path, oflag, mode); 322 } while (m_descriptor < 0 && errno == EINTR); 323 324 if (!DescriptorIsValid()) 325 error.SetErrorToErrno(); 326 else 327 { 328 m_should_close_fd = true; 329 m_options = options; 330 } 331 332 return error; 333} 334 335uint32_t 336File::GetPermissions(const FileSpec &file_spec, Error &error) 337{ 338 if (file_spec) 339 { 340 struct stat file_stats; 341 if (::stat(file_spec.GetCString(), &file_stats) == -1) 342 error.SetErrorToErrno(); 343 else 344 { 345 error.Clear(); 346 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 347 } 348 } 349 else 350 error.SetErrorString ("empty file spec"); 351 return 0; 352} 353 354uint32_t 355File::GetPermissions(Error &error) const 356{ 357 int fd = GetDescriptor(); 358 if (fd != kInvalidDescriptor) 359 { 360 struct stat file_stats; 361 if (::fstat (fd, &file_stats) == -1) 362 error.SetErrorToErrno(); 363 else 364 { 365 error.Clear(); 366 return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 367 } 368 } 369 else 370 { 371 error.SetErrorString ("invalid file descriptor"); 372 } 373 return 0; 374} 375 376 377Error 378File::Close () 379{ 380 Error error; 381 if (StreamIsValid() && m_own_stream) 382 { 383 if (::fclose (m_stream) == EOF) 384 error.SetErrorToErrno(); 385 } 386 387 if (DescriptorIsValid() && m_should_close_fd) 388 { 389 if (::close (m_descriptor) != 0) 390 error.SetErrorToErrno(); 391 } 392 m_descriptor = kInvalidDescriptor; 393 m_stream = kInvalidStream; 394 m_options = 0; 395 m_own_stream = false; 396 m_should_close_fd = false; 397 m_is_interactive = eLazyBoolCalculate; 398 m_is_real_terminal = eLazyBoolCalculate; 399 return error; 400} 401 402 403Error 404File::GetFileSpec (FileSpec &file_spec) const 405{ 406 Error error; 407#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED 408 if (IsValid ()) 409 { 410 char path[PATH_MAX]; 411 if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) 412 error.SetErrorToErrno(); 413 else 414 file_spec.SetFile (path, false); 415 } 416 else 417 { 418 error.SetErrorString("invalid file handle"); 419 } 420#elif defined(__linux__) 421 char proc[64]; 422 char path[PATH_MAX]; 423 if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) 424 error.SetErrorString ("cannot resolve file descriptor"); 425 else 426 { 427 ssize_t len; 428 if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) 429 error.SetErrorToErrno(); 430 else 431 { 432 path[len] = '\0'; 433 file_spec.SetFile (path, false); 434 } 435 } 436#else 437 error.SetErrorString ("File::GetFileSpec is not supported on this platform"); 438#endif 439 440 if (error.Fail()) 441 file_spec.Clear(); 442 return error; 443} 444 445off_t 446File::SeekFromStart (off_t offset, Error *error_ptr) 447{ 448 off_t result = 0; 449 if (DescriptorIsValid()) 450 { 451 result = ::lseek (m_descriptor, offset, SEEK_SET); 452 453 if (error_ptr) 454 { 455 if (result == -1) 456 error_ptr->SetErrorToErrno(); 457 else 458 error_ptr->Clear(); 459 } 460 } 461 else if (StreamIsValid ()) 462 { 463 result = ::fseek(m_stream, offset, SEEK_SET); 464 465 if (error_ptr) 466 { 467 if (result == -1) 468 error_ptr->SetErrorToErrno(); 469 else 470 error_ptr->Clear(); 471 } 472 } 473 else if (error_ptr) 474 { 475 error_ptr->SetErrorString("invalid file handle"); 476 } 477 return result; 478} 479 480off_t 481File::SeekFromCurrent (off_t offset, Error *error_ptr) 482{ 483 off_t result = -1; 484 if (DescriptorIsValid()) 485 { 486 result = ::lseek (m_descriptor, offset, SEEK_CUR); 487 488 if (error_ptr) 489 { 490 if (result == -1) 491 error_ptr->SetErrorToErrno(); 492 else 493 error_ptr->Clear(); 494 } 495 } 496 else if (StreamIsValid ()) 497 { 498 result = ::fseek(m_stream, offset, SEEK_CUR); 499 500 if (error_ptr) 501 { 502 if (result == -1) 503 error_ptr->SetErrorToErrno(); 504 else 505 error_ptr->Clear(); 506 } 507 } 508 else if (error_ptr) 509 { 510 error_ptr->SetErrorString("invalid file handle"); 511 } 512 return result; 513} 514 515off_t 516File::SeekFromEnd (off_t offset, Error *error_ptr) 517{ 518 off_t result = -1; 519 if (DescriptorIsValid()) 520 { 521 result = ::lseek (m_descriptor, offset, SEEK_END); 522 523 if (error_ptr) 524 { 525 if (result == -1) 526 error_ptr->SetErrorToErrno(); 527 else 528 error_ptr->Clear(); 529 } 530 } 531 else if (StreamIsValid ()) 532 { 533 result = ::fseek(m_stream, offset, SEEK_END); 534 535 if (error_ptr) 536 { 537 if (result == -1) 538 error_ptr->SetErrorToErrno(); 539 else 540 error_ptr->Clear(); 541 } 542 } 543 else if (error_ptr) 544 { 545 error_ptr->SetErrorString("invalid file handle"); 546 } 547 return result; 548} 549 550Error 551File::Flush () 552{ 553 Error error; 554 if (StreamIsValid()) 555 { 556 int err = 0; 557 do 558 { 559 err = ::fflush (m_stream); 560 } while (err == EOF && errno == EINTR); 561 562 if (err == EOF) 563 error.SetErrorToErrno(); 564 } 565 else if (!DescriptorIsValid()) 566 { 567 error.SetErrorString("invalid file handle"); 568 } 569 return error; 570} 571 572 573Error 574File::Sync () 575{ 576 Error error; 577 if (DescriptorIsValid()) 578 { 579#ifdef _WIN32 580 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); 581 if (err == 0) 582 error.SetErrorToGenericError(); 583#else 584 int err = 0; 585 do 586 { 587 err = ::fsync (m_descriptor); 588 } while (err == -1 && errno == EINTR); 589 590 if (err == -1) 591 error.SetErrorToErrno(); 592#endif 593 } 594 else 595 { 596 error.SetErrorString("invalid file handle"); 597 } 598 return error; 599} 600 601#if defined (__APPLE__) 602// Darwin kernels only can read/write <= INT_MAX bytes 603#define MAX_READ_SIZE INT_MAX 604#define MAX_WRITE_SIZE INT_MAX 605#endif 606 607Error 608File::Read (void *buf, size_t &num_bytes) 609{ 610 Error error; 611 612#if defined (MAX_READ_SIZE) 613 if (num_bytes > MAX_READ_SIZE) 614 { 615 uint8_t *p = (uint8_t *)buf; 616 size_t bytes_left = num_bytes; 617 // Init the num_bytes read to zero 618 num_bytes = 0; 619 620 while (bytes_left > 0) 621 { 622 size_t curr_num_bytes; 623 if (bytes_left > MAX_READ_SIZE) 624 curr_num_bytes = MAX_READ_SIZE; 625 else 626 curr_num_bytes = bytes_left; 627 628 error = Read (p + num_bytes, curr_num_bytes); 629 630 // Update how many bytes were read 631 num_bytes += curr_num_bytes; 632 if (bytes_left < curr_num_bytes) 633 bytes_left = 0; 634 else 635 bytes_left -= curr_num_bytes; 636 637 if (error.Fail()) 638 break; 639 } 640 return error; 641 } 642#endif 643 644 ssize_t bytes_read = -1; 645 if (DescriptorIsValid()) 646 { 647 do 648 { 649 bytes_read = ::read (m_descriptor, buf, num_bytes); 650 } while (bytes_read < 0 && errno == EINTR); 651 652 if (bytes_read == -1) 653 { 654 error.SetErrorToErrno(); 655 num_bytes = 0; 656 } 657 else 658 num_bytes = bytes_read; 659 } 660 else if (StreamIsValid()) 661 { 662 bytes_read = ::fread (buf, 1, num_bytes, m_stream); 663 664 if (bytes_read == 0) 665 { 666 if (::feof(m_stream)) 667 error.SetErrorString ("feof"); 668 else if (::ferror (m_stream)) 669 error.SetErrorString ("ferror"); 670 num_bytes = 0; 671 } 672 else 673 num_bytes = bytes_read; 674 } 675 else 676 { 677 num_bytes = 0; 678 error.SetErrorString("invalid file handle"); 679 } 680 return error; 681} 682 683Error 684File::Write (const void *buf, size_t &num_bytes) 685{ 686 Error error; 687 688#if defined (MAX_WRITE_SIZE) 689 if (num_bytes > MAX_WRITE_SIZE) 690 { 691 const uint8_t *p = (const uint8_t *)buf; 692 size_t bytes_left = num_bytes; 693 // Init the num_bytes written to zero 694 num_bytes = 0; 695 696 while (bytes_left > 0) 697 { 698 size_t curr_num_bytes; 699 if (bytes_left > MAX_WRITE_SIZE) 700 curr_num_bytes = MAX_WRITE_SIZE; 701 else 702 curr_num_bytes = bytes_left; 703 704 error = Write (p + num_bytes, curr_num_bytes); 705 706 // Update how many bytes were read 707 num_bytes += curr_num_bytes; 708 if (bytes_left < curr_num_bytes) 709 bytes_left = 0; 710 else 711 bytes_left -= curr_num_bytes; 712 713 if (error.Fail()) 714 break; 715 } 716 return error; 717 } 718#endif 719 720 ssize_t bytes_written = -1; 721 if (DescriptorIsValid()) 722 { 723 do 724 { 725 bytes_written = ::write (m_descriptor, buf, num_bytes); 726 } while (bytes_written < 0 && errno == EINTR); 727 728 if (bytes_written == -1) 729 { 730 error.SetErrorToErrno(); 731 num_bytes = 0; 732 } 733 else 734 num_bytes = bytes_written; 735 } 736 else if (StreamIsValid()) 737 { 738 bytes_written = ::fwrite (buf, 1, num_bytes, m_stream); 739 740 if (bytes_written == 0) 741 { 742 if (::feof(m_stream)) 743 error.SetErrorString ("feof"); 744 else if (::ferror (m_stream)) 745 error.SetErrorString ("ferror"); 746 num_bytes = 0; 747 } 748 else 749 num_bytes = bytes_written; 750 751 } 752 else 753 { 754 num_bytes = 0; 755 error.SetErrorString("invalid file handle"); 756 } 757 758 return error; 759} 760 761 762Error 763File::Read (void *buf, size_t &num_bytes, off_t &offset) 764{ 765 Error error; 766 767#if defined (MAX_READ_SIZE) 768 if (num_bytes > MAX_READ_SIZE) 769 { 770 uint8_t *p = (uint8_t *)buf; 771 size_t bytes_left = num_bytes; 772 // Init the num_bytes read to zero 773 num_bytes = 0; 774 775 while (bytes_left > 0) 776 { 777 size_t curr_num_bytes; 778 if (bytes_left > MAX_READ_SIZE) 779 curr_num_bytes = MAX_READ_SIZE; 780 else 781 curr_num_bytes = bytes_left; 782 783 error = Read (p + num_bytes, curr_num_bytes, offset); 784 785 // Update how many bytes were read 786 num_bytes += curr_num_bytes; 787 if (bytes_left < curr_num_bytes) 788 bytes_left = 0; 789 else 790 bytes_left -= curr_num_bytes; 791 792 if (error.Fail()) 793 break; 794 } 795 return error; 796 } 797#endif 798 799#ifndef _WIN32 800 int fd = GetDescriptor(); 801 if (fd != kInvalidDescriptor) 802 { 803 ssize_t bytes_read = -1; 804 do 805 { 806 bytes_read = ::pread (fd, buf, num_bytes, offset); 807 } while (bytes_read < 0 && errno == EINTR); 808 809 if (bytes_read < 0) 810 { 811 num_bytes = 0; 812 error.SetErrorToErrno(); 813 } 814 else 815 { 816 offset += bytes_read; 817 num_bytes = bytes_read; 818 } 819 } 820 else 821 { 822 num_bytes = 0; 823 error.SetErrorString("invalid file handle"); 824 } 825#else 826 long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 827 SeekFromStart(offset); 828 error = Read(buf, num_bytes); 829 if (!error.Fail()) 830 SeekFromStart(cur); 831#endif 832 return error; 833} 834 835Error 836File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp) 837{ 838 Error error; 839 840 if (num_bytes > 0) 841 { 842 int fd = GetDescriptor(); 843 if (fd != kInvalidDescriptor) 844 { 845 struct stat file_stats; 846 if (::fstat (fd, &file_stats) == 0) 847 { 848 if (file_stats.st_size > offset) 849 { 850 const size_t bytes_left = file_stats.st_size - offset; 851 if (num_bytes > bytes_left) 852 num_bytes = bytes_left; 853 854 size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); 855 std::unique_ptr<DataBufferHeap> data_heap_ap; 856 data_heap_ap.reset(new DataBufferHeap()); 857 data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 858 859 if (data_heap_ap.get()) 860 { 861 error = Read (data_heap_ap->GetBytes(), num_bytes, offset); 862 if (error.Success()) 863 { 864 // Make sure we read exactly what we asked for and if we got 865 // less, adjust the array 866 if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) 867 data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 868 data_buffer_sp.reset(data_heap_ap.release()); 869 return error; 870 } 871 } 872 } 873 else 874 error.SetErrorString("file is empty"); 875 } 876 else 877 error.SetErrorToErrno(); 878 } 879 else 880 error.SetErrorString("invalid file handle"); 881 } 882 else 883 error.SetErrorString("invalid file handle"); 884 885 num_bytes = 0; 886 data_buffer_sp.reset(); 887 return error; 888} 889 890Error 891File::Write (const void *buf, size_t &num_bytes, off_t &offset) 892{ 893 Error error; 894 895#if defined (MAX_WRITE_SIZE) 896 if (num_bytes > MAX_WRITE_SIZE) 897 { 898 const uint8_t *p = (const uint8_t *)buf; 899 size_t bytes_left = num_bytes; 900 // Init the num_bytes written to zero 901 num_bytes = 0; 902 903 while (bytes_left > 0) 904 { 905 size_t curr_num_bytes; 906 if (bytes_left > MAX_WRITE_SIZE) 907 curr_num_bytes = MAX_WRITE_SIZE; 908 else 909 curr_num_bytes = bytes_left; 910 911 error = Write (p + num_bytes, curr_num_bytes, offset); 912 913 // Update how many bytes were read 914 num_bytes += curr_num_bytes; 915 if (bytes_left < curr_num_bytes) 916 bytes_left = 0; 917 else 918 bytes_left -= curr_num_bytes; 919 920 if (error.Fail()) 921 break; 922 } 923 return error; 924 } 925#endif 926 927 int fd = GetDescriptor(); 928 if (fd != kInvalidDescriptor) 929 { 930#ifndef _WIN32 931 ssize_t bytes_written = -1; 932 do 933 { 934 bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset); 935 } while (bytes_written < 0 && errno == EINTR); 936 937 if (bytes_written < 0) 938 { 939 num_bytes = 0; 940 error.SetErrorToErrno(); 941 } 942 else 943 { 944 offset += bytes_written; 945 num_bytes = bytes_written; 946 } 947#else 948 long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 949 error = Write(buf, num_bytes); 950 long after = ::lseek(m_descriptor, 0, SEEK_CUR); 951 952 if (!error.Fail()) 953 SeekFromStart(cur); 954 955 offset = after; 956#endif 957 } 958 else 959 { 960 num_bytes = 0; 961 error.SetErrorString("invalid file handle"); 962 } 963 return error; 964} 965 966//------------------------------------------------------------------ 967// Print some formatted output to the stream. 968//------------------------------------------------------------------ 969size_t 970File::Printf (const char *format, ...) 971{ 972 va_list args; 973 va_start (args, format); 974 size_t result = PrintfVarArg (format, args); 975 va_end (args); 976 return result; 977} 978 979//------------------------------------------------------------------ 980// Print some formatted output to the stream. 981//------------------------------------------------------------------ 982size_t 983File::PrintfVarArg (const char *format, va_list args) 984{ 985 size_t result = 0; 986 if (DescriptorIsValid()) 987 { 988 char *s = NULL; 989 result = vasprintf(&s, format, args); 990 if (s != NULL) 991 { 992 if (result > 0) 993 { 994 size_t s_len = result; 995 Write (s, s_len); 996 result = s_len; 997 } 998 free (s); 999 } 1000 } 1001 else if (StreamIsValid()) 1002 { 1003 result = ::vfprintf (m_stream, format, args); 1004 } 1005 return result; 1006} 1007 1008mode_t 1009File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options) 1010{ 1011 mode_t mode = 0; 1012 if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) 1013 mode |= O_RDWR; 1014 else if (open_options & eOpenOptionWrite) 1015 mode |= O_WRONLY; 1016 1017 if (open_options & eOpenOptionAppend) 1018 mode |= O_APPEND; 1019 1020 if (open_options & eOpenOptionTruncate) 1021 mode |= O_TRUNC; 1022 1023 if (open_options & eOpenOptionNonBlocking) 1024 mode |= O_NONBLOCK; 1025 1026 if (open_options & eOpenOptionCanCreateNewOnly) 1027 mode |= O_CREAT | O_EXCL; 1028 else if (open_options & eOpenOptionCanCreate) 1029 mode |= O_CREAT; 1030 1031 return mode; 1032} 1033 1034void 1035File::CalculateInteractiveAndTerminal () 1036{ 1037 const int fd = GetDescriptor(); 1038 if (fd >= 0) 1039 { 1040 m_is_interactive = eLazyBoolNo; 1041 m_is_real_terminal = eLazyBoolNo; 1042#if (defined(_WIN32) || defined(__ANDROID_NDK__)) 1043 if (_isatty(fd)) 1044 { 1045 m_is_interactive = eLazyBoolYes; 1046 m_is_real_terminal = eLazyBoolYes; 1047 } 1048#else 1049 if (isatty(fd)) 1050 { 1051 m_is_interactive = eLazyBoolYes; 1052 struct winsize window_size; 1053 if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0) 1054 { 1055 if (window_size.ws_col > 0) 1056 { 1057 m_is_real_terminal = eLazyBoolYes; 1058 if (llvm::sys::Process::FileDescriptorHasColors(fd)) 1059 m_supports_colors = eLazyBoolYes; 1060 } 1061 } 1062 } 1063#endif 1064 } 1065} 1066 1067bool 1068File::GetIsInteractive () 1069{ 1070 if (m_is_interactive == eLazyBoolCalculate) 1071 CalculateInteractiveAndTerminal (); 1072 return m_is_interactive == eLazyBoolYes; 1073} 1074 1075bool 1076File::GetIsRealTerminal () 1077{ 1078 if (m_is_real_terminal == eLazyBoolCalculate) 1079 CalculateInteractiveAndTerminal(); 1080 return m_is_real_terminal == eLazyBoolYes; 1081} 1082 1083bool 1084File::GetIsTerminalWithColors () 1085{ 1086 if (m_supports_colors == eLazyBoolCalculate) 1087 CalculateInteractiveAndTerminal(); 1088 return m_supports_colors == eLazyBoolYes; 1089} 1090 1091