1 //===-- SBFileSpec.cpp ------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/API/SBFileSpec.h"
10 #include "SBReproducerPrivate.h"
11 #include "Utils.h"
12 #include "lldb/API/SBStream.h"
13 #include "lldb/Host/FileSystem.h"
14 #include "lldb/Host/PosixApi.h"
15 #include "lldb/Utility/FileSpec.h"
16 #include "lldb/Utility/Log.h"
17 #include "lldb/Utility/Stream.h"
18 
19 #include "llvm/ADT/SmallString.h"
20 
21 #include <inttypes.h>
22 #include <limits.h>
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 SBFileSpec::SBFileSpec() : m_opaque_up(new lldb_private::FileSpec()) {
28   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFileSpec);
29 }
30 
31 SBFileSpec::SBFileSpec(const SBFileSpec &rhs) : m_opaque_up() {
32   LLDB_RECORD_CONSTRUCTOR(SBFileSpec, (const lldb::SBFileSpec &), rhs);
33 
34   m_opaque_up = clone(rhs.m_opaque_up);
35 }
36 
37 SBFileSpec::SBFileSpec(const lldb_private::FileSpec &fspec)
38     : m_opaque_up(new lldb_private::FileSpec(fspec)) {}
39 
40 // Deprecated!!!
41 SBFileSpec::SBFileSpec(const char *path) : m_opaque_up(new FileSpec(path)) {
42   LLDB_RECORD_CONSTRUCTOR(SBFileSpec, (const char *), path);
43 
44   FileSystem::Instance().Resolve(*m_opaque_up);
45 }
46 
47 SBFileSpec::SBFileSpec(const char *path, bool resolve)
48     : m_opaque_up(new FileSpec(path)) {
49   LLDB_RECORD_CONSTRUCTOR(SBFileSpec, (const char *, bool), path, resolve);
50 
51   if (resolve)
52     FileSystem::Instance().Resolve(*m_opaque_up);
53 }
54 
55 SBFileSpec::~SBFileSpec() {}
56 
57 const SBFileSpec &SBFileSpec::operator=(const SBFileSpec &rhs) {
58   LLDB_RECORD_METHOD(const lldb::SBFileSpec &,
59                      SBFileSpec, operator=,(const lldb::SBFileSpec &), rhs);
60 
61   if (this != &rhs)
62     m_opaque_up = clone(rhs.m_opaque_up);
63   return *this;
64 }
65 
66 bool SBFileSpec::IsValid() const {
67   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFileSpec, IsValid);
68 
69   return m_opaque_up->operator bool();
70 }
71 
72 bool SBFileSpec::Exists() const {
73   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFileSpec, Exists);
74 
75   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
76 
77   bool result = FileSystem::Instance().Exists(*m_opaque_up);
78 
79   if (log)
80     log->Printf("SBFileSpec(%p)::Exists () => %s",
81                 static_cast<void *>(m_opaque_up.get()),
82                 (result ? "true" : "false"));
83 
84   return result;
85 }
86 
87 bool SBFileSpec::ResolveExecutableLocation() {
88   LLDB_RECORD_METHOD_NO_ARGS(bool, SBFileSpec, ResolveExecutableLocation);
89 
90   return FileSystem::Instance().ResolveExecutableLocation(*m_opaque_up);
91 }
92 
93 int SBFileSpec::ResolvePath(const char *src_path, char *dst_path,
94                             size_t dst_len) {
95   LLDB_RECORD_STATIC_METHOD(int, SBFileSpec, ResolvePath,
96                             (const char *, char *, size_t), src_path, dst_path,
97                             dst_len);
98 
99   llvm::SmallString<64> result(src_path);
100   FileSystem::Instance().Resolve(result);
101   ::snprintf(dst_path, dst_len, "%s", result.c_str());
102   return std::min(dst_len - 1, result.size());
103 }
104 
105 const char *SBFileSpec::GetFilename() const {
106   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFileSpec, GetFilename);
107 
108   const char *s = m_opaque_up->GetFilename().AsCString();
109 
110   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
111   if (log) {
112     if (s)
113       log->Printf("SBFileSpec(%p)::GetFilename () => \"%s\"",
114                   static_cast<void *>(m_opaque_up.get()), s);
115     else
116       log->Printf("SBFileSpec(%p)::GetFilename () => NULL",
117                   static_cast<void *>(m_opaque_up.get()));
118   }
119 
120   return s;
121 }
122 
123 const char *SBFileSpec::GetDirectory() const {
124   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFileSpec, GetDirectory);
125 
126   FileSpec directory{*m_opaque_up};
127   directory.GetFilename().Clear();
128   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
129   if (log) {
130     if (directory)
131       log->Printf("SBFileSpec(%p)::GetDirectory () => \"%s\"",
132                   static_cast<void *>(m_opaque_up.get()),
133                   directory.GetCString());
134     else
135       log->Printf("SBFileSpec(%p)::GetDirectory () => NULL",
136                   static_cast<void *>(m_opaque_up.get()));
137   }
138   return directory.GetCString();
139 }
140 
141 void SBFileSpec::SetFilename(const char *filename) {
142   LLDB_RECORD_METHOD(void, SBFileSpec, SetFilename, (const char *), filename);
143 
144   if (filename && filename[0])
145     m_opaque_up->GetFilename().SetCString(filename);
146   else
147     m_opaque_up->GetFilename().Clear();
148 }
149 
150 void SBFileSpec::SetDirectory(const char *directory) {
151   LLDB_RECORD_METHOD(void, SBFileSpec, SetDirectory, (const char *), directory);
152 
153   if (directory && directory[0])
154     m_opaque_up->GetDirectory().SetCString(directory);
155   else
156     m_opaque_up->GetDirectory().Clear();
157 }
158 
159 uint32_t SBFileSpec::GetPath(char *dst_path, size_t dst_len) const {
160   LLDB_RECORD_METHOD_CONST(uint32_t, SBFileSpec, GetPath, (char *, size_t),
161                            dst_path, dst_len);
162 
163   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
164 
165   uint32_t result = m_opaque_up->GetPath(dst_path, dst_len);
166 
167   if (log)
168     log->Printf("SBFileSpec(%p)::GetPath (dst_path=\"%.*s\", dst_len=%" PRIu64
169                 ") => %u",
170                 static_cast<void *>(m_opaque_up.get()), result, dst_path,
171                 static_cast<uint64_t>(dst_len), result);
172 
173   if (result == 0 && dst_path && dst_len > 0)
174     *dst_path = '\0';
175   return result;
176 }
177 
178 const lldb_private::FileSpec *SBFileSpec::operator->() const {
179   return m_opaque_up.get();
180 }
181 
182 const lldb_private::FileSpec *SBFileSpec::get() const {
183   return m_opaque_up.get();
184 }
185 
186 const lldb_private::FileSpec &SBFileSpec::operator*() const {
187   return *m_opaque_up;
188 }
189 
190 const lldb_private::FileSpec &SBFileSpec::ref() const { return *m_opaque_up; }
191 
192 void SBFileSpec::SetFileSpec(const lldb_private::FileSpec &fs) {
193   *m_opaque_up = fs;
194 }
195 
196 bool SBFileSpec::GetDescription(SBStream &description) const {
197   LLDB_RECORD_METHOD_CONST(bool, SBFileSpec, GetDescription, (lldb::SBStream &),
198                            description);
199 
200   Stream &strm = description.ref();
201   char path[PATH_MAX];
202   if (m_opaque_up->GetPath(path, sizeof(path)))
203     strm.PutCString(path);
204   return true;
205 }
206 
207 void SBFileSpec::AppendPathComponent(const char *fn) {
208   LLDB_RECORD_METHOD(void, SBFileSpec, AppendPathComponent, (const char *), fn);
209 
210   m_opaque_up->AppendPathComponent(fn);
211 }
212