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