2 * Copyright (C) 2012 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include <sys/utsname.h>
21 #include <utils/linked_list.h>
24 typedef struct private_os_info_t private_os_info_t
;
26 ENUM(os_fwd_status_names
, OS_FWD_DISABLED
, OS_FWD_UNKNOWN
,
33 * Private data of an os_info_t object.
36 struct private_os_info_t
{
39 * Public os_info_t interface.
55 METHOD(os_info_t
, get_name
, chunk_t
,
56 private_os_info_t
*this)
61 METHOD(os_info_t
, get_version
, chunk_t
,
62 private_os_info_t
*this)
67 METHOD(os_info_t
, get_fwd_status
, os_fwd_status_t
,
68 private_os_info_t
*this)
70 const char ip_forward
[] = "/proc/sys/net/ipv4/ip_forward";
74 os_fwd_status_t fwd_status
= OS_FWD_UNKNOWN
;
76 file
= fopen(ip_forward
, "r");
79 if (fread(buf
, 1, 1, file
) == 1)
84 fwd_status
= OS_FWD_DISABLED
;
87 fwd_status
= OS_FWD_ENABLED
;
90 DBG1(DBG_IMC
, "\"%s\" returns invalid value ", ip_forward
);
96 DBG1(DBG_IMC
, "could not read from \"%s\"", ip_forward
);
102 DBG1(DBG_IMC
, "failed to open \"%s\"", ip_forward
);
108 METHOD(os_info_t
, get_uptime
, time_t,
109 private_os_info_t
*this)
111 const char proc_uptime
[] = "/proc/uptime";
115 file
= fopen(proc_uptime
, "r");
118 DBG1(DBG_IMC
, "failed to open \"%s\"", proc_uptime
);
121 if (fscanf(file
, "%u", &uptime
) != 1)
123 DBG1(DBG_IMC
, "failed to read file \"%s\"", proc_uptime
);
131 METHOD(os_info_t
, create_package_enumerator
, enumerator_t
*,
132 private_os_info_t
*this)
140 METHOD(os_info_t
, destroy
, void,
141 private_os_info_t
*this)
143 free(this->name
.ptr
);
144 free(this->version
.ptr
);
148 #define RELEASE_LSB 0
149 #define RELEASE_DEBIAN 1
152 * Determine Linux distribution version and hardware platform
154 static bool extract_platform_info(chunk_t
*name
, chunk_t
*version
)
157 u_char buf
[BUF_LEN
], *pos
= buf
;
158 int len
= BUF_LEN
- 1;
159 chunk_t os_name
= chunk_empty
;
160 chunk_t os_version
= chunk_empty
;
161 struct utsname uninfo
;
164 /* Linux/Unix distribution release info (from http://linuxmafia.com) */
165 const char* releases
[] = {
166 "/etc/lsb-release", "/etc/debian_version",
167 "/etc/SuSE-release", "/etc/novell-release",
168 "/etc/sles-release", "/etc/redhat-release",
169 "/etc/fedora-release", "/etc/gentoo-release",
170 "/etc/slackware-version", "/etc/annvix-release",
171 "/etc/arch-release", "/etc/arklinux-release",
172 "/etc/aurox-release", "/etc/blackcat-release",
173 "/etc/cobalt-release", "/etc/conectiva-release",
174 "/etc/debian_release", "/etc/immunix-release",
175 "/etc/lfs-release", "/etc/linuxppc-release",
176 "/etc/mandrake-release", "/etc/mandriva-release",
177 "/etc/mandrakelinux-release", "/etc/mklinux-release",
178 "/etc/pld-release", "/etc/redhat_version",
179 "/etc/slackware-release", "/etc/e-smith-release",
180 "/etc/release", "/etc/sun-release",
181 "/etc/tinysofa-release", "/etc/turbolinux-release",
182 "/etc/ultrapenguin-release", "/etc/UnitedLinux-release",
183 "/etc/va-release", "/etc/yellowdog-release"
186 const char lsb_distrib_id
[] = "DISTRIB_ID=";
187 const char lsb_distrib_release
[] = "DISTRIB_RELEASE=";
189 for (i
= 0; i
< countof(releases
); i
++)
191 file
= fopen(releases
[i
], "r");
197 /* read release file into buffer */
198 fseek(file
, 0, SEEK_END
);
199 len
= min(ftell(file
), len
);
202 if (fread(buf
, 1, len
, file
) != len
)
204 DBG1(DBG_IMC
, "failed to read file \"%s\"", releases
[i
]);
210 DBG1(DBG_IMC
, "processing \"%s\" file", releases
[i
]);
216 /* Determine Distribution ID */
217 pos
= strstr(buf
, lsb_distrib_id
);
220 DBG1(DBG_IMC
, "failed to find begin of DISTRIB_ID field");
223 pos
+= strlen(lsb_distrib_id
);
227 pos
= strchr(pos
, '\n');
230 DBG1(DBG_IMC
, "failed to find end of DISTRIB_ID field");
234 os_name
.len
= pos
- os_name
.ptr
;
236 /* Determine Distribution Release */
237 pos
= strstr(buf
, lsb_distrib_release
);
240 DBG1(DBG_IMC
, "failed to find begin of DISTRIB_RELEASE field");
243 pos
+= strlen(lsb_distrib_release
);
245 os_version
.ptr
= pos
;
247 pos
= strchr(pos
, '\n');
250 DBG1(DBG_IMC
, "failed to find end of DISTRIB_RELEASE field");
254 os_version
.len
= pos
- os_version
.ptr
;
260 char str_debian
[] = "Debian";
262 os_name
= chunk_create(str_debian
, strlen(str_debian
));
263 os_version
.ptr
= buf
;
265 pos
= strchr(buf
, '\n');
268 DBG1(DBG_PTS
, "failed to find end of release string");
272 os_version
.len
= pos
- os_version
.ptr
;
278 const char str_release
[] = " release ";
282 pos
= strstr(buf
, str_release
);
285 DBG1(DBG_IMC
, "failed to find release keyword");
289 os_name
.len
= pos
- os_name
.ptr
;
290 pos
+= strlen(str_release
);
291 os_version
.ptr
= pos
;
293 pos
= strchr(pos
, '\n');
296 DBG1(DBG_IMC
, "failed to find end of release string");
300 os_version
.len
= pos
- os_version
.ptr
;
310 DBG1(DBG_IMC
, "no distribution release file found");
314 if (uname(&uninfo
) < 0)
316 DBG1(DBG_IMC
, "could not retrieve machine architecture");
321 *name
= chunk_clone(os_name
);
323 /* copy OS version and machine architecture */
324 *version
= chunk_alloc(os_version
.len
+ 1 + strlen(uninfo
.machine
));
326 memcpy(pos
, os_version
.ptr
, os_version
.len
);
327 pos
+= os_version
.len
;
329 memcpy(pos
, uninfo
.machine
, strlen(uninfo
.machine
));
337 os_info_t
*os_info_create(void)
339 private_os_info_t
*this;
340 chunk_t name
, version
;
342 /* As an opton OS name and OS version can be configured manually */
343 name
.ptr
= lib
->settings
->get_str(lib
->settings
,
344 "libimcv.os_info.name", NULL
);
345 version
.ptr
= lib
->settings
->get_str(lib
->settings
,
346 "libimcv.os_info.version", NULL
);
347 if (name
.ptr
&& version
.ptr
)
349 name
.len
= strlen(name
.ptr
);
350 name
= chunk_clone(name
);
352 version
.len
= strlen(version
.ptr
);
353 version
= chunk_clone(version
);
357 if (!extract_platform_info(&name
, &version
))
362 DBG1(DBG_IMC
, "operating system name is '%.*s'",
364 DBG1(DBG_IMC
, "operating system version is '%.*s'",
365 version
.len
, version
.ptr
);
369 .get_name
= _get_name
,
370 .get_version
= _get_version
,
371 .get_fwd_status
= _get_fwd_status
,
372 .get_uptime
= _get_uptime
,
373 .create_package_enumerator
= _create_package_enumerator
,
380 return &this->public;