diff options
Diffstat (limited to 'lldb/source/Host/common/File.cpp')
-rw-r--r-- | lldb/source/Host/common/File.cpp | 299 |
1 files changed, 273 insertions, 26 deletions
diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp index 6bfb5d6d901..e2dd32cca00 100644 --- a/lldb/source/Host/common/File.cpp +++ b/lldb/source/Host/common/File.cpp @@ -18,17 +18,160 @@ using namespace lldb; using namespace lldb_private; +static const char * +GetStreamOpenModeFromOptions (uint32_t options) +{ + if (options & File::eOpenOptionAppend) + { + if (options & File::eOpenOptionRead) + { + if (options & File::eOpenOptionCanCreateNewOnly) + return "a+x"; + else + return "a+"; + } + else if (options & File::eOpenOptionWrite) + { + if (options & File::eOpenOptionCanCreateNewOnly) + return "ax"; + else + return "a"; + } + } + else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite) + { + if (options & File::eOpenOptionCanCreate) + { + if (options & File::eOpenOptionCanCreateNewOnly) + return "w+x"; + else + return "w+"; + } + else + return "r+"; + } + else if (options & File::eOpenOptionRead) + { + return "r"; + } + else if (options & File::eOpenOptionWrite) + { + return "w"; + } + return NULL; +} + +int File::kInvalidDescriptor = -1; +FILE * File::kInvalidStream = NULL; + File::File(const char *path, uint32_t options, uint32_t permissions) : - m_file_desc (-1) + m_descriptor (kInvalidDescriptor), + m_stream (kInvalidStream), + m_options (0), + m_owned (false) { Open (path, options, permissions); } +File::File (const File &rhs) : + m_descriptor (kInvalidDescriptor), + m_stream (kInvalidStream), + m_options (0), + m_owned (false) +{ + Duplicate (rhs); +} + + +File & +File::operator = (const File &rhs) +{ + if (this != &rhs) + Duplicate (rhs); + return *this; +} + File::~File() { Close (); } + +int +File::GetDescriptor() const +{ + if (DescriptorIsValid()) + return m_descriptor; + + // Don't open the file descriptor if we don't need to, just get it from the + // stream if we have one. + if (StreamIsValid()) + return fileno (m_stream); + + // Invalid descriptor and invalid stream, return invalid descriptor. + return kInvalidDescriptor; +} + +void +File::SetDescriptor (int fd, bool transfer_ownership) +{ + if (IsValid()) + Close(); + m_descriptor = fd; + m_owned = transfer_ownership; +} + + +FILE * +File::GetStream () +{ + if (!StreamIsValid()) + { + if (DescriptorIsValid()) + { + const char *mode = GetStreamOpenModeFromOptions (m_options); + if (mode) + m_stream = ::fdopen (m_descriptor, mode); + } + } + return m_stream; +} + + +void +File::SetStream (FILE *fh, bool transfer_ownership) +{ + if (IsValid()) + Close(); + m_stream = fh; + m_owned = transfer_ownership; +} + +Error +File::Duplicate (const File &rhs) +{ + Error error; + if (IsValid ()) + Close(); + + if (rhs.DescriptorIsValid()) + { + m_descriptor = ::fcntl(rhs.GetDescriptor(), F_DUPFD); + if (!DescriptorIsValid()) + error.SetErrorToErrno(); + else + { + m_options = rhs.m_options; + m_owned = true; + } + } + else + { + error.SetErrorString ("invalid file to duplicate"); + } + return error; +} + Error File::Open (const char *path, uint32_t options, uint32_t permissions) { @@ -50,6 +193,8 @@ File::Open (const char *path, uint32_t options, uint32_t permissions) if (options & eOpenOptionAppend) oflag |= O_APPEND; + else + oflag |= O_TRUNC; if (options & eOpenOptionCanCreate) oflag |= O_CREAT; @@ -57,8 +202,6 @@ File::Open (const char *path, uint32_t options, uint32_t permissions) if (options & eOpenOptionCanCreateNewOnly) oflag |= O_CREAT | O_EXCL; - if (options & eOpenOptionTruncate) - oflag |= O_TRUNC; if (options & eOpenOptionSharedLock) oflag |= O_SHLOCK; @@ -77,9 +220,11 @@ File::Open (const char *path, uint32_t options, uint32_t permissions) if (permissions & ePermissionsWorldWrite) mode |= S_IWOTH; if (permissions & ePermissionsWorldExecute) mode |= S_IXOTH; - m_file_desc = ::open(path, oflag, mode); - if (m_file_desc == -1) + m_descriptor = ::open(path, oflag, mode); + if (!DescriptorIsValid()) error.SetErrorToErrno(); + else + m_owned = true; return error; } @@ -90,9 +235,24 @@ File::Close () Error error; if (IsValid ()) { - if (::close (m_file_desc) != 0) - error.SetErrorToErrno(); - m_file_desc = -1; + if (m_owned) + { + if (StreamIsValid()) + { + if (::fclose (m_stream) == EOF) + error.SetErrorToErrno(); + } + + if (DescriptorIsValid()) + { + if (::close (m_descriptor) != 0) + error.SetErrorToErrno(); + } + } + m_descriptor = kInvalidDescriptor; + m_stream = kInvalidStream; + m_options = 0; + m_owned = false; } return error; } @@ -105,7 +265,7 @@ File::GetFileSpec (FileSpec &file_spec) const if (IsValid ()) { char path[PATH_MAX]; - if (::fcntl(m_file_desc, F_GETPATH, path) == -1) + if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) error.SetErrorToErrno(); else file_spec.SetFile (path, false); @@ -122,9 +282,9 @@ Error File::SeekFromStart (off_t& offset) { Error error; - if (IsValid ()) + if (DescriptorIsValid()) { - offset = ::lseek (m_file_desc, offset, SEEK_SET); + offset = ::lseek (m_descriptor, offset, SEEK_SET); if (offset == -1) error.SetErrorToErrno(); @@ -140,9 +300,9 @@ Error File::SeekFromCurrent (off_t& offset) { Error error; - if (IsValid ()) + if (DescriptorIsValid()) { - offset = ::lseek (m_file_desc, offset, SEEK_CUR); + offset = ::lseek (m_descriptor, offset, SEEK_CUR); if (offset == -1) error.SetErrorToErrno(); @@ -158,9 +318,9 @@ Error File::SeekFromEnd (off_t& offset) { Error error; - if (IsValid ()) + if (DescriptorIsValid()) { - offset = ::lseek (m_file_desc, offset, SEEK_CUR); + offset = ::lseek (m_descriptor, offset, SEEK_CUR); if (offset == -1) error.SetErrorToErrno(); @@ -173,12 +333,29 @@ File::SeekFromEnd (off_t& offset) } Error +File::Flush () +{ + Error error; + if (StreamIsValid()) + { + if (::fflush (m_stream) == EOF) + error.SetErrorToErrno(); + } + else if (!DescriptorIsValid()) + { + error.SetErrorString("invalid file handle"); + } + return error; +} + + +Error File::Sync () { Error error; - if (IsValid ()) + if (DescriptorIsValid()) { - if (::fsync (m_file_desc) == -1) + if (::fsync (m_descriptor) == -1) error.SetErrorToErrno(); } else @@ -192,9 +369,9 @@ Error File::Read (void *buf, size_t &num_bytes) { Error error; - if (IsValid ()) + if (DescriptorIsValid()) { - ssize_t bytes_read = ::read (m_file_desc, buf, num_bytes); + ssize_t bytes_read = ::read (m_descriptor, buf, num_bytes); if (bytes_read == -1) { error.SetErrorToErrno(); @@ -203,6 +380,20 @@ File::Read (void *buf, size_t &num_bytes) else num_bytes = bytes_read; } + else if (StreamIsValid()) + { + size_t bytes_read = ::fread (buf, 1, num_bytes, m_stream); + if (bytes_read == 0) + { + if (::feof(m_stream)) + error.SetErrorString ("feof"); + else if (::ferror (m_stream)) + error.SetErrorString ("ferror"); + num_bytes = 0; + } + else + num_bytes = bytes_read; + } else { num_bytes = 0; @@ -215,9 +406,9 @@ Error File::Write (const void *buf, size_t &num_bytes) { Error error; - if (IsValid()) + if (DescriptorIsValid()) { - ssize_t bytes_written = ::write (m_file_desc, buf, num_bytes); + ssize_t bytes_written = ::write (m_descriptor, buf, num_bytes); if (bytes_written == -1) { error.SetErrorToErrno(); @@ -226,6 +417,21 @@ File::Write (const void *buf, size_t &num_bytes) else num_bytes = bytes_written; } + else if (StreamIsValid()) + { + size_t bytes_written = ::fwrite (buf, 1, num_bytes, m_stream); + if (bytes_written == 0) + { + if (::feof(m_stream)) + error.SetErrorString ("feof"); + else if (::ferror (m_stream)) + error.SetErrorString ("ferror"); + num_bytes = 0; + } + else + num_bytes = bytes_written; + + } else { num_bytes = 0; @@ -239,9 +445,10 @@ Error File::Read (void *buf, size_t &num_bytes, off_t &offset) { Error error; - if (IsValid ()) + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) { - ssize_t bytes_read = ::pread (m_file_desc, buf, num_bytes, offset); + ssize_t bytes_read = ::pread (fd, buf, num_bytes, offset); if (bytes_read < 0) { num_bytes = 0; @@ -265,9 +472,10 @@ Error File::Write (const void *buf, size_t &num_bytes, off_t &offset) { Error error; - if (IsValid()) + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) { - ssize_t bytes_written = ::pwrite (m_file_desc, buf, num_bytes, offset); + ssize_t bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset); if (bytes_written < 0) { num_bytes = 0; @@ -287,5 +495,44 @@ File::Write (const void *buf, size_t &num_bytes, off_t &offset) return error; } +//------------------------------------------------------------------ +// Print some formatted output to the stream. +//------------------------------------------------------------------ +int +File::Printf (const char *format, ...) +{ + va_list args; + va_start (args, format); + int result = PrintfVarArg (format, args); + va_end (args); + return result; +} - +//------------------------------------------------------------------ +// Print some formatted output to the stream. +//------------------------------------------------------------------ +int +File::PrintfVarArg (const char *format, va_list args) +{ + int result = 0; + if (DescriptorIsValid()) + { + char *s = NULL; + result = vasprintf(&s, format, args); + if (s != NULL) + { + if (result > 0) + { + size_t s_len = result; + Write (s, s_len); + result = s_len; + } + free (s); + } + } + else if (StreamIsValid()) + { + result = ::vfprintf (m_stream, format, args); + } + return result; +} |