SBPlatform.cpp revision 344779
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/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" 21 22#include "llvm/Support/FileSystem.h" 23 24#include <functional> 25 26using namespace lldb; 27using namespace lldb_private; 28 29//---------------------------------------------------------------------- 30// PlatformConnectOptions 31//---------------------------------------------------------------------- 32struct 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() { 37 if (url && url[0]) 38 m_url = url; 39 } 40 41 ~PlatformConnectOptions() {} 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(), m_working_dir(), m_status(0), m_signo(0) { 57 if (shell_command && shell_command[0]) 58 m_command = shell_command; 59 } 60 61 ~PlatformShellCommand() {} 62 63 std::string m_command; 64 std::string m_working_dir; 65 std::string m_output; 66 int m_status; 67 int m_signo; 68 Timeout<std::ratio<1>> m_timeout = llvm::None; 69}; 70//---------------------------------------------------------------------- 71// SBPlatformConnectOptions 72//---------------------------------------------------------------------- 73SBPlatformConnectOptions::SBPlatformConnectOptions(const char *url) 74 : m_opaque_ptr(new PlatformConnectOptions(url)) {} 75 76SBPlatformConnectOptions::SBPlatformConnectOptions( 77 const SBPlatformConnectOptions &rhs) 78 : m_opaque_ptr(new PlatformConnectOptions()) { 79 *m_opaque_ptr = *rhs.m_opaque_ptr; 80} 81 82SBPlatformConnectOptions::~SBPlatformConnectOptions() { delete m_opaque_ptr; } 83 84void SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs) { 85 *m_opaque_ptr = *rhs.m_opaque_ptr; 86} 87 88const char *SBPlatformConnectOptions::GetURL() { 89 if (m_opaque_ptr->m_url.empty()) 90 return NULL; 91 return m_opaque_ptr->m_url.c_str(); 92} 93 94void SBPlatformConnectOptions::SetURL(const char *url) { 95 if (url && url[0]) 96 m_opaque_ptr->m_url = url; 97 else 98 m_opaque_ptr->m_url.clear(); 99} 100 101bool SBPlatformConnectOptions::GetRsyncEnabled() { 102 return m_opaque_ptr->m_rsync_enabled; 103} 104 105void 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; 113 else 114 m_opaque_ptr->m_rsync_remote_path_prefix.clear(); 115 116 if (options && options[0]) 117 m_opaque_ptr->m_rsync_options = options; 118 else 119 m_opaque_ptr->m_rsync_options.clear(); 120} 121 122void SBPlatformConnectOptions::DisableRsync() { 123 m_opaque_ptr->m_rsync_enabled = false; 124} 125 126const char *SBPlatformConnectOptions::GetLocalCacheDirectory() { 127 return m_opaque_ptr->m_local_cache_directory.GetCString(); 128} 129 130void SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path) { 131 if (path && path[0]) 132 m_opaque_ptr->m_local_cache_directory.SetCString(path); 133 else 134 m_opaque_ptr->m_local_cache_directory = ConstString(); 135} 136 137//---------------------------------------------------------------------- 138// SBPlatformShellCommand 139//---------------------------------------------------------------------- 140SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_command) 141 : m_opaque_ptr(new PlatformShellCommand(shell_command)) {} 142 143SBPlatformShellCommand::SBPlatformShellCommand( 144 const SBPlatformShellCommand &rhs) 145 : m_opaque_ptr(new PlatformShellCommand()) { 146 *m_opaque_ptr = *rhs.m_opaque_ptr; 147} 148 149SBPlatformShellCommand::~SBPlatformShellCommand() { delete m_opaque_ptr; } 150 151void SBPlatformShellCommand::Clear() { 152 m_opaque_ptr->m_output = std::string(); 153 m_opaque_ptr->m_status = 0; 154 m_opaque_ptr->m_signo = 0; 155} 156 157const char *SBPlatformShellCommand::GetCommand() { 158 if (m_opaque_ptr->m_command.empty()) 159 return NULL; 160 return m_opaque_ptr->m_command.c_str(); 161} 162 163void SBPlatformShellCommand::SetCommand(const char *shell_command) { 164 if (shell_command && shell_command[0]) 165 m_opaque_ptr->m_command = shell_command; 166 else 167 m_opaque_ptr->m_command.clear(); 168} 169 170const char *SBPlatformShellCommand::GetWorkingDirectory() { 171 if (m_opaque_ptr->m_working_dir.empty()) 172 return NULL; 173 return m_opaque_ptr->m_working_dir.c_str(); 174} 175 176void SBPlatformShellCommand::SetWorkingDirectory(const char *path) { 177 if (path && path[0]) 178 m_opaque_ptr->m_working_dir = path; 179 else 180 m_opaque_ptr->m_working_dir.clear(); 181} 182 183uint32_t SBPlatformShellCommand::GetTimeoutSeconds() { 184 if (m_opaque_ptr->m_timeout) 185 return m_opaque_ptr->m_timeout->count(); 186 return UINT32_MAX; 187} 188 189void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) { 190 if (sec == UINT32_MAX) 191 m_opaque_ptr->m_timeout = llvm::None; 192 else 193 m_opaque_ptr->m_timeout = std::chrono::seconds(sec); 194} 195 196int SBPlatformShellCommand::GetSignal() { return m_opaque_ptr->m_signo; } 197 198int SBPlatformShellCommand::GetStatus() { return m_opaque_ptr->m_status; } 199 200const char *SBPlatformShellCommand::GetOutput() { 201 if (m_opaque_ptr->m_output.empty()) 202 return NULL; 203 return m_opaque_ptr->m_output.c_str(); 204} 205 206//---------------------------------------------------------------------- 207// SBPlatform 208//---------------------------------------------------------------------- 209SBPlatform::SBPlatform() : m_opaque_sp() {} 210 211SBPlatform::SBPlatform(const char *platform_name) : m_opaque_sp() { 212 Status error; 213 if (platform_name && platform_name[0]) 214 m_opaque_sp = Platform::Create(ConstString(platform_name), error); 215} 216 217SBPlatform::~SBPlatform() {} 218 219bool SBPlatform::IsValid() const { return m_opaque_sp.get() != NULL; } 220 221void SBPlatform::Clear() { m_opaque_sp.reset(); } 222 223const char *SBPlatform::GetName() { 224 PlatformSP platform_sp(GetSP()); 225 if (platform_sp) 226 return platform_sp->GetName().GetCString(); 227 return NULL; 228} 229 230lldb::PlatformSP SBPlatform::GetSP() const { return m_opaque_sp; } 231 232void SBPlatform::SetSP(const lldb::PlatformSP &platform_sp) { 233 m_opaque_sp = platform_sp; 234} 235 236const char *SBPlatform::GetWorkingDirectory() { 237 PlatformSP platform_sp(GetSP()); 238 if (platform_sp) 239 return platform_sp->GetWorkingDirectory().GetCString(); 240 return NULL; 241} 242 243bool SBPlatform::SetWorkingDirectory(const char *path) { 244 PlatformSP platform_sp(GetSP()); 245 if (platform_sp) { 246 if (path) 247 platform_sp->SetWorkingDirectory(FileSpec(path)); 248 else 249 platform_sp->SetWorkingDirectory(FileSpec()); 250 return true; 251 } 252 return false; 253} 254 255SBError SBPlatform::ConnectRemote(SBPlatformConnectOptions &connect_options) { 256 SBError sb_error; 257 PlatformSP platform_sp(GetSP()); 258 if (platform_sp && connect_options.GetURL()) { 259 Args args; 260 args.AppendArgument( 261 llvm::StringRef::withNullAsEmpty(connect_options.GetURL())); 262 sb_error.ref() = platform_sp->ConnectRemote(args); 263 } else { 264 sb_error.SetErrorString("invalid platform"); 265 } 266 return sb_error; 267} 268 269void SBPlatform::DisconnectRemote() { 270 PlatformSP platform_sp(GetSP()); 271 if (platform_sp) 272 platform_sp->DisconnectRemote(); 273} 274 275bool SBPlatform::IsConnected() { 276 PlatformSP platform_sp(GetSP()); 277 if (platform_sp) 278 return platform_sp->IsConnected(); 279 return false; 280} 281 282const char *SBPlatform::GetTriple() { 283 PlatformSP platform_sp(GetSP()); 284 if (platform_sp) { 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 288 // the string 289 return ConstString(arch.GetTriple().getTriple().c_str()).GetCString(); 290 } 291 } 292 return NULL; 293} 294 295const char *SBPlatform::GetOSBuild() { 296 PlatformSP platform_sp(GetSP()); 297 if (platform_sp) { 298 std::string s; 299 if (platform_sp->GetOSBuildString(s)) { 300 if (!s.empty()) { 301 // Const-ify the string so we don't need to worry about the lifetime of 302 // the string 303 return ConstString(s.c_str()).GetCString(); 304 } 305 } 306 } 307 return NULL; 308} 309 310const char *SBPlatform::GetOSDescription() { 311 PlatformSP platform_sp(GetSP()); 312 if (platform_sp) { 313 std::string s; 314 if (platform_sp->GetOSKernelDescription(s)) { 315 if (!s.empty()) { 316 // Const-ify the string so we don't need to worry about the lifetime of 317 // the string 318 return ConstString(s.c_str()).GetCString(); 319 } 320 } 321 } 322 return NULL; 323} 324 325const char *SBPlatform::GetHostname() { 326 PlatformSP platform_sp(GetSP()); 327 if (platform_sp) 328 return platform_sp->GetHostname(); 329 return NULL; 330} 331 332uint32_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(); 337} 338 339uint32_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); 344} 345 346uint32_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); 351} 352 353SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) { 354 SBError sb_error; 355 PlatformSP platform_sp(GetSP()); 356 if (platform_sp) { 357 sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref()); 358 } else { 359 sb_error.SetErrorString("invalid platform"); 360 } 361 return sb_error; 362} 363 364SBError SBPlatform::Put(SBFileSpec &src, SBFileSpec &dst) { 365 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 366 if (src.Exists()) { 367 uint32_t permissions = FileSystem::Instance().GetPermissions(src.ref()); 368 if (permissions == 0) { 369 if (FileSystem::Instance().IsDirectory(src.ref())) 370 permissions = eFilePermissionsDirectoryDefault; 371 else 372 permissions = eFilePermissionsFileDefault; 373 } 374 375 return platform_sp->PutFile(src.ref(), dst.ref(), permissions); 376 } 377 378 Status error; 379 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", 380 src.ref().GetPath().c_str()); 381 return error; 382 }); 383} 384 385SBError SBPlatform::Install(SBFileSpec &src, SBFileSpec &dst) { 386 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 387 if (src.Exists()) 388 return platform_sp->Install(src.ref(), dst.ref()); 389 390 Status error; 391 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", 392 src.ref().GetPath().c_str()); 393 return error; 394 }); 395} 396 397SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) { 398 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 399 const char *command = shell_command.GetCommand(); 400 if (!command) 401 return Status("invalid shell command (empty)"); 402 403 const char *working_dir = shell_command.GetWorkingDirectory(); 404 if (working_dir == NULL) { 405 working_dir = platform_sp->GetWorkingDirectory().GetCString(); 406 if (working_dir) 407 shell_command.SetWorkingDirectory(working_dir); 408 } 409 return platform_sp->RunShellCommand(command, FileSpec(working_dir), 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); 414 }); 415} 416 417SBError 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); 422 return error; 423 }); 424} 425 426SBError SBPlatform::Kill(const lldb::pid_t pid) { 427 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 428 return platform_sp->KillProcess(pid); 429 }); 430} 431 432SBError SBPlatform::ExecuteConnected( 433 const std::function<Status(const lldb::PlatformSP &)> &func) { 434 SBError sb_error; 435 const auto platform_sp(GetSP()); 436 if (platform_sp) { 437 if (platform_sp->IsConnected()) 438 sb_error.ref() = func(platform_sp); 439 else 440 sb_error.SetErrorString("not connected"); 441 } else 442 sb_error.SetErrorString("invalid platform"); 443 444 return sb_error; 445} 446 447SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) { 448 SBError sb_error; 449 PlatformSP platform_sp(GetSP()); 450 if (platform_sp) { 451 sb_error.ref() = 452 platform_sp->MakeDirectory(FileSpec(path), file_permissions); 453 } else { 454 sb_error.SetErrorString("invalid platform"); 455 } 456 return sb_error; 457} 458 459uint32_t SBPlatform::GetFilePermissions(const char *path) { 460 PlatformSP platform_sp(GetSP()); 461 if (platform_sp) { 462 uint32_t file_permissions = 0; 463 platform_sp->GetFilePermissions(FileSpec(path), file_permissions); 464 return file_permissions; 465 } 466 return 0; 467} 468 469SBError SBPlatform::SetFilePermissions(const char *path, 470 uint32_t file_permissions) { 471 SBError sb_error; 472 PlatformSP platform_sp(GetSP()); 473 if (platform_sp) { 474 sb_error.ref() = 475 platform_sp->SetFilePermissions(FileSpec(path), file_permissions); 476 } else { 477 sb_error.SetErrorString("invalid platform"); 478 } 479 return sb_error; 480} 481 482SBUnixSignals SBPlatform::GetUnixSignals() const { 483 if (auto platform_sp = GetSP()) 484 return SBUnixSignals{platform_sp}; 485 486 return {}; 487} 488