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