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 24 using namespace lldb; 25 using namespace lldb_private; 26 27 //---------------------------------------------------------------------- 28 // PlatformConnectOptions 29 //---------------------------------------------------------------------- 30 struct 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 //---------------------------------------------------------------------- 58 struct 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 //---------------------------------------------------------------------- 84 SBPlatformConnectOptions::SBPlatformConnectOptions (const char *url) : 85 m_opaque_ptr(new PlatformConnectOptions(url)) 86 { 87 88 } 89 90 SBPlatformConnectOptions::SBPlatformConnectOptions(const SBPlatformConnectOptions &rhs) : 91 m_opaque_ptr(new PlatformConnectOptions()) 92 { 93 *m_opaque_ptr = *rhs.m_opaque_ptr; 94 } 95 96 SBPlatformConnectOptions::~SBPlatformConnectOptions () 97 { 98 delete m_opaque_ptr; 99 } 100 101 void 102 SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs) 103 { 104 *m_opaque_ptr = *rhs.m_opaque_ptr; 105 } 106 107 const char * 108 SBPlatformConnectOptions::GetURL() 109 { 110 if (m_opaque_ptr->m_url.empty()) 111 return NULL; 112 return m_opaque_ptr->m_url.c_str(); 113 } 114 115 void 116 SBPlatformConnectOptions::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 124 bool 125 SBPlatformConnectOptions::GetRsyncEnabled() 126 { 127 return m_opaque_ptr->m_rsync_enabled; 128 } 129 130 void 131 SBPlatformConnectOptions::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 149 void 150 SBPlatformConnectOptions::DisableRsync () 151 { 152 m_opaque_ptr->m_rsync_enabled = false; 153 } 154 155 const char * 156 SBPlatformConnectOptions::GetLocalCacheDirectory() 157 { 158 return m_opaque_ptr->m_local_cache_directory.GetCString(); 159 } 160 161 void 162 SBPlatformConnectOptions::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 //---------------------------------------------------------------------- 173 SBPlatformShellCommand::SBPlatformShellCommand (const char *shell_command) : 174 m_opaque_ptr(new PlatformShellCommand(shell_command)) 175 { 176 } 177 178 SBPlatformShellCommand::SBPlatformShellCommand (const SBPlatformShellCommand &rhs) : 179 m_opaque_ptr(new PlatformShellCommand()) 180 { 181 *m_opaque_ptr = *rhs.m_opaque_ptr; 182 } 183 184 SBPlatformShellCommand::~SBPlatformShellCommand() 185 { 186 delete m_opaque_ptr; 187 } 188 189 void 190 SBPlatformShellCommand::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 197 const char * 198 SBPlatformShellCommand::GetCommand() 199 { 200 if (m_opaque_ptr->m_command.empty()) 201 return NULL; 202 return m_opaque_ptr->m_command.c_str(); 203 } 204 205 void 206 SBPlatformShellCommand::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 214 const char * 215 SBPlatformShellCommand::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 222 void 223 SBPlatformShellCommand::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 231 uint32_t 232 SBPlatformShellCommand::GetTimeoutSeconds () 233 { 234 return m_opaque_ptr->m_timeout_sec; 235 } 236 237 void 238 SBPlatformShellCommand::SetTimeoutSeconds (uint32_t sec) 239 { 240 m_opaque_ptr->m_timeout_sec = sec; 241 } 242 243 int 244 SBPlatformShellCommand::GetSignal () 245 { 246 return m_opaque_ptr->m_signo; 247 } 248 249 int 250 SBPlatformShellCommand::GetStatus () 251 { 252 return m_opaque_ptr->m_status; 253 } 254 255 const char * 256 SBPlatformShellCommand::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 //---------------------------------------------------------------------- 266 SBPlatform::SBPlatform () : 267 m_opaque_sp () 268 { 269 270 } 271 272 SBPlatform::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 280 SBPlatform::~SBPlatform() 281 { 282 } 283 284 bool 285 SBPlatform::IsValid () const 286 { 287 return m_opaque_sp.get() != NULL; 288 } 289 290 void 291 SBPlatform::Clear () 292 { 293 m_opaque_sp.reset(); 294 } 295 296 const char * 297 SBPlatform::GetName () 298 { 299 PlatformSP platform_sp(GetSP()); 300 if (platform_sp) 301 return platform_sp->GetName().GetCString(); 302 return NULL; 303 } 304 305 lldb::PlatformSP 306 SBPlatform::GetSP () const 307 { 308 return m_opaque_sp; 309 } 310 311 void 312 SBPlatform::SetSP (const lldb::PlatformSP& platform_sp) 313 { 314 m_opaque_sp = platform_sp; 315 } 316 317 const char * 318 SBPlatform::GetWorkingDirectory() 319 { 320 PlatformSP platform_sp(GetSP()); 321 if (platform_sp) 322 return platform_sp->GetWorkingDirectory().GetCString(); 323 return NULL; 324 } 325 326 bool 327 SBPlatform::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 341 SBError 342 SBPlatform::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 359 void 360 SBPlatform::DisconnectRemote () 361 { 362 PlatformSP platform_sp(GetSP()); 363 if (platform_sp) 364 platform_sp->DisconnectRemote(); 365 } 366 367 bool 368 SBPlatform::IsConnected() 369 { 370 PlatformSP platform_sp(GetSP()); 371 if (platform_sp) 372 platform_sp->IsConnected(); 373 return false; 374 } 375 376 const char * 377 SBPlatform::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 392 const char * 393 SBPlatform::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 411 const char * 412 SBPlatform::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 430 const char * 431 SBPlatform::GetHostname () 432 { 433 PlatformSP platform_sp(GetSP()); 434 if (platform_sp) 435 return platform_sp->GetHostname(); 436 return NULL; 437 } 438 439 uint32_t 440 SBPlatform::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 450 uint32_t 451 SBPlatform::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 460 uint32_t 461 SBPlatform::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 470 SBError 471 SBPlatform::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 487 SBError 488 SBPlatform::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 514 SBError 515 SBPlatform::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 531 SBError 532 SBPlatform::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 557 SBError 558 SBPlatform::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 567 SBError 568 SBPlatform::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 577 SBError 578 SBPlatform::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 595 SBError 596 SBPlatform::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 611 uint32_t 612 SBPlatform::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 625 SBError 626 SBPlatform::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 642 SBUnixSignals 643 SBPlatform::GetUnixSignals() const 644 { 645 if (auto platform_sp = GetSP()) 646 return SBUnixSignals{platform_sp}; 647 648 return {}; 649 } 650