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/Target.h"
20 #include "lldb/Target/Platform.h"
21
22 #include <functional>
23
24 using namespace lldb;
25 using namespace lldb_private;
26
27 //----------------------------------------------------------------------
28 // PlatformConnectOptions
29 //----------------------------------------------------------------------
30 struct PlatformConnectOptions {
PlatformConnectOptionsPlatformConnectOptions31 PlatformConnectOptions(const char *url = NULL) :
32 m_url(),
33 m_rsync_options(),
34 m_rsync_remote_path_prefix(),
35 m_rsync_enabled(false),
36 m_rsync_omit_hostname_from_remote_path(false),
37 m_local_cache_directory ()
38 {
39 if (url && url[0])
40 m_url = url;
41 }
42
~PlatformConnectOptionsPlatformConnectOptions43 ~PlatformConnectOptions()
44 {
45 }
46
47 std::string m_url;
48 std::string m_rsync_options;
49 std::string m_rsync_remote_path_prefix;
50 bool m_rsync_enabled;
51 bool m_rsync_omit_hostname_from_remote_path;
52 ConstString m_local_cache_directory;
53 };
54
55 //----------------------------------------------------------------------
56 // PlatformShellCommand
57 //----------------------------------------------------------------------
58 struct PlatformShellCommand {
PlatformShellCommandPlatformShellCommand59 PlatformShellCommand(const char *shell_command = NULL) :
60 m_command(),
61 m_working_dir(),
62 m_status(0),
63 m_signo(0),
64 m_timeout_sec(UINT32_MAX)
65 {
66 if (shell_command && shell_command[0])
67 m_command = shell_command;
68 }
69
~PlatformShellCommandPlatformShellCommand70 ~PlatformShellCommand()
71 {
72 }
73
74 std::string m_command;
75 std::string m_working_dir;
76 std::string m_output;
77 int m_status;
78 int m_signo;
79 uint32_t m_timeout_sec;
80 };
81 //----------------------------------------------------------------------
82 // SBPlatformConnectOptions
83 //----------------------------------------------------------------------
SBPlatformConnectOptions(const char * url)84 SBPlatformConnectOptions::SBPlatformConnectOptions (const char *url) :
85 m_opaque_ptr(new PlatformConnectOptions(url))
86 {
87
88 }
89
SBPlatformConnectOptions(const SBPlatformConnectOptions & rhs)90 SBPlatformConnectOptions::SBPlatformConnectOptions(const SBPlatformConnectOptions &rhs) :
91 m_opaque_ptr(new PlatformConnectOptions())
92 {
93 *m_opaque_ptr = *rhs.m_opaque_ptr;
94 }
95
~SBPlatformConnectOptions()96 SBPlatformConnectOptions::~SBPlatformConnectOptions ()
97 {
98 delete m_opaque_ptr;
99 }
100
101 void
operator =(const SBPlatformConnectOptions & rhs)102 SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs)
103 {
104 *m_opaque_ptr = *rhs.m_opaque_ptr;
105 }
106
107 const char *
GetURL()108 SBPlatformConnectOptions::GetURL()
109 {
110 if (m_opaque_ptr->m_url.empty())
111 return NULL;
112 return m_opaque_ptr->m_url.c_str();
113 }
114
115 void
SetURL(const char * url)116 SBPlatformConnectOptions::SetURL(const char *url)
117 {
118 if (url && url[0])
119 m_opaque_ptr->m_url = url;
120 else
121 m_opaque_ptr->m_url.clear();
122 }
123
124 bool
GetRsyncEnabled()125 SBPlatformConnectOptions::GetRsyncEnabled()
126 {
127 return m_opaque_ptr->m_rsync_enabled;
128 }
129
130 void
EnableRsync(const char * options,const char * remote_path_prefix,bool omit_hostname_from_remote_path)131 SBPlatformConnectOptions::EnableRsync (const char *options,
132 const char *remote_path_prefix,
133 bool omit_hostname_from_remote_path)
134 {
135 m_opaque_ptr->m_rsync_enabled = true;
136 m_opaque_ptr->m_rsync_omit_hostname_from_remote_path = omit_hostname_from_remote_path;
137 if (remote_path_prefix && remote_path_prefix[0])
138 m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
139 else
140 m_opaque_ptr->m_rsync_remote_path_prefix.clear();
141
142 if (options && options[0])
143 m_opaque_ptr->m_rsync_options = options;
144 else
145 m_opaque_ptr->m_rsync_options.clear();
146
147 }
148
149 void
DisableRsync()150 SBPlatformConnectOptions::DisableRsync ()
151 {
152 m_opaque_ptr->m_rsync_enabled = false;
153 }
154
155 const char *
GetLocalCacheDirectory()156 SBPlatformConnectOptions::GetLocalCacheDirectory()
157 {
158 return m_opaque_ptr->m_local_cache_directory.GetCString();
159 }
160
161 void
SetLocalCacheDirectory(const char * path)162 SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path)
163 {
164 if (path && path[0])
165 m_opaque_ptr->m_local_cache_directory.SetCString(path);
166 else
167 m_opaque_ptr->m_local_cache_directory = ConstString();
168 }
169
170 //----------------------------------------------------------------------
171 // SBPlatformShellCommand
172 //----------------------------------------------------------------------
SBPlatformShellCommand(const char * shell_command)173 SBPlatformShellCommand::SBPlatformShellCommand (const char *shell_command) :
174 m_opaque_ptr(new PlatformShellCommand(shell_command))
175 {
176 }
177
SBPlatformShellCommand(const SBPlatformShellCommand & rhs)178 SBPlatformShellCommand::SBPlatformShellCommand (const SBPlatformShellCommand &rhs) :
179 m_opaque_ptr(new PlatformShellCommand())
180 {
181 *m_opaque_ptr = *rhs.m_opaque_ptr;
182 }
183
~SBPlatformShellCommand()184 SBPlatformShellCommand::~SBPlatformShellCommand()
185 {
186 delete m_opaque_ptr;
187 }
188
189 void
Clear()190 SBPlatformShellCommand::Clear()
191 {
192 m_opaque_ptr->m_output = std::move(std::string());
193 m_opaque_ptr->m_status = 0;
194 m_opaque_ptr->m_signo = 0;
195 }
196
197 const char *
GetCommand()198 SBPlatformShellCommand::GetCommand()
199 {
200 if (m_opaque_ptr->m_command.empty())
201 return NULL;
202 return m_opaque_ptr->m_command.c_str();
203 }
204
205 void
SetCommand(const char * shell_command)206 SBPlatformShellCommand::SetCommand(const char *shell_command)
207 {
208 if (shell_command && shell_command[0])
209 m_opaque_ptr->m_command = shell_command;
210 else
211 m_opaque_ptr->m_command.clear();
212 }
213
214 const char *
GetWorkingDirectory()215 SBPlatformShellCommand::GetWorkingDirectory ()
216 {
217 if (m_opaque_ptr->m_working_dir.empty())
218 return NULL;
219 return m_opaque_ptr->m_working_dir.c_str();
220 }
221
222 void
SetWorkingDirectory(const char * path)223 SBPlatformShellCommand::SetWorkingDirectory (const char *path)
224 {
225 if (path && path[0])
226 m_opaque_ptr->m_working_dir = path;
227 else
228 m_opaque_ptr->m_working_dir.clear();
229 }
230
231 uint32_t
GetTimeoutSeconds()232 SBPlatformShellCommand::GetTimeoutSeconds ()
233 {
234 return m_opaque_ptr->m_timeout_sec;
235 }
236
237 void
SetTimeoutSeconds(uint32_t sec)238 SBPlatformShellCommand::SetTimeoutSeconds (uint32_t sec)
239 {
240 m_opaque_ptr->m_timeout_sec = sec;
241 }
242
243 int
GetSignal()244 SBPlatformShellCommand::GetSignal ()
245 {
246 return m_opaque_ptr->m_signo;
247 }
248
249 int
GetStatus()250 SBPlatformShellCommand::GetStatus ()
251 {
252 return m_opaque_ptr->m_status;
253 }
254
255 const char *
GetOutput()256 SBPlatformShellCommand::GetOutput ()
257 {
258 if (m_opaque_ptr->m_output.empty())
259 return NULL;
260 return m_opaque_ptr->m_output.c_str();
261 }
262
263 //----------------------------------------------------------------------
264 // SBPlatform
265 //----------------------------------------------------------------------
SBPlatform()266 SBPlatform::SBPlatform () :
267 m_opaque_sp ()
268 {
269
270 }
271
SBPlatform(const char * platform_name)272 SBPlatform::SBPlatform (const char *platform_name) :
273 m_opaque_sp ()
274 {
275 Error error;
276 if (platform_name && platform_name[0])
277 m_opaque_sp = Platform::Create (ConstString(platform_name), error);
278 }
279
~SBPlatform()280 SBPlatform::~SBPlatform()
281 {
282 }
283
284 bool
IsValid() const285 SBPlatform::IsValid () const
286 {
287 return m_opaque_sp.get() != NULL;
288 }
289
290 void
Clear()291 SBPlatform::Clear ()
292 {
293 m_opaque_sp.reset();
294 }
295
296 const char *
GetName()297 SBPlatform::GetName ()
298 {
299 PlatformSP platform_sp(GetSP());
300 if (platform_sp)
301 return platform_sp->GetName().GetCString();
302 return NULL;
303 }
304
305 lldb::PlatformSP
GetSP() const306 SBPlatform::GetSP () const
307 {
308 return m_opaque_sp;
309 }
310
311 void
SetSP(const lldb::PlatformSP & platform_sp)312 SBPlatform::SetSP (const lldb::PlatformSP& platform_sp)
313 {
314 m_opaque_sp = platform_sp;
315 }
316
317 const char *
GetWorkingDirectory()318 SBPlatform::GetWorkingDirectory()
319 {
320 PlatformSP platform_sp(GetSP());
321 if (platform_sp)
322 return platform_sp->GetWorkingDirectory().GetCString();
323 return NULL;
324 }
325
326 bool
SetWorkingDirectory(const char * path)327 SBPlatform::SetWorkingDirectory(const char *path)
328 {
329 PlatformSP platform_sp(GetSP());
330 if (platform_sp)
331 {
332 if (path)
333 platform_sp->SetWorkingDirectory(FileSpec{path, false});
334 else
335 platform_sp->SetWorkingDirectory(FileSpec{});
336 return true;
337 }
338 return false;
339 }
340
341 SBError
ConnectRemote(SBPlatformConnectOptions & connect_options)342 SBPlatform::ConnectRemote (SBPlatformConnectOptions &connect_options)
343 {
344 SBError sb_error;
345 PlatformSP platform_sp(GetSP());
346 if (platform_sp && connect_options.GetURL())
347 {
348 Args args;
349 args.AppendArgument(connect_options.GetURL());
350 sb_error.ref() = platform_sp->ConnectRemote(args);
351 }
352 else
353 {
354 sb_error.SetErrorString("invalid platform");
355 }
356 return sb_error;
357 }
358
359 void
DisconnectRemote()360 SBPlatform::DisconnectRemote ()
361 {
362 PlatformSP platform_sp(GetSP());
363 if (platform_sp)
364 platform_sp->DisconnectRemote();
365 }
366
367 bool
IsConnected()368 SBPlatform::IsConnected()
369 {
370 PlatformSP platform_sp(GetSP());
371 if (platform_sp)
372 platform_sp->IsConnected();
373 return false;
374 }
375
376 const char *
GetTriple()377 SBPlatform::GetTriple()
378 {
379 PlatformSP platform_sp(GetSP());
380 if (platform_sp)
381 {
382 ArchSpec arch(platform_sp->GetSystemArchitecture());
383 if (arch.IsValid())
384 {
385 // Const-ify the string so we don't need to worry about the lifetime of the string
386 return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
387 }
388 }
389 return NULL;
390 }
391
392 const char *
GetOSBuild()393 SBPlatform::GetOSBuild()
394 {
395 PlatformSP platform_sp(GetSP());
396 if (platform_sp)
397 {
398 std::string s;
399 if (platform_sp->GetOSBuildString(s))
400 {
401 if (!s.empty())
402 {
403 // Const-ify the string so we don't need to worry about the lifetime of the string
404 return ConstString(s.c_str()).GetCString();
405 }
406 }
407 }
408 return NULL;
409 }
410
411 const char *
GetOSDescription()412 SBPlatform::GetOSDescription()
413 {
414 PlatformSP platform_sp(GetSP());
415 if (platform_sp)
416 {
417 std::string s;
418 if (platform_sp->GetOSKernelDescription(s))
419 {
420 if (!s.empty())
421 {
422 // Const-ify the string so we don't need to worry about the lifetime of the string
423 return ConstString(s.c_str()).GetCString();
424 }
425 }
426 }
427 return NULL;
428 }
429
430 const char *
GetHostname()431 SBPlatform::GetHostname ()
432 {
433 PlatformSP platform_sp(GetSP());
434 if (platform_sp)
435 return platform_sp->GetHostname();
436 return NULL;
437 }
438
439 uint32_t
GetOSMajorVersion()440 SBPlatform::GetOSMajorVersion ()
441 {
442 uint32_t major, minor, update;
443 PlatformSP platform_sp(GetSP());
444 if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
445 return major;
446 return UINT32_MAX;
447
448 }
449
450 uint32_t
GetOSMinorVersion()451 SBPlatform::GetOSMinorVersion ()
452 {
453 uint32_t major, minor, update;
454 PlatformSP platform_sp(GetSP());
455 if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
456 return minor;
457 return UINT32_MAX;
458 }
459
460 uint32_t
GetOSUpdateVersion()461 SBPlatform::GetOSUpdateVersion ()
462 {
463 uint32_t major, minor, update;
464 PlatformSP platform_sp(GetSP());
465 if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
466 return update;
467 return UINT32_MAX;
468 }
469
470 SBError
Get(SBFileSpec & src,SBFileSpec & dst)471 SBPlatform::Get (SBFileSpec &src,
472 SBFileSpec &dst)
473 {
474 SBError sb_error;
475 PlatformSP platform_sp(GetSP());
476 if (platform_sp)
477 {
478 sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());
479 }
480 else
481 {
482 sb_error.SetErrorString("invalid platform");
483 }
484 return sb_error;
485 }
486
487 SBError
Put(SBFileSpec & src,SBFileSpec & dst)488 SBPlatform::Put (SBFileSpec &src,
489 SBFileSpec &dst)
490 {
491 return ExecuteConnected(
492 [&](const lldb::PlatformSP& platform_sp)
493 {
494 if (src.Exists())
495 {
496 uint32_t permissions = src.ref().GetPermissions();
497 if (permissions == 0)
498 {
499 if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory)
500 permissions = eFilePermissionsDirectoryDefault;
501 else
502 permissions = eFilePermissionsFileDefault;
503 }
504
505 return platform_sp->PutFile(src.ref(), dst.ref(), permissions);
506 }
507
508 Error error;
509 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
510 return error;
511 });
512 }
513
514 SBError
Install(SBFileSpec & src,SBFileSpec & dst)515 SBPlatform::Install (SBFileSpec &src,
516 SBFileSpec &dst)
517 {
518 return ExecuteConnected(
519 [&](const lldb::PlatformSP& platform_sp)
520 {
521 if (src.Exists())
522 return platform_sp->Install(src.ref(), dst.ref());
523
524 Error error;
525 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
526 return error;
527 });
528 }
529
530
531 SBError
Run(SBPlatformShellCommand & shell_command)532 SBPlatform::Run (SBPlatformShellCommand &shell_command)
533 {
534 return ExecuteConnected(
535 [&](const lldb::PlatformSP& platform_sp)
536 {
537 const char *command = shell_command.GetCommand();
538 if (!command)
539 return Error("invalid shell command (empty)");
540
541 const char *working_dir = shell_command.GetWorkingDirectory();
542 if (working_dir == NULL)
543 {
544 working_dir = platform_sp->GetWorkingDirectory().GetCString();
545 if (working_dir)
546 shell_command.SetWorkingDirectory(working_dir);
547 }
548 return platform_sp->RunShellCommand(command,
549 FileSpec{working_dir, false},
550 &shell_command.m_opaque_ptr->m_status,
551 &shell_command.m_opaque_ptr->m_signo,
552 &shell_command.m_opaque_ptr->m_output,
553 shell_command.m_opaque_ptr->m_timeout_sec);
554 });
555 }
556
557 SBError
Launch(SBLaunchInfo & launch_info)558 SBPlatform::Launch (SBLaunchInfo &launch_info)
559 {
560 return ExecuteConnected(
561 [&](const lldb::PlatformSP& platform_sp)
562 {
563 return platform_sp->LaunchProcess(launch_info.ref());
564 });
565 }
566
567 SBError
Kill(const lldb::pid_t pid)568 SBPlatform::Kill (const lldb::pid_t pid)
569 {
570 return ExecuteConnected(
571 [&](const lldb::PlatformSP& platform_sp)
572 {
573 return platform_sp->KillProcess(pid);
574 });
575 }
576
577 SBError
ExecuteConnected(const std::function<Error (const lldb::PlatformSP &)> & func)578 SBPlatform::ExecuteConnected (const std::function<Error(const lldb::PlatformSP&)>& func)
579 {
580 SBError sb_error;
581 const auto platform_sp(GetSP());
582 if (platform_sp)
583 {
584 if (platform_sp->IsConnected())
585 sb_error.ref() = func(platform_sp);
586 else
587 sb_error.SetErrorString("not connected");
588 }
589 else
590 sb_error.SetErrorString("invalid platform");
591
592 return sb_error;
593 }
594
595 SBError
MakeDirectory(const char * path,uint32_t file_permissions)596 SBPlatform::MakeDirectory (const char *path, uint32_t file_permissions)
597 {
598 SBError sb_error;
599 PlatformSP platform_sp(GetSP());
600 if (platform_sp)
601 {
602 sb_error.ref() = platform_sp->MakeDirectory(FileSpec{path, false}, file_permissions);
603 }
604 else
605 {
606 sb_error.SetErrorString("invalid platform");
607 }
608 return sb_error;
609 }
610
611 uint32_t
GetFilePermissions(const char * path)612 SBPlatform::GetFilePermissions (const char *path)
613 {
614 PlatformSP platform_sp(GetSP());
615 if (platform_sp)
616 {
617 uint32_t file_permissions = 0;
618 platform_sp->GetFilePermissions(FileSpec{path, false}, file_permissions);
619 return file_permissions;
620 }
621 return 0;
622
623 }
624
625 SBError
SetFilePermissions(const char * path,uint32_t file_permissions)626 SBPlatform::SetFilePermissions (const char *path, uint32_t file_permissions)
627 {
628 SBError sb_error;
629 PlatformSP platform_sp(GetSP());
630 if (platform_sp)
631 {
632 sb_error.ref() = platform_sp->SetFilePermissions(FileSpec{path, false}, file_permissions);
633 }
634 else
635 {
636 sb_error.SetErrorString("invalid platform");
637 }
638 return sb_error;
639
640 }
641
642 SBUnixSignals
GetUnixSignals() const643 SBPlatform::GetUnixSignals() const
644 {
645 if (auto platform_sp = GetSP())
646 return SBUnixSignals{platform_sp};
647
648 return {};
649 }
650