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(connect_options.GetURL()); 255 sb_error.ref() = platform_sp->ConnectRemote(args); 256 } else { 257 sb_error.SetErrorString("invalid platform"); 258 } 259 return sb_error; 260 } 261 262 void SBPlatform::DisconnectRemote() { 263 PlatformSP platform_sp(GetSP()); 264 if (platform_sp) 265 platform_sp->DisconnectRemote(); 266 } 267 268 bool SBPlatform::IsConnected() { 269 PlatformSP platform_sp(GetSP()); 270 if (platform_sp) 271 platform_sp->IsConnected(); 272 return false; 273 } 274 275 const char *SBPlatform::GetTriple() { 276 PlatformSP platform_sp(GetSP()); 277 if (platform_sp) { 278 ArchSpec arch(platform_sp->GetSystemArchitecture()); 279 if (arch.IsValid()) { 280 // Const-ify the string so we don't need to worry about the lifetime of 281 // the string 282 return ConstString(arch.GetTriple().getTriple().c_str()).GetCString(); 283 } 284 } 285 return NULL; 286 } 287 288 const char *SBPlatform::GetOSBuild() { 289 PlatformSP platform_sp(GetSP()); 290 if (platform_sp) { 291 std::string s; 292 if (platform_sp->GetOSBuildString(s)) { 293 if (!s.empty()) { 294 // Const-ify the string so we don't need to worry about the lifetime of 295 // the string 296 return ConstString(s.c_str()).GetCString(); 297 } 298 } 299 } 300 return NULL; 301 } 302 303 const char *SBPlatform::GetOSDescription() { 304 PlatformSP platform_sp(GetSP()); 305 if (platform_sp) { 306 std::string s; 307 if (platform_sp->GetOSKernelDescription(s)) { 308 if (!s.empty()) { 309 // Const-ify the string so we don't need to worry about the lifetime of 310 // the string 311 return ConstString(s.c_str()).GetCString(); 312 } 313 } 314 } 315 return NULL; 316 } 317 318 const char *SBPlatform::GetHostname() { 319 PlatformSP platform_sp(GetSP()); 320 if (platform_sp) 321 return platform_sp->GetHostname(); 322 return NULL; 323 } 324 325 uint32_t SBPlatform::GetOSMajorVersion() { 326 uint32_t major, minor, update; 327 PlatformSP platform_sp(GetSP()); 328 if (platform_sp && platform_sp->GetOSVersion(major, minor, update)) 329 return major; 330 return UINT32_MAX; 331 } 332 333 uint32_t SBPlatform::GetOSMinorVersion() { 334 uint32_t major, minor, update; 335 PlatformSP platform_sp(GetSP()); 336 if (platform_sp && platform_sp->GetOSVersion(major, minor, update)) 337 return minor; 338 return UINT32_MAX; 339 } 340 341 uint32_t SBPlatform::GetOSUpdateVersion() { 342 uint32_t major, minor, update; 343 PlatformSP platform_sp(GetSP()); 344 if (platform_sp && platform_sp->GetOSVersion(major, minor, update)) 345 return update; 346 return UINT32_MAX; 347 } 348 349 SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) { 350 SBError sb_error; 351 PlatformSP platform_sp(GetSP()); 352 if (platform_sp) { 353 sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref()); 354 } else { 355 sb_error.SetErrorString("invalid platform"); 356 } 357 return sb_error; 358 } 359 360 SBError SBPlatform::Put(SBFileSpec &src, SBFileSpec &dst) { 361 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 362 if (src.Exists()) { 363 uint32_t permissions = src.ref().GetPermissions(); 364 if (permissions == 0) { 365 if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory) 366 permissions = eFilePermissionsDirectoryDefault; 367 else 368 permissions = eFilePermissionsFileDefault; 369 } 370 371 return platform_sp->PutFile(src.ref(), dst.ref(), permissions); 372 } 373 374 Error error; 375 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", 376 src.ref().GetPath().c_str()); 377 return error; 378 }); 379 } 380 381 SBError SBPlatform::Install(SBFileSpec &src, SBFileSpec &dst) { 382 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 383 if (src.Exists()) 384 return platform_sp->Install(src.ref(), dst.ref()); 385 386 Error error; 387 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", 388 src.ref().GetPath().c_str()); 389 return error; 390 }); 391 } 392 393 SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) { 394 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 395 const char *command = shell_command.GetCommand(); 396 if (!command) 397 return Error("invalid shell command (empty)"); 398 399 const char *working_dir = shell_command.GetWorkingDirectory(); 400 if (working_dir == NULL) { 401 working_dir = platform_sp->GetWorkingDirectory().GetCString(); 402 if (working_dir) 403 shell_command.SetWorkingDirectory(working_dir); 404 } 405 return platform_sp->RunShellCommand( 406 command, FileSpec{working_dir, false}, 407 &shell_command.m_opaque_ptr->m_status, 408 &shell_command.m_opaque_ptr->m_signo, 409 &shell_command.m_opaque_ptr->m_output, 410 shell_command.m_opaque_ptr->m_timeout_sec); 411 }); 412 } 413 414 SBError SBPlatform::Launch(SBLaunchInfo &launch_info) { 415 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 416 return platform_sp->LaunchProcess(launch_info.ref()); 417 }); 418 } 419 420 SBError SBPlatform::Kill(const lldb::pid_t pid) { 421 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 422 return platform_sp->KillProcess(pid); 423 }); 424 } 425 426 SBError SBPlatform::ExecuteConnected( 427 const std::function<Error(const lldb::PlatformSP &)> &func) { 428 SBError sb_error; 429 const auto platform_sp(GetSP()); 430 if (platform_sp) { 431 if (platform_sp->IsConnected()) 432 sb_error.ref() = func(platform_sp); 433 else 434 sb_error.SetErrorString("not connected"); 435 } else 436 sb_error.SetErrorString("invalid platform"); 437 438 return sb_error; 439 } 440 441 SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) { 442 SBError sb_error; 443 PlatformSP platform_sp(GetSP()); 444 if (platform_sp) { 445 sb_error.ref() = 446 platform_sp->MakeDirectory(FileSpec{path, false}, file_permissions); 447 } else { 448 sb_error.SetErrorString("invalid platform"); 449 } 450 return sb_error; 451 } 452 453 uint32_t SBPlatform::GetFilePermissions(const char *path) { 454 PlatformSP platform_sp(GetSP()); 455 if (platform_sp) { 456 uint32_t file_permissions = 0; 457 platform_sp->GetFilePermissions(FileSpec{path, false}, file_permissions); 458 return file_permissions; 459 } 460 return 0; 461 } 462 463 SBError SBPlatform::SetFilePermissions(const char *path, 464 uint32_t file_permissions) { 465 SBError sb_error; 466 PlatformSP platform_sp(GetSP()); 467 if (platform_sp) { 468 sb_error.ref() = platform_sp->SetFilePermissions(FileSpec{path, false}, 469 file_permissions); 470 } else { 471 sb_error.SetErrorString("invalid platform"); 472 } 473 return sb_error; 474 } 475 476 SBUnixSignals SBPlatform::GetUnixSignals() const { 477 if (auto platform_sp = GetSP()) 478 return SBUnixSignals{platform_sp}; 479 480 return {}; 481 } 482