1 //===-- HostInfoPosix.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/lldb-python.h"
11 
12 #include "lldb/Core/Log.h"
13 #include "lldb/Host/posix/HostInfoPosix.h"
14 
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/Support/raw_ostream.h"
17 
18 #include <grp.h>
19 #include <limits.h>
20 #include <netdb.h>
21 #include <pwd.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 
25 using namespace lldb_private;
26 
27 size_t
28 HostInfoPosix::GetPageSize()
29 {
30     return ::getpagesize();
31 }
32 
33 bool
34 HostInfoPosix::GetHostname(std::string &s)
35 {
36     char hostname[PATH_MAX];
37     hostname[sizeof(hostname) - 1] = '\0';
38     if (::gethostname(hostname, sizeof(hostname) - 1) == 0)
39     {
40         struct hostent *h = ::gethostbyname(hostname);
41         if (h)
42             s.assign(h->h_name);
43         else
44             s.assign(hostname);
45         return true;
46     }
47     return false;
48 }
49 
50 const char *
51 HostInfoPosix::LookupUserName(uint32_t uid, std::string &user_name)
52 {
53     struct passwd user_info;
54     struct passwd *user_info_ptr = &user_info;
55     char user_buffer[PATH_MAX];
56     size_t user_buffer_size = sizeof(user_buffer);
57     if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size, &user_info_ptr) == 0)
58     {
59         if (user_info_ptr)
60         {
61             user_name.assign(user_info_ptr->pw_name);
62             return user_name.c_str();
63         }
64     }
65     user_name.clear();
66     return NULL;
67 }
68 
69 const char *
70 HostInfoPosix::LookupGroupName(uint32_t gid, std::string &group_name)
71 {
72     char group_buffer[PATH_MAX];
73     size_t group_buffer_size = sizeof(group_buffer);
74     struct group group_info;
75     struct group *group_info_ptr = &group_info;
76     // Try the threadsafe version first
77     if (::getgrgid_r(gid, &group_info, group_buffer, group_buffer_size, &group_info_ptr) == 0)
78     {
79         if (group_info_ptr)
80         {
81             group_name.assign(group_info_ptr->gr_name);
82             return group_name.c_str();
83         }
84     }
85     else
86     {
87         // The threadsafe version isn't currently working for me on darwin, but the non-threadsafe version
88         // is, so I am calling it below.
89         group_info_ptr = ::getgrgid(gid);
90         if (group_info_ptr)
91         {
92             group_name.assign(group_info_ptr->gr_name);
93             return group_name.c_str();
94         }
95     }
96     group_name.clear();
97     return NULL;
98 }
99 
100 uint32_t
101 HostInfoPosix::GetUserID()
102 {
103     return getuid();
104 }
105 
106 uint32_t
107 HostInfoPosix::GetGroupID()
108 {
109     return getgid();
110 }
111 
112 uint32_t
113 HostInfoPosix::GetEffectiveUserID()
114 {
115     return geteuid();
116 }
117 
118 uint32_t
119 HostInfoPosix::GetEffectiveGroupID()
120 {
121     return getegid();
122 }
123 
124 bool
125 HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec)
126 {
127     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
128 
129     FileSpec lldb_file_spec;
130     if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
131         return false;
132 
133     char raw_path[PATH_MAX];
134     lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
135 
136     // Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with */bin as the base
137     // directory for helper exe programs.  This will fail if the /lib and /bin directories are
138     // rooted in entirely different trees.
139     if (log)
140         log->Printf("HostInfoPosix::ComputeSupportExeDirectory() attempting to derive the bin path (ePathTypeSupportExecutableDir) from "
141                     "this path: %s",
142                     raw_path);
143     char *lib_pos = ::strstr(raw_path, "/lib");
144     if (lib_pos != nullptr)
145     {
146         // First terminate the raw path at the start of lib.
147         *lib_pos = '\0';
148 
149         // Now write in bin in place of lib.
150         ::strncpy(lib_pos, "/bin", PATH_MAX - (lib_pos - raw_path));
151 
152         if (log)
153             log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__, raw_path);
154     }
155     else
156     {
157         if (log)
158             log->Printf("Host::%s() failed to find /lib/liblldb within the shared lib path, bailing on bin path construction",
159                         __FUNCTION__);
160     }
161     file_spec.GetDirectory().SetCString(raw_path);
162     return (bool)file_spec.GetDirectory();
163 }
164 
165 bool
166 HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec)
167 {
168     FileSpec temp_file("/opt/local/include/lldb", false);
169     file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
170     return true;
171 }
172 
173 bool
174 HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec)
175 {
176     return false; // No Python in FreeBSD base system
177 #if 0
178     FileSpec lldb_file_spec;
179     if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
180         return false;
181 
182     char raw_path[PATH_MAX];
183     lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
184 
185     llvm::SmallString<256> python_version_dir;
186     llvm::raw_svector_ostream os(python_version_dir);
187     os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages";
188     os.flush();
189 
190     // We may get our string truncated. Should we protect this with an assert?
191     ::strncat(raw_path, python_version_dir.c_str(), sizeof(raw_path) - strlen(raw_path) - 1);
192 
193     file_spec.GetDirectory().SetCString(raw_path);
194     return true;
195 #endif
196 }
197