1 //===-- HostInfoLinux.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/Core/Log.h" 11 #include "lldb/Host/linux/HostInfoLinux.h" 12 13 #include <stdio.h> 14 #include <string.h> 15 #include <sys/utsname.h> 16 17 #include <algorithm> 18 19 using namespace lldb_private; 20 21 std::string HostInfoLinux::m_distribution_id; 22 uint32_t HostInfoLinux::m_os_major = 0; 23 uint32_t HostInfoLinux::m_os_minor = 0; 24 uint32_t HostInfoLinux::m_os_update = 0; 25 26 bool 27 HostInfoLinux::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) 28 { 29 static bool is_initialized = false; 30 static bool success = false; 31 32 if (!is_initialized) 33 { 34 is_initialized = true; 35 struct utsname un; 36 37 if (uname(&un)) 38 goto finished; 39 40 int status = sscanf(un.release, "%u.%u.%u", &major, &minor, &update); 41 if (status == 3) 42 { 43 success = true; 44 goto finished; 45 } 46 47 // Some kernels omit the update version, so try looking for just "X.Y" and 48 // set update to 0. 49 update = 0; 50 status = sscanf(un.release, "%u.%u", &major, &minor); 51 success = !!(status == 2); 52 } 53 54 finished: 55 major = m_os_major; 56 minor = m_os_minor; 57 update = m_os_update; 58 return success; 59 } 60 61 llvm::StringRef 62 HostInfoLinux::GetDistributionId() 63 { 64 static bool is_initialized = false; 65 // Try to run 'lbs_release -i', and use that response 66 // for the distribution id. 67 68 if (!is_initialized) 69 { 70 is_initialized = true; 71 72 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST)); 73 if (log) 74 log->Printf("attempting to determine Linux distribution..."); 75 76 // check if the lsb_release command exists at one of the 77 // following paths 78 const char *const exe_paths[] = {"/bin/lsb_release", "/usr/bin/lsb_release"}; 79 80 for (size_t exe_index = 0; exe_index < sizeof(exe_paths) / sizeof(exe_paths[0]); ++exe_index) 81 { 82 const char *const get_distribution_info_exe = exe_paths[exe_index]; 83 if (access(get_distribution_info_exe, F_OK)) 84 { 85 // this exe doesn't exist, move on to next exe 86 if (log) 87 log->Printf("executable doesn't exist: %s", get_distribution_info_exe); 88 continue; 89 } 90 91 // execute the distribution-retrieval command, read output 92 std::string get_distribution_id_command(get_distribution_info_exe); 93 get_distribution_id_command += " -i"; 94 95 FILE *file = popen(get_distribution_id_command.c_str(), "r"); 96 if (!file) 97 { 98 if (log) 99 log->Printf("failed to run command: \"%s\", cannot retrieve " 100 "platform information", 101 get_distribution_id_command.c_str()); 102 break; 103 } 104 105 // retrieve the distribution id string. 106 char distribution_id[256] = {'\0'}; 107 if (fgets(distribution_id, sizeof(distribution_id) - 1, file) != NULL) 108 { 109 if (log) 110 log->Printf("distribution id command returned \"%s\"", distribution_id); 111 112 const char *const distributor_id_key = "Distributor ID:\t"; 113 if (strstr(distribution_id, distributor_id_key)) 114 { 115 // strip newlines 116 std::string id_string(distribution_id + strlen(distributor_id_key)); 117 id_string.erase(std::remove(id_string.begin(), id_string.end(), '\n'), id_string.end()); 118 119 // lower case it and convert whitespace to underscores 120 std::transform(id_string.begin(), id_string.end(), id_string.begin(), [](char ch) 121 { 122 return tolower(isspace(ch) ? '_' : ch); 123 }); 124 125 m_distribution_id = id_string; 126 if (log) 127 log->Printf("distribution id set to \"%s\"", m_distribution_id.c_str()); 128 } 129 else 130 { 131 if (log) 132 log->Printf("failed to find \"%s\" field in \"%s\"", distributor_id_key, distribution_id); 133 } 134 } 135 else 136 { 137 if (log) 138 log->Printf("failed to retrieve distribution id, \"%s\" returned no" 139 " lines", 140 get_distribution_id_command.c_str()); 141 } 142 143 // clean up the file 144 pclose(file); 145 } 146 } 147 148 return m_distribution_id.c_str(); 149 } 150