File.cpp revision 296417
1258884Semaste//===-- File.cpp ------------------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/Host/File.h" 11254721Semaste 12254721Semaste#include <errno.h> 13254721Semaste#include <fcntl.h> 14254721Semaste#include <limits.h> 15254721Semaste#include <stdarg.h> 16262528Semaste#include <stdio.h> 17254721Semaste#include <sys/stat.h> 18254721Semaste 19258054Semaste#ifdef _WIN32 20258054Semaste#include "lldb/Host/windows/windows.h" 21262528Semaste#else 22262528Semaste#include <sys/ioctl.h> 23258054Semaste#endif 24258054Semaste 25296417Sdim#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors() 26296417Sdim 27254721Semaste#include "lldb/Core/DataBufferHeap.h" 28254721Semaste#include "lldb/Core/Error.h" 29276479Sdim#include "lldb/Core/Log.h" 30254721Semaste#include "lldb/Host/Config.h" 31254721Semaste#include "lldb/Host/FileSpec.h" 32254721Semaste 33254721Semasteusing namespace lldb; 34254721Semasteusing namespace lldb_private; 35254721Semaste 36254721Semastestatic const char * 37254721SemasteGetStreamOpenModeFromOptions (uint32_t options) 38254721Semaste{ 39254721Semaste if (options & File::eOpenOptionAppend) 40254721Semaste { 41254721Semaste if (options & File::eOpenOptionRead) 42254721Semaste { 43254721Semaste if (options & File::eOpenOptionCanCreateNewOnly) 44254721Semaste return "a+x"; 45254721Semaste else 46254721Semaste return "a+"; 47254721Semaste } 48254721Semaste else if (options & File::eOpenOptionWrite) 49254721Semaste { 50254721Semaste if (options & File::eOpenOptionCanCreateNewOnly) 51254721Semaste return "ax"; 52254721Semaste else 53254721Semaste return "a"; 54254721Semaste } 55254721Semaste } 56254721Semaste else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite) 57254721Semaste { 58254721Semaste if (options & File::eOpenOptionCanCreate) 59254721Semaste { 60254721Semaste if (options & File::eOpenOptionCanCreateNewOnly) 61254721Semaste return "w+x"; 62254721Semaste else 63254721Semaste return "w+"; 64254721Semaste } 65254721Semaste else 66254721Semaste return "r+"; 67254721Semaste } 68254721Semaste else if (options & File::eOpenOptionRead) 69254721Semaste { 70254721Semaste return "r"; 71254721Semaste } 72254721Semaste else if (options & File::eOpenOptionWrite) 73254721Semaste { 74254721Semaste return "w"; 75254721Semaste } 76254721Semaste return NULL; 77254721Semaste} 78254721Semaste 79254721Semasteint File::kInvalidDescriptor = -1; 80254721SemasteFILE * File::kInvalidStream = NULL; 81254721Semaste 82254721SemasteFile::File(const char *path, uint32_t options, uint32_t permissions) : 83276479Sdim IOObject(eFDTypeFile, false), 84254721Semaste m_descriptor (kInvalidDescriptor), 85254721Semaste m_stream (kInvalidStream), 86262528Semaste m_options (), 87262528Semaste m_own_stream (false), 88262528Semaste m_is_interactive (eLazyBoolCalculate), 89262528Semaste m_is_real_terminal (eLazyBoolCalculate) 90254721Semaste{ 91254721Semaste Open (path, options, permissions); 92254721Semaste} 93254721Semaste 94258054SemasteFile::File (const FileSpec& filespec, 95258054Semaste uint32_t options, 96258054Semaste uint32_t permissions) : 97276479Sdim IOObject(eFDTypeFile, false), 98258054Semaste m_descriptor (kInvalidDescriptor), 99258054Semaste m_stream (kInvalidStream), 100258054Semaste m_options (0), 101262528Semaste m_own_stream (false), 102262528Semaste m_is_interactive (eLazyBoolCalculate), 103262528Semaste m_is_real_terminal (eLazyBoolCalculate) 104262528Semaste 105258054Semaste{ 106258054Semaste if (filespec) 107258054Semaste { 108258054Semaste Open (filespec.GetPath().c_str(), options, permissions); 109258054Semaste } 110258054Semaste} 111258054Semaste 112254721SemasteFile::File (const File &rhs) : 113276479Sdim IOObject(eFDTypeFile, false), 114254721Semaste m_descriptor (kInvalidDescriptor), 115254721Semaste m_stream (kInvalidStream), 116254721Semaste m_options (0), 117262528Semaste m_own_stream (false), 118262528Semaste m_is_interactive (eLazyBoolCalculate), 119262528Semaste m_is_real_terminal (eLazyBoolCalculate) 120254721Semaste{ 121254721Semaste Duplicate (rhs); 122254721Semaste} 123254721Semaste 124254721Semaste 125254721SemasteFile & 126254721SemasteFile::operator = (const File &rhs) 127254721Semaste{ 128254721Semaste if (this != &rhs) 129254721Semaste Duplicate (rhs); 130254721Semaste return *this; 131254721Semaste} 132254721Semaste 133254721SemasteFile::~File() 134254721Semaste{ 135254721Semaste Close (); 136254721Semaste} 137254721Semaste 138254721Semaste 139254721Semasteint 140254721SemasteFile::GetDescriptor() const 141254721Semaste{ 142254721Semaste if (DescriptorIsValid()) 143254721Semaste return m_descriptor; 144254721Semaste 145254721Semaste // Don't open the file descriptor if we don't need to, just get it from the 146254721Semaste // stream if we have one. 147254721Semaste if (StreamIsValid()) 148296417Sdim { 149296417Sdim#if defined(LLVM_ON_WIN32) 150296417Sdim return _fileno(m_stream); 151296417Sdim#else 152296417Sdim return fileno(m_stream); 153296417Sdim#endif 154296417Sdim } 155254721Semaste 156254721Semaste // Invalid descriptor and invalid stream, return invalid descriptor. 157254721Semaste return kInvalidDescriptor; 158254721Semaste} 159254721Semaste 160276479SdimIOObject::WaitableHandle 161276479SdimFile::GetWaitableHandle() 162276479Sdim{ 163276479Sdim return m_descriptor; 164276479Sdim} 165276479Sdim 166276479Sdim 167254721Semastevoid 168254721SemasteFile::SetDescriptor (int fd, bool transfer_ownership) 169254721Semaste{ 170254721Semaste if (IsValid()) 171254721Semaste Close(); 172254721Semaste m_descriptor = fd; 173276479Sdim m_should_close_fd = transfer_ownership; 174254721Semaste} 175254721Semaste 176254721Semaste 177254721SemasteFILE * 178254721SemasteFile::GetStream () 179254721Semaste{ 180254721Semaste if (!StreamIsValid()) 181254721Semaste { 182254721Semaste if (DescriptorIsValid()) 183254721Semaste { 184254721Semaste const char *mode = GetStreamOpenModeFromOptions (m_options); 185254721Semaste if (mode) 186254721Semaste { 187276479Sdim if (!m_should_close_fd) 188262528Semaste { 189262528Semaste // We must duplicate the file descriptor if we don't own it because 190262528Semaste // when you call fdopen, the stream will own the fd 191262528Semaste#ifdef _WIN32 192262528Semaste m_descriptor = ::_dup(GetDescriptor()); 193262528Semaste#else 194262528Semaste m_descriptor = ::fcntl(GetDescriptor(), F_DUPFD); 195262528Semaste#endif 196276479Sdim m_should_close_fd = true; 197262528Semaste } 198262528Semaste 199254721Semaste do 200254721Semaste { 201254721Semaste m_stream = ::fdopen (m_descriptor, mode); 202254721Semaste } while (m_stream == NULL && errno == EINTR); 203262528Semaste 204262528Semaste // If we got a stream, then we own the stream and should no 205262528Semaste // longer own the descriptor because fclose() will close it for us 206262528Semaste 207262528Semaste if (m_stream) 208262528Semaste { 209262528Semaste m_own_stream = true; 210276479Sdim m_should_close_fd = false; 211262528Semaste } 212254721Semaste } 213254721Semaste } 214254721Semaste } 215254721Semaste return m_stream; 216254721Semaste} 217254721Semaste 218254721Semaste 219254721Semastevoid 220254721SemasteFile::SetStream (FILE *fh, bool transfer_ownership) 221254721Semaste{ 222254721Semaste if (IsValid()) 223254721Semaste Close(); 224254721Semaste m_stream = fh; 225262528Semaste m_own_stream = transfer_ownership; 226254721Semaste} 227254721Semaste 228254721SemasteError 229254721SemasteFile::Duplicate (const File &rhs) 230254721Semaste{ 231254721Semaste Error error; 232254721Semaste if (IsValid ()) 233254721Semaste Close(); 234254721Semaste 235254721Semaste if (rhs.DescriptorIsValid()) 236254721Semaste { 237258054Semaste#ifdef _WIN32 238258054Semaste m_descriptor = ::_dup(rhs.GetDescriptor()); 239258054Semaste#else 240254721Semaste m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD); 241258054Semaste#endif 242254721Semaste if (!DescriptorIsValid()) 243254721Semaste error.SetErrorToErrno(); 244254721Semaste else 245254721Semaste { 246254721Semaste m_options = rhs.m_options; 247276479Sdim m_should_close_fd = true; 248254721Semaste } 249254721Semaste } 250254721Semaste else 251254721Semaste { 252254721Semaste error.SetErrorString ("invalid file to duplicate"); 253254721Semaste } 254254721Semaste return error; 255254721Semaste} 256254721Semaste 257254721SemasteError 258254721SemasteFile::Open (const char *path, uint32_t options, uint32_t permissions) 259254721Semaste{ 260254721Semaste Error error; 261254721Semaste if (IsValid()) 262254721Semaste Close (); 263254721Semaste 264254721Semaste int oflag = 0; 265254721Semaste const bool read = options & eOpenOptionRead; 266254721Semaste const bool write = options & eOpenOptionWrite; 267254721Semaste if (write) 268254721Semaste { 269254721Semaste if (read) 270254721Semaste oflag |= O_RDWR; 271254721Semaste else 272254721Semaste oflag |= O_WRONLY; 273254721Semaste 274254721Semaste if (options & eOpenOptionAppend) 275254721Semaste oflag |= O_APPEND; 276254721Semaste 277254721Semaste if (options & eOpenOptionTruncate) 278254721Semaste oflag |= O_TRUNC; 279254721Semaste 280254721Semaste if (options & eOpenOptionCanCreate) 281254721Semaste oflag |= O_CREAT; 282254721Semaste 283254721Semaste if (options & eOpenOptionCanCreateNewOnly) 284254721Semaste oflag |= O_CREAT | O_EXCL; 285254721Semaste } 286254721Semaste else if (read) 287254721Semaste { 288254721Semaste oflag |= O_RDONLY; 289258884Semaste 290258884Semaste#ifndef _WIN32 291258884Semaste if (options & eOpenoptionDontFollowSymlinks) 292258884Semaste oflag |= O_NOFOLLOW; 293258884Semaste#endif 294254721Semaste } 295254721Semaste 296258054Semaste#ifndef _WIN32 297254721Semaste if (options & eOpenOptionNonBlocking) 298254721Semaste oflag |= O_NONBLOCK; 299288943Sdim if (options & eOpenOptionCloseOnExec) 300288943Sdim oflag |= O_CLOEXEC; 301258054Semaste#else 302258054Semaste oflag |= O_BINARY; 303258054Semaste#endif 304254721Semaste 305254721Semaste mode_t mode = 0; 306254721Semaste if (oflag & O_CREAT) 307254721Semaste { 308258884Semaste if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR; 309258884Semaste if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR; 310258884Semaste if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR; 311258884Semaste if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP; 312258884Semaste if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP; 313258884Semaste if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP; 314258884Semaste if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH; 315258884Semaste if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH; 316258884Semaste if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH; 317254721Semaste } 318254721Semaste 319254721Semaste do 320254721Semaste { 321254721Semaste m_descriptor = ::open(path, oflag, mode); 322254721Semaste } while (m_descriptor < 0 && errno == EINTR); 323254721Semaste 324254721Semaste if (!DescriptorIsValid()) 325254721Semaste error.SetErrorToErrno(); 326254721Semaste else 327262528Semaste { 328276479Sdim m_should_close_fd = true; 329262528Semaste m_options = options; 330262528Semaste } 331254721Semaste 332254721Semaste return error; 333254721Semaste} 334254721Semaste 335258054Semasteuint32_t 336288943SdimFile::GetPermissions(const FileSpec &file_spec, Error &error) 337258054Semaste{ 338288943Sdim if (file_spec) 339258054Semaste { 340258054Semaste struct stat file_stats; 341288943Sdim if (::stat(file_spec.GetCString(), &file_stats) == -1) 342258054Semaste error.SetErrorToErrno(); 343258054Semaste else 344258054Semaste { 345258054Semaste error.Clear(); 346258884Semaste return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 347258054Semaste } 348258054Semaste } 349258054Semaste else 350288943Sdim error.SetErrorString ("empty file spec"); 351258054Semaste return 0; 352258054Semaste} 353258054Semaste 354258054Semasteuint32_t 355258054SemasteFile::GetPermissions(Error &error) const 356258054Semaste{ 357258054Semaste int fd = GetDescriptor(); 358258054Semaste if (fd != kInvalidDescriptor) 359258054Semaste { 360258054Semaste struct stat file_stats; 361258054Semaste if (::fstat (fd, &file_stats) == -1) 362258054Semaste error.SetErrorToErrno(); 363258054Semaste else 364258054Semaste { 365258054Semaste error.Clear(); 366258884Semaste return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 367258054Semaste } 368258054Semaste } 369258054Semaste else 370258054Semaste { 371258054Semaste error.SetErrorString ("invalid file descriptor"); 372258054Semaste } 373258054Semaste return 0; 374258054Semaste} 375258054Semaste 376258054Semaste 377254721SemasteError 378254721SemasteFile::Close () 379254721Semaste{ 380254721Semaste Error error; 381262528Semaste if (StreamIsValid() && m_own_stream) 382254721Semaste { 383262528Semaste if (::fclose (m_stream) == EOF) 384262528Semaste error.SetErrorToErrno(); 385254721Semaste } 386262528Semaste 387276479Sdim if (DescriptorIsValid() && m_should_close_fd) 388262528Semaste { 389262528Semaste if (::close (m_descriptor) != 0) 390262528Semaste error.SetErrorToErrno(); 391262528Semaste } 392262528Semaste m_descriptor = kInvalidDescriptor; 393262528Semaste m_stream = kInvalidStream; 394262528Semaste m_options = 0; 395262528Semaste m_own_stream = false; 396276479Sdim m_should_close_fd = false; 397262528Semaste m_is_interactive = eLazyBoolCalculate; 398262528Semaste m_is_real_terminal = eLazyBoolCalculate; 399254721Semaste return error; 400254721Semaste} 401254721Semaste 402254721Semaste 403254721SemasteError 404254721SemasteFile::GetFileSpec (FileSpec &file_spec) const 405254721Semaste{ 406254721Semaste Error error; 407254721Semaste#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED 408254721Semaste if (IsValid ()) 409254721Semaste { 410254721Semaste char path[PATH_MAX]; 411254721Semaste if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) 412254721Semaste error.SetErrorToErrno(); 413254721Semaste else 414254721Semaste file_spec.SetFile (path, false); 415254721Semaste } 416254721Semaste else 417254721Semaste { 418254721Semaste error.SetErrorString("invalid file handle"); 419254721Semaste } 420254721Semaste#elif defined(__linux__) 421254721Semaste char proc[64]; 422254721Semaste char path[PATH_MAX]; 423254721Semaste if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) 424254721Semaste error.SetErrorString ("cannot resolve file descriptor"); 425254721Semaste else 426254721Semaste { 427254721Semaste ssize_t len; 428254721Semaste if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) 429254721Semaste error.SetErrorToErrno(); 430254721Semaste else 431254721Semaste { 432254721Semaste path[len] = '\0'; 433254721Semaste file_spec.SetFile (path, false); 434254721Semaste } 435254721Semaste } 436254721Semaste#else 437254721Semaste error.SetErrorString ("File::GetFileSpec is not supported on this platform"); 438254721Semaste#endif 439254721Semaste 440254721Semaste if (error.Fail()) 441254721Semaste file_spec.Clear(); 442254721Semaste return error; 443254721Semaste} 444254721Semaste 445254721Semasteoff_t 446254721SemasteFile::SeekFromStart (off_t offset, Error *error_ptr) 447254721Semaste{ 448254721Semaste off_t result = 0; 449254721Semaste if (DescriptorIsValid()) 450254721Semaste { 451254721Semaste result = ::lseek (m_descriptor, offset, SEEK_SET); 452254721Semaste 453254721Semaste if (error_ptr) 454254721Semaste { 455254721Semaste if (result == -1) 456254721Semaste error_ptr->SetErrorToErrno(); 457254721Semaste else 458254721Semaste error_ptr->Clear(); 459254721Semaste } 460254721Semaste } 461254721Semaste else if (StreamIsValid ()) 462254721Semaste { 463254721Semaste result = ::fseek(m_stream, offset, SEEK_SET); 464254721Semaste 465254721Semaste if (error_ptr) 466254721Semaste { 467254721Semaste if (result == -1) 468254721Semaste error_ptr->SetErrorToErrno(); 469254721Semaste else 470254721Semaste error_ptr->Clear(); 471254721Semaste } 472254721Semaste } 473254721Semaste else if (error_ptr) 474254721Semaste { 475254721Semaste error_ptr->SetErrorString("invalid file handle"); 476254721Semaste } 477254721Semaste return result; 478254721Semaste} 479254721Semaste 480254721Semasteoff_t 481254721SemasteFile::SeekFromCurrent (off_t offset, Error *error_ptr) 482254721Semaste{ 483254721Semaste off_t result = -1; 484254721Semaste if (DescriptorIsValid()) 485254721Semaste { 486254721Semaste result = ::lseek (m_descriptor, offset, SEEK_CUR); 487254721Semaste 488254721Semaste if (error_ptr) 489254721Semaste { 490254721Semaste if (result == -1) 491254721Semaste error_ptr->SetErrorToErrno(); 492254721Semaste else 493254721Semaste error_ptr->Clear(); 494254721Semaste } 495254721Semaste } 496254721Semaste else if (StreamIsValid ()) 497254721Semaste { 498254721Semaste result = ::fseek(m_stream, offset, SEEK_CUR); 499254721Semaste 500254721Semaste if (error_ptr) 501254721Semaste { 502254721Semaste if (result == -1) 503254721Semaste error_ptr->SetErrorToErrno(); 504254721Semaste else 505254721Semaste error_ptr->Clear(); 506254721Semaste } 507254721Semaste } 508254721Semaste else if (error_ptr) 509254721Semaste { 510254721Semaste error_ptr->SetErrorString("invalid file handle"); 511254721Semaste } 512254721Semaste return result; 513254721Semaste} 514254721Semaste 515254721Semasteoff_t 516254721SemasteFile::SeekFromEnd (off_t offset, Error *error_ptr) 517254721Semaste{ 518254721Semaste off_t result = -1; 519254721Semaste if (DescriptorIsValid()) 520254721Semaste { 521254721Semaste result = ::lseek (m_descriptor, offset, SEEK_END); 522254721Semaste 523254721Semaste if (error_ptr) 524254721Semaste { 525254721Semaste if (result == -1) 526254721Semaste error_ptr->SetErrorToErrno(); 527254721Semaste else 528254721Semaste error_ptr->Clear(); 529254721Semaste } 530254721Semaste } 531254721Semaste else if (StreamIsValid ()) 532254721Semaste { 533254721Semaste result = ::fseek(m_stream, offset, SEEK_END); 534254721Semaste 535254721Semaste if (error_ptr) 536254721Semaste { 537254721Semaste if (result == -1) 538254721Semaste error_ptr->SetErrorToErrno(); 539254721Semaste else 540254721Semaste error_ptr->Clear(); 541254721Semaste } 542254721Semaste } 543254721Semaste else if (error_ptr) 544254721Semaste { 545254721Semaste error_ptr->SetErrorString("invalid file handle"); 546254721Semaste } 547254721Semaste return result; 548254721Semaste} 549254721Semaste 550254721SemasteError 551254721SemasteFile::Flush () 552254721Semaste{ 553254721Semaste Error error; 554254721Semaste if (StreamIsValid()) 555254721Semaste { 556254721Semaste int err = 0; 557254721Semaste do 558254721Semaste { 559254721Semaste err = ::fflush (m_stream); 560254721Semaste } while (err == EOF && errno == EINTR); 561254721Semaste 562254721Semaste if (err == EOF) 563254721Semaste error.SetErrorToErrno(); 564254721Semaste } 565254721Semaste else if (!DescriptorIsValid()) 566254721Semaste { 567254721Semaste error.SetErrorString("invalid file handle"); 568254721Semaste } 569254721Semaste return error; 570254721Semaste} 571254721Semaste 572254721Semaste 573254721SemasteError 574254721SemasteFile::Sync () 575254721Semaste{ 576254721Semaste Error error; 577254721Semaste if (DescriptorIsValid()) 578254721Semaste { 579258054Semaste#ifdef _WIN32 580258054Semaste int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); 581258054Semaste if (err == 0) 582258054Semaste error.SetErrorToGenericError(); 583258054Semaste#else 584254721Semaste int err = 0; 585254721Semaste do 586254721Semaste { 587254721Semaste err = ::fsync (m_descriptor); 588254721Semaste } while (err == -1 && errno == EINTR); 589254721Semaste 590254721Semaste if (err == -1) 591254721Semaste error.SetErrorToErrno(); 592258054Semaste#endif 593254721Semaste } 594254721Semaste else 595254721Semaste { 596254721Semaste error.SetErrorString("invalid file handle"); 597254721Semaste } 598254721Semaste return error; 599254721Semaste} 600254721Semaste 601288943Sdim#if defined (__APPLE__) 602288943Sdim// Darwin kernels only can read/write <= INT_MAX bytes 603288943Sdim#define MAX_READ_SIZE INT_MAX 604288943Sdim#define MAX_WRITE_SIZE INT_MAX 605288943Sdim#endif 606288943Sdim 607254721SemasteError 608254721SemasteFile::Read (void *buf, size_t &num_bytes) 609254721Semaste{ 610254721Semaste Error error; 611288943Sdim 612288943Sdim#if defined (MAX_READ_SIZE) 613288943Sdim if (num_bytes > MAX_READ_SIZE) 614288943Sdim { 615288943Sdim uint8_t *p = (uint8_t *)buf; 616288943Sdim size_t bytes_left = num_bytes; 617288943Sdim // Init the num_bytes read to zero 618288943Sdim num_bytes = 0; 619288943Sdim 620288943Sdim while (bytes_left > 0) 621288943Sdim { 622288943Sdim size_t curr_num_bytes; 623288943Sdim if (bytes_left > MAX_READ_SIZE) 624288943Sdim curr_num_bytes = MAX_READ_SIZE; 625288943Sdim else 626288943Sdim curr_num_bytes = bytes_left; 627288943Sdim 628288943Sdim error = Read (p + num_bytes, curr_num_bytes); 629288943Sdim 630288943Sdim // Update how many bytes were read 631288943Sdim num_bytes += curr_num_bytes; 632288943Sdim if (bytes_left < curr_num_bytes) 633288943Sdim bytes_left = 0; 634288943Sdim else 635288943Sdim bytes_left -= curr_num_bytes; 636288943Sdim 637288943Sdim if (error.Fail()) 638288943Sdim break; 639288943Sdim } 640288943Sdim return error; 641288943Sdim } 642288943Sdim#endif 643288943Sdim 644254721Semaste ssize_t bytes_read = -1; 645254721Semaste if (DescriptorIsValid()) 646254721Semaste { 647254721Semaste do 648254721Semaste { 649254721Semaste bytes_read = ::read (m_descriptor, buf, num_bytes); 650254721Semaste } while (bytes_read < 0 && errno == EINTR); 651254721Semaste 652254721Semaste if (bytes_read == -1) 653254721Semaste { 654254721Semaste error.SetErrorToErrno(); 655254721Semaste num_bytes = 0; 656254721Semaste } 657254721Semaste else 658254721Semaste num_bytes = bytes_read; 659254721Semaste } 660254721Semaste else if (StreamIsValid()) 661254721Semaste { 662254721Semaste bytes_read = ::fread (buf, 1, num_bytes, m_stream); 663254721Semaste 664254721Semaste if (bytes_read == 0) 665254721Semaste { 666254721Semaste if (::feof(m_stream)) 667254721Semaste error.SetErrorString ("feof"); 668254721Semaste else if (::ferror (m_stream)) 669254721Semaste error.SetErrorString ("ferror"); 670254721Semaste num_bytes = 0; 671254721Semaste } 672254721Semaste else 673254721Semaste num_bytes = bytes_read; 674254721Semaste } 675254721Semaste else 676254721Semaste { 677254721Semaste num_bytes = 0; 678254721Semaste error.SetErrorString("invalid file handle"); 679254721Semaste } 680254721Semaste return error; 681254721Semaste} 682254721Semaste 683254721SemasteError 684254721SemasteFile::Write (const void *buf, size_t &num_bytes) 685254721Semaste{ 686254721Semaste Error error; 687288943Sdim 688288943Sdim#if defined (MAX_WRITE_SIZE) 689288943Sdim if (num_bytes > MAX_WRITE_SIZE) 690288943Sdim { 691288943Sdim const uint8_t *p = (const uint8_t *)buf; 692288943Sdim size_t bytes_left = num_bytes; 693288943Sdim // Init the num_bytes written to zero 694288943Sdim num_bytes = 0; 695288943Sdim 696288943Sdim while (bytes_left > 0) 697288943Sdim { 698288943Sdim size_t curr_num_bytes; 699288943Sdim if (bytes_left > MAX_WRITE_SIZE) 700288943Sdim curr_num_bytes = MAX_WRITE_SIZE; 701288943Sdim else 702288943Sdim curr_num_bytes = bytes_left; 703288943Sdim 704288943Sdim error = Write (p + num_bytes, curr_num_bytes); 705288943Sdim 706288943Sdim // Update how many bytes were read 707288943Sdim num_bytes += curr_num_bytes; 708288943Sdim if (bytes_left < curr_num_bytes) 709288943Sdim bytes_left = 0; 710288943Sdim else 711288943Sdim bytes_left -= curr_num_bytes; 712288943Sdim 713288943Sdim if (error.Fail()) 714288943Sdim break; 715288943Sdim } 716288943Sdim return error; 717288943Sdim } 718288943Sdim#endif 719288943Sdim 720254721Semaste ssize_t bytes_written = -1; 721254721Semaste if (DescriptorIsValid()) 722254721Semaste { 723254721Semaste do 724254721Semaste { 725254721Semaste bytes_written = ::write (m_descriptor, buf, num_bytes); 726254721Semaste } while (bytes_written < 0 && errno == EINTR); 727254721Semaste 728254721Semaste if (bytes_written == -1) 729254721Semaste { 730254721Semaste error.SetErrorToErrno(); 731254721Semaste num_bytes = 0; 732254721Semaste } 733254721Semaste else 734254721Semaste num_bytes = bytes_written; 735254721Semaste } 736254721Semaste else if (StreamIsValid()) 737254721Semaste { 738254721Semaste bytes_written = ::fwrite (buf, 1, num_bytes, m_stream); 739254721Semaste 740254721Semaste if (bytes_written == 0) 741254721Semaste { 742254721Semaste if (::feof(m_stream)) 743254721Semaste error.SetErrorString ("feof"); 744254721Semaste else if (::ferror (m_stream)) 745254721Semaste error.SetErrorString ("ferror"); 746254721Semaste num_bytes = 0; 747254721Semaste } 748254721Semaste else 749254721Semaste num_bytes = bytes_written; 750254721Semaste 751254721Semaste } 752254721Semaste else 753254721Semaste { 754254721Semaste num_bytes = 0; 755254721Semaste error.SetErrorString("invalid file handle"); 756254721Semaste } 757276479Sdim 758254721Semaste return error; 759254721Semaste} 760254721Semaste 761254721Semaste 762254721SemasteError 763254721SemasteFile::Read (void *buf, size_t &num_bytes, off_t &offset) 764254721Semaste{ 765288943Sdim Error error; 766288943Sdim 767288943Sdim#if defined (MAX_READ_SIZE) 768288943Sdim if (num_bytes > MAX_READ_SIZE) 769288943Sdim { 770288943Sdim uint8_t *p = (uint8_t *)buf; 771288943Sdim size_t bytes_left = num_bytes; 772288943Sdim // Init the num_bytes read to zero 773288943Sdim num_bytes = 0; 774288943Sdim 775288943Sdim while (bytes_left > 0) 776288943Sdim { 777288943Sdim size_t curr_num_bytes; 778288943Sdim if (bytes_left > MAX_READ_SIZE) 779288943Sdim curr_num_bytes = MAX_READ_SIZE; 780288943Sdim else 781288943Sdim curr_num_bytes = bytes_left; 782288943Sdim 783288943Sdim error = Read (p + num_bytes, curr_num_bytes, offset); 784288943Sdim 785288943Sdim // Update how many bytes were read 786288943Sdim num_bytes += curr_num_bytes; 787288943Sdim if (bytes_left < curr_num_bytes) 788288943Sdim bytes_left = 0; 789288943Sdim else 790288943Sdim bytes_left -= curr_num_bytes; 791288943Sdim 792288943Sdim if (error.Fail()) 793288943Sdim break; 794288943Sdim } 795288943Sdim return error; 796288943Sdim } 797288943Sdim#endif 798288943Sdim 799258054Semaste#ifndef _WIN32 800254721Semaste int fd = GetDescriptor(); 801254721Semaste if (fd != kInvalidDescriptor) 802254721Semaste { 803254721Semaste ssize_t bytes_read = -1; 804254721Semaste do 805254721Semaste { 806254721Semaste bytes_read = ::pread (fd, buf, num_bytes, offset); 807254721Semaste } while (bytes_read < 0 && errno == EINTR); 808254721Semaste 809254721Semaste if (bytes_read < 0) 810254721Semaste { 811254721Semaste num_bytes = 0; 812254721Semaste error.SetErrorToErrno(); 813254721Semaste } 814254721Semaste else 815254721Semaste { 816254721Semaste offset += bytes_read; 817254721Semaste num_bytes = bytes_read; 818254721Semaste } 819254721Semaste } 820254721Semaste else 821254721Semaste { 822254721Semaste num_bytes = 0; 823254721Semaste error.SetErrorString("invalid file handle"); 824254721Semaste } 825258054Semaste#else 826258054Semaste long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 827258054Semaste SeekFromStart(offset); 828288943Sdim error = Read(buf, num_bytes); 829258054Semaste if (!error.Fail()) 830258054Semaste SeekFromStart(cur); 831288943Sdim#endif 832258054Semaste return error; 833254721Semaste} 834254721Semaste 835254721SemasteError 836254721SemasteFile::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp) 837254721Semaste{ 838254721Semaste Error error; 839254721Semaste 840254721Semaste if (num_bytes > 0) 841254721Semaste { 842254721Semaste int fd = GetDescriptor(); 843254721Semaste if (fd != kInvalidDescriptor) 844254721Semaste { 845254721Semaste struct stat file_stats; 846254721Semaste if (::fstat (fd, &file_stats) == 0) 847254721Semaste { 848254721Semaste if (file_stats.st_size > offset) 849254721Semaste { 850254721Semaste const size_t bytes_left = file_stats.st_size - offset; 851254721Semaste if (num_bytes > bytes_left) 852254721Semaste num_bytes = bytes_left; 853254721Semaste 854288943Sdim size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); 855254721Semaste std::unique_ptr<DataBufferHeap> data_heap_ap; 856288943Sdim data_heap_ap.reset(new DataBufferHeap()); 857288943Sdim data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 858254721Semaste 859254721Semaste if (data_heap_ap.get()) 860254721Semaste { 861254721Semaste error = Read (data_heap_ap->GetBytes(), num_bytes, offset); 862254721Semaste if (error.Success()) 863254721Semaste { 864254721Semaste // Make sure we read exactly what we asked for and if we got 865254721Semaste // less, adjust the array 866288943Sdim if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) 867288943Sdim data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 868254721Semaste data_buffer_sp.reset(data_heap_ap.release()); 869254721Semaste return error; 870254721Semaste } 871254721Semaste } 872254721Semaste } 873254721Semaste else 874254721Semaste error.SetErrorString("file is empty"); 875254721Semaste } 876254721Semaste else 877254721Semaste error.SetErrorToErrno(); 878254721Semaste } 879254721Semaste else 880254721Semaste error.SetErrorString("invalid file handle"); 881254721Semaste } 882254721Semaste else 883254721Semaste error.SetErrorString("invalid file handle"); 884254721Semaste 885254721Semaste num_bytes = 0; 886254721Semaste data_buffer_sp.reset(); 887254721Semaste return error; 888254721Semaste} 889254721Semaste 890254721SemasteError 891254721SemasteFile::Write (const void *buf, size_t &num_bytes, off_t &offset) 892254721Semaste{ 893254721Semaste Error error; 894288943Sdim 895288943Sdim#if defined (MAX_WRITE_SIZE) 896288943Sdim if (num_bytes > MAX_WRITE_SIZE) 897288943Sdim { 898288943Sdim const uint8_t *p = (const uint8_t *)buf; 899288943Sdim size_t bytes_left = num_bytes; 900288943Sdim // Init the num_bytes written to zero 901288943Sdim num_bytes = 0; 902288943Sdim 903288943Sdim while (bytes_left > 0) 904288943Sdim { 905288943Sdim size_t curr_num_bytes; 906288943Sdim if (bytes_left > MAX_WRITE_SIZE) 907288943Sdim curr_num_bytes = MAX_WRITE_SIZE; 908288943Sdim else 909288943Sdim curr_num_bytes = bytes_left; 910288943Sdim 911288943Sdim error = Write (p + num_bytes, curr_num_bytes, offset); 912288943Sdim 913288943Sdim // Update how many bytes were read 914288943Sdim num_bytes += curr_num_bytes; 915288943Sdim if (bytes_left < curr_num_bytes) 916288943Sdim bytes_left = 0; 917288943Sdim else 918288943Sdim bytes_left -= curr_num_bytes; 919288943Sdim 920288943Sdim if (error.Fail()) 921288943Sdim break; 922288943Sdim } 923288943Sdim return error; 924288943Sdim } 925288943Sdim#endif 926288943Sdim 927254721Semaste int fd = GetDescriptor(); 928254721Semaste if (fd != kInvalidDescriptor) 929254721Semaste { 930258054Semaste#ifndef _WIN32 931254721Semaste ssize_t bytes_written = -1; 932254721Semaste do 933254721Semaste { 934254721Semaste bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset); 935254721Semaste } while (bytes_written < 0 && errno == EINTR); 936254721Semaste 937254721Semaste if (bytes_written < 0) 938254721Semaste { 939254721Semaste num_bytes = 0; 940254721Semaste error.SetErrorToErrno(); 941254721Semaste } 942254721Semaste else 943254721Semaste { 944254721Semaste offset += bytes_written; 945254721Semaste num_bytes = bytes_written; 946254721Semaste } 947258054Semaste#else 948258054Semaste long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 949258054Semaste error = Write(buf, num_bytes); 950258054Semaste long after = ::lseek(m_descriptor, 0, SEEK_CUR); 951258054Semaste 952258054Semaste if (!error.Fail()) 953258054Semaste SeekFromStart(cur); 954258054Semaste 955258054Semaste offset = after; 956258054Semaste#endif 957254721Semaste } 958254721Semaste else 959254721Semaste { 960254721Semaste num_bytes = 0; 961254721Semaste error.SetErrorString("invalid file handle"); 962254721Semaste } 963254721Semaste return error; 964254721Semaste} 965254721Semaste 966254721Semaste//------------------------------------------------------------------ 967254721Semaste// Print some formatted output to the stream. 968254721Semaste//------------------------------------------------------------------ 969254721Semastesize_t 970254721SemasteFile::Printf (const char *format, ...) 971254721Semaste{ 972254721Semaste va_list args; 973254721Semaste va_start (args, format); 974254721Semaste size_t result = PrintfVarArg (format, args); 975254721Semaste va_end (args); 976254721Semaste return result; 977254721Semaste} 978254721Semaste 979254721Semaste//------------------------------------------------------------------ 980254721Semaste// Print some formatted output to the stream. 981254721Semaste//------------------------------------------------------------------ 982254721Semastesize_t 983254721SemasteFile::PrintfVarArg (const char *format, va_list args) 984254721Semaste{ 985254721Semaste size_t result = 0; 986254721Semaste if (DescriptorIsValid()) 987254721Semaste { 988254721Semaste char *s = NULL; 989254721Semaste result = vasprintf(&s, format, args); 990254721Semaste if (s != NULL) 991254721Semaste { 992254721Semaste if (result > 0) 993254721Semaste { 994254721Semaste size_t s_len = result; 995254721Semaste Write (s, s_len); 996254721Semaste result = s_len; 997254721Semaste } 998254721Semaste free (s); 999254721Semaste } 1000254721Semaste } 1001254721Semaste else if (StreamIsValid()) 1002254721Semaste { 1003254721Semaste result = ::vfprintf (m_stream, format, args); 1004254721Semaste } 1005254721Semaste return result; 1006254721Semaste} 1007258054Semaste 1008258054Semastemode_t 1009258054SemasteFile::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options) 1010258054Semaste{ 1011258054Semaste mode_t mode = 0; 1012258054Semaste if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) 1013258054Semaste mode |= O_RDWR; 1014258054Semaste else if (open_options & eOpenOptionWrite) 1015258054Semaste mode |= O_WRONLY; 1016258054Semaste 1017258054Semaste if (open_options & eOpenOptionAppend) 1018258054Semaste mode |= O_APPEND; 1019258054Semaste 1020258054Semaste if (open_options & eOpenOptionTruncate) 1021258054Semaste mode |= O_TRUNC; 1022258054Semaste 1023258054Semaste if (open_options & eOpenOptionNonBlocking) 1024258054Semaste mode |= O_NONBLOCK; 1025258054Semaste 1026258054Semaste if (open_options & eOpenOptionCanCreateNewOnly) 1027258054Semaste mode |= O_CREAT | O_EXCL; 1028258054Semaste else if (open_options & eOpenOptionCanCreate) 1029258054Semaste mode |= O_CREAT; 1030258054Semaste 1031258054Semaste return mode; 1032258054Semaste} 1033262528Semaste 1034262528Semastevoid 1035262528SemasteFile::CalculateInteractiveAndTerminal () 1036262528Semaste{ 1037262528Semaste const int fd = GetDescriptor(); 1038262528Semaste if (fd >= 0) 1039262528Semaste { 1040262528Semaste m_is_interactive = eLazyBoolNo; 1041262528Semaste m_is_real_terminal = eLazyBoolNo; 1042280031Sdim#if (defined(_WIN32) || defined(__ANDROID_NDK__)) 1043276479Sdim if (_isatty(fd)) 1044276479Sdim { 1045276479Sdim m_is_interactive = eLazyBoolYes; 1046276479Sdim m_is_real_terminal = eLazyBoolYes; 1047276479Sdim } 1048276479Sdim#else 1049262528Semaste if (isatty(fd)) 1050262528Semaste { 1051262528Semaste m_is_interactive = eLazyBoolYes; 1052262528Semaste struct winsize window_size; 1053262528Semaste if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0) 1054262528Semaste { 1055262528Semaste if (window_size.ws_col > 0) 1056296417Sdim { 1057262528Semaste m_is_real_terminal = eLazyBoolYes; 1058296417Sdim if (llvm::sys::Process::FileDescriptorHasColors(fd)) 1059296417Sdim m_supports_colors = eLazyBoolYes; 1060296417Sdim } 1061262528Semaste } 1062262528Semaste } 1063262528Semaste#endif 1064262528Semaste } 1065262528Semaste} 1066262528Semaste 1067262528Semastebool 1068262528SemasteFile::GetIsInteractive () 1069262528Semaste{ 1070262528Semaste if (m_is_interactive == eLazyBoolCalculate) 1071262528Semaste CalculateInteractiveAndTerminal (); 1072262528Semaste return m_is_interactive == eLazyBoolYes; 1073262528Semaste} 1074262528Semaste 1075262528Semastebool 1076262528SemasteFile::GetIsRealTerminal () 1077262528Semaste{ 1078262528Semaste if (m_is_real_terminal == eLazyBoolCalculate) 1079262528Semaste CalculateInteractiveAndTerminal(); 1080262528Semaste return m_is_real_terminal == eLazyBoolYes; 1081262528Semaste} 1082262528Semaste 1083296417Sdimbool 1084296417SdimFile::GetIsTerminalWithColors () 1085296417Sdim{ 1086296417Sdim if (m_supports_colors == eLazyBoolCalculate) 1087296417Sdim CalculateInteractiveAndTerminal(); 1088296417Sdim return m_supports_colors == eLazyBoolYes; 1089296417Sdim} 1090296417Sdim 1091