1 //===-- PlatformPOSIX.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 "PlatformPOSIX.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 17 #include "lldb/Core/DataBufferHeap.h" 18 #include "lldb/Core/Log.h" 19 #include "lldb/Core/StreamString.h" 20 #include "lldb/Host/File.h" 21 #include "lldb/Host/FileCache.h" 22 #include "lldb/Host/FileSpec.h" 23 #include "lldb/Host/FileSystem.h" 24 #include "lldb/Host/Host.h" 25 #include "lldb/Target/ProcessLaunchInfo.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 31 //------------------------------------------------------------------ 32 /// Default Constructor 33 //------------------------------------------------------------------ 34 PlatformPOSIX::PlatformPOSIX (bool is_host) : 35 Platform(is_host), // This is the local host platform 36 m_remote_platform_sp () 37 { 38 } 39 40 //------------------------------------------------------------------ 41 /// Destructor. 42 /// 43 /// The destructor is virtual since this class is designed to be 44 /// inherited from by the plug-in instance. 45 //------------------------------------------------------------------ 46 PlatformPOSIX::~PlatformPOSIX() 47 { 48 } 49 50 lldb_private::OptionGroupOptions* 51 PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter) 52 { 53 if (m_options.get() == NULL) 54 { 55 m_options.reset(new OptionGroupOptions(interpreter)); 56 m_options->Append(new OptionGroupPlatformRSync()); 57 m_options->Append(new OptionGroupPlatformSSH()); 58 m_options->Append(new OptionGroupPlatformCaching()); 59 } 60 return m_options.get(); 61 } 62 63 bool 64 PlatformPOSIX::IsConnected () const 65 { 66 if (IsHost()) 67 return true; 68 else if (m_remote_platform_sp) 69 return m_remote_platform_sp->IsConnected(); 70 return false; 71 } 72 73 lldb_private::Error 74 PlatformPOSIX::RunShellCommand (const char *command, // Shouldn't be NULL 75 const char *working_dir, // Pass NULL to use the current working directory 76 int *status_ptr, // Pass NULL if you don't want the process exit status 77 int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 78 std::string *command_output, // Pass NULL if you don't want the command output 79 uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 80 { 81 if (IsHost()) 82 return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 83 else 84 { 85 if (m_remote_platform_sp) 86 return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 87 else 88 return Error("unable to run a remote command without a platform"); 89 } 90 } 91 92 Error 93 PlatformPOSIX::MakeDirectory (const char *path, uint32_t file_permissions) 94 { 95 if (m_remote_platform_sp) 96 return m_remote_platform_sp->MakeDirectory(path, file_permissions); 97 else 98 return Platform::MakeDirectory(path ,file_permissions); 99 } 100 101 Error 102 PlatformPOSIX::GetFilePermissions (const char *path, uint32_t &file_permissions) 103 { 104 if (m_remote_platform_sp) 105 return m_remote_platform_sp->GetFilePermissions(path, file_permissions); 106 else 107 return Platform::GetFilePermissions(path ,file_permissions); 108 } 109 110 Error 111 PlatformPOSIX::SetFilePermissions (const char *path, uint32_t file_permissions) 112 { 113 if (m_remote_platform_sp) 114 return m_remote_platform_sp->SetFilePermissions(path, file_permissions); 115 else 116 return Platform::SetFilePermissions(path ,file_permissions); 117 } 118 119 lldb::user_id_t 120 PlatformPOSIX::OpenFile (const FileSpec& file_spec, 121 uint32_t flags, 122 uint32_t mode, 123 Error &error) 124 { 125 if (IsHost()) 126 return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error); 127 else if (m_remote_platform_sp) 128 return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error); 129 else 130 return Platform::OpenFile(file_spec, flags, mode, error); 131 } 132 133 bool 134 PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error) 135 { 136 if (IsHost()) 137 return FileCache::GetInstance().CloseFile(fd, error); 138 else if (m_remote_platform_sp) 139 return m_remote_platform_sp->CloseFile(fd, error); 140 else 141 return Platform::CloseFile(fd, error); 142 } 143 144 uint64_t 145 PlatformPOSIX::ReadFile (lldb::user_id_t fd, 146 uint64_t offset, 147 void *dst, 148 uint64_t dst_len, 149 Error &error) 150 { 151 if (IsHost()) 152 return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error); 153 else if (m_remote_platform_sp) 154 return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error); 155 else 156 return Platform::ReadFile(fd, offset, dst, dst_len, error); 157 } 158 159 uint64_t 160 PlatformPOSIX::WriteFile (lldb::user_id_t fd, 161 uint64_t offset, 162 const void* src, 163 uint64_t src_len, 164 Error &error) 165 { 166 if (IsHost()) 167 return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error); 168 else if (m_remote_platform_sp) 169 return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error); 170 else 171 return Platform::WriteFile(fd, offset, src, src_len, error); 172 } 173 174 static uint32_t 175 chown_file(Platform *platform, 176 const char* path, 177 uint32_t uid = UINT32_MAX, 178 uint32_t gid = UINT32_MAX) 179 { 180 if (!platform || !path || *path == 0) 181 return UINT32_MAX; 182 183 if (uid == UINT32_MAX && gid == UINT32_MAX) 184 return 0; // pretend I did chown correctly - actually I just didn't care 185 186 StreamString command; 187 command.PutCString("chown "); 188 if (uid != UINT32_MAX) 189 command.Printf("%d",uid); 190 if (gid != UINT32_MAX) 191 command.Printf(":%d",gid); 192 command.Printf("%s",path); 193 int status; 194 platform->RunShellCommand(command.GetData(), 195 NULL, 196 &status, 197 NULL, 198 NULL, 199 10); 200 return status; 201 } 202 203 lldb_private::Error 204 PlatformPOSIX::PutFile (const lldb_private::FileSpec& source, 205 const lldb_private::FileSpec& destination, 206 uint32_t uid, 207 uint32_t gid) 208 { 209 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 210 211 if (IsHost()) 212 { 213 if (FileSpec::Equal(source, destination, true)) 214 return Error(); 215 // cp src dst 216 // chown uid:gid dst 217 std::string src_path (source.GetPath()); 218 if (src_path.empty()) 219 return Error("unable to get file path for source"); 220 std::string dst_path (destination.GetPath()); 221 if (dst_path.empty()) 222 return Error("unable to get file path for destination"); 223 StreamString command; 224 command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 225 int status; 226 RunShellCommand(command.GetData(), 227 NULL, 228 &status, 229 NULL, 230 NULL, 231 10); 232 if (status != 0) 233 return Error("unable to perform copy"); 234 if (uid == UINT32_MAX && gid == UINT32_MAX) 235 return Error(); 236 if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 237 return Error("unable to perform chown"); 238 return Error(); 239 } 240 else if (m_remote_platform_sp) 241 { 242 if (GetSupportsRSync()) 243 { 244 std::string src_path (source.GetPath()); 245 if (src_path.empty()) 246 return Error("unable to get file path for source"); 247 std::string dst_path (destination.GetPath()); 248 if (dst_path.empty()) 249 return Error("unable to get file path for destination"); 250 StreamString command; 251 if (GetIgnoresRemoteHostname()) 252 { 253 if (!GetRSyncPrefix()) 254 command.Printf("rsync %s %s %s", 255 GetRSyncOpts(), 256 src_path.c_str(), 257 dst_path.c_str()); 258 else 259 command.Printf("rsync %s %s %s%s", 260 GetRSyncOpts(), 261 src_path.c_str(), 262 GetRSyncPrefix(), 263 dst_path.c_str()); 264 } 265 else 266 command.Printf("rsync %s %s %s:%s", 267 GetRSyncOpts(), 268 src_path.c_str(), 269 GetHostname(), 270 dst_path.c_str()); 271 if (log) 272 log->Printf("[PutFile] Running command: %s\n", command.GetData()); 273 int retcode; 274 Host::RunShellCommand(command.GetData(), 275 NULL, 276 &retcode, 277 NULL, 278 NULL, 279 60); 280 if (retcode == 0) 281 { 282 // Don't chown a local file for a remote system 283 // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 284 // return Error("unable to perform chown"); 285 return Error(); 286 } 287 // if we are still here rsync has failed - let's try the slow way before giving up 288 } 289 290 if (log) 291 log->Printf ("PlatformPOSIX::PutFile(src='%s', dst='%s', uid=%u, gid=%u)", 292 source.GetPath().c_str(), 293 destination.GetPath().c_str(), 294 uid, 295 gid); // REMOVE THIS PRINTF PRIOR TO CHECKIN 296 // open 297 // read, write, read, write, ... 298 // close 299 // chown uid:gid dst 300 if (log) 301 log->Printf("[PutFile] Using block by block transfer....\n"); 302 303 uint32_t source_open_options = File::eOpenOptionRead; 304 if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink) 305 source_open_options |= File::eOpenoptionDontFollowSymlinks; 306 307 File source_file(source, source_open_options, lldb::eFilePermissionsUserRW); 308 Error error; 309 uint32_t permissions = source_file.GetPermissions(error); 310 if (permissions == 0) 311 permissions = lldb::eFilePermissionsFileDefault; 312 313 if (!source_file.IsValid()) 314 return Error("unable to open source file"); 315 lldb::user_id_t dest_file = OpenFile (destination, 316 File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, 317 permissions, 318 error); 319 if (log) 320 log->Printf ("dest_file = %" PRIu64 "\n", dest_file); 321 if (error.Fail()) 322 return error; 323 if (dest_file == UINT64_MAX) 324 return Error("unable to open target file"); 325 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 326 uint64_t offset = 0; 327 while (error.Success()) 328 { 329 size_t bytes_read = buffer_sp->GetByteSize(); 330 error = source_file.Read(buffer_sp->GetBytes(), bytes_read); 331 if (bytes_read) 332 { 333 const uint64_t bytes_written = WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error); 334 offset += bytes_written; 335 if (bytes_written != bytes_read) 336 { 337 // We didn't write the correct numbe of bytes, so adjust 338 // the file position in the source file we are reading from... 339 source_file.SeekFromStart(offset); 340 } 341 } 342 else 343 break; 344 } 345 CloseFile(dest_file, error); 346 if (uid == UINT32_MAX && gid == UINT32_MAX) 347 return error; 348 // This is remopve, don't chown a local file... 349 // std::string dst_path (destination.GetPath()); 350 // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 351 // return Error("unable to perform chown"); 352 353 354 uint64_t src_md5[2]; 355 uint64_t dst_md5[2]; 356 357 if (FileSystem::CalculateMD5 (source, src_md5[0], src_md5[1]) && CalculateMD5 (destination, dst_md5[0], dst_md5[1])) 358 { 359 if (src_md5[0] != dst_md5[0] || src_md5[1] != dst_md5[1]) 360 { 361 error.SetErrorString("md5 checksum of installed file doesn't match, installation failed"); 362 } 363 } 364 return error; 365 } 366 return Platform::PutFile(source,destination,uid,gid); 367 } 368 369 lldb::user_id_t 370 PlatformPOSIX::GetFileSize (const FileSpec& file_spec) 371 { 372 if (IsHost()) 373 return FileSystem::GetFileSize(file_spec); 374 else if (m_remote_platform_sp) 375 return m_remote_platform_sp->GetFileSize(file_spec); 376 else 377 return Platform::GetFileSize(file_spec); 378 } 379 380 Error 381 PlatformPOSIX::CreateSymlink(const char *src, const char *dst) 382 { 383 if (IsHost()) 384 return FileSystem::Symlink(src, dst); 385 else if (m_remote_platform_sp) 386 return m_remote_platform_sp->CreateSymlink(src, dst); 387 else 388 return Platform::CreateSymlink(src, dst); 389 } 390 391 bool 392 PlatformPOSIX::GetFileExists (const FileSpec& file_spec) 393 { 394 if (IsHost()) 395 return file_spec.Exists(); 396 else if (m_remote_platform_sp) 397 return m_remote_platform_sp->GetFileExists(file_spec); 398 else 399 return Platform::GetFileExists(file_spec); 400 } 401 402 Error 403 PlatformPOSIX::Unlink (const char *path) 404 { 405 if (IsHost()) 406 return FileSystem::Unlink(path); 407 else if (m_remote_platform_sp) 408 return m_remote_platform_sp->Unlink(path); 409 else 410 return Platform::Unlink(path); 411 } 412 413 lldb_private::Error 414 PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path */, 415 const lldb_private::FileSpec& destination /* local file path */) 416 { 417 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 418 419 // Check the args, first. 420 std::string src_path (source.GetPath()); 421 if (src_path.empty()) 422 return Error("unable to get file path for source"); 423 std::string dst_path (destination.GetPath()); 424 if (dst_path.empty()) 425 return Error("unable to get file path for destination"); 426 if (IsHost()) 427 { 428 if (FileSpec::Equal(source, destination, true)) 429 return Error("local scenario->source and destination are the same file path: no operation performed"); 430 // cp src dst 431 StreamString cp_command; 432 cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 433 int status; 434 RunShellCommand(cp_command.GetData(), 435 NULL, 436 &status, 437 NULL, 438 NULL, 439 10); 440 if (status != 0) 441 return Error("unable to perform copy"); 442 return Error(); 443 } 444 else if (m_remote_platform_sp) 445 { 446 if (GetSupportsRSync()) 447 { 448 StreamString command; 449 if (GetIgnoresRemoteHostname()) 450 { 451 if (!GetRSyncPrefix()) 452 command.Printf("rsync %s %s %s", 453 GetRSyncOpts(), 454 src_path.c_str(), 455 dst_path.c_str()); 456 else 457 command.Printf("rsync %s %s%s %s", 458 GetRSyncOpts(), 459 GetRSyncPrefix(), 460 src_path.c_str(), 461 dst_path.c_str()); 462 } 463 else 464 command.Printf("rsync %s %s:%s %s", 465 GetRSyncOpts(), 466 m_remote_platform_sp->GetHostname(), 467 src_path.c_str(), 468 dst_path.c_str()); 469 if (log) 470 log->Printf("[GetFile] Running command: %s\n", command.GetData()); 471 int retcode; 472 Host::RunShellCommand(command.GetData(), 473 NULL, 474 &retcode, 475 NULL, 476 NULL, 477 60); 478 if (retcode == 0) 479 return Error(); 480 // If we are here, rsync has failed - let's try the slow way before giving up 481 } 482 // open src and dst 483 // read/write, read/write, read/write, ... 484 // close src 485 // close dst 486 if (log) 487 log->Printf("[GetFile] Using block by block transfer....\n"); 488 Error error; 489 user_id_t fd_src = OpenFile (source, 490 File::eOpenOptionRead, 491 lldb::eFilePermissionsFileDefault, 492 error); 493 494 if (fd_src == UINT64_MAX) 495 return Error("unable to open source file"); 496 497 uint32_t permissions = 0; 498 error = GetFilePermissions(source.GetPath().c_str(), permissions); 499 500 if (permissions == 0) 501 permissions = lldb::eFilePermissionsFileDefault; 502 503 user_id_t fd_dst = FileCache::GetInstance().OpenFile( 504 destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, permissions, 505 error); 506 507 if (fd_dst == UINT64_MAX) 508 { 509 if (error.Success()) 510 error.SetErrorString("unable to open destination file"); 511 } 512 513 if (error.Success()) 514 { 515 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 516 uint64_t offset = 0; 517 error.Clear(); 518 while (error.Success()) 519 { 520 const uint64_t n_read = ReadFile (fd_src, 521 offset, 522 buffer_sp->GetBytes(), 523 buffer_sp->GetByteSize(), 524 error); 525 if (error.Fail()) 526 break; 527 if (n_read == 0) 528 break; 529 if (FileCache::GetInstance().WriteFile(fd_dst, offset, buffer_sp->GetBytes(), n_read, error) != n_read) 530 { 531 if (!error.Fail()) 532 error.SetErrorString("unable to write to destination file"); 533 break; 534 } 535 offset += n_read; 536 } 537 } 538 // Ignore the close error of src. 539 if (fd_src != UINT64_MAX) 540 CloseFile(fd_src, error); 541 // And close the dst file descriptot. 542 if (fd_dst != UINT64_MAX && !FileCache::GetInstance().CloseFile(fd_dst, error)) 543 { 544 if (!error.Fail()) 545 error.SetErrorString("unable to close destination file"); 546 547 } 548 return error; 549 } 550 return Platform::GetFile(source,destination); 551 } 552 553 std::string 554 PlatformPOSIX::GetPlatformSpecificConnectionInformation() 555 { 556 StreamString stream; 557 if (GetSupportsRSync()) 558 { 559 stream.PutCString("rsync"); 560 if ( (GetRSyncOpts() && *GetRSyncOpts()) || 561 (GetRSyncPrefix() && *GetRSyncPrefix()) || 562 GetIgnoresRemoteHostname()) 563 { 564 stream.Printf(", options: "); 565 if (GetRSyncOpts() && *GetRSyncOpts()) 566 stream.Printf("'%s' ",GetRSyncOpts()); 567 stream.Printf(", prefix: "); 568 if (GetRSyncPrefix() && *GetRSyncPrefix()) 569 stream.Printf("'%s' ",GetRSyncPrefix()); 570 if (GetIgnoresRemoteHostname()) 571 stream.Printf("ignore remote-hostname "); 572 } 573 } 574 if (GetSupportsSSH()) 575 { 576 stream.PutCString("ssh"); 577 if (GetSSHOpts() && *GetSSHOpts()) 578 stream.Printf(", options: '%s' ",GetSSHOpts()); 579 } 580 if (GetLocalCacheDirectory() && *GetLocalCacheDirectory()) 581 stream.Printf("cache dir: %s",GetLocalCacheDirectory()); 582 if (stream.GetSize()) 583 return stream.GetData(); 584 else 585 return ""; 586 } 587 588 bool 589 PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec, 590 uint64_t &low, 591 uint64_t &high) 592 { 593 if (IsHost()) 594 return Platform::CalculateMD5 (file_spec, low, high); 595 if (m_remote_platform_sp) 596 return m_remote_platform_sp->CalculateMD5(file_spec, low, high); 597 return false; 598 } 599 600 lldb_private::ConstString 601 PlatformPOSIX::GetRemoteWorkingDirectory() 602 { 603 if (IsRemote() && m_remote_platform_sp) 604 return m_remote_platform_sp->GetRemoteWorkingDirectory(); 605 else 606 return Platform::GetRemoteWorkingDirectory(); 607 } 608 609 bool 610 PlatformPOSIX::SetRemoteWorkingDirectory(const lldb_private::ConstString &path) 611 { 612 if (IsRemote() && m_remote_platform_sp) 613 return m_remote_platform_sp->SetRemoteWorkingDirectory(path); 614 else 615 return Platform::SetRemoteWorkingDirectory(path); 616 } 617 618 bool 619 PlatformPOSIX::GetRemoteOSVersion () 620 { 621 if (m_remote_platform_sp) 622 return m_remote_platform_sp->GetOSVersion (m_major_os_version, 623 m_minor_os_version, 624 m_update_os_version); 625 return false; 626 } 627 628 bool 629 PlatformPOSIX::GetRemoteOSBuildString (std::string &s) 630 { 631 if (m_remote_platform_sp) 632 return m_remote_platform_sp->GetRemoteOSBuildString (s); 633 s.clear(); 634 return false; 635 } 636 637 size_t 638 PlatformPOSIX::GetEnvironment (StringList &env) 639 { 640 if (IsRemote()) 641 { 642 if (m_remote_platform_sp) 643 return m_remote_platform_sp->GetEnvironment(env); 644 return 0; 645 } 646 return Host::GetEnvironment(env); 647 } 648 649 bool 650 PlatformPOSIX::GetRemoteOSKernelDescription (std::string &s) 651 { 652 if (m_remote_platform_sp) 653 return m_remote_platform_sp->GetRemoteOSKernelDescription (s); 654 s.clear(); 655 return false; 656 } 657 658 // Remote Platform subclasses need to override this function 659 ArchSpec 660 PlatformPOSIX::GetRemoteSystemArchitecture () 661 { 662 if (m_remote_platform_sp) 663 return m_remote_platform_sp->GetRemoteSystemArchitecture (); 664 return ArchSpec(); 665 } 666 667 const char * 668 PlatformPOSIX::GetHostname () 669 { 670 if (IsHost()) 671 return Platform::GetHostname(); 672 673 if (m_remote_platform_sp) 674 return m_remote_platform_sp->GetHostname (); 675 return NULL; 676 } 677 678 const char * 679 PlatformPOSIX::GetUserName (uint32_t uid) 680 { 681 // Check the cache in Platform in case we have already looked this uid up 682 const char *user_name = Platform::GetUserName(uid); 683 if (user_name) 684 return user_name; 685 686 if (IsRemote() && m_remote_platform_sp) 687 return m_remote_platform_sp->GetUserName(uid); 688 return NULL; 689 } 690 691 const char * 692 PlatformPOSIX::GetGroupName (uint32_t gid) 693 { 694 const char *group_name = Platform::GetGroupName(gid); 695 if (group_name) 696 return group_name; 697 698 if (IsRemote() && m_remote_platform_sp) 699 return m_remote_platform_sp->GetGroupName(gid); 700 return NULL; 701 } 702 703 Error 704 PlatformPOSIX::ConnectRemote (Args& args) 705 { 706 Error error; 707 if (IsHost()) 708 { 709 error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); 710 } 711 else 712 { 713 if (!m_remote_platform_sp) 714 m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error); 715 716 if (m_remote_platform_sp && error.Success()) 717 error = m_remote_platform_sp->ConnectRemote (args); 718 else 719 error.SetErrorString ("failed to create a 'remote-gdb-server' platform"); 720 721 if (error.Fail()) 722 m_remote_platform_sp.reset(); 723 } 724 725 if (error.Success() && m_remote_platform_sp) 726 { 727 if (m_options.get()) 728 { 729 OptionGroupOptions* options = m_options.get(); 730 OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r'); 731 OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s'); 732 OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c'); 733 734 if (m_rsync_options->m_rsync) 735 { 736 SetSupportsRSync(true); 737 SetRSyncOpts(m_rsync_options->m_rsync_opts.c_str()); 738 SetRSyncPrefix(m_rsync_options->m_rsync_prefix.c_str()); 739 SetIgnoresRemoteHostname(m_rsync_options->m_ignores_remote_hostname); 740 } 741 if (m_ssh_options->m_ssh) 742 { 743 SetSupportsSSH(true); 744 SetSSHOpts(m_ssh_options->m_ssh_opts.c_str()); 745 } 746 SetLocalCacheDirectory(m_cache_options->m_cache_dir.c_str()); 747 } 748 } 749 750 return error; 751 } 752 753 Error 754 PlatformPOSIX::DisconnectRemote () 755 { 756 Error error; 757 758 if (IsHost()) 759 { 760 error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString()); 761 } 762 else 763 { 764 if (m_remote_platform_sp) 765 error = m_remote_platform_sp->DisconnectRemote (); 766 else 767 error.SetErrorString ("the platform is not currently connected"); 768 } 769 return error; 770 } 771 772 lldb::ProcessSP 773 PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info, 774 Debugger &debugger, 775 Target *target, // Can be NULL, if NULL create a new target, else use existing one 776 Listener &listener, 777 Error &error) 778 { 779 ProcessSP process_sp; 780 781 if (IsHost()) 782 { 783 // We are going to hand this process off to debugserver which will be in charge of setting the exit status. 784 // We still need to reap it from lldb but if we let the monitor thread also set the exit status, we set up a 785 // race between debugserver & us for who will find out about the debugged process's death. 786 launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus); 787 process_sp = Platform::DebugProcess (launch_info, debugger, target, listener, error); 788 } 789 else 790 { 791 if (m_remote_platform_sp) 792 process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, listener, error); 793 else 794 error.SetErrorString ("the platform is not currently connected"); 795 } 796 return process_sp; 797 798 } 799 800 void 801 PlatformPOSIX::CalculateTrapHandlerSymbolNames () 802 { 803 m_trap_handlers.push_back (ConstString ("_sigtramp")); 804 } 805