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 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(), 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 //---------------------------------------------------------------------- 52 struct 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 //---------------------------------------------------------------------- 72 SBPlatformConnectOptions::SBPlatformConnectOptions(const char *url) 73 : m_opaque_ptr(new PlatformConnectOptions(url)) {} 74 75 SBPlatformConnectOptions::SBPlatformConnectOptions( 76 const SBPlatformConnectOptions &rhs) 77 : m_opaque_ptr(new PlatformConnectOptions()) { 78 *m_opaque_ptr = *rhs.m_opaque_ptr; 79 } 80 81 SBPlatformConnectOptions::~SBPlatformConnectOptions() { delete m_opaque_ptr; } 82 83 void SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs) { 84 *m_opaque_ptr = *rhs.m_opaque_ptr; 85 } 86 87 const 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 93 void 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 100 bool SBPlatformConnectOptions::GetRsyncEnabled() { 101 return m_opaque_ptr->m_rsync_enabled; 102 } 103 104 void 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 121 void SBPlatformConnectOptions::DisableRsync() { 122 m_opaque_ptr->m_rsync_enabled = false; 123 } 124 125 const char *SBPlatformConnectOptions::GetLocalCacheDirectory() { 126 return m_opaque_ptr->m_local_cache_directory.GetCString(); 127 } 128 129 void 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 //---------------------------------------------------------------------- 139 SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_command) 140 : m_opaque_ptr(new PlatformShellCommand(shell_command)) {} 141 142 SBPlatformShellCommand::SBPlatformShellCommand( 143 const SBPlatformShellCommand &rhs) 144 : m_opaque_ptr(new PlatformShellCommand()) { 145 *m_opaque_ptr = *rhs.m_opaque_ptr; 146 } 147 148 SBPlatformShellCommand::~SBPlatformShellCommand() { delete m_opaque_ptr; } 149 150 void 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 156 const 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 162 void 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 169 const 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 175 void 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 182 uint32_t SBPlatformShellCommand::GetTimeoutSeconds() { 183 return m_opaque_ptr->m_timeout_sec; 184 } 185 186 void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) { 187 m_opaque_ptr->m_timeout_sec = sec; 188 } 189 190 int SBPlatformShellCommand::GetSignal() { return m_opaque_ptr->m_signo; } 191 192 int SBPlatformShellCommand::GetStatus() { return m_opaque_ptr->m_status; } 193 194 const 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 //---------------------------------------------------------------------- 203 SBPlatform::SBPlatform() : m_opaque_sp() {} 204 205 SBPlatform::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 211 SBPlatform::~SBPlatform() {} 212 213 bool SBPlatform::IsValid() const { return m_opaque_sp.get() != NULL; } 214 215 void SBPlatform::Clear() { m_opaque_sp.reset(); } 216 217 const char *SBPlatform::GetName() { 218 PlatformSP platform_sp(GetSP()); 219 if (platform_sp) 220 return platform_sp->GetName().GetCString(); 221 return NULL; 222 } 223 224 lldb::PlatformSP SBPlatform::GetSP() const { return m_opaque_sp; } 225 226 void SBPlatform::SetSP(const lldb::PlatformSP &platform_sp) { 227 m_opaque_sp = platform_sp; 228 } 229 230 const char *SBPlatform::GetWorkingDirectory() { 231 PlatformSP platform_sp(GetSP()); 232 if (platform_sp) 233 return platform_sp->GetWorkingDirectory().GetCString(); 234 return NULL; 235 } 236 237 bool 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 249 SBError 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 263 void SBPlatform::DisconnectRemote() { 264 PlatformSP platform_sp(GetSP()); 265 if (platform_sp) 266 platform_sp->DisconnectRemote(); 267 } 268 269 bool SBPlatform::IsConnected() { 270 PlatformSP platform_sp(GetSP()); 271 if (platform_sp) 272 platform_sp->IsConnected(); 273 return false; 274 } 275 276 const 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 289 const 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 304 const 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 319 const char *SBPlatform::GetHostname() { 320 PlatformSP platform_sp(GetSP()); 321 if (platform_sp) 322 return platform_sp->GetHostname(); 323 return NULL; 324 } 325 326 uint32_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 334 uint32_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 342 uint32_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 350 SBError 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 361 SBError 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 382 SBError 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 394 SBError 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 415 SBError SBPlatform::Launch(SBLaunchInfo &launch_info) { 416 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 417 return platform_sp->LaunchProcess(launch_info.ref()); 418 }); 419 } 420 421 SBError SBPlatform::Kill(const lldb::pid_t pid) { 422 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 423 return platform_sp->KillProcess(pid); 424 }); 425 } 426 427 SBError 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 442 SBError 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 454 uint32_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 464 SBError 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 477 SBUnixSignals SBPlatform::GetUnixSignals() const { 478 if (auto platform_sp = GetSP()) 479 return SBUnixSignals{platform_sp}; 480 481 return {}; 482 } 483