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/API/SBPlatform.cpp b/lldb/source/API/SBPlatform.cpp
new file mode 100644
index 0000000..9914852
--- /dev/null
+++ b/lldb/source/API/SBPlatform.cpp
@@ -0,0 +1,632 @@
+//===-- SBPlatform.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBPlatform.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Host/File.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Platform.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// PlatformConnectOptions
+//----------------------------------------------------------------------
+struct PlatformConnectOptions {
+    PlatformConnectOptions(const char *url = NULL) :
+        m_url(),
+        m_rsync_options(),
+        m_rsync_remote_path_prefix(),
+        m_rsync_enabled(false),
+        m_rsync_omit_hostname_from_remote_path(false),
+        m_local_cache_directory ()
+    {
+        if (url && url[0])
+            m_url = url;
+    }
+    
+    ~PlatformConnectOptions()
+    {
+    }
+
+    std::string m_url;
+    std::string m_rsync_options;
+    std::string m_rsync_remote_path_prefix;
+    bool m_rsync_enabled;
+    bool m_rsync_omit_hostname_from_remote_path;
+    ConstString m_local_cache_directory;
+};
+
+//----------------------------------------------------------------------
+// PlatformShellCommand
+//----------------------------------------------------------------------
+struct PlatformShellCommand {
+    PlatformShellCommand(const char *shell_command = NULL) :
+        m_command(),
+        m_working_dir(),
+        m_status(0),
+        m_signo(0),
+        m_timeout_sec(UINT32_MAX)
+    {
+        if (shell_command && shell_command[0])
+            m_command = shell_command;
+    }
+    
+    ~PlatformShellCommand()
+    {
+    }
+    
+    std::string m_command;
+    std::string m_working_dir;
+    std::string m_output;
+    int m_status;
+    int m_signo;
+    uint32_t m_timeout_sec;
+};
+//----------------------------------------------------------------------
+// SBPlatformConnectOptions
+//----------------------------------------------------------------------
+SBPlatformConnectOptions::SBPlatformConnectOptions (const char *url) :
+    m_opaque_ptr(new PlatformConnectOptions(url))
+{
+    
+}
+
+SBPlatformConnectOptions::SBPlatformConnectOptions(const SBPlatformConnectOptions &rhs) :
+    m_opaque_ptr(new PlatformConnectOptions())
+{
+    *m_opaque_ptr = *rhs.m_opaque_ptr;
+}
+    
+SBPlatformConnectOptions::~SBPlatformConnectOptions ()
+{
+    delete m_opaque_ptr;
+}
+
+void
+SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs)
+{
+    *m_opaque_ptr = *rhs.m_opaque_ptr;
+}
+
+const char *
+SBPlatformConnectOptions::GetURL()
+{
+    if (m_opaque_ptr->m_url.empty())
+        return NULL;
+    return m_opaque_ptr->m_url.c_str();
+}
+    
+void
+SBPlatformConnectOptions::SetURL(const char *url)
+{
+    if (url && url[0])
+        m_opaque_ptr->m_url = url;
+    else
+        m_opaque_ptr->m_url.clear();
+}
+
+bool
+SBPlatformConnectOptions::GetRsyncEnabled()
+{
+    return m_opaque_ptr->m_rsync_enabled;
+}
+    
+void
+SBPlatformConnectOptions::EnableRsync (const char *options,
+                                       const char *remote_path_prefix,
+                                       bool omit_hostname_from_remote_path)
+{
+    m_opaque_ptr->m_rsync_enabled = true;
+    m_opaque_ptr->m_rsync_omit_hostname_from_remote_path = omit_hostname_from_remote_path;
+    if (remote_path_prefix && remote_path_prefix[0])
+        m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
+    else
+        m_opaque_ptr->m_rsync_remote_path_prefix.clear();
+
+    if (options && options[0])
+        m_opaque_ptr->m_rsync_options = options;
+    else
+        m_opaque_ptr->m_rsync_options.clear();
+
+}
+
+void
+SBPlatformConnectOptions::DisableRsync ()
+{
+    m_opaque_ptr->m_rsync_enabled = false;
+}
+    
+const char *
+SBPlatformConnectOptions::GetLocalCacheDirectory()
+{
+    return m_opaque_ptr->m_local_cache_directory.GetCString();
+}
+    
+void
+SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path)
+{
+    if (path && path[0])
+        m_opaque_ptr->m_local_cache_directory.SetCString(path);
+    else
+        m_opaque_ptr->m_local_cache_directory = ConstString();
+}
+
+//----------------------------------------------------------------------
+// SBPlatformShellCommand
+//----------------------------------------------------------------------
+SBPlatformShellCommand::SBPlatformShellCommand (const char *shell_command) :
+    m_opaque_ptr(new PlatformShellCommand(shell_command))
+{
+}
+
+SBPlatformShellCommand::SBPlatformShellCommand (const SBPlatformShellCommand &rhs) :
+    m_opaque_ptr(new PlatformShellCommand())
+{
+    *m_opaque_ptr = *rhs.m_opaque_ptr;
+}
+
+SBPlatformShellCommand::~SBPlatformShellCommand()
+{
+    delete m_opaque_ptr;
+}
+
+void
+SBPlatformShellCommand::Clear()
+{
+    m_opaque_ptr->m_output = std::move(std::string());
+    m_opaque_ptr->m_status = 0;
+    m_opaque_ptr->m_signo = 0;
+}
+
+const char *
+SBPlatformShellCommand::GetCommand()
+{
+    if (m_opaque_ptr->m_command.empty())
+        return NULL;
+    return m_opaque_ptr->m_command.c_str();
+}
+
+void
+SBPlatformShellCommand::SetCommand(const char *shell_command)
+{
+    if (shell_command && shell_command[0])
+        m_opaque_ptr->m_command = shell_command;
+    else
+        m_opaque_ptr->m_command.clear();
+}
+
+const char *
+SBPlatformShellCommand::GetWorkingDirectory ()
+{
+    if (m_opaque_ptr->m_working_dir.empty())
+        return NULL;
+    return m_opaque_ptr->m_working_dir.c_str();
+}
+
+void
+SBPlatformShellCommand::SetWorkingDirectory (const char *path)
+{
+    if (path && path[0])
+        m_opaque_ptr->m_working_dir = path;
+    else
+        m_opaque_ptr->m_working_dir.clear();
+}
+
+uint32_t
+SBPlatformShellCommand::GetTimeoutSeconds ()
+{
+    return m_opaque_ptr->m_timeout_sec;
+}
+
+void
+SBPlatformShellCommand::SetTimeoutSeconds (uint32_t sec)
+{
+    m_opaque_ptr->m_timeout_sec = sec;
+}
+
+int
+SBPlatformShellCommand::GetSignal ()
+{
+    return m_opaque_ptr->m_signo;
+}
+
+int
+SBPlatformShellCommand::GetStatus ()
+{
+    return m_opaque_ptr->m_status;
+}
+
+const char *
+SBPlatformShellCommand::GetOutput ()
+{
+    if (m_opaque_ptr->m_output.empty())
+        return NULL;
+    return m_opaque_ptr->m_output.c_str();
+}
+
+//----------------------------------------------------------------------
+// SBPlatform
+//----------------------------------------------------------------------
+SBPlatform::SBPlatform () :
+    m_opaque_sp ()
+{
+    
+}
+
+SBPlatform::SBPlatform (const char *platform_name) :
+    m_opaque_sp ()
+{
+    Error error;
+    m_opaque_sp = Platform::Create (platform_name, error);
+}
+
+SBPlatform::~SBPlatform()
+{
+}
+
+bool
+SBPlatform::IsValid () const
+{
+    return m_opaque_sp.get() != NULL;
+}
+
+void
+SBPlatform::Clear ()
+{
+    m_opaque_sp.reset();
+}
+
+const char *
+SBPlatform::GetName ()
+{
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+        return platform_sp->GetName().GetCString();
+    return NULL;
+}
+
+lldb::PlatformSP
+SBPlatform::GetSP () const
+{
+    return m_opaque_sp;
+}
+
+void
+SBPlatform::SetSP (const lldb::PlatformSP& platform_sp)
+{
+    m_opaque_sp = platform_sp;
+}
+
+const char *
+SBPlatform::GetWorkingDirectory()
+{
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+        return platform_sp->GetWorkingDirectory().GetCString();
+    return NULL;
+}
+
+bool
+SBPlatform::SetWorkingDirectory(const char *path)
+{
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        if (path)
+            platform_sp->SetWorkingDirectory(ConstString(path));
+        else
+            platform_sp->SetWorkingDirectory(ConstString());
+        return true;
+    }
+    return false;
+}
+
+SBError
+SBPlatform::ConnectRemote (SBPlatformConnectOptions &connect_options)
+{
+    SBError sb_error;
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp && connect_options.GetURL())
+    {
+        Args args;
+        args.AppendArgument(connect_options.GetURL());
+        sb_error.ref() = platform_sp->ConnectRemote(args);
+    }
+    else
+    {
+        sb_error.SetErrorString("invalid platform");
+    }
+    return sb_error;
+}
+
+void
+SBPlatform::DisconnectRemote ()
+{
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+        platform_sp->DisconnectRemote();
+}
+
+bool
+SBPlatform::IsConnected()
+{
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+        platform_sp->IsConnected();
+    return false;
+}
+
+const char *
+SBPlatform::GetTriple()
+{
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        ArchSpec arch(platform_sp->GetRemoteSystemArchitecture());
+        if (arch.IsValid())
+        {
+            // Const-ify the string so we don't need to worry about the lifetime of the string
+            return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
+        }
+    }
+    return NULL;
+}
+
+const char *
+SBPlatform::GetOSBuild()
+{
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        std::string s;
+        if (platform_sp->GetOSBuildString(s))
+        {
+            if (!s.empty())
+            {
+                // Const-ify the string so we don't need to worry about the lifetime of the string
+                return ConstString(s.c_str()).GetCString();
+            }
+        }
+    }
+    return NULL;
+}
+
+const char *
+SBPlatform::GetOSDescription()
+{
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        std::string s;
+        if (platform_sp->GetOSKernelDescription(s))
+        {
+            if (!s.empty())
+            {
+                // Const-ify the string so we don't need to worry about the lifetime of the string
+                return ConstString(s.c_str()).GetCString();
+            }
+        }
+    }
+    return NULL;
+}
+
+const char *
+SBPlatform::GetHostname ()
+{
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+        return platform_sp->GetHostname();
+    return NULL;
+}
+
+uint32_t
+SBPlatform::GetOSMajorVersion ()
+{
+    uint32_t major, minor, update;
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
+        return major;
+    return UINT32_MAX;
+    
+}
+
+uint32_t
+SBPlatform::GetOSMinorVersion ()
+{
+    uint32_t major, minor, update;
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
+        return minor;
+    return UINT32_MAX;
+}
+
+uint32_t
+SBPlatform::GetOSUpdateVersion ()
+{
+    uint32_t major, minor, update;
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
+        return update;
+    return UINT32_MAX;
+}
+
+SBError
+SBPlatform::Get (SBFileSpec &src,
+                 SBFileSpec &dst)
+{
+    SBError sb_error;
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());
+    }
+    else
+    {
+        sb_error.SetErrorString("invalid platform");
+    }
+    return sb_error;
+}
+
+SBError
+SBPlatform::Put (SBFileSpec &src,
+                 SBFileSpec &dst)
+{
+    SBError sb_error;
+    
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        if (src.Exists())
+        {
+            uint32_t permissions = src.ref().GetPermissions();
+            if (permissions == 0)
+            {
+                if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory)
+                    permissions = eFilePermissionsDirectoryDefault;
+                else
+                    permissions = eFilePermissionsFileDefault;
+            }
+
+            sb_error.ref() = platform_sp->PutFile(src.ref(),
+                                                  dst.ref(),
+                                                  permissions);
+        }
+        else
+        {
+            sb_error.ref().SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
+        }
+    }
+    else
+    {
+        sb_error.SetErrorString("invalid platform");
+    }
+    return sb_error;
+}
+
+SBError
+SBPlatform::Install (SBFileSpec &src,
+                     SBFileSpec &dst)
+{
+    SBError sb_error;
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        if (src.Exists())
+        {
+            sb_error.ref() = platform_sp->Install(src.ref(), dst.ref());
+        }
+        else
+        {
+            sb_error.ref().SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
+        }
+    }
+    else
+    {
+        sb_error.SetErrorString("invalid platform");
+    }
+    return sb_error;
+}
+
+
+SBError
+SBPlatform::Run (SBPlatformShellCommand &shell_command)
+{
+    SBError sb_error;
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        if (platform_sp->IsConnected())
+        {
+            const char *command = shell_command.GetCommand();
+            if (command)
+            {
+                const char *working_dir = shell_command.GetWorkingDirectory();
+                if (working_dir == NULL)
+                {
+                    working_dir = platform_sp->GetWorkingDirectory().GetCString();
+                    if (working_dir)
+                        shell_command.SetWorkingDirectory(working_dir);
+                }
+                sb_error.ref() = platform_sp->RunShellCommand(command,
+                                                              working_dir,
+                                                              &shell_command.m_opaque_ptr->m_status,
+                                                              &shell_command.m_opaque_ptr->m_signo,
+                                                              &shell_command.m_opaque_ptr->m_output,
+                                                              shell_command.m_opaque_ptr->m_timeout_sec);
+            }
+            else
+            {
+                sb_error.SetErrorString("invalid shell command (empty)");
+            }
+        }
+        else
+        {
+            sb_error.SetErrorString("not connected");
+        }
+    }
+    else
+    {
+        sb_error.SetErrorString("invalid platform");
+    }
+    return sb_error;
+}
+
+SBError
+SBPlatform::MakeDirectory (const char *path, uint32_t file_permissions)
+{
+    SBError sb_error;
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        sb_error.ref() = platform_sp->MakeDirectory(path, file_permissions);
+    }
+    else
+    {
+        sb_error.SetErrorString("invalid platform");
+    }
+    return sb_error;
+}
+
+uint32_t
+SBPlatform::GetFilePermissions (const char *path)
+{
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        uint32_t file_permissions = 0;
+        platform_sp->GetFilePermissions(path, file_permissions);
+        return file_permissions;
+    }
+    return 0;
+    
+}
+
+SBError
+SBPlatform::SetFilePermissions (const char *path, uint32_t file_permissions)
+{
+    SBError sb_error;
+    PlatformSP platform_sp(GetSP());
+    if (platform_sp)
+    {
+        sb_error.ref() = platform_sp->SetFilePermissions(path, file_permissions);
+    }
+    else
+    {
+        sb_error.SetErrorString("invalid platform");
+    }
+    return sb_error;
+    
+}
+