HostInfoPosix.cpp revision 275129
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
25using namespace lldb_private;
26
27size_t
28HostInfoPosix::GetPageSize()
29{
30    return ::getpagesize();
31}
32
33bool
34HostInfoPosix::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
50const char *
51HostInfoPosix::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
69const char *
70HostInfoPosix::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
100uint32_t
101HostInfoPosix::GetUserID()
102{
103    return getuid();
104}
105
106uint32_t
107HostInfoPosix::GetGroupID()
108{
109    return getgid();
110}
111
112uint32_t
113HostInfoPosix::GetEffectiveUserID()
114{
115    return geteuid();
116}
117
118uint32_t
119HostInfoPosix::GetEffectiveGroupID()
120{
121    return getegid();
122}
123
124bool
125HostInfoPosix::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
165bool
166HostInfoPosix::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
173bool
174HostInfoPosix::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