Expose SBPlatform through the public API.

Example code:

remote_platform = lldb.SBPlatform("remote-macosx"); 
remote_platform.SetWorkingDirectory("/private/tmp")
debugger.SetSelectedPlatform(remote_platform)

connect_options = lldb.SBPlatformConnectOptions("connect://localhost:1111"); 
err = remote_platform.ConnectRemote(connect_options)
if err.Success():
    print >> result, 'Connected to remote platform:'
    print >> result, 'hostname: %s' % (remote_platform.GetHostname())
    src = lldb.SBFileSpec("/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework", False)
    dst = lldb.SBFileSpec()
    # copy src to platform working directory since "dst" is empty
    err = remote_platform.Install(src, dst);
    if err.Success():
        print >> result, '%s installed successfully' % (src)
    else:
        print >> result, 'error: failed to install "%s": %s' % (src, err)


Implemented many calls needed in lldb-platform to be able to install a directory that contains symlinks, file and directories.

The remote lldb-platform can now launch GDB servers on the remote system so that remote debugging can be spawned through the remote platform when connected to a remote platform.

The API in SBPlatform is subject to change and will be getting many new functions.

llvm-svn: 195273
diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp
index addd435..c8dff19 100644
--- a/lldb/source/Host/common/File.cpp
+++ b/lldb/source/Host/common/File.cpp
@@ -1,4 +1,4 @@
-//===-- FileSpec.cpp --------------------------------------------*- C++ -*-===//
+//===-- File.cpp ------------------------------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,7 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-
 #include "lldb/Host/File.h"
 
 #include <errno.h>
@@ -237,6 +236,9 @@
     else if (read)
     {
         oflag |= O_RDONLY;
+
+        if (options & eOpenoptionDontFollowSymlinks)
+            oflag |= O_NOFOLLOW;
     }
     
 #ifndef _WIN32
@@ -249,15 +251,15 @@
     mode_t mode = 0;
     if (oflag & O_CREAT)
     {
-        if (permissions & ePermissionsUserRead)     mode |= S_IRUSR;
-        if (permissions & ePermissionsUserWrite)    mode |= S_IWUSR;
-        if (permissions & ePermissionsUserExecute)  mode |= S_IXUSR;
-        if (permissions & ePermissionsGroupRead)    mode |= S_IRGRP;
-        if (permissions & ePermissionsGroupWrite)   mode |= S_IWGRP;
-        if (permissions & ePermissionsGroupExecute) mode |= S_IXGRP;
-        if (permissions & ePermissionsWorldRead)    mode |= S_IROTH;
-        if (permissions & ePermissionsWorldWrite)   mode |= S_IWOTH;
-        if (permissions & ePermissionsWorldExecute) mode |= S_IXOTH;
+        if (permissions & lldb::eFilePermissionsUserRead)     mode |= S_IRUSR;
+        if (permissions & lldb::eFilePermissionsUserWrite)    mode |= S_IWUSR;
+        if (permissions & lldb::eFilePermissionsUserExecute)  mode |= S_IXUSR;
+        if (permissions & lldb::eFilePermissionsGroupRead)    mode |= S_IRGRP;
+        if (permissions & lldb::eFilePermissionsGroupWrite)   mode |= S_IWGRP;
+        if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP;
+        if (permissions & lldb::eFilePermissionsWorldRead)    mode |= S_IROTH;
+        if (permissions & lldb::eFilePermissionsWorldWrite)   mode |= S_IWOTH;
+        if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH;
     }
 
     do
diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp
index 33de198..48f1ac7 100644
--- a/lldb/source/Host/common/FileSpec.cpp
+++ b/lldb/source/Host/common/FileSpec.cpp
@@ -34,6 +34,7 @@
 #include "lldb/Core/StreamString.h"
 #include "lldb/Host/File.h"
 #include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/DataBufferMemoryMap.h"
 #include "lldb/Core/RegularExpression.h"
@@ -646,6 +647,15 @@
     return eFileTypeInvalid;
 }
 
+uint32_t
+FileSpec::GetPermissions () const
+{
+    uint32_t file_permissions = 0;
+    if (*this)
+        Host::GetFilePermissions(GetPath().c_str(), file_permissions);
+    return file_permissions;
+}
+
 TimeValue
 FileSpec::GetModificationTime () const
 {
@@ -1161,26 +1171,26 @@
         return FileSpec(m_directory.GetCString(),resolve);
 }
 
-const char*
+ConstString
 FileSpec::GetLastPathComponent () const
 {
-    if (m_filename.IsEmpty() && m_directory.IsEmpty())
-        return NULL;
-    if (m_filename.IsEmpty())
+    if (m_filename)
+        return m_filename;
+    if (m_directory)
     {
         const char* dir_cstr = m_directory.GetCString();
         const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
         if (last_slash_ptr == NULL)
-            return m_directory.GetCString();
+            return m_directory;
         if (last_slash_ptr == dir_cstr)
         {
             if (last_slash_ptr[1] == 0)
-                return last_slash_ptr;
+                return ConstString(last_slash_ptr);
             else
-                return last_slash_ptr+1;
+                return ConstString(last_slash_ptr+1);
         }
         if (last_slash_ptr[1] != 0)
-            return last_slash_ptr+1;
+            return ConstString(last_slash_ptr+1);
         const char* penultimate_slash_ptr = last_slash_ptr;
         while (*penultimate_slash_ptr)
         {
@@ -1190,10 +1200,10 @@
             if (*penultimate_slash_ptr == '/')
                 break;
         }
-        ConstString new_path(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr);
-        return new_path.AsCString();
+        ConstString result(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr);
+        return result;
     }
-    return m_filename.GetCString();
+    return ConstString();
 }
 
 void
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index 296e4b4..c095e6b 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -1826,11 +1826,130 @@
     return LLDB_INVALID_PROCESS_ID;
 }
 
-uint32_t
-Host::MakeDirectory (const char* path, mode_t mode)
+#endif
+
+
+#ifdef LLDB_DISABLE_POSIX
+
+Error
+Host::MakeDirectory (const char* path, uint32_t mode)
 {
-    return UINT32_MAX;
+    Error error;
+    error.SetErrorString("%s in not implemented on this host", __PRETTY_FUNCTION__);
+    return error;
 }
+
+Error
+Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
+{
+    Error error;
+    error.SetErrorString("%s is not supported on this host", __PRETTY_FUNCTION__);
+    return error;
+}
+
+Error
+Host::SetFilePermissions (const char* path, uint32_t file_permissions)
+{
+    Error error;
+    error.SetErrorString("%s is not supported on this host", __PRETTY_FUNCTION__);
+    return error;
+}
+
+Error
+Host::Symlink (const char *src, const char *dst)
+{
+    Error error;
+    error.SetErrorString("%s is not supported on this host", __PRETTY_FUNCTION__);
+    return error;
+}
+
+Error
+Host::Readlink (const char *path, char *buf, size_t buf_len)
+{
+    Error error;
+    error.SetErrorString("%s is not supported on this host", __PRETTY_FUNCTION__);
+    return error;
+}
+
+Error
+Host::Unlink (const char *path)
+{
+    Error error;
+    error.SetErrorString("%s is not supported on this host", __PRETTY_FUNCTION__);
+    return error;
+}
+
+#else
+
+Error
+Host::MakeDirectory (const char* path, uint32_t file_permissions)
+{
+    Error error;
+    if (::mkdir(path, file_permissions) != 0)
+        error.SetErrorToErrno();
+    return error;
+}
+
+Error
+Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
+{
+    Error error;
+    struct stat file_stats;
+    if (::stat (path, &file_stats) == 0)
+    {
+        // The bits in "st_mode" currently match the definitions
+        // for the file mode bits in unix.
+        file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+    }
+    else
+    {
+        error.SetErrorToErrno();
+    }
+    return error;
+}
+
+Error
+Host::SetFilePermissions (const char* path, uint32_t file_permissions)
+{
+    Error error;
+    if (::chmod(path, file_permissions) != 0)
+        error.SetErrorToErrno();
+    return error;
+}
+
+Error
+Host::Symlink (const char *src, const char *dst)
+{
+    Error error;
+    if (::symlink(dst, src) == -1)
+        error.SetErrorToErrno();
+    return error;
+}
+
+Error
+Host::Unlink (const char *path)
+{
+    Error error;
+    if (::unlink(path) == -1)
+        error.SetErrorToErrno();
+    return error;
+}
+
+Error
+Host::Readlink (const char *path, char *buf, size_t buf_len)
+{
+    Error error;
+    ssize_t count = ::readlink(path, buf, buf_len);
+    if (count < 0)
+        error.SetErrorToErrno();
+    else if (count < (buf_len-1))
+        buf[count] = '\0'; // Success
+    else
+        error.SetErrorString("'buf' buffer is too small to contain link contents");
+    return error;
+}
+
+
 #endif
 
 typedef std::map<lldb::user_id_t, lldb::FileSP> FDToFileMap;
@@ -1843,7 +1962,7 @@
 lldb::user_id_t
 Host::OpenFile (const FileSpec& file_spec,
                 uint32_t flags,
-                mode_t mode,
+                uint32_t mode,
                 Error &error)
 {
     std::string path (file_spec.GetPath());