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/Host/File.h" 17 #include "lldb/Interpreter/Args.h" 18 #include "lldb/Target/Platform.h" 19 #include "lldb/Target/Target.h" 20 #include "lldb/Utility/Error.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 Error 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 Error 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 Error 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 Error("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 return platform_sp->LaunchProcess(launch_info.ref()); 420 }); 421 } 422 423 SBError SBPlatform::Kill(const lldb::pid_t pid) { 424 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 425 return platform_sp->KillProcess(pid); 426 }); 427 } 428 429 SBError SBPlatform::ExecuteConnected( 430 const std::function<Error(const lldb::PlatformSP &)> &func) { 431 SBError sb_error; 432 const auto platform_sp(GetSP()); 433 if (platform_sp) { 434 if (platform_sp->IsConnected()) 435 sb_error.ref() = func(platform_sp); 436 else 437 sb_error.SetErrorString("not connected"); 438 } else 439 sb_error.SetErrorString("invalid platform"); 440 441 return sb_error; 442 } 443 444 SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) { 445 SBError sb_error; 446 PlatformSP platform_sp(GetSP()); 447 if (platform_sp) { 448 sb_error.ref() = 449 platform_sp->MakeDirectory(FileSpec{path, false}, file_permissions); 450 } else { 451 sb_error.SetErrorString("invalid platform"); 452 } 453 return sb_error; 454 } 455 456 uint32_t SBPlatform::GetFilePermissions(const char *path) { 457 PlatformSP platform_sp(GetSP()); 458 if (platform_sp) { 459 uint32_t file_permissions = 0; 460 platform_sp->GetFilePermissions(FileSpec{path, false}, file_permissions); 461 return file_permissions; 462 } 463 return 0; 464 } 465 466 SBError SBPlatform::SetFilePermissions(const char *path, 467 uint32_t file_permissions) { 468 SBError sb_error; 469 PlatformSP platform_sp(GetSP()); 470 if (platform_sp) { 471 sb_error.ref() = platform_sp->SetFilePermissions(FileSpec{path, false}, 472 file_permissions); 473 } else { 474 sb_error.SetErrorString("invalid platform"); 475 } 476 return sb_error; 477 } 478 479 SBUnixSignals SBPlatform::GetUnixSignals() const { 480 if (auto platform_sp = GetSP()) 481 return SBUnixSignals{platform_sp}; 482 483 return {}; 484 } 485