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