[Lldb-commits] [lldb] r154677 - in /lldb/branches/lldb-platform-work: include/lldb/Host/FileSpec.h include/lldb/Target/Platform.h source/Commands/CommandObjectPlatform.cpp source/Host/common/FileSpec.cpp source/Target/Platform.cpp

Enrico Granata egranata at apple.com
Fri Apr 13 10:58:02 PDT 2012


Author: enrico
Date: Fri Apr 13 12:58:01 2012
New Revision: 154677

URL: http://llvm.org/viewvc/llvm-project?rev=154677&view=rev
Log:
Providing a basic implementation of a platform target-install command that correctly copies bundles and individual executable files from local to remote. Advanced features like correct handling of dependencies and interaction with dyld are still missing and will take additional work

Modified:
    lldb/branches/lldb-platform-work/include/lldb/Host/FileSpec.h
    lldb/branches/lldb-platform-work/include/lldb/Target/Platform.h
    lldb/branches/lldb-platform-work/source/Commands/CommandObjectPlatform.cpp
    lldb/branches/lldb-platform-work/source/Host/common/FileSpec.cpp
    lldb/branches/lldb-platform-work/source/Target/Platform.cpp

Modified: lldb/branches/lldb-platform-work/include/lldb/Host/FileSpec.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/include/lldb/Host/FileSpec.h?rev=154677&r1=154676&r2=154677&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/include/lldb/Host/FileSpec.h (original)
+++ lldb/branches/lldb-platform-work/include/lldb/Host/FileSpec.h Fri Apr 13 12:58:01 2012
@@ -563,6 +563,15 @@
     static size_t
     Resolve (const char *src_path, char *dst_path, size_t dst_len);
 
+    FileSpec
+    AppendPathComponent (const char *new_path, bool resolve = false);
+    
+    FileSpec
+    RemoveLastPathComponent (bool resolve = false);
+    
+    const char*
+    GetLastPathComponent () const;
+    
     //------------------------------------------------------------------
     /// Resolves the user name at the beginning of \a src_path, and writes the output
     /// to \a dst_path.  Note, \a src_path can contain other path components after the

Modified: lldb/branches/lldb-platform-work/include/lldb/Target/Platform.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/include/lldb/Target/Platform.h?rev=154677&r1=154676&r2=154677&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/include/lldb/Target/Platform.h (original)
+++ lldb/branches/lldb-platform-work/include/lldb/Target/Platform.h Fri Apr 13 12:58:01 2012
@@ -463,6 +463,12 @@
             return UINT32_MAX;
         }
         
+        // this need not be virtual: the core behavior is in
+        // MakeDirectory(std::string,mode_t)
+        uint32_t
+        MakeDirectory (const FileSpec &spec,
+                       mode_t mode);
+        
         virtual lldb::user_id_t
         OpenFile (const FileSpec& file_spec,
                   uint32_t flags,

Modified: lldb/branches/lldb-platform-work/source/Commands/CommandObjectPlatform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Commands/CommandObjectPlatform.cpp?rev=154677&r1=154676&r2=154677&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Commands/CommandObjectPlatform.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Commands/CommandObjectPlatform.cpp Fri Apr 13 12:58:01 2012
@@ -27,6 +27,35 @@
 using namespace lldb;
 using namespace lldb_private;
 
+static mode_t
+ParsePermissionString(const char* permissions)
+{
+    mode_t retval = 0;
+    if (strlen(permissions) != 9)
+        return retval;
+    bool user_r,user_w,user_x,
+    group_r,group_w,group_x,
+    world_r,world_w,world_x;
+    
+    user_r = (permissions[0] == 'r');
+    user_w = (permissions[1] == 'w');
+    user_x = (permissions[2] == 'x');
+    
+    group_r = (permissions[3] == 'r');
+    group_w = (permissions[4] == 'w');
+    group_x = (permissions[5] == 'x');
+    
+    world_r = (permissions[6] == 'r');
+    world_w = (permissions[7] == 'w');
+    world_x = (permissions[8] == 'x');
+    
+    mode_t user,group,world;
+    user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
+    group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
+    world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
+    
+    return user | group | world;
+}
 
 //----------------------------------------------------------------------
 // "platform select <platform-name>"
@@ -1493,6 +1522,86 @@
     DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess);
 };
 
+struct RecurseCopyBaton
+{
+    const std::string& destination;
+    const PlatformSP& platform_sp;
+    Error error;
+};
+
+
+static FileSpec::EnumerateDirectoryResult
+RecurseCopy_Callback (void *baton,
+                      FileSpec::FileType file_type,
+                      const FileSpec &spec)
+{
+    RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton;
+    switch (file_type)
+    {
+        case FileSpec::eFileTypePipe:
+        case FileSpec::eFileTypeSocket:
+            // we have no way to copy pipes and sockets - ignore them and continue
+            return FileSpec::eEnumerateDirectoryResultNext;
+            break;
+            
+        case FileSpec::eFileTypeSymbolicLink:
+            // what to do for symlinks?
+            return FileSpec::eEnumerateDirectoryResultNext;
+            break;
+            
+        case FileSpec::eFileTypeDirectory:
+        {
+            // make the new directory and get in there
+            FileSpec new_directory(rc_baton->destination.c_str(),false);
+            new_directory = new_directory.AppendPathComponent(spec.GetLastPathComponent());
+            uint32_t errcode = rc_baton->platform_sp->MakeDirectory(new_directory, 0777);
+            std::string new_directory_path;
+            new_directory.GetPath(new_directory_path);
+            if (errcode != 0)
+            {
+                rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end",new_directory_path.c_str());
+                return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+            }
+            
+            // now recurse
+            std::string local_path;
+            spec.GetPath(local_path);
+            RecurseCopyBaton rc_baton2 = { new_directory_path, rc_baton->platform_sp, Error() };
+            FileSpec::EnumerateDirectory(local_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2);
+            if (rc_baton2.error.Fail())
+            {
+                rc_baton->error.SetErrorString(rc_baton2.error.AsCString());
+                return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+            }
+            return FileSpec::eEnumerateDirectoryResultNext;
+        }
+            break;
+            
+        case FileSpec::eFileTypeRegular:
+        {
+            // copy the file and keep going
+            std::string dest(rc_baton->destination);
+            dest.append(spec.GetFilename().GetCString());
+            Error err = rc_baton->platform_sp->PutFile(spec, FileSpec(dest.c_str(), false));
+            if (err.Fail())
+            {
+                rc_baton->error.SetErrorString(err.AsCString());
+                return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+            }
+            return FileSpec::eEnumerateDirectoryResultNext;
+        }
+            break;
+            
+        case FileSpec::eFileTypeInvalid:
+        case FileSpec::eFileTypeOther:
+        case FileSpec::eFileTypeUnknown:
+        default:
+            rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s/%s", spec.GetDirectory().GetCString(), spec.GetFilename().GetCString());
+            return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+            break;
+    }
+}
+
 //----------------------------------------------------------------------
 // "platform install" - install a target to a remote end
 //----------------------------------------------------------------------
@@ -1524,10 +1633,80 @@
         }
         std::string local_thing(args.GetArgumentAtIndex(0));
         std::string remote_sandbox(args.GetArgumentAtIndex(1));
-        result.AppendWarningWithFormat("error in installing %s into %s", local_thing.c_str(), remote_sandbox.c_str());
-        result.AppendError("platform target-install is unimplemented - use put-file and mkdir as required");
-        result.SetStatus(eReturnStatusFailed);
-        return false;
+        FileSpec source(local_thing.c_str(), true);
+        if (source.Exists() == false)
+        {
+            result.AppendError("source location does not exist or is not accessible");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+        if (!platform_sp)
+        {
+            result.AppendError ("no platform currently selected");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        FileSpec::FileType source_type(source.GetFileType());
+        if (source_type == FileSpec::eFileTypeDirectory)
+        {
+            FileSpec remote_folder(remote_sandbox.c_str(), false);
+            remote_folder.AppendPathComponent(source.GetLastPathComponent());
+            // TODO: default permissions are bad
+            uint32_t errcode = platform_sp->MakeDirectory(remote_folder, 0777);
+            if (errcode != 0)
+            {
+                result.AppendError("unable to setup target directory on remote end");
+                result.SetStatus(eReturnStatusSuccessFinishNoResult);
+                return result.Succeeded();
+            }
+            // now recurse
+            std::string remote_folder_path;
+            remote_folder.GetPath(remote_folder_path);
+            Error err = RecurseCopy(source,remote_folder_path,platform_sp);
+            if (err.Fail())
+            {
+                result.AppendError(err.AsCString());
+                result.SetStatus(eReturnStatusFailed);
+            }
+            else
+                result.SetStatus(eReturnStatusSuccessFinishResult);
+            return result.Succeeded();
+        }
+        else if (source_type == FileSpec::eFileTypeRegular)
+        {
+            // just a plain file - push it to remote and be done
+            remote_sandbox.append(source.GetFilename().GetCString());
+            FileSpec destination(remote_sandbox.c_str(),false);
+            Error err = platform_sp->PutFile(source, destination);
+            if (err.Success())
+                result.SetStatus(eReturnStatusSuccessFinishResult);
+            else
+            {
+                result.AppendError(err.AsCString());
+                result.SetStatus(eReturnStatusFailed);
+            }
+            return result.Succeeded();
+        }
+        else
+        {
+            result.AppendError("source is not a known type of file");
+            result.SetStatus(eReturnStatusFailed);
+            return result.Succeeded();
+        }
+    }
+private:
+    
+    Error
+    RecurseCopy (const FileSpec& source,
+                 const std::string& destination,
+                 const PlatformSP& platform_sp)
+    {
+        std::string source_path;
+        source.GetPath(source_path);
+        RecurseCopyBaton baton = { destination, platform_sp, Error() };
+        FileSpec::EnumerateDirectory(source_path.c_str(), true, true, true, RecurseCopy_Callback, &baton);
+        return baton.error;
     }
 };
 

Modified: lldb/branches/lldb-platform-work/source/Host/common/FileSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/common/FileSpec.cpp?rev=154677&r1=154676&r2=154677&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/common/FileSpec.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/common/FileSpec.cpp Fri Apr 13 12:58:01 2012
@@ -24,11 +24,11 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
 
+#include "lldb/Core/StreamString.h"
 #include "lldb/Host/File.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/DataBufferMemoryMap.h"
-#include "lldb/Core/Stream.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Utility/CleanUp.h"
 
@@ -978,3 +978,78 @@
     return eEnumerateDirectoryResultNext;    
 }
 
+FileSpec
+FileSpec::AppendPathComponent (const char *new_path, bool resolve)
+{
+    if (m_filename.IsEmpty() && m_directory.IsEmpty())
+        return FileSpec(new_path,resolve);
+    StreamString stream;
+    if (m_filename.IsEmpty())
+        stream.Printf("%s/%s",m_directory.GetCString(),new_path);
+    else if (m_directory.IsEmpty())
+        stream.Printf("%s/%s",m_filename.GetCString(),new_path);
+    else
+        stream.Printf("%s/%s/%s",m_directory.GetCString(), m_filename.GetCString(),new_path);
+    return FileSpec(stream.GetData(),resolve);
+}
+
+FileSpec
+FileSpec::RemoveLastPathComponent (bool resolve)
+{
+    if (m_filename.IsEmpty() && m_directory.IsEmpty())
+        return FileSpec("",resolve);
+    if (m_directory.IsEmpty())
+        return FileSpec("",resolve);
+    if (m_filename.IsEmpty())
+    {
+        const char* dir_cstr = m_directory.GetCString();
+        const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+        
+        // check for obvious cases before doing the full thing
+        if (!last_slash_ptr)
+            return FileSpec("",resolve);
+        if (last_slash_ptr == dir_cstr)
+            return FileSpec("/",resolve);
+        
+        size_t last_slash_pos = last_slash_ptr - dir_cstr+1;
+        ConstString new_path(dir_cstr,last_slash_pos);
+        return FileSpec(new_path.GetCString(),resolve);
+    }
+    else
+        return FileSpec(m_directory.GetCString(),resolve);
+}
+
+const char*
+FileSpec::GetLastPathComponent () const
+{
+    if (m_filename.IsEmpty() && m_directory.IsEmpty())
+        return NULL;
+    if (m_filename.IsEmpty())
+    {
+        const char* dir_cstr = m_directory.GetCString();
+        const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
+        if (last_slash_ptr == NULL)
+            return m_directory.GetCString();
+        if (last_slash_ptr == dir_cstr)
+        {
+            if (last_slash_ptr[1] == 0)
+                return last_slash_ptr;
+            else
+                return last_slash_ptr+1;
+        }
+        if (last_slash_ptr[1] != 0)
+            return last_slash_ptr+1;
+        const char* penultimate_slash_ptr = last_slash_ptr;
+        while (*penultimate_slash_ptr)
+        {
+            --penultimate_slash_ptr;
+            if (penultimate_slash_ptr == dir_cstr)
+                break;
+            if (*penultimate_slash_ptr == '/')
+                break;
+        }
+        ConstString new_path(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr);
+        return new_path.AsCString();
+    }
+    return m_filename.GetCString();
+}

Modified: lldb/branches/lldb-platform-work/source/Target/Platform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Target/Platform.cpp?rev=154677&r1=154676&r2=154677&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Target/Platform.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Target/Platform.cpp Fri Apr 13 12:58:01 2012
@@ -673,7 +673,15 @@
             return true;
     }
     return false;
-    
+}
+
+uint32_t
+Platform::MakeDirectory (const FileSpec &spec,
+                         mode_t mode)
+{
+    std::string path;
+    spec.GetPath(path);
+    return this->MakeDirectory(path,mode);
 }
 
 Error
@@ -694,4 +702,3 @@
     return error;
 }
 
-





More information about the lldb-commits mailing list