e837ca725db74274d4b12868f102a8c4ade6a1d5
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)
52 return (0);
54 len = strlen (uuid);
56 if (len < UUID_PRINTABLE_COMPACT_LENGTH)
57 return (0);
59 while (*uuid) {
60 if (!isxdigit ((int)*uuid) && *uuid != '-')
61 return (0);
62 uuid++;
63 }
64 return (1);
65 }
67 static char *
68 uuid_parse_dmidecode(FILE *file)
69 {
70 char line[1024];
72 while (fgets (line, sizeof (line), file) != NULL)
73 {
74 char *fields[4];
75 int fields_num;
77 strstripnewline (line);
79 /* Look for a line reading:
80 * UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
81 */
82 fields_num = strsplit (line, fields, STATIC_ARRAY_SIZE (fields));
83 if (fields_num != 2)
84 continue;
86 if (strcmp("UUID:", fields[0]) != 0)
87 continue;
89 if (!looks_like_a_uuid (fields[1]))
90 continue;
92 return (strdup (fields[1]));
93 }
94 return (NULL);
95 }
97 static char *
98 uuid_get_from_dmidecode(void)
99 {
100 FILE *dmidecode = popen("dmidecode -t system 2>/dev/null", "r");
101 char *uuid;
103 if (!dmidecode)
104 return (NULL);
106 uuid = uuid_parse_dmidecode(dmidecode);
108 pclose(dmidecode);
109 return (uuid);
110 }
112 #if HAVE_LIBHAL_H
114 #define UUID_PATH "/org/freedesktop/Hal/devices/computer"
115 #define UUID_PROPERTY "smbios.system.uuid"
117 static char *
118 uuid_get_from_hal(void)
119 {
120 LibHalContext *ctx;
122 DBusError error;
123 DBusConnection *con;
125 dbus_error_init(&error);
127 if (!(con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)))
128 goto bailout_nobus;
130 ctx = libhal_ctx_new();
131 libhal_ctx_set_dbus_connection(ctx, con);
133 if (!libhal_ctx_init(ctx, &error))
134 goto bailout;
136 if (!libhal_device_property_exists(ctx,
137 UUID_PATH,
138 UUID_PROPERTY,
139 &error))
140 goto bailout;
142 char *uuid = libhal_device_get_property_string(ctx,
143 UUID_PATH,
144 UUID_PROPERTY,
145 &error);
146 if (looks_like_a_uuid (uuid))
147 return (uuid);
149 bailout:
150 {
151 DBusError ctxerror;
152 dbus_error_init(&ctxerror);
153 if (!(libhal_ctx_shutdown(ctx, &ctxerror)))
154 dbus_error_free(&ctxerror);
155 }
157 libhal_ctx_free(ctx);
159 bailout_nobus:
160 if (dbus_error_is_set(&error))
161 dbus_error_free(&error);
162 return (NULL);
163 }
164 #endif
166 static char *
167 uuid_get_from_file(const char *path)
168 {
169 FILE *file;
170 char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1] = "";
172 file = fopen (path, "r");
173 if (file == NULL)
174 return (NULL);
176 if (!fgets(uuid, sizeof(uuid), file)) {
177 fclose(file);
178 return (NULL);
179 }
180 fclose(file);
181 strstripnewline (uuid);
183 return (strdup (uuid));
184 }
186 static char *
187 uuid_get_local(void)
188 {
189 char *uuid;
191 /* Check /etc/uuid / UUIDFile before any other method. */
192 if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL)
193 return (uuid);
195 #if defined(__linux__)
196 if ((uuid = uuid_get_from_file("/sys/class/dmi/id/product_uuid")) != NULL)
197 return (uuid);
198 #endif
200 #if HAVE_LIBHAL_H
201 if ((uuid = uuid_get_from_hal()) != NULL)
202 return (uuid);
203 #endif
205 if ((uuid = uuid_get_from_dmidecode()) != NULL)
206 return (uuid);
208 #if defined(__linux__)
209 if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL)
210 return (uuid);
211 #endif
213 return (NULL);
214 }
216 static int
217 uuid_config (const char *key, const char *value)
218 {
219 if (strcasecmp (key, "UUIDFile") == 0) {
220 char *tmp = strdup (value);
221 if (tmp == NULL)
222 return (-1);
223 sfree (uuidfile);
224 uuidfile = tmp;
225 return (0);
226 }
228 return (1);
229 }
231 static int
232 uuid_init (void)
233 {
234 char *uuid = uuid_get_local ();
236 if (uuid) {
237 sstrncpy (hostname_g, uuid, DATA_MAX_NAME_LEN);
238 sfree (uuid);
239 return (0);
240 }
242 WARNING ("uuid: could not read UUID using any known method");
243 return (0);
244 }
246 void module_register (void)
247 {
248 plugin_register_config ("uuid", uuid_config,
249 config_keys, STATIC_ARRAY_SIZE (config_keys));
250 plugin_register_init ("uuid", uuid_init);
251 }
253 /*
254 * vim: set tabstop=4:
255 * vim: set shiftwidth=4:
256 * vim: set expandtab:
257 */
258 /*
259 * Local variables:
260 * indent-tabs-mode: nil
261 * c-indent-level: 4
262 * c-basic-offset: 4
263 * tab-width: 4
264 * End:
265 */