Merge branch 'master' of verplant.org:/var/lib/git/collection4
[collection4.git] / src / graph_ident.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <strings.h>
6 #include <errno.h>
7 #include <limits.h> /* PATH_MAX */
8 #include <sys/types.h>
9 #include <sys/stat.h>
10
11 #include "graph_ident.h"
12 #include "common.h"
13 #include "filesystem.h"
14
15 #include <fcgiapp.h>
16 #include <fcgi_stdio.h>
17
18 /*
19  * Data types
20  */
21 struct graph_ident_s /* {{{ */
22 {
23   char *host;
24   char *plugin;
25   char *plugin_instance;
26   char *type;
27   char *type_instance;
28 }; /* }}} struct graph_ident_s */
29
30 /*
31  * Private functions
32  */
33 static char *part_copy_with_selector (const char *selector, /* {{{ */
34     const char *part, unsigned int flags)
35 {
36   if ((selector == NULL) || (part == NULL))
37     return (NULL);
38
39   if ((flags & IDENT_FLAG_REPLACE_ANY) && IS_ANY (part))
40     return (NULL);
41
42   if ((flags & IDENT_FLAG_REPLACE_ALL) && IS_ALL (part))
43     return (NULL);
44
45   /* Replace the ANY and ALL flags if requested and if the selecter actually
46    * *is* that flag. */
47   if (IS_ANY (selector))
48   {
49     if (flags & IDENT_FLAG_REPLACE_ANY)
50       return (strdup (part));
51     else
52       return (strdup (selector));
53   }
54
55   if (IS_ALL (selector))
56   {
57     if (flags & IDENT_FLAG_REPLACE_ALL)
58       return (strdup (part));
59     else
60       return (strdup (selector));
61   }
62
63   if (strcmp (selector, part) != 0)
64     return (NULL);
65
66   /* Otherwise (no replacement), return a copy of the selector. */
67   return (strdup (selector));
68 } /* }}} char *part_copy_with_selector */
69
70 static _Bool part_matches (const char *selector, /* {{{ */
71     const char *part)
72 {
73   if ((selector == NULL) && (part == NULL))
74     return (1);
75
76   if (selector == NULL) /* && (part != NULL) */
77     return (0);
78
79   if (IS_ANY(selector) || IS_ALL(selector))
80     return (1);
81
82   if (part == NULL) /* && (selector != NULL) */
83     return (0);
84
85   if (strcmp (selector, part) == 0)
86     return (1);
87
88   return (0);
89 } /* }}} _Bool part_matches */
90
91 /*
92  * Public functions
93  */
94 graph_ident_t *ident_create (const char *host, /* {{{ */
95     const char *plugin, const char *plugin_instance,
96     const char *type, const char *type_instance)
97 {
98   graph_ident_t *ret;
99
100   if ((host == NULL)
101       || (plugin == NULL) || (plugin_instance == NULL)
102       || (type == NULL) || (type_instance == NULL))
103     return (NULL);
104
105   ret = malloc (sizeof (*ret));
106   if (ret == NULL)
107     return (NULL);
108   memset (ret, 0, sizeof (*ret));
109
110   ret->host = NULL;
111   ret->host = NULL;
112   ret->plugin = NULL;
113   ret->plugin_instance = NULL;
114   ret->type = NULL;
115   ret->type_instance = NULL;
116
117 #define COPY_PART(p) do {        \
118   ret->p = strdup (p);           \
119   if (ret->p == NULL)            \
120   {                              \
121     free (ret->host);            \
122     free (ret->plugin);          \
123     free (ret->plugin_instance); \
124     free (ret->type);            \
125     free (ret->type_instance);   \
126     free (ret);                  \
127     return (NULL);               \
128   }                              \
129 } while (0)
130
131   COPY_PART(host);
132   COPY_PART(plugin);
133   COPY_PART(plugin_instance);
134   COPY_PART(type);
135   COPY_PART(type_instance);
136
137 #undef COPY_PART
138
139   return (ret);
140 } /* }}} graph_ident_t *ident_create */
141
142 graph_ident_t *ident_clone (const graph_ident_t *ident) /* {{{ */
143 {
144   return (ident_create (ident->host,
145         ident->plugin, ident->plugin_instance,
146         ident->type, ident->type_instance));
147 } /* }}} graph_ident_t *ident_clone */
148
149 graph_ident_t *ident_copy_with_selector (const graph_ident_t *selector, /* {{{ */
150     const graph_ident_t *ident, unsigned int flags)
151 {
152   graph_ident_t *ret;
153
154   if ((selector == NULL) || (ident == NULL))
155     return (NULL);
156
157   ret = malloc (sizeof (*ret));
158   if (ret == NULL)
159     return (NULL);
160   memset (ret, 0, sizeof (*ret));
161   ret->host = NULL;
162   ret->plugin = NULL;
163   ret->plugin_instance = NULL;
164   ret->type = NULL;
165   ret->type_instance = NULL;
166
167 #define COPY_PART(p) do {                                  \
168   ret->p = part_copy_with_selector (selector->p, ident->p, flags); \
169   if (ret->p == NULL)                                      \
170   {                                                        \
171     free (ret->host);                                      \
172     free (ret->plugin);                                    \
173     free (ret->plugin_instance);                           \
174     free (ret->type);                                      \
175     free (ret->type_instance);                             \
176     return (NULL);                                         \
177   }                                                        \
178 } while (0)
179
180   COPY_PART (host);
181   COPY_PART (plugin);
182   COPY_PART (plugin_instance);
183   COPY_PART (type);
184   COPY_PART (type_instance);
185
186 #undef COPY_PART
187
188   return (ret);
189 } /* }}} graph_ident_t *ident_copy_with_selector */
190
191 void ident_destroy (graph_ident_t *ident) /* {{{ */
192 {
193   if (ident == NULL)
194     return;
195
196   free (ident->host);
197   free (ident->plugin);
198   free (ident->plugin_instance);
199   free (ident->type);
200   free (ident->type_instance);
201
202   free (ident);
203 } /* }}} void ident_destroy */
204
205 /* ident_get_* methods {{{ */
206 const char *ident_get_host (graph_ident_t *ident) /* {{{ */
207 {
208   if (ident == NULL)
209     return (NULL);
210
211   return (ident->host);
212 } /* }}} char *ident_get_host */
213
214 const char *ident_get_plugin (graph_ident_t *ident) /* {{{ */
215 {
216   if (ident == NULL)
217     return (NULL);
218
219   return (ident->plugin);
220 } /* }}} char *ident_get_plugin */
221
222 const char *ident_get_plugin_instance (graph_ident_t *ident) /* {{{ */
223 {
224   if (ident == NULL)
225     return (NULL);
226
227   return (ident->plugin_instance);
228 } /* }}} char *ident_get_plugin_instance */
229
230 const char *ident_get_type (graph_ident_t *ident) /* {{{ */
231 {
232   if (ident == NULL)
233     return (NULL);
234
235   return (ident->type);
236 } /* }}} char *ident_get_type */
237
238 const char *ident_get_type_instance (graph_ident_t *ident) /* {{{ */
239 {
240   if (ident == NULL)
241     return (NULL);
242
243   return (ident->type_instance);
244 } /* }}} char *ident_get_type_instance */
245
246 const char *ident_get_field (graph_ident_t *ident, /* {{{ */
247     graph_ident_field_t field)
248 {
249   if ((ident == NULL) || (field >= _GIF_LAST))
250     return (NULL);
251
252   if (field == GIF_HOST)
253     return (ident->host);
254   else if (field == GIF_PLUGIN)
255     return (ident->plugin);
256   else if (field == GIF_PLUGIN_INSTANCE)
257     return (ident->plugin_instance);
258   else if (field == GIF_TYPE)
259     return (ident->type);
260   else if (field == GIF_TYPE_INSTANCE)
261     return (ident->type_instance);
262   else
263     return (NULL); /* never reached */
264 } /* }}} const char *ident_get_field */
265 /* }}} ident_get_* methods */
266
267 /* ident_set_* methods {{{ */
268 int ident_set_host (graph_ident_t *ident, const char *host) /* {{{ */
269 {
270   char *tmp;
271
272   if ((ident == NULL) || (host == NULL))
273     return (EINVAL);
274
275   tmp = strdup (host);
276   if (tmp == NULL)
277     return (ENOMEM);
278
279   free (ident->host);
280   ident->host = tmp;
281
282   return (0);
283 } /* }}} int ident_set_host */
284
285 int ident_set_plugin (graph_ident_t *ident, const char *plugin) /* {{{ */
286 {
287   char *tmp;
288
289   if ((ident == NULL) || (plugin == NULL))
290     return (EINVAL);
291
292   tmp = strdup (plugin);
293   if (tmp == NULL)
294     return (ENOMEM);
295
296   free (ident->plugin);
297   ident->plugin = tmp;
298
299   return (0);
300 } /* }}} int ident_set_plugin */
301
302 int ident_set_plugin_instance (graph_ident_t *ident, const char *plugin_instance) /* {{{ */
303 {
304   char *tmp;
305
306   if ((ident == NULL) || (plugin_instance == NULL))
307     return (EINVAL);
308
309   tmp = strdup (plugin_instance);
310   if (tmp == NULL)
311     return (ENOMEM);
312
313   free (ident->plugin_instance);
314   ident->plugin_instance = tmp;
315
316   return (0);
317 } /* }}} int ident_set_plugin_instance */
318
319 int ident_set_type (graph_ident_t *ident, const char *type) /* {{{ */
320 {
321   char *tmp;
322
323   if ((ident == NULL) || (type == NULL))
324     return (EINVAL);
325
326   tmp = strdup (type);
327   if (tmp == NULL)
328     return (ENOMEM);
329
330   free (ident->type);
331   ident->type = tmp;
332
333   return (0);
334 } /* }}} int ident_set_type */
335
336 int ident_set_type_instance (graph_ident_t *ident, const char *type_instance) /* {{{ */
337 {
338   char *tmp;
339
340   if ((ident == NULL) || (type_instance == NULL))
341     return (EINVAL);
342
343   tmp = strdup (type_instance);
344   if (tmp == NULL)
345     return (ENOMEM);
346
347   free (ident->type_instance);
348   ident->type_instance = tmp;
349
350   return (0);
351 } /* }}} int ident_set_type_instance */
352
353 /* }}} ident_set_* methods */
354
355 int ident_compare (const graph_ident_t *i0, /* {{{ */
356     const graph_ident_t *i1)
357 {
358   int status;
359
360 #define COMPARE_PART(p) do {       \
361   status = strcmp (i0->p, i1->p);  \
362   if (status != 0)                 \
363     return (status);               \
364 } while (0)
365
366   COMPARE_PART (host);
367   COMPARE_PART (plugin);
368   COMPARE_PART (plugin_instance);
369   COMPARE_PART (type);
370   COMPARE_PART (type_instance);
371
372 #undef COMPARE_PART
373
374   return (0);
375 } /* }}} int ident_compare */
376
377 _Bool ident_matches (const graph_ident_t *selector, /* {{{ */
378     const graph_ident_t *ident)
379 {
380   if ((selector == NULL) && (ident == NULL))
381     return (0);
382   else if (selector == NULL)
383     return (-1);
384   else if (ident == NULL)
385     return (1);
386
387   if (!part_matches (selector->host, ident->host))
388     return (0);
389
390   if (!part_matches (selector->plugin, ident->plugin))
391     return (0);
392
393   if (!part_matches (selector->plugin_instance, ident->plugin_instance))
394     return (0);
395
396   if (!part_matches (selector->type, ident->type))
397     return (0);
398
399   if (!part_matches (selector->type_instance, ident->type_instance))
400     return (0);
401
402   return (1);
403 } /* }}} _Bool ident_matches */
404
405 char *ident_to_string (const graph_ident_t *ident) /* {{{ */
406 {
407   char buffer[PATH_MAX];
408
409   buffer[0] = 0;
410
411   strlcat (buffer, ident->host, sizeof (buffer));
412   strlcat (buffer, "/", sizeof (buffer));
413   strlcat (buffer, ident->plugin, sizeof (buffer));
414   if (ident->plugin_instance[0] != 0)
415   {
416     strlcat (buffer, "-", sizeof (buffer));
417     strlcat (buffer, ident->plugin_instance, sizeof (buffer));
418   }
419   strlcat (buffer, "/", sizeof (buffer));
420   strlcat (buffer, ident->type, sizeof (buffer));
421   if (ident->type_instance[0] != 0)
422   {
423     strlcat (buffer, "-", sizeof (buffer));
424     strlcat (buffer, ident->type_instance, sizeof (buffer));
425   }
426
427   return (strdup (buffer));
428 } /* }}} char *ident_to_string */
429
430 char *ident_to_file (const graph_ident_t *ident) /* {{{ */
431 {
432   char buffer[PATH_MAX];
433
434   buffer[0] = 0;
435
436   strlcat (buffer, DATA_DIR, sizeof (buffer));
437   strlcat (buffer, "/", sizeof (buffer));
438
439   strlcat (buffer, ident->host, sizeof (buffer));
440   strlcat (buffer, "/", sizeof (buffer));
441   strlcat (buffer, ident->plugin, sizeof (buffer));
442   if (ident->plugin_instance[0] != 0)
443   {
444     strlcat (buffer, "-", sizeof (buffer));
445     strlcat (buffer, ident->plugin_instance, sizeof (buffer));
446   }
447   strlcat (buffer, "/", sizeof (buffer));
448   strlcat (buffer, ident->type, sizeof (buffer));
449   if (ident->type_instance[0] != 0)
450   {
451     strlcat (buffer, "-", sizeof (buffer));
452     strlcat (buffer, ident->type_instance, sizeof (buffer));
453   }
454
455   strlcat (buffer, ".rrd", sizeof (buffer));
456
457   return (strdup (buffer));
458 } /* }}} char *ident_to_file */
459
460 char *ident_to_json (const graph_ident_t *ident) /* {{{ */
461 {
462   char buffer[4096];
463
464   buffer[0] = 0;
465
466   strlcat (buffer, "{\"host\":\"", sizeof (buffer));
467   strlcat (buffer, ident->host, sizeof (buffer));
468   strlcat (buffer, "\",\"plugin\":\"", sizeof (buffer));
469   strlcat (buffer, ident->plugin, sizeof (buffer));
470   strlcat (buffer, "\",\"plugin_instance\":\"", sizeof (buffer));
471   strlcat (buffer, ident->plugin_instance, sizeof (buffer));
472   strlcat (buffer, "\",\"type\":\"", sizeof (buffer));
473   strlcat (buffer, ident->type, sizeof (buffer));
474   strlcat (buffer, "\",\"type_instance\":\"", sizeof (buffer));
475   strlcat (buffer, ident->type_instance, sizeof (buffer));
476   strlcat (buffer, "\"}", sizeof (buffer));
477
478   return (strdup (buffer));
479 } /* }}} char *ident_to_json */
480
481 time_t ident_get_mtime (const graph_ident_t *ident) /* {{{ */
482 {
483   char *file;
484   struct stat statbuf;
485   int status;
486
487   if (ident == NULL)
488     return (0);
489
490   file = ident_to_file (ident);
491   if (file == NULL)
492     return (0);
493
494   memset (&statbuf, 0, sizeof (statbuf));
495   status = stat (file, &statbuf);
496   if (status != 0)
497   {
498     fprintf (stderr, "ident_get_mtime: stat'ing file \"%s\" failed: %s\n",
499         file, strerror (errno));
500     return (0);
501   }
502
503   free (file);
504   return (statbuf.st_mtime);
505 } /* }}} time_t ident_get_mtime */
506
507 /* vim: set sw=2 sts=2 et fdm=marker : */
508