Use Host::File in lldb_private::StreamFile and other places to cleanup host
layer a bit more.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@125149 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp
index 6bfb5d6..e2dd32c 100644
--- a/source/Host/common/File.cpp
+++ b/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 @@
 
     if (options & eOpenOptionAppend)
         oflag |= O_APPEND;
+    else
+        oflag |= O_TRUNC;
 
     if (options & eOpenOptionCanCreate)
         oflag |= O_CREAT;
@@ -57,8 +202,6 @@
     if (options & eOpenOptionCanCreateNewOnly)
         oflag |= O_CREAT | O_EXCL;
     
-    if (options & eOpenOptionTruncate)
-        oflag |= O_TRUNC;
     
     if (options & eOpenOptionSharedLock)
         oflag |= O_SHLOCK;
@@ -77,9 +220,11 @@
     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 @@
     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 @@
     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 @@
 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 @@
 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 @@
 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 @@
 }
 
 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 @@
 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 @@
         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 @@
 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 @@
         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 @@
 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 @@
 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 @@
     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;
+}