1 //===-- SBPlatform.cpp ------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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/Host/File.h"
16 #include "lldb/Target/Platform.h"
17 #include "lldb/Target/Target.h"
18 #include "lldb/Utility/ArchSpec.h"
19 #include "lldb/Utility/Args.h"
20 #include "lldb/Utility/Status.h"
22 #include "llvm/Support/FileSystem.h"
27 using namespace lldb_private;
29 //----------------------------------------------------------------------
30 // PlatformConnectOptions
31 //----------------------------------------------------------------------
32 struct PlatformConnectOptions {
33 PlatformConnectOptions(const char *url = NULL)
34 : m_url(), m_rsync_options(), m_rsync_remote_path_prefix(),
35 m_rsync_enabled(false), m_rsync_omit_hostname_from_remote_path(false),
36 m_local_cache_directory() {
41 ~PlatformConnectOptions() {}
44 std::string m_rsync_options;
45 std::string m_rsync_remote_path_prefix;
47 bool m_rsync_omit_hostname_from_remote_path;
48 ConstString m_local_cache_directory;
51 //----------------------------------------------------------------------
52 // PlatformShellCommand
53 //----------------------------------------------------------------------
54 struct PlatformShellCommand {
55 PlatformShellCommand(const char *shell_command = NULL)
56 : m_command(), m_working_dir(), m_status(0), m_signo(0) {
57 if (shell_command && shell_command[0])
58 m_command = shell_command;
61 ~PlatformShellCommand() {}
63 std::string m_command;
64 std::string m_working_dir;
68 Timeout<std::ratio<1>> m_timeout = llvm::None;
70 //----------------------------------------------------------------------
71 // SBPlatformConnectOptions
72 //----------------------------------------------------------------------
73 SBPlatformConnectOptions::SBPlatformConnectOptions(const char *url)
74 : m_opaque_ptr(new PlatformConnectOptions(url)) {}
76 SBPlatformConnectOptions::SBPlatformConnectOptions(
77 const SBPlatformConnectOptions &rhs)
78 : m_opaque_ptr(new PlatformConnectOptions()) {
79 *m_opaque_ptr = *rhs.m_opaque_ptr;
82 SBPlatformConnectOptions::~SBPlatformConnectOptions() { delete m_opaque_ptr; }
84 void SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs) {
85 *m_opaque_ptr = *rhs.m_opaque_ptr;
88 const char *SBPlatformConnectOptions::GetURL() {
89 if (m_opaque_ptr->m_url.empty())
91 return m_opaque_ptr->m_url.c_str();
94 void SBPlatformConnectOptions::SetURL(const char *url) {
96 m_opaque_ptr->m_url = url;
98 m_opaque_ptr->m_url.clear();
101 bool SBPlatformConnectOptions::GetRsyncEnabled() {
102 return m_opaque_ptr->m_rsync_enabled;
105 void SBPlatformConnectOptions::EnableRsync(
106 const char *options, const char *remote_path_prefix,
107 bool omit_hostname_from_remote_path) {
108 m_opaque_ptr->m_rsync_enabled = true;
109 m_opaque_ptr->m_rsync_omit_hostname_from_remote_path =
110 omit_hostname_from_remote_path;
111 if (remote_path_prefix && remote_path_prefix[0])
112 m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
114 m_opaque_ptr->m_rsync_remote_path_prefix.clear();
116 if (options && options[0])
117 m_opaque_ptr->m_rsync_options = options;
119 m_opaque_ptr->m_rsync_options.clear();
122 void SBPlatformConnectOptions::DisableRsync() {
123 m_opaque_ptr->m_rsync_enabled = false;
126 const char *SBPlatformConnectOptions::GetLocalCacheDirectory() {
127 return m_opaque_ptr->m_local_cache_directory.GetCString();
130 void SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path) {
132 m_opaque_ptr->m_local_cache_directory.SetCString(path);
134 m_opaque_ptr->m_local_cache_directory = ConstString();
137 //----------------------------------------------------------------------
138 // SBPlatformShellCommand
139 //----------------------------------------------------------------------
140 SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_command)
141 : m_opaque_ptr(new PlatformShellCommand(shell_command)) {}
143 SBPlatformShellCommand::SBPlatformShellCommand(
144 const SBPlatformShellCommand &rhs)
145 : m_opaque_ptr(new PlatformShellCommand()) {
146 *m_opaque_ptr = *rhs.m_opaque_ptr;
149 SBPlatformShellCommand::~SBPlatformShellCommand() { delete m_opaque_ptr; }
151 void SBPlatformShellCommand::Clear() {
152 m_opaque_ptr->m_output = std::string();
153 m_opaque_ptr->m_status = 0;
154 m_opaque_ptr->m_signo = 0;
157 const char *SBPlatformShellCommand::GetCommand() {
158 if (m_opaque_ptr->m_command.empty())
160 return m_opaque_ptr->m_command.c_str();
163 void SBPlatformShellCommand::SetCommand(const char *shell_command) {
164 if (shell_command && shell_command[0])
165 m_opaque_ptr->m_command = shell_command;
167 m_opaque_ptr->m_command.clear();
170 const char *SBPlatformShellCommand::GetWorkingDirectory() {
171 if (m_opaque_ptr->m_working_dir.empty())
173 return m_opaque_ptr->m_working_dir.c_str();
176 void SBPlatformShellCommand::SetWorkingDirectory(const char *path) {
178 m_opaque_ptr->m_working_dir = path;
180 m_opaque_ptr->m_working_dir.clear();
183 uint32_t SBPlatformShellCommand::GetTimeoutSeconds() {
184 if (m_opaque_ptr->m_timeout)
185 return m_opaque_ptr->m_timeout->count();
189 void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) {
190 if (sec == UINT32_MAX)
191 m_opaque_ptr->m_timeout = llvm::None;
193 m_opaque_ptr->m_timeout = std::chrono::seconds(sec);
196 int SBPlatformShellCommand::GetSignal() { return m_opaque_ptr->m_signo; }
198 int SBPlatformShellCommand::GetStatus() { return m_opaque_ptr->m_status; }
200 const char *SBPlatformShellCommand::GetOutput() {
201 if (m_opaque_ptr->m_output.empty())
203 return m_opaque_ptr->m_output.c_str();
206 //----------------------------------------------------------------------
208 //----------------------------------------------------------------------
209 SBPlatform::SBPlatform() : m_opaque_sp() {}
211 SBPlatform::SBPlatform(const char *platform_name) : m_opaque_sp() {
213 if (platform_name && platform_name[0])
214 m_opaque_sp = Platform::Create(ConstString(platform_name), error);
217 SBPlatform::~SBPlatform() {}
219 bool SBPlatform::IsValid() const { return m_opaque_sp.get() != NULL; }
221 void SBPlatform::Clear() { m_opaque_sp.reset(); }
223 const char *SBPlatform::GetName() {
224 PlatformSP platform_sp(GetSP());
226 return platform_sp->GetName().GetCString();
230 lldb::PlatformSP SBPlatform::GetSP() const { return m_opaque_sp; }
232 void SBPlatform::SetSP(const lldb::PlatformSP &platform_sp) {
233 m_opaque_sp = platform_sp;
236 const char *SBPlatform::GetWorkingDirectory() {
237 PlatformSP platform_sp(GetSP());
239 return platform_sp->GetWorkingDirectory().GetCString();
243 bool SBPlatform::SetWorkingDirectory(const char *path) {
244 PlatformSP platform_sp(GetSP());
247 platform_sp->SetWorkingDirectory(FileSpec{path, false});
249 platform_sp->SetWorkingDirectory(FileSpec{});
255 SBError SBPlatform::ConnectRemote(SBPlatformConnectOptions &connect_options) {
257 PlatformSP platform_sp(GetSP());
258 if (platform_sp && connect_options.GetURL()) {
261 llvm::StringRef::withNullAsEmpty(connect_options.GetURL()));
262 sb_error.ref() = platform_sp->ConnectRemote(args);
264 sb_error.SetErrorString("invalid platform");
269 void SBPlatform::DisconnectRemote() {
270 PlatformSP platform_sp(GetSP());
272 platform_sp->DisconnectRemote();
275 bool SBPlatform::IsConnected() {
276 PlatformSP platform_sp(GetSP());
278 return platform_sp->IsConnected();
282 const char *SBPlatform::GetTriple() {
283 PlatformSP platform_sp(GetSP());
285 ArchSpec arch(platform_sp->GetSystemArchitecture());
286 if (arch.IsValid()) {
287 // Const-ify the string so we don't need to worry about the lifetime of
289 return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
295 const char *SBPlatform::GetOSBuild() {
296 PlatformSP platform_sp(GetSP());
299 if (platform_sp->GetOSBuildString(s)) {
301 // Const-ify the string so we don't need to worry about the lifetime of
303 return ConstString(s.c_str()).GetCString();
310 const char *SBPlatform::GetOSDescription() {
311 PlatformSP platform_sp(GetSP());
314 if (platform_sp->GetOSKernelDescription(s)) {
316 // Const-ify the string so we don't need to worry about the lifetime of
318 return ConstString(s.c_str()).GetCString();
325 const char *SBPlatform::GetHostname() {
326 PlatformSP platform_sp(GetSP());
328 return platform_sp->GetHostname();
332 uint32_t SBPlatform::GetOSMajorVersion() {
333 llvm::VersionTuple version;
334 if (PlatformSP platform_sp = GetSP())
335 version = platform_sp->GetOSVersion();
336 return version.empty() ? UINT32_MAX : version.getMajor();
339 uint32_t SBPlatform::GetOSMinorVersion() {
340 llvm::VersionTuple version;
341 if (PlatformSP platform_sp = GetSP())
342 version = platform_sp->GetOSVersion();
343 return version.getMinor().getValueOr(UINT32_MAX);
346 uint32_t SBPlatform::GetOSUpdateVersion() {
347 llvm::VersionTuple version;
348 if (PlatformSP platform_sp = GetSP())
349 version = platform_sp->GetOSVersion();
350 return version.getSubminor().getValueOr(UINT32_MAX);
353 SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) {
355 PlatformSP platform_sp(GetSP());
357 sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());
359 sb_error.SetErrorString("invalid platform");
364 SBError SBPlatform::Put(SBFileSpec &src, SBFileSpec &dst) {
365 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
367 uint32_t permissions = src.ref().GetPermissions();
368 if (permissions == 0) {
369 if (llvm::sys::fs::is_directory(src.ref().GetPath()))
370 permissions = eFilePermissionsDirectoryDefault;
372 permissions = eFilePermissionsFileDefault;
375 return platform_sp->PutFile(src.ref(), dst.ref(), permissions);
379 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'",
380 src.ref().GetPath().c_str());
385 SBError SBPlatform::Install(SBFileSpec &src, SBFileSpec &dst) {
386 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
388 return platform_sp->Install(src.ref(), dst.ref());
391 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'",
392 src.ref().GetPath().c_str());
397 SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) {
398 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
399 const char *command = shell_command.GetCommand();
401 return Status("invalid shell command (empty)");
403 const char *working_dir = shell_command.GetWorkingDirectory();
404 if (working_dir == NULL) {
405 working_dir = platform_sp->GetWorkingDirectory().GetCString();
407 shell_command.SetWorkingDirectory(working_dir);
409 return platform_sp->RunShellCommand(command, FileSpec{working_dir, false},
410 &shell_command.m_opaque_ptr->m_status,
411 &shell_command.m_opaque_ptr->m_signo,
412 &shell_command.m_opaque_ptr->m_output,
413 shell_command.m_opaque_ptr->m_timeout);
417 SBError SBPlatform::Launch(SBLaunchInfo &launch_info) {
418 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
419 ProcessLaunchInfo info = launch_info.ref();
420 Status error = platform_sp->LaunchProcess(info);
421 launch_info.set_ref(info);
426 SBError SBPlatform::Kill(const lldb::pid_t pid) {
427 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
428 return platform_sp->KillProcess(pid);
432 SBError SBPlatform::ExecuteConnected(
433 const std::function<Status(const lldb::PlatformSP &)> &func) {
435 const auto platform_sp(GetSP());
437 if (platform_sp->IsConnected())
438 sb_error.ref() = func(platform_sp);
440 sb_error.SetErrorString("not connected");
442 sb_error.SetErrorString("invalid platform");
447 SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) {
449 PlatformSP platform_sp(GetSP());
452 platform_sp->MakeDirectory(FileSpec{path, false}, file_permissions);
454 sb_error.SetErrorString("invalid platform");
459 uint32_t SBPlatform::GetFilePermissions(const char *path) {
460 PlatformSP platform_sp(GetSP());
462 uint32_t file_permissions = 0;
463 platform_sp->GetFilePermissions(FileSpec{path, false}, file_permissions);
464 return file_permissions;
469 SBError SBPlatform::SetFilePermissions(const char *path,
470 uint32_t file_permissions) {
472 PlatformSP platform_sp(GetSP());
474 sb_error.ref() = platform_sp->SetFilePermissions(FileSpec{path, false},
477 sb_error.SetErrorString("invalid platform");
482 SBUnixSignals SBPlatform::GetUnixSignals() const {
483 if (auto platform_sp = GetSP())
484 return SBUnixSignals{platform_sp};