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