SBPlatform.cpp revision 296417
1//===-- SBPlatform.cpp ------------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/API/SBPlatform.h"
11#include "lldb/API/SBError.h"
12#include "lldb/API/SBFileSpec.h"
13#include "lldb/API/SBLaunchInfo.h"
14#include "lldb/API/SBUnixSignals.h"
15#include "lldb/Core/ArchSpec.h"
16#include "lldb/Core/Error.h"
17#include "lldb/Host/File.h"
18#include "lldb/Interpreter/Args.h"
19#include "lldb/Target/Target.h"
20#include "lldb/Target/Platform.h"
21
22#include <functional>
23
24using namespace lldb;
25using namespace lldb_private;
26
27//----------------------------------------------------------------------
28// PlatformConnectOptions
29//----------------------------------------------------------------------
30struct PlatformConnectOptions {
31    PlatformConnectOptions(const char *url = NULL) :
32        m_url(),
33        m_rsync_options(),
34        m_rsync_remote_path_prefix(),
35        m_rsync_enabled(false),
36        m_rsync_omit_hostname_from_remote_path(false),
37        m_local_cache_directory ()
38    {
39        if (url && url[0])
40            m_url = url;
41    }
42
43    ~PlatformConnectOptions()
44    {
45    }
46
47    std::string m_url;
48    std::string m_rsync_options;
49    std::string m_rsync_remote_path_prefix;
50    bool m_rsync_enabled;
51    bool m_rsync_omit_hostname_from_remote_path;
52    ConstString m_local_cache_directory;
53};
54
55//----------------------------------------------------------------------
56// PlatformShellCommand
57//----------------------------------------------------------------------
58struct PlatformShellCommand {
59    PlatformShellCommand(const char *shell_command = NULL) :
60        m_command(),
61        m_working_dir(),
62        m_status(0),
63        m_signo(0),
64        m_timeout_sec(UINT32_MAX)
65    {
66        if (shell_command && shell_command[0])
67            m_command = shell_command;
68    }
69
70    ~PlatformShellCommand()
71    {
72    }
73
74    std::string m_command;
75    std::string m_working_dir;
76    std::string m_output;
77    int m_status;
78    int m_signo;
79    uint32_t m_timeout_sec;
80};
81//----------------------------------------------------------------------
82// SBPlatformConnectOptions
83//----------------------------------------------------------------------
84SBPlatformConnectOptions::SBPlatformConnectOptions (const char *url) :
85    m_opaque_ptr(new PlatformConnectOptions(url))
86{
87
88}
89
90SBPlatformConnectOptions::SBPlatformConnectOptions(const SBPlatformConnectOptions &rhs) :
91    m_opaque_ptr(new PlatformConnectOptions())
92{
93    *m_opaque_ptr = *rhs.m_opaque_ptr;
94}
95
96SBPlatformConnectOptions::~SBPlatformConnectOptions ()
97{
98    delete m_opaque_ptr;
99}
100
101void
102SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs)
103{
104    *m_opaque_ptr = *rhs.m_opaque_ptr;
105}
106
107const char *
108SBPlatformConnectOptions::GetURL()
109{
110    if (m_opaque_ptr->m_url.empty())
111        return NULL;
112    return m_opaque_ptr->m_url.c_str();
113}
114
115void
116SBPlatformConnectOptions::SetURL(const char *url)
117{
118    if (url && url[0])
119        m_opaque_ptr->m_url = url;
120    else
121        m_opaque_ptr->m_url.clear();
122}
123
124bool
125SBPlatformConnectOptions::GetRsyncEnabled()
126{
127    return m_opaque_ptr->m_rsync_enabled;
128}
129
130void
131SBPlatformConnectOptions::EnableRsync (const char *options,
132                                       const char *remote_path_prefix,
133                                       bool omit_hostname_from_remote_path)
134{
135    m_opaque_ptr->m_rsync_enabled = true;
136    m_opaque_ptr->m_rsync_omit_hostname_from_remote_path = omit_hostname_from_remote_path;
137    if (remote_path_prefix && remote_path_prefix[0])
138        m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
139    else
140        m_opaque_ptr->m_rsync_remote_path_prefix.clear();
141
142    if (options && options[0])
143        m_opaque_ptr->m_rsync_options = options;
144    else
145        m_opaque_ptr->m_rsync_options.clear();
146
147}
148
149void
150SBPlatformConnectOptions::DisableRsync ()
151{
152    m_opaque_ptr->m_rsync_enabled = false;
153}
154
155const char *
156SBPlatformConnectOptions::GetLocalCacheDirectory()
157{
158    return m_opaque_ptr->m_local_cache_directory.GetCString();
159}
160
161void
162SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path)
163{
164    if (path && path[0])
165        m_opaque_ptr->m_local_cache_directory.SetCString(path);
166    else
167        m_opaque_ptr->m_local_cache_directory = ConstString();
168}
169
170//----------------------------------------------------------------------
171// SBPlatformShellCommand
172//----------------------------------------------------------------------
173SBPlatformShellCommand::SBPlatformShellCommand (const char *shell_command) :
174    m_opaque_ptr(new PlatformShellCommand(shell_command))
175{
176}
177
178SBPlatformShellCommand::SBPlatformShellCommand (const SBPlatformShellCommand &rhs) :
179    m_opaque_ptr(new PlatformShellCommand())
180{
181    *m_opaque_ptr = *rhs.m_opaque_ptr;
182}
183
184SBPlatformShellCommand::~SBPlatformShellCommand()
185{
186    delete m_opaque_ptr;
187}
188
189void
190SBPlatformShellCommand::Clear()
191{
192    m_opaque_ptr->m_output = std::string();
193    m_opaque_ptr->m_status = 0;
194    m_opaque_ptr->m_signo = 0;
195}
196
197const char *
198SBPlatformShellCommand::GetCommand()
199{
200    if (m_opaque_ptr->m_command.empty())
201        return NULL;
202    return m_opaque_ptr->m_command.c_str();
203}
204
205void
206SBPlatformShellCommand::SetCommand(const char *shell_command)
207{
208    if (shell_command && shell_command[0])
209        m_opaque_ptr->m_command = shell_command;
210    else
211        m_opaque_ptr->m_command.clear();
212}
213
214const char *
215SBPlatformShellCommand::GetWorkingDirectory ()
216{
217    if (m_opaque_ptr->m_working_dir.empty())
218        return NULL;
219    return m_opaque_ptr->m_working_dir.c_str();
220}
221
222void
223SBPlatformShellCommand::SetWorkingDirectory (const char *path)
224{
225    if (path && path[0])
226        m_opaque_ptr->m_working_dir = path;
227    else
228        m_opaque_ptr->m_working_dir.clear();
229}
230
231uint32_t
232SBPlatformShellCommand::GetTimeoutSeconds ()
233{
234    return m_opaque_ptr->m_timeout_sec;
235}
236
237void
238SBPlatformShellCommand::SetTimeoutSeconds (uint32_t sec)
239{
240    m_opaque_ptr->m_timeout_sec = sec;
241}
242
243int
244SBPlatformShellCommand::GetSignal ()
245{
246    return m_opaque_ptr->m_signo;
247}
248
249int
250SBPlatformShellCommand::GetStatus ()
251{
252    return m_opaque_ptr->m_status;
253}
254
255const char *
256SBPlatformShellCommand::GetOutput ()
257{
258    if (m_opaque_ptr->m_output.empty())
259        return NULL;
260    return m_opaque_ptr->m_output.c_str();
261}
262
263//----------------------------------------------------------------------
264// SBPlatform
265//----------------------------------------------------------------------
266SBPlatform::SBPlatform () :
267    m_opaque_sp ()
268{
269
270}
271
272SBPlatform::SBPlatform (const char *platform_name) :
273    m_opaque_sp ()
274{
275    Error error;
276    if (platform_name && platform_name[0])
277        m_opaque_sp = Platform::Create (ConstString(platform_name), error);
278}
279
280SBPlatform::~SBPlatform()
281{
282}
283
284bool
285SBPlatform::IsValid () const
286{
287    return m_opaque_sp.get() != NULL;
288}
289
290void
291SBPlatform::Clear ()
292{
293    m_opaque_sp.reset();
294}
295
296const char *
297SBPlatform::GetName ()
298{
299    PlatformSP platform_sp(GetSP());
300    if (platform_sp)
301        return platform_sp->GetName().GetCString();
302    return NULL;
303}
304
305lldb::PlatformSP
306SBPlatform::GetSP () const
307{
308    return m_opaque_sp;
309}
310
311void
312SBPlatform::SetSP (const lldb::PlatformSP& platform_sp)
313{
314    m_opaque_sp = platform_sp;
315}
316
317const char *
318SBPlatform::GetWorkingDirectory()
319{
320    PlatformSP platform_sp(GetSP());
321    if (platform_sp)
322        return platform_sp->GetWorkingDirectory().GetCString();
323    return NULL;
324}
325
326bool
327SBPlatform::SetWorkingDirectory(const char *path)
328{
329    PlatformSP platform_sp(GetSP());
330    if (platform_sp)
331    {
332        if (path)
333            platform_sp->SetWorkingDirectory(FileSpec{path, false});
334        else
335            platform_sp->SetWorkingDirectory(FileSpec{});
336        return true;
337    }
338    return false;
339}
340
341SBError
342SBPlatform::ConnectRemote (SBPlatformConnectOptions &connect_options)
343{
344    SBError sb_error;
345    PlatformSP platform_sp(GetSP());
346    if (platform_sp && connect_options.GetURL())
347    {
348        Args args;
349        args.AppendArgument(connect_options.GetURL());
350        sb_error.ref() = platform_sp->ConnectRemote(args);
351    }
352    else
353    {
354        sb_error.SetErrorString("invalid platform");
355    }
356    return sb_error;
357}
358
359void
360SBPlatform::DisconnectRemote ()
361{
362    PlatformSP platform_sp(GetSP());
363    if (platform_sp)
364        platform_sp->DisconnectRemote();
365}
366
367bool
368SBPlatform::IsConnected()
369{
370    PlatformSP platform_sp(GetSP());
371    if (platform_sp)
372        platform_sp->IsConnected();
373    return false;
374}
375
376const char *
377SBPlatform::GetTriple()
378{
379    PlatformSP platform_sp(GetSP());
380    if (platform_sp)
381    {
382        ArchSpec arch(platform_sp->GetSystemArchitecture());
383        if (arch.IsValid())
384        {
385            // Const-ify the string so we don't need to worry about the lifetime of the string
386            return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
387        }
388    }
389    return NULL;
390}
391
392const char *
393SBPlatform::GetOSBuild()
394{
395    PlatformSP platform_sp(GetSP());
396    if (platform_sp)
397    {
398        std::string s;
399        if (platform_sp->GetOSBuildString(s))
400        {
401            if (!s.empty())
402            {
403                // Const-ify the string so we don't need to worry about the lifetime of the string
404                return ConstString(s.c_str()).GetCString();
405            }
406        }
407    }
408    return NULL;
409}
410
411const char *
412SBPlatform::GetOSDescription()
413{
414    PlatformSP platform_sp(GetSP());
415    if (platform_sp)
416    {
417        std::string s;
418        if (platform_sp->GetOSKernelDescription(s))
419        {
420            if (!s.empty())
421            {
422                // Const-ify the string so we don't need to worry about the lifetime of the string
423                return ConstString(s.c_str()).GetCString();
424            }
425        }
426    }
427    return NULL;
428}
429
430const char *
431SBPlatform::GetHostname ()
432{
433    PlatformSP platform_sp(GetSP());
434    if (platform_sp)
435        return platform_sp->GetHostname();
436    return NULL;
437}
438
439uint32_t
440SBPlatform::GetOSMajorVersion ()
441{
442    uint32_t major, minor, update;
443    PlatformSP platform_sp(GetSP());
444    if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
445        return major;
446    return UINT32_MAX;
447
448}
449
450uint32_t
451SBPlatform::GetOSMinorVersion ()
452{
453    uint32_t major, minor, update;
454    PlatformSP platform_sp(GetSP());
455    if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
456        return minor;
457    return UINT32_MAX;
458}
459
460uint32_t
461SBPlatform::GetOSUpdateVersion ()
462{
463    uint32_t major, minor, update;
464    PlatformSP platform_sp(GetSP());
465    if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
466        return update;
467    return UINT32_MAX;
468}
469
470SBError
471SBPlatform::Get (SBFileSpec &src,
472                 SBFileSpec &dst)
473{
474    SBError sb_error;
475    PlatformSP platform_sp(GetSP());
476    if (platform_sp)
477    {
478        sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());
479    }
480    else
481    {
482        sb_error.SetErrorString("invalid platform");
483    }
484    return sb_error;
485}
486
487SBError
488SBPlatform::Put (SBFileSpec &src,
489                 SBFileSpec &dst)
490{
491  return ExecuteConnected(
492      [&](const lldb::PlatformSP& platform_sp)
493      {
494          if (src.Exists())
495          {
496              uint32_t permissions = src.ref().GetPermissions();
497              if (permissions == 0)
498              {
499                  if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory)
500                      permissions = eFilePermissionsDirectoryDefault;
501                  else
502                      permissions = eFilePermissionsFileDefault;
503              }
504
505              return platform_sp->PutFile(src.ref(), dst.ref(), permissions);
506          }
507
508          Error error;
509          error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
510          return error;
511      });
512}
513
514SBError
515SBPlatform::Install (SBFileSpec &src,
516                     SBFileSpec &dst)
517{
518  return ExecuteConnected(
519      [&](const lldb::PlatformSP& platform_sp)
520      {
521          if (src.Exists())
522              return platform_sp->Install(src.ref(), dst.ref());
523
524          Error error;
525          error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
526          return error;
527      });
528}
529
530
531SBError
532SBPlatform::Run (SBPlatformShellCommand &shell_command)
533{
534    return ExecuteConnected(
535        [&](const lldb::PlatformSP& platform_sp)
536        {
537            const char *command = shell_command.GetCommand();
538            if (!command)
539                return Error("invalid shell command (empty)");
540
541            const char *working_dir = shell_command.GetWorkingDirectory();
542            if (working_dir == NULL)
543            {
544                working_dir = platform_sp->GetWorkingDirectory().GetCString();
545                if (working_dir)
546                    shell_command.SetWorkingDirectory(working_dir);
547            }
548            return platform_sp->RunShellCommand(command,
549                                                FileSpec{working_dir, false},
550                                                &shell_command.m_opaque_ptr->m_status,
551                                                &shell_command.m_opaque_ptr->m_signo,
552                                                &shell_command.m_opaque_ptr->m_output,
553                                                shell_command.m_opaque_ptr->m_timeout_sec);
554        });
555}
556
557SBError
558SBPlatform::Launch (SBLaunchInfo &launch_info)
559{
560    return ExecuteConnected(
561        [&](const lldb::PlatformSP& platform_sp)
562        {
563            return platform_sp->LaunchProcess(launch_info.ref());
564        });
565}
566
567SBError
568SBPlatform::Kill (const lldb::pid_t pid)
569{
570    return ExecuteConnected(
571        [&](const lldb::PlatformSP& platform_sp)
572        {
573            return platform_sp->KillProcess(pid);
574        });
575}
576
577SBError
578SBPlatform::ExecuteConnected (const std::function<Error(const lldb::PlatformSP&)>& func)
579{
580    SBError sb_error;
581    const auto platform_sp(GetSP());
582    if (platform_sp)
583    {
584        if (platform_sp->IsConnected())
585            sb_error.ref() = func(platform_sp);
586        else
587            sb_error.SetErrorString("not connected");
588    }
589    else
590        sb_error.SetErrorString("invalid platform");
591
592  return sb_error;
593}
594
595SBError
596SBPlatform::MakeDirectory (const char *path, uint32_t file_permissions)
597{
598    SBError sb_error;
599    PlatformSP platform_sp(GetSP());
600    if (platform_sp)
601    {
602        sb_error.ref() = platform_sp->MakeDirectory(FileSpec{path, false}, file_permissions);
603    }
604    else
605    {
606        sb_error.SetErrorString("invalid platform");
607    }
608    return sb_error;
609}
610
611uint32_t
612SBPlatform::GetFilePermissions (const char *path)
613{
614    PlatformSP platform_sp(GetSP());
615    if (platform_sp)
616    {
617        uint32_t file_permissions = 0;
618        platform_sp->GetFilePermissions(FileSpec{path, false}, file_permissions);
619        return file_permissions;
620    }
621    return 0;
622
623}
624
625SBError
626SBPlatform::SetFilePermissions (const char *path, uint32_t file_permissions)
627{
628    SBError sb_error;
629    PlatformSP platform_sp(GetSP());
630    if (platform_sp)
631    {
632        sb_error.ref() = platform_sp->SetFilePermissions(FileSpec{path, false}, file_permissions);
633    }
634    else
635    {
636        sb_error.SetErrorString("invalid platform");
637    }
638    return sb_error;
639
640}
641
642SBUnixSignals
643SBPlatform::GetUnixSignals() const
644{
645    if (auto platform_sp = GetSP())
646        return SBUnixSignals{platform_sp};
647
648    return {};
649}
650