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