File.cpp revision 258884
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> 16254721Semaste#include <sys/stat.h> 17254721Semaste 18258054Semaste#ifdef _WIN32 19258054Semaste#include "lldb/Host/windows/windows.h" 20258054Semaste#endif 21258054Semaste 22254721Semaste#include "lldb/Core/DataBufferHeap.h" 23254721Semaste#include "lldb/Core/Error.h" 24254721Semaste#include "lldb/Host/Config.h" 25254721Semaste#include "lldb/Host/FileSpec.h" 26254721Semaste 27254721Semasteusing namespace lldb; 28254721Semasteusing namespace lldb_private; 29254721Semaste 30254721Semastestatic const char * 31254721SemasteGetStreamOpenModeFromOptions (uint32_t options) 32254721Semaste{ 33254721Semaste if (options & File::eOpenOptionAppend) 34254721Semaste { 35254721Semaste if (options & File::eOpenOptionRead) 36254721Semaste { 37254721Semaste if (options & File::eOpenOptionCanCreateNewOnly) 38254721Semaste return "a+x"; 39254721Semaste else 40254721Semaste return "a+"; 41254721Semaste } 42254721Semaste else if (options & File::eOpenOptionWrite) 43254721Semaste { 44254721Semaste if (options & File::eOpenOptionCanCreateNewOnly) 45254721Semaste return "ax"; 46254721Semaste else 47254721Semaste return "a"; 48254721Semaste } 49254721Semaste } 50254721Semaste else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite) 51254721Semaste { 52254721Semaste if (options & File::eOpenOptionCanCreate) 53254721Semaste { 54254721Semaste if (options & File::eOpenOptionCanCreateNewOnly) 55254721Semaste return "w+x"; 56254721Semaste else 57254721Semaste return "w+"; 58254721Semaste } 59254721Semaste else 60254721Semaste return "r+"; 61254721Semaste } 62254721Semaste else if (options & File::eOpenOptionRead) 63254721Semaste { 64254721Semaste return "r"; 65254721Semaste } 66254721Semaste else if (options & File::eOpenOptionWrite) 67254721Semaste { 68254721Semaste return "w"; 69254721Semaste } 70254721Semaste return NULL; 71254721Semaste} 72254721Semaste 73254721Semasteint File::kInvalidDescriptor = -1; 74254721SemasteFILE * File::kInvalidStream = NULL; 75254721Semaste 76254721SemasteFile::File(const char *path, uint32_t options, uint32_t permissions) : 77254721Semaste m_descriptor (kInvalidDescriptor), 78254721Semaste m_stream (kInvalidStream), 79254721Semaste m_options (0), 80254721Semaste m_owned (false) 81254721Semaste{ 82254721Semaste Open (path, options, permissions); 83254721Semaste} 84254721Semaste 85258054SemasteFile::File (const FileSpec& filespec, 86258054Semaste uint32_t options, 87258054Semaste uint32_t permissions) : 88258054Semaste m_descriptor (kInvalidDescriptor), 89258054Semaste m_stream (kInvalidStream), 90258054Semaste m_options (0), 91258054Semaste m_owned (false) 92258054Semaste{ 93258054Semaste if (filespec) 94258054Semaste { 95258054Semaste Open (filespec.GetPath().c_str(), options, permissions); 96258054Semaste } 97258054Semaste} 98258054Semaste 99254721SemasteFile::File (const File &rhs) : 100254721Semaste m_descriptor (kInvalidDescriptor), 101254721Semaste m_stream (kInvalidStream), 102254721Semaste m_options (0), 103254721Semaste m_owned (false) 104254721Semaste{ 105254721Semaste Duplicate (rhs); 106254721Semaste} 107254721Semaste 108254721Semaste 109254721SemasteFile & 110254721SemasteFile::operator = (const File &rhs) 111254721Semaste{ 112254721Semaste if (this != &rhs) 113254721Semaste Duplicate (rhs); 114254721Semaste return *this; 115254721Semaste} 116254721Semaste 117254721SemasteFile::~File() 118254721Semaste{ 119254721Semaste Close (); 120254721Semaste} 121254721Semaste 122254721Semaste 123254721Semasteint 124254721SemasteFile::GetDescriptor() const 125254721Semaste{ 126254721Semaste if (DescriptorIsValid()) 127254721Semaste return m_descriptor; 128254721Semaste 129254721Semaste // Don't open the file descriptor if we don't need to, just get it from the 130254721Semaste // stream if we have one. 131254721Semaste if (StreamIsValid()) 132254721Semaste return fileno (m_stream); 133254721Semaste 134254721Semaste // Invalid descriptor and invalid stream, return invalid descriptor. 135254721Semaste return kInvalidDescriptor; 136254721Semaste} 137254721Semaste 138254721Semastevoid 139254721SemasteFile::SetDescriptor (int fd, bool transfer_ownership) 140254721Semaste{ 141254721Semaste if (IsValid()) 142254721Semaste Close(); 143254721Semaste m_descriptor = fd; 144254721Semaste m_owned = transfer_ownership; 145254721Semaste} 146254721Semaste 147254721Semaste 148254721SemasteFILE * 149254721SemasteFile::GetStream () 150254721Semaste{ 151254721Semaste if (!StreamIsValid()) 152254721Semaste { 153254721Semaste if (DescriptorIsValid()) 154254721Semaste { 155254721Semaste const char *mode = GetStreamOpenModeFromOptions (m_options); 156254721Semaste if (mode) 157254721Semaste { 158254721Semaste do 159254721Semaste { 160254721Semaste m_stream = ::fdopen (m_descriptor, mode); 161254721Semaste } while (m_stream == NULL && errno == EINTR); 162254721Semaste } 163254721Semaste } 164254721Semaste } 165254721Semaste return m_stream; 166254721Semaste} 167254721Semaste 168254721Semaste 169254721Semastevoid 170254721SemasteFile::SetStream (FILE *fh, bool transfer_ownership) 171254721Semaste{ 172254721Semaste if (IsValid()) 173254721Semaste Close(); 174254721Semaste m_stream = fh; 175254721Semaste m_owned = transfer_ownership; 176254721Semaste} 177254721Semaste 178254721SemasteError 179254721SemasteFile::Duplicate (const File &rhs) 180254721Semaste{ 181254721Semaste Error error; 182254721Semaste if (IsValid ()) 183254721Semaste Close(); 184254721Semaste 185254721Semaste if (rhs.DescriptorIsValid()) 186254721Semaste { 187258054Semaste#ifdef _WIN32 188258054Semaste m_descriptor = ::_dup(rhs.GetDescriptor()); 189258054Semaste#else 190254721Semaste m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD); 191258054Semaste#endif 192254721Semaste if (!DescriptorIsValid()) 193254721Semaste error.SetErrorToErrno(); 194254721Semaste else 195254721Semaste { 196254721Semaste m_options = rhs.m_options; 197254721Semaste m_owned = true; 198254721Semaste } 199254721Semaste } 200254721Semaste else 201254721Semaste { 202254721Semaste error.SetErrorString ("invalid file to duplicate"); 203254721Semaste } 204254721Semaste return error; 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 241258884Semaste if (options & eOpenoptionDontFollowSymlinks) 242258884Semaste oflag |= O_NOFOLLOW; 243258884Semaste#endif 244254721Semaste } 245254721Semaste 246258054Semaste#ifndef _WIN32 247254721Semaste if (options & eOpenOptionNonBlocking) 248254721Semaste oflag |= O_NONBLOCK; 249258054Semaste#else 250258054Semaste oflag |= O_BINARY; 251258054Semaste#endif 252254721Semaste 253254721Semaste mode_t mode = 0; 254254721Semaste if (oflag & O_CREAT) 255254721Semaste { 256258884Semaste if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR; 257258884Semaste if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR; 258258884Semaste if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR; 259258884Semaste if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP; 260258884Semaste if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP; 261258884Semaste if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP; 262258884Semaste if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH; 263258884Semaste if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH; 264258884Semaste if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH; 265254721Semaste } 266254721Semaste 267254721Semaste do 268254721Semaste { 269254721Semaste m_descriptor = ::open(path, oflag, mode); 270254721Semaste } while (m_descriptor < 0 && errno == EINTR); 271254721Semaste 272254721Semaste if (!DescriptorIsValid()) 273254721Semaste error.SetErrorToErrno(); 274254721Semaste else 275254721Semaste m_owned = true; 276254721Semaste 277254721Semaste return error; 278254721Semaste} 279254721Semaste 280258054Semasteuint32_t 281258054SemasteFile::GetPermissions (const char *path, Error &error) 282258054Semaste{ 283258054Semaste if (path && path[0]) 284258054Semaste { 285258054Semaste struct stat file_stats; 286258054Semaste if (::stat (path, &file_stats) == -1) 287258054Semaste error.SetErrorToErrno(); 288258054Semaste else 289258054Semaste { 290258054Semaste error.Clear(); 291258884Semaste return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 292258054Semaste } 293258054Semaste } 294258054Semaste else 295258054Semaste { 296258054Semaste if (path) 297258054Semaste error.SetErrorString ("invalid path"); 298258054Semaste else 299258054Semaste error.SetErrorString ("empty path"); 300258054Semaste } 301258054Semaste return 0; 302258054Semaste} 303258054Semaste 304258054Semasteuint32_t 305258054SemasteFile::GetPermissions(Error &error) const 306258054Semaste{ 307258054Semaste int fd = GetDescriptor(); 308258054Semaste if (fd != kInvalidDescriptor) 309258054Semaste { 310258054Semaste struct stat file_stats; 311258054Semaste if (::fstat (fd, &file_stats) == -1) 312258054Semaste error.SetErrorToErrno(); 313258054Semaste else 314258054Semaste { 315258054Semaste error.Clear(); 316258884Semaste return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 317258054Semaste } 318258054Semaste } 319258054Semaste else 320258054Semaste { 321258054Semaste error.SetErrorString ("invalid file descriptor"); 322258054Semaste } 323258054Semaste return 0; 324258054Semaste} 325258054Semaste 326258054Semaste 327254721SemasteError 328254721SemasteFile::Close () 329254721Semaste{ 330254721Semaste Error error; 331254721Semaste if (IsValid ()) 332254721Semaste { 333254721Semaste if (m_owned) 334254721Semaste { 335254721Semaste if (StreamIsValid()) 336254721Semaste { 337254721Semaste if (::fclose (m_stream) == EOF) 338254721Semaste error.SetErrorToErrno(); 339254721Semaste } 340254721Semaste 341254721Semaste if (DescriptorIsValid()) 342254721Semaste { 343254721Semaste if (::close (m_descriptor) != 0) 344254721Semaste error.SetErrorToErrno(); 345254721Semaste } 346254721Semaste } 347254721Semaste m_descriptor = kInvalidDescriptor; 348254721Semaste m_stream = kInvalidStream; 349254721Semaste m_options = 0; 350254721Semaste m_owned = false; 351254721Semaste } 352254721Semaste return error; 353254721Semaste} 354254721Semaste 355254721Semaste 356254721SemasteError 357254721SemasteFile::GetFileSpec (FileSpec &file_spec) const 358254721Semaste{ 359254721Semaste Error error; 360254721Semaste#ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED 361254721Semaste if (IsValid ()) 362254721Semaste { 363254721Semaste char path[PATH_MAX]; 364254721Semaste if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) 365254721Semaste error.SetErrorToErrno(); 366254721Semaste else 367254721Semaste file_spec.SetFile (path, false); 368254721Semaste } 369254721Semaste else 370254721Semaste { 371254721Semaste error.SetErrorString("invalid file handle"); 372254721Semaste } 373254721Semaste#elif defined(__linux__) 374254721Semaste char proc[64]; 375254721Semaste char path[PATH_MAX]; 376254721Semaste if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) 377254721Semaste error.SetErrorString ("cannot resolve file descriptor"); 378254721Semaste else 379254721Semaste { 380254721Semaste ssize_t len; 381254721Semaste if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) 382254721Semaste error.SetErrorToErrno(); 383254721Semaste else 384254721Semaste { 385254721Semaste path[len] = '\0'; 386254721Semaste file_spec.SetFile (path, false); 387254721Semaste } 388254721Semaste } 389254721Semaste#else 390254721Semaste error.SetErrorString ("File::GetFileSpec is not supported on this platform"); 391254721Semaste#endif 392254721Semaste 393254721Semaste if (error.Fail()) 394254721Semaste file_spec.Clear(); 395254721Semaste return error; 396254721Semaste} 397254721Semaste 398254721Semasteoff_t 399254721SemasteFile::SeekFromStart (off_t offset, Error *error_ptr) 400254721Semaste{ 401254721Semaste off_t result = 0; 402254721Semaste if (DescriptorIsValid()) 403254721Semaste { 404254721Semaste result = ::lseek (m_descriptor, offset, SEEK_SET); 405254721Semaste 406254721Semaste if (error_ptr) 407254721Semaste { 408254721Semaste if (result == -1) 409254721Semaste error_ptr->SetErrorToErrno(); 410254721Semaste else 411254721Semaste error_ptr->Clear(); 412254721Semaste } 413254721Semaste } 414254721Semaste else if (StreamIsValid ()) 415254721Semaste { 416254721Semaste result = ::fseek(m_stream, offset, SEEK_SET); 417254721Semaste 418254721Semaste if (error_ptr) 419254721Semaste { 420254721Semaste if (result == -1) 421254721Semaste error_ptr->SetErrorToErrno(); 422254721Semaste else 423254721Semaste error_ptr->Clear(); 424254721Semaste } 425254721Semaste } 426254721Semaste else if (error_ptr) 427254721Semaste { 428254721Semaste error_ptr->SetErrorString("invalid file handle"); 429254721Semaste } 430254721Semaste return result; 431254721Semaste} 432254721Semaste 433254721Semasteoff_t 434254721SemasteFile::SeekFromCurrent (off_t offset, Error *error_ptr) 435254721Semaste{ 436254721Semaste off_t result = -1; 437254721Semaste if (DescriptorIsValid()) 438254721Semaste { 439254721Semaste result = ::lseek (m_descriptor, offset, SEEK_CUR); 440254721Semaste 441254721Semaste if (error_ptr) 442254721Semaste { 443254721Semaste if (result == -1) 444254721Semaste error_ptr->SetErrorToErrno(); 445254721Semaste else 446254721Semaste error_ptr->Clear(); 447254721Semaste } 448254721Semaste } 449254721Semaste else if (StreamIsValid ()) 450254721Semaste { 451254721Semaste result = ::fseek(m_stream, offset, SEEK_CUR); 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 (error_ptr) 462254721Semaste { 463254721Semaste error_ptr->SetErrorString("invalid file handle"); 464254721Semaste } 465254721Semaste return result; 466254721Semaste} 467254721Semaste 468254721Semasteoff_t 469254721SemasteFile::SeekFromEnd (off_t offset, Error *error_ptr) 470254721Semaste{ 471254721Semaste off_t result = -1; 472254721Semaste if (DescriptorIsValid()) 473254721Semaste { 474254721Semaste result = ::lseek (m_descriptor, offset, SEEK_END); 475254721Semaste 476254721Semaste if (error_ptr) 477254721Semaste { 478254721Semaste if (result == -1) 479254721Semaste error_ptr->SetErrorToErrno(); 480254721Semaste else 481254721Semaste error_ptr->Clear(); 482254721Semaste } 483254721Semaste } 484254721Semaste else if (StreamIsValid ()) 485254721Semaste { 486254721Semaste result = ::fseek(m_stream, offset, SEEK_END); 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 (error_ptr) 497254721Semaste { 498254721Semaste error_ptr->SetErrorString("invalid file handle"); 499254721Semaste } 500254721Semaste return result; 501254721Semaste} 502254721Semaste 503254721SemasteError 504254721SemasteFile::Flush () 505254721Semaste{ 506254721Semaste Error error; 507254721Semaste if (StreamIsValid()) 508254721Semaste { 509254721Semaste int err = 0; 510254721Semaste do 511254721Semaste { 512254721Semaste err = ::fflush (m_stream); 513254721Semaste } while (err == EOF && errno == EINTR); 514254721Semaste 515254721Semaste if (err == EOF) 516254721Semaste error.SetErrorToErrno(); 517254721Semaste } 518254721Semaste else if (!DescriptorIsValid()) 519254721Semaste { 520254721Semaste error.SetErrorString("invalid file handle"); 521254721Semaste } 522254721Semaste return error; 523254721Semaste} 524254721Semaste 525254721Semaste 526254721SemasteError 527254721SemasteFile::Sync () 528254721Semaste{ 529254721Semaste Error error; 530254721Semaste if (DescriptorIsValid()) 531254721Semaste { 532258054Semaste#ifdef _WIN32 533258054Semaste int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); 534258054Semaste if (err == 0) 535258054Semaste error.SetErrorToGenericError(); 536258054Semaste#else 537254721Semaste int err = 0; 538254721Semaste do 539254721Semaste { 540254721Semaste err = ::fsync (m_descriptor); 541254721Semaste } while (err == -1 && errno == EINTR); 542254721Semaste 543254721Semaste if (err == -1) 544254721Semaste error.SetErrorToErrno(); 545258054Semaste#endif 546254721Semaste } 547254721Semaste else 548254721Semaste { 549254721Semaste error.SetErrorString("invalid file handle"); 550254721Semaste } 551254721Semaste return error; 552254721Semaste} 553254721Semaste 554254721SemasteError 555254721SemasteFile::Read (void *buf, size_t &num_bytes) 556254721Semaste{ 557254721Semaste Error error; 558254721Semaste ssize_t bytes_read = -1; 559254721Semaste if (DescriptorIsValid()) 560254721Semaste { 561254721Semaste do 562254721Semaste { 563254721Semaste bytes_read = ::read (m_descriptor, buf, num_bytes); 564254721Semaste } while (bytes_read < 0 && errno == EINTR); 565254721Semaste 566254721Semaste if (bytes_read == -1) 567254721Semaste { 568254721Semaste error.SetErrorToErrno(); 569254721Semaste num_bytes = 0; 570254721Semaste } 571254721Semaste else 572254721Semaste num_bytes = bytes_read; 573254721Semaste } 574254721Semaste else if (StreamIsValid()) 575254721Semaste { 576254721Semaste bytes_read = ::fread (buf, 1, num_bytes, m_stream); 577254721Semaste 578254721Semaste if (bytes_read == 0) 579254721Semaste { 580254721Semaste if (::feof(m_stream)) 581254721Semaste error.SetErrorString ("feof"); 582254721Semaste else if (::ferror (m_stream)) 583254721Semaste error.SetErrorString ("ferror"); 584254721Semaste num_bytes = 0; 585254721Semaste } 586254721Semaste else 587254721Semaste num_bytes = bytes_read; 588254721Semaste } 589254721Semaste else 590254721Semaste { 591254721Semaste num_bytes = 0; 592254721Semaste error.SetErrorString("invalid file handle"); 593254721Semaste } 594254721Semaste return error; 595254721Semaste} 596254721Semaste 597254721SemasteError 598254721SemasteFile::Write (const void *buf, size_t &num_bytes) 599254721Semaste{ 600254721Semaste Error error; 601254721Semaste ssize_t bytes_written = -1; 602254721Semaste if (DescriptorIsValid()) 603254721Semaste { 604254721Semaste do 605254721Semaste { 606254721Semaste bytes_written = ::write (m_descriptor, buf, num_bytes); 607254721Semaste } while (bytes_written < 0 && errno == EINTR); 608254721Semaste 609254721Semaste if (bytes_written == -1) 610254721Semaste { 611254721Semaste error.SetErrorToErrno(); 612254721Semaste num_bytes = 0; 613254721Semaste } 614254721Semaste else 615254721Semaste num_bytes = bytes_written; 616254721Semaste } 617254721Semaste else if (StreamIsValid()) 618254721Semaste { 619254721Semaste bytes_written = ::fwrite (buf, 1, num_bytes, m_stream); 620254721Semaste 621254721Semaste if (bytes_written == 0) 622254721Semaste { 623254721Semaste if (::feof(m_stream)) 624254721Semaste error.SetErrorString ("feof"); 625254721Semaste else if (::ferror (m_stream)) 626254721Semaste error.SetErrorString ("ferror"); 627254721Semaste num_bytes = 0; 628254721Semaste } 629254721Semaste else 630254721Semaste num_bytes = bytes_written; 631254721Semaste 632254721Semaste } 633254721Semaste else 634254721Semaste { 635254721Semaste num_bytes = 0; 636254721Semaste error.SetErrorString("invalid file handle"); 637254721Semaste } 638254721Semaste return error; 639254721Semaste} 640254721Semaste 641254721Semaste 642254721SemasteError 643254721SemasteFile::Read (void *buf, size_t &num_bytes, off_t &offset) 644254721Semaste{ 645258054Semaste#ifndef _WIN32 646254721Semaste Error error; 647254721Semaste int fd = GetDescriptor(); 648254721Semaste if (fd != kInvalidDescriptor) 649254721Semaste { 650254721Semaste ssize_t bytes_read = -1; 651254721Semaste do 652254721Semaste { 653254721Semaste bytes_read = ::pread (fd, buf, num_bytes, offset); 654254721Semaste } while (bytes_read < 0 && errno == EINTR); 655254721Semaste 656254721Semaste if (bytes_read < 0) 657254721Semaste { 658254721Semaste num_bytes = 0; 659254721Semaste error.SetErrorToErrno(); 660254721Semaste } 661254721Semaste else 662254721Semaste { 663254721Semaste offset += bytes_read; 664254721Semaste num_bytes = bytes_read; 665254721Semaste } 666254721Semaste } 667254721Semaste else 668254721Semaste { 669254721Semaste num_bytes = 0; 670254721Semaste error.SetErrorString("invalid file handle"); 671254721Semaste } 672254721Semaste return error; 673258054Semaste#else 674258054Semaste long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 675258054Semaste SeekFromStart(offset); 676258054Semaste Error error = Read(buf, num_bytes); 677258054Semaste if (!error.Fail()) 678258054Semaste SeekFromStart(cur); 679258054Semaste return error; 680258054Semaste#endif 681254721Semaste} 682254721Semaste 683254721SemasteError 684254721SemasteFile::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp) 685254721Semaste{ 686254721Semaste Error error; 687254721Semaste 688254721Semaste if (num_bytes > 0) 689254721Semaste { 690254721Semaste int fd = GetDescriptor(); 691254721Semaste if (fd != kInvalidDescriptor) 692254721Semaste { 693254721Semaste struct stat file_stats; 694254721Semaste if (::fstat (fd, &file_stats) == 0) 695254721Semaste { 696254721Semaste if (file_stats.st_size > offset) 697254721Semaste { 698254721Semaste const size_t bytes_left = file_stats.st_size - offset; 699254721Semaste if (num_bytes > bytes_left) 700254721Semaste num_bytes = bytes_left; 701254721Semaste 702254721Semaste std::unique_ptr<DataBufferHeap> data_heap_ap; 703254721Semaste data_heap_ap.reset(new DataBufferHeap(num_bytes + (null_terminate ? 1 : 0), '\0')); 704254721Semaste 705254721Semaste if (data_heap_ap.get()) 706254721Semaste { 707254721Semaste error = Read (data_heap_ap->GetBytes(), num_bytes, offset); 708254721Semaste if (error.Success()) 709254721Semaste { 710254721Semaste // Make sure we read exactly what we asked for and if we got 711254721Semaste // less, adjust the array 712254721Semaste if (num_bytes < data_heap_ap->GetByteSize()) 713254721Semaste data_heap_ap->SetByteSize(num_bytes); 714254721Semaste data_buffer_sp.reset(data_heap_ap.release()); 715254721Semaste return error; 716254721Semaste } 717254721Semaste } 718254721Semaste } 719254721Semaste else 720254721Semaste error.SetErrorString("file is empty"); 721254721Semaste } 722254721Semaste else 723254721Semaste error.SetErrorToErrno(); 724254721Semaste } 725254721Semaste else 726254721Semaste error.SetErrorString("invalid file handle"); 727254721Semaste } 728254721Semaste else 729254721Semaste error.SetErrorString("invalid file handle"); 730254721Semaste 731254721Semaste num_bytes = 0; 732254721Semaste data_buffer_sp.reset(); 733254721Semaste return error; 734254721Semaste} 735254721Semaste 736254721SemasteError 737254721SemasteFile::Write (const void *buf, size_t &num_bytes, off_t &offset) 738254721Semaste{ 739254721Semaste Error error; 740254721Semaste int fd = GetDescriptor(); 741254721Semaste if (fd != kInvalidDescriptor) 742254721Semaste { 743258054Semaste#ifndef _WIN32 744254721Semaste ssize_t bytes_written = -1; 745254721Semaste do 746254721Semaste { 747254721Semaste bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset); 748254721Semaste } while (bytes_written < 0 && errno == EINTR); 749254721Semaste 750254721Semaste if (bytes_written < 0) 751254721Semaste { 752254721Semaste num_bytes = 0; 753254721Semaste error.SetErrorToErrno(); 754254721Semaste } 755254721Semaste else 756254721Semaste { 757254721Semaste offset += bytes_written; 758254721Semaste num_bytes = bytes_written; 759254721Semaste } 760258054Semaste#else 761258054Semaste long cur = ::lseek(m_descriptor, 0, SEEK_CUR); 762258054Semaste error = Write(buf, num_bytes); 763258054Semaste long after = ::lseek(m_descriptor, 0, SEEK_CUR); 764258054Semaste 765258054Semaste if (!error.Fail()) 766258054Semaste SeekFromStart(cur); 767258054Semaste 768258054Semaste ssize_t bytes_written = after - cur; 769258054Semaste offset = after; 770258054Semaste#endif 771254721Semaste } 772254721Semaste else 773254721Semaste { 774254721Semaste num_bytes = 0; 775254721Semaste error.SetErrorString("invalid file handle"); 776254721Semaste } 777254721Semaste return error; 778254721Semaste} 779254721Semaste 780254721Semaste//------------------------------------------------------------------ 781254721Semaste// Print some formatted output to the stream. 782254721Semaste//------------------------------------------------------------------ 783254721Semastesize_t 784254721SemasteFile::Printf (const char *format, ...) 785254721Semaste{ 786254721Semaste va_list args; 787254721Semaste va_start (args, format); 788254721Semaste size_t result = PrintfVarArg (format, args); 789254721Semaste va_end (args); 790254721Semaste return result; 791254721Semaste} 792254721Semaste 793254721Semaste//------------------------------------------------------------------ 794254721Semaste// Print some formatted output to the stream. 795254721Semaste//------------------------------------------------------------------ 796254721Semastesize_t 797254721SemasteFile::PrintfVarArg (const char *format, va_list args) 798254721Semaste{ 799254721Semaste size_t result = 0; 800254721Semaste if (DescriptorIsValid()) 801254721Semaste { 802254721Semaste char *s = NULL; 803254721Semaste result = vasprintf(&s, format, args); 804254721Semaste if (s != NULL) 805254721Semaste { 806254721Semaste if (result > 0) 807254721Semaste { 808254721Semaste size_t s_len = result; 809254721Semaste Write (s, s_len); 810254721Semaste result = s_len; 811254721Semaste } 812254721Semaste free (s); 813254721Semaste } 814254721Semaste } 815254721Semaste else if (StreamIsValid()) 816254721Semaste { 817254721Semaste result = ::vfprintf (m_stream, format, args); 818254721Semaste } 819254721Semaste return result; 820254721Semaste} 821258054Semaste 822258054Semastemode_t 823258054SemasteFile::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options) 824258054Semaste{ 825258054Semaste mode_t mode = 0; 826258054Semaste if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) 827258054Semaste mode |= O_RDWR; 828258054Semaste else if (open_options & eOpenOptionWrite) 829258054Semaste mode |= O_WRONLY; 830258054Semaste 831258054Semaste if (open_options & eOpenOptionAppend) 832258054Semaste mode |= O_APPEND; 833258054Semaste 834258054Semaste if (open_options & eOpenOptionTruncate) 835258054Semaste mode |= O_TRUNC; 836258054Semaste 837258054Semaste if (open_options & eOpenOptionNonBlocking) 838258054Semaste mode |= O_NONBLOCK; 839258054Semaste 840258054Semaste if (open_options & eOpenOptionCanCreateNewOnly) 841258054Semaste mode |= O_CREAT | O_EXCL; 842258054Semaste else if (open_options & eOpenOptionCanCreate) 843258054Semaste mode |= O_CREAT; 844258054Semaste 845258054Semaste return mode; 846258054Semaste} 847