069f0432753cb201afc4f72d72e9e34a18a119c2
1 /**
2 * collectd - src/uuid.c
3 * Copyright (C) 2007 Red Hat Inc.
4 *
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; only version 2 of the License is applicable.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 * Authors:
19 * Dan Berrange <berrange@redhat.com>
20 * Richard W.M. Jones <rjones@redhat.com>
21 *
22 * Derived from UUID detection code by Dan Berrange <berrange@redhat.com>
23 * http://hg.et.redhat.com/virt/daemons/spectre--devel?f=f6e3a1b06433;file=lib/uuid.c
24 **/
26 #include "collectd.h"
28 #include "common.h"
29 #include "configfile.h"
30 #include "plugin.h"
32 #if HAVE_LIBHAL_H
33 #include <libhal.h>
34 #endif
36 #define UUID_RAW_LENGTH 16
37 #define UUID_PRINTABLE_COMPACT_LENGTH (UUID_RAW_LENGTH * 2)
38 #define UUID_PRINTABLE_NORMAL_LENGTH (UUID_PRINTABLE_COMPACT_LENGTH + 4)
40 static char *uuidfile = NULL;
42 static const char *config_keys[] = {
43 "UUIDFile"
44 };
46 static int
47 looks_like_a_uuid (const char *uuid)
48 {
49 int len;
51 if (!uuid) return 0;
53 len = strlen (uuid);
55 if (len < UUID_PRINTABLE_COMPACT_LENGTH)
56 return 0;
58 while (*uuid) {
59 if (!isxdigit ((int)*uuid) && *uuid != '-') return 0;
60 uuid++;
61 }
62 return 1;
63 }
65 static char *
66 uuid_parse_dmidecode(FILE *file)
67 {
68 char line[1024];
70 while (fgets (line, sizeof (line), file) != NULL)
71 {
72 char *fields[4];
73 int fields_num;
75 strstripnewline (line);
77 /* Look for a line reading:
78 * UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
79 */
80 fields_num = strsplit (line, fields, STATIC_ARRAY_SIZE (fields));
81 if (fields_num != 2)
82 continue;
84 if (strcmp("UUID:", fields[0]) != 0)
85 continue;
87 if (!looks_like_a_uuid (fields[1]))
88 continue;
90 return strdup (fields[1]);
91 }
92 return NULL;
93 }
95 static char *
96 uuid_get_from_dmidecode(void)
97 {
98 FILE *dmidecode = popen("dmidecode 2>/dev/null", "r");
99 char *uuid;
101 if (!dmidecode) {
102 return NULL;
103 }
105 uuid = uuid_parse_dmidecode(dmidecode);
107 pclose(dmidecode);
108 return uuid;
109 }
111 #if HAVE_LIBHAL_H
113 #define UUID_PATH "/org/freedesktop/Hal/devices/computer"
114 #define UUID_PROPERTY "smbios.system.uuid"
116 static char *
117 uuid_get_from_hal(void)
118 {
119 LibHalContext *ctx;
121 DBusError error;
122 DBusConnection *con;
124 dbus_error_init(&error);
126 if (!(con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) ) {
127 goto bailout_nobus;
128 }
130 ctx = libhal_ctx_new();
131 libhal_ctx_set_dbus_connection(ctx, con);
133 if (!libhal_ctx_init(ctx, &error)) {
134 goto bailout;
135 }
137 if (!libhal_device_property_exists(ctx,
138 UUID_PATH,
139 UUID_PROPERTY,
140 &error)) {
141 goto bailout;
142 }
144 char *uuid = libhal_device_get_property_string(ctx,
145 UUID_PATH,
146 UUID_PROPERTY,
147 &error);
148 if (looks_like_a_uuid (uuid)) {
149 return uuid;
150 }
152 bailout:
153 {
154 DBusError ctxerror;
155 dbus_error_init(&ctxerror);
156 if (!(libhal_ctx_shutdown(ctx, &ctxerror))) {
157 dbus_error_free(&ctxerror);
158 }
159 }
161 libhal_ctx_free(ctx);
162 //dbus_connection_unref(con);
164 bailout_nobus:
165 if (dbus_error_is_set(&error)) {
166 /*printf("Error %s\n", error.name);*/
167 dbus_error_free(&error);
168 }
169 return NULL;
170 }
171 #endif
173 static char *
174 uuid_get_from_file(const char *path)
175 {
176 FILE *file;
177 char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1] = "";
179 file = fopen (path, "r");
180 if (file == NULL)
181 return NULL;
183 if (!fgets(uuid, sizeof(uuid), file)) {
184 fclose(file);
185 return NULL;
186 }
187 fclose(file);
188 strstripnewline (uuid);
190 return strdup (uuid);
191 }
193 static char *
194 uuid_get_local(void)
195 {
196 char *uuid;
198 /* Check /etc/uuid / UUIDFile before any other method. */
199 if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL){
200 return uuid;
201 }
203 #if HAVE_LIBHAL_H
204 if ((uuid = uuid_get_from_hal()) != NULL) {
205 return uuid;
206 }
207 #endif
209 if ((uuid = uuid_get_from_dmidecode()) != NULL) {
210 return uuid;
211 }
213 if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL) {
214 return uuid;
215 }
217 return NULL;
218 }
220 static int
221 uuid_config (const char *key, const char *value)
222 {
223 if (strcasecmp (key, "UUIDFile") == 0) {
224 char *tmp = strdup (value);
225 if (tmp == NULL)
226 return -1;
227 sfree (uuidfile);
228 uuidfile = tmp;
229 } else {
230 return 1;
231 }
233 return 0;
234 }
236 static int
237 uuid_init (void)
238 {
239 char *uuid = uuid_get_local ();
241 if (uuid) {
242 sstrncpy (hostname_g, uuid, DATA_MAX_NAME_LEN);
243 sfree (uuid);
244 return 0;
245 }
247 WARNING ("uuid: could not read UUID using any known method");
248 return 0;
249 }
251 void module_register (void)
252 {
253 plugin_register_config ("uuid", uuid_config,
254 config_keys, STATIC_ARRAY_SIZE (config_keys));
255 plugin_register_init ("uuid", uuid_init);
256 }
258 /*
259 * vim: set tabstop=4:
260 * vim: set shiftwidth=4:
261 * vim: set expandtab:
262 */
263 /*
264 * Local variables:
265 * indent-tabs-mode: nil
266 * c-indent-level: 4
267 * c-basic-offset: 4
268 * tab-width: 4
269 * End:
270 */