File.cpp revision 309124
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 18258054Semaste#ifdef _WIN32 19258054Semaste#include "lldb/Host/windows/windows.h" 20262528Semaste#else 21262528Semaste#include <sys/ioctl.h> 22258054Semaste#endif 23258054Semaste 24309124Sdim#include "llvm/Support/ConvertUTF.h" 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" 32309124Sdim#include "lldb/Host/FileSystem.h" 33254721Semaste 34254721Semasteusing namespace lldb; 35254721Semasteusing namespace lldb_private; 36254721Semaste 37254721Semastestatic const char * 38254721SemasteGetStreamOpenModeFromOptions (uint32_t options) 39254721Semaste{ 40254721Semaste if (options & File::eOpenOptionAppend) 41254721Semaste { 42254721Semaste if (options & File::eOpenOptionRead) 43254721Semaste { 44254721Semaste if (options & File::eOpenOptionCanCreateNewOnly) 45254721Semaste return "a+x"; 46254721Semaste else 47254721Semaste return "a+"; 48254721Semaste } 49254721Semaste else if (options & File::eOpenOptionWrite) 50254721Semaste { 51254721Semaste if (options & File::eOpenOptionCanCreateNewOnly) 52254721Semaste return "ax"; 53254721Semaste else 54254721Semaste return "a"; 55254721Semaste } 56254721Semaste } 57254721Semaste else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite) 58254721Semaste { 59254721Semaste if (options & File::eOpenOptionCanCreate) 60254721Semaste { 61254721Semaste if (options & File::eOpenOptionCanCreateNewOnly) 62254721Semaste return "w+x"; 63254721Semaste else 64254721Semaste return "w+"; 65254721Semaste } 66254721Semaste else 67254721Semaste return "r+"; 68254721Semaste } 69254721Semaste else if (options & File::eOpenOptionRead) 70254721Semaste { 71254721Semaste return "r"; 72254721Semaste } 73254721Semaste else if (options & File::eOpenOptionWrite) 74254721Semaste { 75254721Semaste return "w"; 76254721Semaste } 77254721Semaste return NULL; 78254721Semaste} 79254721Semaste 80254721Semasteint File::kInvalidDescriptor = -1; 81254721SemasteFILE * File::kInvalidStream = NULL; 82254721Semaste 83254721SemasteFile::File(const char *path, uint32_t options, uint32_t permissions) : 84276479Sdim IOObject(eFDTypeFile, false), 85254721Semaste m_descriptor (kInvalidDescriptor), 86254721Semaste m_stream (kInvalidStream), 87262528Semaste m_options (), 88262528Semaste m_own_stream (false), 89262528Semaste m_is_interactive (eLazyBoolCalculate), 90262528Semaste m_is_real_terminal (eLazyBoolCalculate) 91254721Semaste{ 92254721Semaste Open (path, options, permissions); 93254721Semaste} 94254721Semaste 95258054SemasteFile::File (const FileSpec& filespec, 96258054Semaste uint32_t options, 97258054Semaste uint32_t permissions) : 98276479Sdim IOObject(eFDTypeFile, false), 99258054Semaste m_descriptor (kInvalidDescriptor), 100258054Semaste m_stream (kInvalidStream), 101258054Semaste m_options (0), 102262528Semaste m_own_stream (false), 103262528Semaste m_is_interactive (eLazyBoolCalculate), 104262528Semaste m_is_real_terminal (eLazyBoolCalculate) 105262528Semaste 106258054Semaste{ 107258054Semaste if (filespec) 108258054Semaste { 109258054Semaste Open (filespec.GetPath().c_str(), options, permissions); 110258054Semaste } 111258054Semaste} 112258054Semaste 113254721SemasteFile::~File() 114254721Semaste{ 115254721Semaste Close (); 116254721Semaste} 117254721Semaste 118254721Semaste 119254721Semasteint 120254721SemasteFile::GetDescriptor() const 121254721Semaste{ 122254721Semaste if (DescriptorIsValid()) 123254721Semaste return m_descriptor; 124254721Semaste 125254721Semaste // Don't open the file descriptor if we don't need to, just get it from the 126254721Semaste // stream if we have one. 127254721Semaste if (StreamIsValid()) 128296417Sdim { 129296417Sdim#if defined(LLVM_ON_WIN32) 130296417Sdim return _fileno(m_stream); 131296417Sdim#else 132296417Sdim return fileno(m_stream); 133296417Sdim#endif 134296417Sdim } 135254721Semaste 136254721Semaste // Invalid descriptor and invalid stream, return invalid descriptor. 137254721Semaste return kInvalidDescriptor; 138254721Semaste} 139254721Semaste 140276479SdimIOObject::WaitableHandle 141276479SdimFile::GetWaitableHandle() 142276479Sdim{ 143276479Sdim return m_descriptor; 144276479Sdim} 145276479Sdim 146276479Sdim 147254721Semastevoid 148254721SemasteFile::SetDescriptor (int fd, bool transfer_ownership) 149254721Semaste{ 150254721Semaste if (IsValid()) 151254721Semaste Close(); 152254721Semaste m_descriptor = fd; 153276479Sdim m_should_close_fd = transfer_ownership; 154254721Semaste} 155254721Semaste 156254721Semaste 157254721SemasteFILE * 158254721SemasteFile::GetStream () 159254721Semaste{ 160254721Semaste if (!StreamIsValid()) 161254721Semaste { 162254721Semaste if (DescriptorIsValid()) 163254721Semaste { 164254721Semaste const char *mode = GetStreamOpenModeFromOptions (m_options); 165254721Semaste if (mode) 166254721Semaste { 167276479Sdim if (!m_should_close_fd) 168262528Semaste { 169262528Semaste // We must duplicate the file descriptor if we don't own it because 170262528Semaste // when you call fdopen, the stream will own the fd 171262528Semaste#ifdef _WIN32 172262528Semaste m_descriptor = ::_dup(GetDescriptor()); 173262528Semaste#else 174309124Sdim m_descriptor = dup(GetDescriptor()); 175262528Semaste#endif 176276479Sdim m_should_close_fd = true; 177262528Semaste } 178262528Semaste 179254721Semaste do 180254721Semaste { 181254721Semaste m_stream = ::fdopen (m_descriptor, mode); 182254721Semaste } while (m_stream == NULL && errno == EINTR); 183262528Semaste 184262528Semaste // If we got a stream, then we own the stream and should no 185262528Semaste // longer own the descriptor because fclose() will close it for us 186262528Semaste 187262528Semaste if (m_stream) 188262528Semaste { 189262528Semaste m_own_stream = true; 190276479Sdim m_should_close_fd = false; 191262528Semaste } 192254721Semaste } 193254721Semaste } 194254721Semaste } 195254721Semaste return m_stream; 196254721Semaste} 197254721Semaste 198254721Semastevoid 199254721SemasteFile::SetStream (FILE *fh, bool transfer_ownership) 200254721Semaste{ 201254721Semaste if (IsValid()) 202254721Semaste Close(); 203254721Semaste m_stream = fh; 204262528Semaste m_own_stream = transfer_ownership; 205254721Semaste} 206254721Semaste 207254721SemasteError 208254721SemasteFile::Open (const char *path, uint32_t options, uint32_t permissions) 209254721Semaste{ 210254721Semaste Error error; 211254721Semaste if (IsValid()) 212254721Semaste Close (); 213254721Semaste 214254721Semaste int oflag = 0; 215254721Semaste const bool read = options & eOpenOptionRead; 216254721Semaste const bool write = options & eOpenOptionWrite; 217254721Semaste if (write) 218254721Semaste { 219254721Semaste if (read) 220254721Semaste oflag |= O_RDWR; 221254721Semaste else 222254721Semaste oflag |= O_WRONLY; 223254721Semaste 224254721Semaste if (options & eOpenOptionAppend) 225254721Semaste oflag |= O_APPEND; 226254721Semaste 227254721Semaste if (options & eOpenOptionTruncate) 228254721Semaste oflag |= O_TRUNC; 229254721Semaste 230254721Semaste if (options & eOpenOptionCanCreate) 231254721Semaste oflag |= O_CREAT; 232254721Semaste 233254721Semaste if (options & eOpenOptionCanCreateNewOnly) 234254721Semaste oflag |= O_CREAT | O_EXCL; 235254721Semaste } 236254721Semaste else if (read) 237254721Semaste { 238254721Semaste oflag |= O_RDONLY; 239258884Semaste 240258884Semaste#ifndef _WIN32 241309124Sdim if (options & eOpenOptionDontFollowSymlinks) 242258884Semaste oflag |= O_NOFOLLOW; 243258884Semaste#endif 244254721Semaste } 245254721Semaste 246258054Semaste#ifndef _WIN32 247254721Semaste if (options & eOpenOptionNonBlocking) 248254721Semaste oflag |= O_NONBLOCK; 249288943Sdim if (options & eOpenOptionCloseOnExec) 250288943Sdim oflag |= O_CLOEXEC; 251258054Semaste#else 252258054Semaste oflag |= O_BINARY; 253258054Semaste#endif 254254721Semaste 255254721Semaste mode_t mode = 0; 256254721Semaste if (oflag & O_CREAT) 257254721Semaste { 258258884Semaste if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR; 259258884Semaste if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR; 260258884Semaste if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR; 261258884Semaste if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP; 262258884Semaste if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP; 263258884Semaste if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP; 264258884Semaste if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH; 265258884Semaste if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH; 266258884Semaste if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH; 267254721Semaste } 268254721Semaste 269254721Semaste do 270254721Semaste { 271309124Sdim#ifdef _WIN32 272309124Sdim std::wstring wpath; 273309124Sdim if (!llvm::ConvertUTF8toWide(path, wpath)) 274309124Sdim { 275309124Sdim m_descriptor = -1; 276309124Sdim error.SetErrorString("Error converting path to UTF-16"); 277309124Sdim return error; 278309124Sdim } 279309124Sdim ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode); 280309124Sdim#else 281254721Semaste m_descriptor = ::open(path, oflag, mode); 282309124Sdim#endif 283254721Semaste } while (m_descriptor < 0 && errno == EINTR); 284254721Semaste 285254721Semaste if (!DescriptorIsValid()) 286254721Semaste error.SetErrorToErrno(); 287254721Semaste else 288262528Semaste { 289276479Sdim m_should_close_fd = true; 290262528Semaste m_options = options; 291262528Semaste } 292254721Semaste 293254721Semaste return error; 294254721Semaste} 295254721Semaste 296258054Semasteuint32_t 297288943SdimFile::GetPermissions(const FileSpec &file_spec, Error &error) 298258054Semaste{ 299288943Sdim if (file_spec) 300258054Semaste { 301258054Semaste struct stat file_stats; 302309124Sdim int stat_result = FileSystem::Stat(file_spec.GetCString(), &file_stats); 303309124Sdim if (stat_result == -1) 304258054Semaste error.SetErrorToErrno(); 305258054Semaste else 306258054Semaste { 307258054Semaste error.Clear(); 308258884Semaste return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 309258054Semaste } 310258054Semaste } 311258054Semaste else 312288943Sdim error.SetErrorString ("empty file spec"); 313258054Semaste return 0; 314258054Semaste} 315258054Semaste 316258054Semasteuint32_t 317258054SemasteFile::GetPermissions(Error &error) const 318258054Semaste{ 319258054Semaste int fd = GetDescriptor(); 320258054Semaste if (fd != kInvalidDescriptor) 321258054Semaste { 322258054Semaste struct stat file_stats; 323258054Semaste if (::fstat (fd, &file_stats) == -1) 324258054Semaste error.SetErrorToErrno(); 325258054Semaste else 326258054Semaste { 327258054Semaste error.Clear(); 328258884Semaste return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 329258054Semaste } 330258054Semaste } 331258054Semaste else 332258054Semaste { 333258054Semaste error.SetErrorString ("invalid file descriptor"); 334258054Semaste } 335258054Semaste return 0; 336258054Semaste} 337258054Semaste 338258054Semaste 339254721SemasteError 340254721SemasteFile::Close () 341254721Semaste{ 342254721Semaste Error error; 343262528Semaste if (StreamIsValid() && m_own_stream) 344254721Semaste { 345262528Semaste if (::fclose (m_stream) == EOF) 346262528Semaste error.SetErrorToErrno(); 347254721Semaste } 348262528Semaste 349276479Sdim if (DescriptorIsValid() && m_should_close_fd) 350262528Semaste { 351262528Semaste if (::close (m_descriptor) != 0) 352262528Semaste error.SetErrorToErrno(); 353262528Semaste } 354262528Semaste m_descriptor = kInvalidDescriptor; 355262528Semaste m_stream = kInvalidStream; 356262528Semaste m_options = 0; 357262528Semaste m_own_stream = false; 358276479Sdim m_should_close_fd = false; 359262528Semaste m_is_interactive = eLazyBoolCalculate; 360262528Semaste m_is_real_terminal = eLazyBoolCalculate; 361254721Semaste return error; 362254721Semaste} 363254721Semaste 364309124Sdimvoid 365309124SdimFile::Clear () 366309124Sdim{ 367309124Sdim m_stream = nullptr; 368309124Sdim m_descriptor = -1; 369309124Sdim m_options = 0; 370309124Sdim m_own_stream = false; 371309124Sdim m_is_interactive = m_supports_colors = m_is_real_terminal = eLazyBoolCalculate; 372309124Sdim} 373254721Semaste 374254721SemasteError 375254721SemasteFile::GetFileSpec (FileSpec &file_spec) const 376254721Semaste{ 377254721Semaste Error error; 378254721Semaste#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED 379254721Semaste if (IsValid ()) 380254721Semaste { 381254721Semaste char path[PATH_MAX]; 382254721Semaste if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) 383254721Semaste error.SetErrorToErrno(); 384254721Semaste else 385254721Semaste file_spec.SetFile (path, false); 386254721Semaste } 387254721Semaste else 388254721Semaste { 389254721Semaste error.SetErrorString("invalid file handle"); 390254721Semaste } 391254721Semaste#elif defined(__linux__) 392254721Semaste char proc[64]; 393254721Semaste char path[PATH_MAX]; 394254721Semaste if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) 395254721Semaste error.SetErrorString ("cannot resolve file descriptor"); 396254721Semaste else 397254721Semaste { 398254721Semaste ssize_t len; 399254721Semaste if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) 400254721Semaste error.SetErrorToErrno(); 401254721Semaste else 402254721Semaste { 403254721Semaste path[len] = '\0'; 404254721Semaste file_spec.SetFile (path, false); 405254721Semaste } 406254721Semaste } 407254721Semaste#else 408254721Semaste error.SetErrorString ("File::GetFileSpec is not supported on this platform"); 409254721Semaste#endif 410254721Semaste 411254721Semaste if (error.Fail()) 412254721Semaste file_spec.Clear(); 413254721Semaste return error; 414254721Semaste} 415254721Semaste 416254721Semasteoff_t 417254721SemasteFile::SeekFromStart (off_t offset, Error *error_ptr) 418254721Semaste{ 419254721Semaste off_t result = 0; 420254721Semaste if (DescriptorIsValid()) 421254721Semaste { 422254721Semaste result = ::lseek (m_descriptor, offset, SEEK_SET); 423254721Semaste 424254721Semaste if (error_ptr) 425254721Semaste { 426254721Semaste if (result == -1) 427254721Semaste error_ptr->SetErrorToErrno(); 428254721Semaste else 429254721Semaste error_ptr->Clear(); 430254721Semaste } 431254721Semaste } 432254721Semaste else if (StreamIsValid ()) 433254721Semaste { 434254721Semaste result = ::fseek(m_stream, offset, SEEK_SET); 435254721Semaste 436254721Semaste if (error_ptr) 437254721Semaste { 438254721Semaste if (result == -1) 439254721Semaste error_ptr->SetErrorToErrno(); 440254721Semaste else 441254721Semaste error_ptr->Clear(); 442254721Semaste } 443254721Semaste } 444254721Semaste else if (error_ptr) 445254721Semaste { 446254721Semaste error_ptr->SetErrorString("invalid file handle"); 447254721Semaste } 448254721Semaste return result; 449254721Semaste} 450254721Semaste 451254721Semasteoff_t 452254721SemasteFile::SeekFromCurrent (off_t offset, Error *error_ptr) 453254721Semaste{ 454254721Semaste off_t result = -1; 455254721Semaste if (DescriptorIsValid()) 456254721Semaste { 457254721Semaste result = ::lseek (m_descriptor, offset, SEEK_CUR); 458254721Semaste 459254721Semaste if (error_ptr) 460254721Semaste { 461254721Semaste if (result == -1) 462254721Semaste error_ptr->SetErrorToErrno(); 463254721Semaste else 464254721Semaste error_ptr->Clear(); 465254721Semaste } 466254721Semaste } 467254721Semaste else if (StreamIsValid ()) 468254721Semaste { 469254721Semaste result = ::fseek(m_stream, offset, SEEK_CUR); 470254721Semaste 471254721Semaste if (error_ptr) 472254721Semaste { 473254721Semaste if (result == -1) 474254721Semaste error_ptr->SetErrorToErrno(); 475254721Semaste else 476254721Semaste error_ptr->Clear(); 477254721Semaste } 478254721Semaste } 479254721Semaste else if (error_ptr) 480254721Semaste { 481254721Semaste error_ptr->SetErrorString("invalid file handle"); 482254721Semaste } 483254721Semaste return result; 484254721Semaste} 485254721Semaste 486254721Semasteoff_t 487254721SemasteFile::SeekFromEnd (off_t offset, Error *error_ptr) 488254721Semaste{ 489254721Semaste off_t result = -1; 490254721Semaste if (DescriptorIsValid()) 491254721Semaste { 492254721Semaste result = ::lseek (m_descriptor, offset, SEEK_END); 493254721Semaste 494254721Semaste if (error_ptr) 495254721Semaste { 496254721Semaste if (result == -1) 497254721Semaste error_ptr->SetErrorToErrno(); 498254721Semaste else 499254721Semaste error_ptr->Clear(); 500254721Semaste } 501254721Semaste } 502254721Semaste else if (StreamIsValid ()) 503254721Semaste { 504254721Semaste result = ::fseek(m_stream, offset, SEEK_END); 505254721Semaste 506254721Semaste if (error_ptr) 507254721Semaste { 508254721Semaste if (result == -1) 509254721Semaste error_ptr->SetErrorToErrno(); 510254721Semaste else 511254721Semaste error_ptr->Clear(); 512254721Semaste } 513254721Semaste } 514254721Semaste else if (error_ptr) 515254721Semaste { 516254721Semaste error_ptr->SetErrorString("invalid file handle"); 517254721Semaste } 518254721Semaste return result; 519254721Semaste} 520254721Semaste 521254721SemasteError 522254721SemasteFile::Flush () 523254721Semaste{ 524254721Semaste Error error; 525254721Semaste if (StreamIsValid()) 526254721Semaste { 527254721Semaste int err = 0; 528254721Semaste do 529254721Semaste { 530254721Semaste err = ::fflush (m_stream); 531254721Semaste } while (err == EOF && errno == EINTR); 532254721Semaste 533254721Semaste if (err == EOF) 534254721Semaste error.SetErrorToErrno(); 535254721Semaste } 536254721Semaste else if (!DescriptorIsValid()) 537254721Semaste { 538254721Semaste error.SetErrorString("invalid file handle"); 539254721Semaste } 540254721Semaste return error; 541254721Semaste} 542254721Semaste 543254721Semaste 544254721SemasteError 545254721SemasteFile::Sync () 546254721Semaste{ 547254721Semaste Error error; 548254721Semaste if (DescriptorIsValid()) 549254721Semaste { 550258054Semaste#ifdef _WIN32 551258054Semaste int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); 552258054Semaste if (err == 0) 553258054Semaste error.SetErrorToGenericError(); 554258054Semaste#else 555254721Semaste int err = 0; 556254721Semaste do 557254721Semaste { 558254721Semaste err = ::fsync (m_descriptor); 559254721Semaste } while (err == -1 && errno == EINTR); 560254721Semaste 561254721Semaste if (err == -1) 562254721Semaste error.SetErrorToErrno(); 563258054Semaste#endif 564254721Semaste } 565254721Semaste else 566254721Semaste { 567254721Semaste error.SetErrorString("invalid file handle"); 568254721Semaste } 569254721Semaste return error; 570254721Semaste} 571254721Semaste 572288943Sdim#if defined (__APPLE__) 573288943Sdim// Darwin kernels only can read/write <= INT_MAX bytes 574288943Sdim#define MAX_READ_SIZE INT_MAX 575288943Sdim#define MAX_WRITE_SIZE INT_MAX 576288943Sdim#endif 577288943Sdim 578254721SemasteError 579254721SemasteFile::Read (void *buf, size_t &num_bytes) 580254721Semaste{ 581254721Semaste Error error; 582288943Sdim 583288943Sdim#if defined (MAX_READ_SIZE) 584288943Sdim if (num_bytes > MAX_READ_SIZE) 585288943Sdim { 586288943Sdim uint8_t *p = (uint8_t *)buf; 587288943Sdim size_t bytes_left = num_bytes; 588288943Sdim // Init the num_bytes read to zero 589288943Sdim num_bytes = 0; 590288943Sdim 591288943Sdim while (bytes_left > 0) 592288943Sdim { 593288943Sdim size_t curr_num_bytes; 594288943Sdim if (bytes_left > MAX_READ_SIZE) 595288943Sdim curr_num_bytes = MAX_READ_SIZE; 596288943Sdim else 597288943Sdim curr_num_bytes = bytes_left; 598288943Sdim 599288943Sdim error = Read (p + num_bytes, curr_num_bytes); 600288943Sdim 601288943Sdim // Update how many bytes were read 602288943Sdim num_bytes += curr_num_bytes; 603288943Sdim if (bytes_left < curr_num_bytes) 604288943Sdim bytes_left = 0; 605288943Sdim else 606288943Sdim bytes_left -= curr_num_bytes; 607288943Sdim 608288943Sdim if (error.Fail()) 609288943Sdim break; 610288943Sdim } 611288943Sdim return error; 612288943Sdim } 613288943Sdim#endif 614288943Sdim 615254721Semaste ssize_t bytes_read = -1; 616254721Semaste if (DescriptorIsValid()) 617254721Semaste { 618254721Semaste do 619254721Semaste { 620254721Semaste bytes_read = ::read (m_descriptor, buf, num_bytes); 621254721Semaste } while (bytes_read < 0 && errno == EINTR); 622254721Semaste 623254721Semaste if (bytes_read == -1) 624254721Semaste { 625254721Semaste error.SetErrorToErrno(); 626254721Semaste num_bytes = 0; 627254721Semaste } 628254721Semaste else 629254721Semaste num_bytes = bytes_read; 630254721Semaste } 631254721Semaste else if (StreamIsValid()) 632254721Semaste { 633254721Semaste bytes_read = ::fread (buf, 1, num_bytes, m_stream); 634254721Semaste 635254721Semaste if (bytes_read == 0) 636254721Semaste { 637254721Semaste if (::feof(m_stream)) 638254721Semaste error.SetErrorString ("feof"); 639254721Semaste else if (::ferror (m_stream)) 640254721Semaste error.SetErrorString ("ferror"); 641254721Semaste num_bytes = 0; 642254721Semaste } 643254721Semaste else 644254721Semaste num_bytes = bytes_read; 645254721Semaste } 646254721Semaste else 647254721Semaste { 648254721Semaste num_bytes = 0; 649254721Semaste error.SetErrorString("invalid file handle"); 650254721Semaste } 651254721Semaste return error; 652254721Semaste} 653254721Semaste 654254721SemasteError 655254721SemasteFile::Write (const void *buf, size_t &num_bytes) 656254721Semaste{ 657254721Semaste Error error; 658288943Sdim 659288943Sdim#if defined (MAX_WRITE_SIZE) 660288943Sdim if (num_bytes > MAX_WRITE_SIZE) 661288943Sdim { 662288943Sdim const uint8_t *p = (const uint8_t *)buf; 663288943Sdim size_t bytes_left = num_bytes; 664288943Sdim // Init the num_bytes written to zero 665288943Sdim num_bytes = 0; 666288943Sdim 667288943Sdim while (bytes_left > 0) 668288943Sdim { 669288943Sdim size_t curr_num_bytes; 670288943Sdim if (bytes_left > MAX_WRITE_SIZE) 671288943Sdim curr_num_bytes = MAX_WRITE_SIZE; 672288943Sdim else 673288943Sdim curr_num_bytes = bytes_left; 674288943Sdim 675288943Sdim error = Write (p + num_bytes, curr_num_bytes); 676288943Sdim 677288943Sdim // Update how many bytes were read 678288943Sdim num_bytes += curr_num_bytes; 679288943Sdim if (bytes_left < curr_num_bytes) 680288943Sdim bytes_left = 0; 681288943Sdim else 682288943Sdim bytes_left -= curr_num_bytes; 683288943Sdim 684288943Sdim if (error.Fail()) 685288943Sdim break; 686288943Sdim } 687288943Sdim return error; 688288943Sdim } 689288943Sdim#endif 690288943Sdim 691254721Semaste ssize_t bytes_written = -1; 692254721Semaste if (DescriptorIsValid()) 693254721Semaste { 694254721Semaste do 695254721Semaste { 696254721Semaste bytes_written = ::write (m_descriptor, buf, num_bytes); 697254721Semaste } while (bytes_written < 0 && errno == EINTR); 698254721Semaste 699254721Semaste if (bytes_written == -1) 700254721Semaste { 701254721Semaste error.SetErrorToErrno(); 702254721Semaste num_bytes = 0; 703254721Semaste } 704254721Semaste else 705254721Semaste num_bytes = bytes_written; 706254721Semaste } 707254721Semaste else if (StreamIsValid()) 708254721Semaste { 709254721Semaste bytes_written = ::fwrite (buf, 1, num_bytes, m_stream); 710254721Semaste 711254721Semaste if (bytes_written == 0) 712254721Semaste { 713254721Semaste if (::feof(m_stream)) 714254721Semaste error.SetErrorString ("feof"); 715254721Semaste else if (::ferror (m_stream)) 716254721Semaste error.SetErrorString ("ferror"); 717254721Semaste num_bytes = 0; 718254721Semaste } 719254721Semaste else 720254721Semaste num_bytes = bytes_written; 721254721Semaste 722254721Semaste } 723254721Semaste else 724254721Semaste { 725254721Semaste num_bytes = 0; 726254721Semaste error.SetErrorString("invalid file handle"); 727254721Semaste } 728276479Sdim 729254721Semaste return error; 730254721Semaste} 731254721Semaste 732254721Semaste 733254721SemasteError 734254721SemasteFile::Read (void *buf, size_t &num_bytes, off_t &offset) 735254721Semaste{ 736288943Sdim Error error; 737288943Sdim 738288943Sdim#if defined (MAX_READ_SIZE) 739288943Sdim if (num_bytes > MAX_READ_SIZE) 740288943Sdim { 741288943Sdim uint8_t *p = (uint8_t *)buf; 742288943Sdim size_t bytes_left = num_bytes; 743288943Sdim // Init the num_bytes read to zero 744288943Sdim num_bytes = 0; 745288943Sdim 746288943Sdim while (bytes_left > 0) 747288943Sdim { 748288943Sdim size_t curr_num_bytes; 749288943Sdim if (bytes_left > MAX_READ_SIZE) 750288943Sdim curr_num_bytes = MAX_READ_SIZE; 751288943Sdim else 752288943Sdim curr_num_bytes = bytes_left; 753288943Sdim 754288943Sdim error = Read (p + num_bytes, curr_num_bytes, offset); 755288943Sdim 756288943Sdim // Update how many bytes were read 757288943Sdim num_bytes += curr_num_bytes; 758288943Sdim if (bytes_left < curr_num_bytes) 759288943Sdim bytes_left = 0; 760288943Sdim else 761288943Sdim bytes_left -= curr_num_bytes; 762288943Sdim 763288943Sdim if (error.Fail()) 764288943Sdim break; 765288943Sdim } 766288943Sdim return error; 767288943Sdim } 768288943Sdim#endif 769288943Sdim 770258054Semaste#ifndef _WIN32 771254721Semaste int fd = GetDescriptor(); 772254721Semaste if (fd != kInvalidDescriptor) 773254721Semaste { 774254721Semaste ssize_t bytes_read = -1; 775254721Semaste do 776254721Semaste { 777254721Semaste bytes_read = ::pread (fd, buf, num_bytes, offset); 778254721Semaste } while (bytes_read < 0 && errno == EINTR); 779254721Semaste 780254721Semaste if (bytes_read < 0) 781254721Semaste { 782254721Semaste num_bytes = 0; 783254721Semaste error.SetErrorToErrno(); 784254721Semaste } 785254721Semaste else 786254721Semaste { 787254721Semaste offset += bytes_read; 788254721Semaste num_bytes = bytes_read; 789254721Semaste } 790254721Semaste } 791254721Semaste else 792254721Semaste { 793254721Semaste num_bytes = 0; 794254721Semaste error.SetErrorString("invalid file handle"); 795254721Semaste } 796258054Semaste#else 797258054Semaste long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 798258054Semaste SeekFromStart(offset); 799288943Sdim error = Read(buf, num_bytes); 800258054Semaste if (!error.Fail()) 801258054Semaste SeekFromStart(cur); 802288943Sdim#endif 803258054Semaste return error; 804254721Semaste} 805254721Semaste 806254721SemasteError 807254721SemasteFile::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp) 808254721Semaste{ 809254721Semaste Error error; 810254721Semaste 811254721Semaste if (num_bytes > 0) 812254721Semaste { 813254721Semaste int fd = GetDescriptor(); 814254721Semaste if (fd != kInvalidDescriptor) 815254721Semaste { 816254721Semaste struct stat file_stats; 817254721Semaste if (::fstat (fd, &file_stats) == 0) 818254721Semaste { 819254721Semaste if (file_stats.st_size > offset) 820254721Semaste { 821254721Semaste const size_t bytes_left = file_stats.st_size - offset; 822254721Semaste if (num_bytes > bytes_left) 823254721Semaste num_bytes = bytes_left; 824254721Semaste 825288943Sdim size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); 826254721Semaste std::unique_ptr<DataBufferHeap> data_heap_ap; 827288943Sdim data_heap_ap.reset(new DataBufferHeap()); 828288943Sdim data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 829254721Semaste 830254721Semaste if (data_heap_ap.get()) 831254721Semaste { 832254721Semaste error = Read (data_heap_ap->GetBytes(), num_bytes, offset); 833254721Semaste if (error.Success()) 834254721Semaste { 835254721Semaste // Make sure we read exactly what we asked for and if we got 836254721Semaste // less, adjust the array 837288943Sdim if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) 838288943Sdim data_heap_ap->SetByteSize(num_bytes_plus_nul_char); 839254721Semaste data_buffer_sp.reset(data_heap_ap.release()); 840254721Semaste return error; 841254721Semaste } 842254721Semaste } 843254721Semaste } 844254721Semaste else 845254721Semaste error.SetErrorString("file is empty"); 846254721Semaste } 847254721Semaste else 848254721Semaste error.SetErrorToErrno(); 849254721Semaste } 850254721Semaste else 851254721Semaste error.SetErrorString("invalid file handle"); 852254721Semaste } 853254721Semaste else 854254721Semaste error.SetErrorString("invalid file handle"); 855254721Semaste 856254721Semaste num_bytes = 0; 857254721Semaste data_buffer_sp.reset(); 858254721Semaste return error; 859254721Semaste} 860254721Semaste 861254721SemasteError 862254721SemasteFile::Write (const void *buf, size_t &num_bytes, off_t &offset) 863254721Semaste{ 864254721Semaste Error error; 865288943Sdim 866288943Sdim#if defined (MAX_WRITE_SIZE) 867288943Sdim if (num_bytes > MAX_WRITE_SIZE) 868288943Sdim { 869288943Sdim const uint8_t *p = (const uint8_t *)buf; 870288943Sdim size_t bytes_left = num_bytes; 871288943Sdim // Init the num_bytes written to zero 872288943Sdim num_bytes = 0; 873288943Sdim 874288943Sdim while (bytes_left > 0) 875288943Sdim { 876288943Sdim size_t curr_num_bytes; 877288943Sdim if (bytes_left > MAX_WRITE_SIZE) 878288943Sdim curr_num_bytes = MAX_WRITE_SIZE; 879288943Sdim else 880288943Sdim curr_num_bytes = bytes_left; 881288943Sdim 882288943Sdim error = Write (p + num_bytes, curr_num_bytes, offset); 883288943Sdim 884288943Sdim // Update how many bytes were read 885288943Sdim num_bytes += curr_num_bytes; 886288943Sdim if (bytes_left < curr_num_bytes) 887288943Sdim bytes_left = 0; 888288943Sdim else 889288943Sdim bytes_left -= curr_num_bytes; 890288943Sdim 891288943Sdim if (error.Fail()) 892288943Sdim break; 893288943Sdim } 894288943Sdim return error; 895288943Sdim } 896288943Sdim#endif 897288943Sdim 898254721Semaste int fd = GetDescriptor(); 899254721Semaste if (fd != kInvalidDescriptor) 900254721Semaste { 901258054Semaste#ifndef _WIN32 902254721Semaste ssize_t bytes_written = -1; 903254721Semaste do 904254721Semaste { 905254721Semaste bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset); 906254721Semaste } while (bytes_written < 0 && errno == EINTR); 907254721Semaste 908254721Semaste if (bytes_written < 0) 909254721Semaste { 910254721Semaste num_bytes = 0; 911254721Semaste error.SetErrorToErrno(); 912254721Semaste } 913254721Semaste else 914254721Semaste { 915254721Semaste offset += bytes_written; 916254721Semaste num_bytes = bytes_written; 917254721Semaste } 918258054Semaste#else 919258054Semaste long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 920258054Semaste error = Write(buf, num_bytes); 921258054Semaste long after = ::lseek(m_descriptor, 0, SEEK_CUR); 922258054Semaste 923258054Semaste if (!error.Fail()) 924258054Semaste SeekFromStart(cur); 925258054Semaste 926258054Semaste offset = after; 927258054Semaste#endif 928254721Semaste } 929254721Semaste else 930254721Semaste { 931254721Semaste num_bytes = 0; 932254721Semaste error.SetErrorString("invalid file handle"); 933254721Semaste } 934254721Semaste return error; 935254721Semaste} 936254721Semaste 937254721Semaste//------------------------------------------------------------------ 938254721Semaste// Print some formatted output to the stream. 939254721Semaste//------------------------------------------------------------------ 940254721Semastesize_t 941254721SemasteFile::Printf (const char *format, ...) 942254721Semaste{ 943254721Semaste va_list args; 944254721Semaste va_start (args, format); 945254721Semaste size_t result = PrintfVarArg (format, args); 946254721Semaste va_end (args); 947254721Semaste return result; 948254721Semaste} 949254721Semaste 950254721Semaste//------------------------------------------------------------------ 951254721Semaste// Print some formatted output to the stream. 952254721Semaste//------------------------------------------------------------------ 953254721Semastesize_t 954254721SemasteFile::PrintfVarArg (const char *format, va_list args) 955254721Semaste{ 956254721Semaste size_t result = 0; 957254721Semaste if (DescriptorIsValid()) 958254721Semaste { 959254721Semaste char *s = NULL; 960254721Semaste result = vasprintf(&s, format, args); 961254721Semaste if (s != NULL) 962254721Semaste { 963254721Semaste if (result > 0) 964254721Semaste { 965254721Semaste size_t s_len = result; 966254721Semaste Write (s, s_len); 967254721Semaste result = s_len; 968254721Semaste } 969254721Semaste free (s); 970254721Semaste } 971254721Semaste } 972254721Semaste else if (StreamIsValid()) 973254721Semaste { 974254721Semaste result = ::vfprintf (m_stream, format, args); 975254721Semaste } 976254721Semaste return result; 977254721Semaste} 978258054Semaste 979258054Semastemode_t 980258054SemasteFile::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options) 981258054Semaste{ 982258054Semaste mode_t mode = 0; 983258054Semaste if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) 984258054Semaste mode |= O_RDWR; 985258054Semaste else if (open_options & eOpenOptionWrite) 986258054Semaste mode |= O_WRONLY; 987258054Semaste 988258054Semaste if (open_options & eOpenOptionAppend) 989258054Semaste mode |= O_APPEND; 990258054Semaste 991258054Semaste if (open_options & eOpenOptionTruncate) 992258054Semaste mode |= O_TRUNC; 993258054Semaste 994258054Semaste if (open_options & eOpenOptionNonBlocking) 995258054Semaste mode |= O_NONBLOCK; 996258054Semaste 997258054Semaste if (open_options & eOpenOptionCanCreateNewOnly) 998258054Semaste mode |= O_CREAT | O_EXCL; 999258054Semaste else if (open_options & eOpenOptionCanCreate) 1000258054Semaste mode |= O_CREAT; 1001258054Semaste 1002258054Semaste return mode; 1003258054Semaste} 1004262528Semaste 1005262528Semastevoid 1006262528SemasteFile::CalculateInteractiveAndTerminal () 1007262528Semaste{ 1008262528Semaste const int fd = GetDescriptor(); 1009262528Semaste if (fd >= 0) 1010262528Semaste { 1011262528Semaste m_is_interactive = eLazyBoolNo; 1012262528Semaste m_is_real_terminal = eLazyBoolNo; 1013309124Sdim#if defined(_WIN32) 1014276479Sdim if (_isatty(fd)) 1015276479Sdim { 1016276479Sdim m_is_interactive = eLazyBoolYes; 1017276479Sdim m_is_real_terminal = eLazyBoolYes; 1018276479Sdim } 1019276479Sdim#else 1020262528Semaste if (isatty(fd)) 1021262528Semaste { 1022262528Semaste m_is_interactive = eLazyBoolYes; 1023262528Semaste struct winsize window_size; 1024262528Semaste if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0) 1025262528Semaste { 1026262528Semaste if (window_size.ws_col > 0) 1027296417Sdim { 1028262528Semaste m_is_real_terminal = eLazyBoolYes; 1029296417Sdim if (llvm::sys::Process::FileDescriptorHasColors(fd)) 1030296417Sdim m_supports_colors = eLazyBoolYes; 1031296417Sdim } 1032262528Semaste } 1033262528Semaste } 1034262528Semaste#endif 1035262528Semaste } 1036262528Semaste} 1037262528Semaste 1038262528Semastebool 1039262528SemasteFile::GetIsInteractive () 1040262528Semaste{ 1041262528Semaste if (m_is_interactive == eLazyBoolCalculate) 1042262528Semaste CalculateInteractiveAndTerminal (); 1043262528Semaste return m_is_interactive == eLazyBoolYes; 1044262528Semaste} 1045262528Semaste 1046262528Semastebool 1047262528SemasteFile::GetIsRealTerminal () 1048262528Semaste{ 1049262528Semaste if (m_is_real_terminal == eLazyBoolCalculate) 1050262528Semaste CalculateInteractiveAndTerminal(); 1051262528Semaste return m_is_real_terminal == eLazyBoolYes; 1052262528Semaste} 1053262528Semaste 1054296417Sdimbool 1055296417SdimFile::GetIsTerminalWithColors () 1056296417Sdim{ 1057296417Sdim if (m_supports_colors == eLazyBoolCalculate) 1058296417Sdim CalculateInteractiveAndTerminal(); 1059296417Sdim return m_supports_colors == eLazyBoolYes; 1060296417Sdim} 1061296417Sdim 1062