2 * collectd - src/uuid.c
3 * Copyright (C) 2007 Red Hat Inc.
4 * Copyright (C) 2015 Ruben Kerkhof
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; only version 2 of the License is applicable.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Dan Berrange <berrange@redhat.com>
21 * Richard W.M. Jones <rjones@redhat.com>
23 * Derived from UUID detection code by Dan Berrange <berrange@redhat.com>
24 * http://hg.et.redhat.com/virt/daemons/spectre--devel?f=f6e3a1b06433;file=lib/uuid.c
30 #include "utils/common/common.h"
32 #if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME) || defined(__OpenBSD__)
33 /* Implies have BSD variant */
34 #include <sys/sysctl.h>
37 #define UUID_RAW_LENGTH 16
38 #define UUID_PRINTABLE_COMPACT_LENGTH (UUID_RAW_LENGTH * 2)
39 #define UUID_PRINTABLE_NORMAL_LENGTH (UUID_PRINTABLE_COMPACT_LENGTH + 4)
41 static char *uuidfile;
43 static const char *config_keys[] = {"UUIDFile"};
45 static int looks_like_a_uuid(const char *uuid) {
49 size_t len = strlen(uuid);
50 if (len < UUID_PRINTABLE_COMPACT_LENGTH)
54 if (!isxdigit((int)*uuid) && *uuid != '-')
61 static char *uuid_parse_dmidecode(FILE *file) {
64 while (fgets(line, sizeof(line), file) != NULL) {
68 strstripnewline(line);
70 /* Look for a line reading:
71 * UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
73 fields_num = strsplit(line, fields, STATIC_ARRAY_SIZE(fields));
77 if (strcmp("UUID:", fields[0]) != 0)
80 if (!looks_like_a_uuid(fields[1]))
83 return strdup(fields[1]);
88 static char *uuid_get_from_dmidecode(void) {
89 FILE *dmidecode = popen("dmidecode -t system 2>/dev/null", "r");
95 uuid = uuid_parse_dmidecode(dmidecode);
101 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
102 static char *uuid_get_from_sysctlbyname(const char *name) {
103 char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1];
104 size_t len = sizeof(uuid);
105 if (sysctlbyname(name, &uuid, &len, NULL, 0) == -1)
109 #elif defined(__OpenBSD__)
110 static char *uuid_get_from_sysctl(void) {
111 char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1];
112 size_t len = sizeof(uuid);
118 if (sysctl(mib, 2, uuid, &len, NULL, 0) == -1)
124 static char *uuid_get_from_file(const char *path) {
126 char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1] = "";
128 file = fopen(path, "r");
132 if (!fgets(uuid, sizeof(uuid), file)) {
137 strstripnewline(uuid);
142 static char *uuid_get_local(void) {
145 /* Check /etc/uuid / UUIDFile before any other method. */
146 if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL)
149 #if defined(__APPLE__)
150 if ((uuid = uuid_get_from_sysctlbyname("kern.uuid")) != NULL)
152 #elif defined(__FreeBSD__)
153 if ((uuid = uuid_get_from_sysctlbyname("kern.hostuuid")) != NULL)
155 #elif defined(__NetBSD__)
156 if ((uuid = uuid_get_from_sysctlbyname("machdep.dmi.system-uuid")) != NULL)
158 #elif defined(__OpenBSD__)
159 if ((uuid = uuid_get_from_sysctl()) != NULL)
161 #elif defined(__linux__)
162 if ((uuid = uuid_get_from_file("/sys/class/dmi/id/product_uuid")) != NULL)
166 if ((uuid = uuid_get_from_dmidecode()) != NULL)
169 #if defined(__linux__)
170 if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL)
177 static int uuid_config(const char *key, const char *value) {
178 if (strcasecmp(key, "UUIDFile") == 0) {
179 char *tmp = strdup(value);
190 static int uuid_init(void) {
191 char *uuid = uuid_get_local();
199 WARNING("uuid: could not read UUID using any known method");
203 void module_register(void) {
204 plugin_register_config("uuid", uuid_config, config_keys,
205 STATIC_ARRAY_SIZE(config_keys));
206 plugin_register_init("uuid", uuid_init);