RSC  0.16.0
LinuxHostInfo.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is part of the RSC project
4  *
5  * Copyright (C) 2014 Jan Moringen
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #include "HostInfo.h"
28 
29 #include <errno.h>
30 #include <string.h>
31 #include <unistd.h>
32 
33 #include <stdexcept>
34 #include <fstream>
35 #include <sstream>
36 
37 #include <boost/lexical_cast.hpp>
38 #include <boost/format.hpp>
39 
40 #include <boost/date_time/posix_time/posix_time.hpp>
41 
42 namespace rsc {
43 namespace os {
44 
45 // {Machine,Software} {Type,Version}
46 
47 std::string currentMachineVersion() {
48  // Read entire contents of /proc/cpuinfo, preserving whitespace.
49  const std::string procCPUInfo = "/proc/cpuinfo";
50  std::ifstream stream(procCPUInfo.c_str());
51  stream >> std::noskipws;
52  std::string content;
53  std::copy(std::istream_iterator<char>(stream),
54  std::istream_iterator<char>(),
55  std::back_inserter(content));
56  // Locate the "model name" field.
57  std::string pattern("model name : ");
58  std::string::iterator start = std::search(content.begin(), content.end(),
59  pattern.begin(), pattern.end());
60  if (start == content.end()) {
61  throw std::runtime_error(
62  boost::str(boost::format("Could not determine machine version "
63  "since the \"%1\" entry could not be "
64  "found in the \"%2%\" file.")
65  % pattern % procCPUInfo));
66  }
67  // Field value is everything from ": " to end of line.
68  std::string::iterator end = std::find(start, content.end(), '\n');
69  if (end == content.end()) {
70  throw std::runtime_error(
71  boost::str(boost::format("Could not determine machine version "
72  "since the end of the \"%1\" entry "
73  "could not be found in the \"%2%\" "
74  "file.")
75  % pattern % procCPUInfo));
76  }
77  std::string value;
78  std::copy(start + pattern.size(), end, std::back_inserter(value));
79  return value;
80 }
81 
82 // Host ID
83 
84 std::string tryFile(const std::string& filename) {
85  std::string result = "";
86  std::ifstream stream(filename.c_str());
87  if (stream.good()) {
88  stream >> result;
89  }
90  return result;
91 }
92 
93 std::string hostId() {
94  std::ostringstream stream;
95  stream << std::hex << gethostid(); // cannot fail according to gethostid(3)
96  return stream.str();
97 }
98 
99 std::string currentHostId() {
100  std::string result;
101  if (!(result = tryFile("/etc/machine-id")).empty()) {
102  return result;
103  } else if (!(result = tryFile("/var/lib/dbus/machine-id")).empty()) {
104  return result;
105  } else {
106  return hostId();
107  }
108 }
109 
110 boost::posix_time::ptime currentBootTime() {
111  // Read system boot time in integral seconds since UNIX epoch.
112  // See /proc/stat section in proc(5).
113  boost::uint32_t bootTimeUNIXSeconds;
114 
115  const std::string procStat = "/proc/stat";
116  std::ifstream stream(procStat.c_str());
117  stream >> std::noskipws;
118  std::string content;
119  std::copy(std::istream_iterator<char>(stream),
120  std::istream_iterator<char>() ,
121  std::back_inserter(content));
122  std::string pattern("btime ");
123  std::string::iterator start = std::search(content.begin(), content.end(),
124  pattern.begin(), pattern.end());
125  if (start == content.end()) {
126  throw std::runtime_error(
127  boost::str(boost::format("Could not determine the boot time "
128  "since the \"%1\" entry could not be "
129  "found in the \"%2%\" file.")
130  % pattern % procStat));
131  }
132  std::string::iterator end = std::find(start, content.end(), '\n');
133  if (end == content.end()) {
134  throw std::runtime_error(
135  boost::str(boost::format("Could not determine the boot time "
136  "since the end of the \"%1\" entry "
137  "could not be found in the \"%2%\" "
138  "file.")
139  % pattern % procStat));
140  }
141  std::string value;
142  std::copy(start + pattern.size(), end, std::back_inserter(value));
143  try {
144  bootTimeUNIXSeconds = boost::lexical_cast<boost::int32_t>(value);
145  } catch (const boost::bad_lexical_cast& e) {
146  throw std::runtime_error(
147  boost::str(boost::format("Could not determine the boot time "
148  "since the \"%1\" entry in the "
149  "\"%2%\" file could not be parsed. "
150  "Reason: %3%")
151  % pattern % procStat % e.what()));
152  }
153 
154  return boost::posix_time::from_time_t(bootTimeUNIXSeconds);
155 }
156 
157 }
158 }
RSC_EXPORT std::string currentHostId()
Determine and return a unique id string of the local machine.
RSC_EXPORT boost::posix_time::ptime currentBootTime()
Return the boot time of the local machine.
RSC_EXPORT std::string currentMachineVersion()
Determine and return the version within its type, usually the CPU identification string, of the local machine.
std::string hostId()
std::string tryFile(const std::string &filename)