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