Code

Merge remote-tracking branch 'github/pr/387'
[collectd.git] / src / uuid.c
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"
27 #include "common.h"
28 #include "configfile.h"
29 #include "plugin.h"
31 #if HAVE_LIBHAL
32 #include <libhal.h>
33 #endif
35 #define UUID_RAW_LENGTH 16
36 #define UUID_PRINTABLE_COMPACT_LENGTH  (UUID_RAW_LENGTH * 2)
37 #define UUID_PRINTABLE_NORMAL_LENGTH  (UUID_PRINTABLE_COMPACT_LENGTH + 4)
39 static char *uuidfile = NULL;
41 static const char *config_keys[] = {
42     "UUIDFile"
43 };
45 static int
46 looks_like_a_uuid (const char *uuid)
47 {
48     int len;
50     if (!uuid) return 0;
52     len = strlen (uuid);
54     if (len < UUID_PRINTABLE_COMPACT_LENGTH)
55         return 0;
57     while (*uuid) {
58         if (!isxdigit ((int)*uuid) && *uuid != '-') return 0;
59         uuid++;
60     }
61     return 1;
62 }
64 static char *
65 uuid_parse_dmidecode(FILE *file)
66 {
67     char line[1024];
69     while (fgets (line, sizeof (line), file) != NULL)
70     {
71         char *fields[4];
72         int fields_num;
74         strstripnewline (line);
76         /* Look for a line reading:
77          *   UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
78          */
79         fields_num = strsplit (line, fields, STATIC_ARRAY_SIZE (fields));
80         if (fields_num != 2)
81             continue;
83         if (strcmp("UUID:", fields[0]) != 0)
84             continue;
86         if (!looks_like_a_uuid (fields[1]))
87             continue;
89         return strdup (fields[1]);
90     }
91     return NULL;
92 }
94 static char *
95 uuid_get_from_dmidecode(void)
96 {
97     FILE *dmidecode = popen("dmidecode 2>/dev/null", "r");
98     char *uuid;
100     if (!dmidecode) {
101         return NULL;
102     }
103     
104     uuid = uuid_parse_dmidecode(dmidecode);
106     pclose(dmidecode);
107     return uuid;
110 #if HAVE_LIBHAL
112 #define UUID_PATH "/org/freedesktop/Hal/devices/computer"
113 #define UUID_PROPERTY "smbios.system.uuid"
115 static char *
116 uuid_get_from_hal(void)
118     LibHalContext *ctx;
120     DBusError error;
121     DBusConnection *con;
123     dbus_error_init(&error);
125     if (!(con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) ) {
126         goto bailout_nobus;
127     }
129     ctx = libhal_ctx_new();
130     libhal_ctx_set_dbus_connection(ctx, con);
132     if (!libhal_ctx_init(ctx, &error)) {
133         goto bailout;
134     }
136     if (!libhal_device_property_exists(ctx,
137                                        UUID_PATH,
138                                        UUID_PROPERTY,
139                                        &error)) {
140         goto bailout;
141     }
143     char *uuid  = libhal_device_get_property_string(ctx,
144                                                     UUID_PATH,
145                                                     UUID_PROPERTY,
146                                                     &error);
147     if (looks_like_a_uuid (uuid)) {
148         return uuid;
149     }
151  bailout:
152     {
153         DBusError ctxerror;
154         dbus_error_init(&ctxerror);
155         if (!(libhal_ctx_shutdown(ctx, &ctxerror))) {
156             dbus_error_free(&ctxerror);
157         }
158     }
160     libhal_ctx_free(ctx);
161     //dbus_connection_unref(con);
163  bailout_nobus:
164     if (dbus_error_is_set(&error)) {
165         /*printf("Error %s\n", error.name);*/
166         dbus_error_free(&error);
167     }
168     return NULL;
170 #endif
172 static char *
173 uuid_get_from_file(const char *path)
175     FILE *file;
176     char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1] = "";
178     file = fopen (path, "r");
179     if (file == NULL)
180         return NULL;
182     if (!fgets(uuid, sizeof(uuid), file)) {
183         fclose(file);
184         return NULL;
185     }
186     fclose(file);
187     strstripnewline (uuid);
189     return strdup (uuid);
192 static char *
193 uuid_get_local(void)
195     char *uuid;
197     /* Check /etc/uuid / UUIDFile before any other method. */
198     if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL){
199         return uuid;
200     }
202 #if HAVE_LIBHAL
203     if ((uuid = uuid_get_from_hal()) != NULL) {
204         return uuid;
205     }
206 #endif
208     if ((uuid = uuid_get_from_dmidecode()) != NULL) {
209         return uuid;
210     }
212     if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL) {
213         return uuid;
214     }
216     return NULL;
219 static int
220 uuid_config (const char *key, const char *value)
222     if (strcasecmp (key, "UUIDFile") == 0) {
223         char *tmp = strdup (value);
224         if (tmp == NULL)
225             return -1;
226         sfree (uuidfile);
227         uuidfile = tmp;
228     } else {
229         return 1;
230     }
232     return 0;
235 static int
236 uuid_init (void)
238     char *uuid = uuid_get_local ();
240     if (uuid) {
241         sstrncpy (hostname_g, uuid, DATA_MAX_NAME_LEN);
242         sfree (uuid);
243         return 0;
244     }
246     WARNING ("uuid: could not read UUID using any known method");
247     return 0;
250 void module_register (void)
252     plugin_register_config ("uuid", uuid_config,
253             config_keys, STATIC_ARRAY_SIZE (config_keys));
254     plugin_register_init ("uuid", uuid_init);
257 /*
258  * vim: set tabstop=4:
259  * vim: set shiftwidth=4:
260  * vim: set expandtab:
261  */
262 /*
263  * Local variables:
264  *  indent-tabs-mode: nil
265  *  c-indent-level: 4
266  *  c-basic-offset: 4
267  *  tab-width: 4
268  * End:
269  */