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