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