5d2a67deaef7276cb0e86c6c4da8ce9b51dec13f
[collection4.git] / common.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8 #include <dirent.h>
9 #include <assert.h>
10
11 #include <rrd.h>
12
13 #include "common.h"
14 #include "graph_list.h"
15
16 static int foreach_rrd_file (const char *dir, /* {{{ */
17     int (*callback) (const char *, void *),
18     void *user_data)
19 {
20   DIR *dh;
21   struct dirent *entry;
22   int status;
23
24   if (callback == NULL)
25     return (EINVAL);
26
27   dh = opendir (dir);
28   if (dh == NULL)
29     return (errno);
30
31   while ((entry = readdir (dh)) != NULL)
32   {
33     struct stat statbuf;
34     char abspath[PATH_MAX + 1];
35     size_t d_name_len;
36
37     if (entry->d_name[0] == '.')
38       continue;
39
40     d_name_len = strlen (entry->d_name);
41     if (d_name_len <= 4)
42       continue;
43
44     if (strcasecmp (".rrd", entry->d_name + (d_name_len - 4)) != 0)
45       continue;
46
47     snprintf (abspath, sizeof (abspath), "%s/%s", dir, entry->d_name);
48     abspath[sizeof (abspath) - 1] = 0;
49
50     memset (&statbuf, 0, sizeof (statbuf));
51
52     status = stat (abspath, &statbuf);
53     if (status != 0)
54       continue;
55
56     if (!S_ISREG (statbuf.st_mode))
57       continue;
58
59     entry->d_name[d_name_len - 4] = 0;
60
61     status = (*callback) (entry->d_name, user_data);
62     if (status != 0)
63       break;
64   } /* while (readdir) */
65
66   closedir (dh);
67   return (status);
68 } /* }}} int foreach_rrd_file */
69
70 static int foreach_dir (const char *dir, /* {{{ */
71     int (*callback) (const char *, void *),
72     void *user_data)
73 {
74   DIR *dh;
75   struct dirent *entry;
76   int status;
77
78   if (callback == NULL)
79     return (EINVAL);
80
81   dh = opendir (dir);
82   if (dh == NULL)
83     return (errno);
84
85   while ((entry = readdir (dh)) != NULL)
86   {
87     struct stat statbuf;
88     char abspath[PATH_MAX + 1];
89
90     if (entry->d_name[0] == '.')
91       continue;
92
93     snprintf (abspath, sizeof (abspath), "%s/%s", dir, entry->d_name);
94     abspath[sizeof (abspath) - 1] = 0;
95
96     memset (&statbuf, 0, sizeof (statbuf));
97
98     status = stat (abspath, &statbuf);
99     if (status != 0)
100       continue;
101
102     if (!S_ISDIR (statbuf.st_mode))
103       continue;
104
105     status = (*callback) (entry->d_name, user_data);
106     if (status != 0)
107       break;
108   } /* while (readdir) */
109
110   closedir (dh);
111   return (status);
112 } /* }}} int foreach_dir */
113
114 int foreach_type (const char *host, const char *plugin, /* {{{ */
115     callback_type_t callback, void *user_data)
116 {
117   char abspath[PATH_MAX + 1];
118
119   if ((host == NULL) || (plugin == NULL))
120     return (EINVAL);
121
122   snprintf (abspath, sizeof (abspath), "%s/%s/%s", DATA_DIR, host, plugin);
123   abspath[sizeof (abspath) - 1] = 0;
124
125   return (foreach_rrd_file (abspath, callback, user_data));
126 } /* }}} int foreach_type */
127
128 int foreach_plugin (const char *host, /* {{{ */
129     callback_plugin_t callback,
130     void *user_data)
131 {
132   char abspath[PATH_MAX + 1];
133
134   if (host == NULL)
135     return (EINVAL);
136
137   snprintf (abspath, sizeof (abspath), "%s/%s", DATA_DIR, host);
138   abspath[sizeof (abspath) - 1] = 0;
139
140   return (foreach_dir (abspath, callback, user_data));
141 } /* }}} int foreach_plugin */
142
143 int foreach_host (callback_host_t callback, /* {{{ */
144     void *user_data)
145 {
146   return (foreach_dir (DATA_DIR, callback, user_data));
147 } /* }}} int foreach_host */
148
149 size_t c_strlcat (char *dst, const char *src, size_t size) /* {{{ */
150 {
151   size_t retval;
152   size_t dst_len;
153   size_t src_len;
154
155   dst_len = strlen (dst);
156   src_len = strlen (src);
157   retval = dst_len + src_len;
158
159   if ((dst_len + 1) >= size)
160     return (retval);
161
162   dst  += dst_len;
163   size -= dst_len;
164   assert (size >= 2);
165
166   /* Result will be truncated. */
167   if (src_len >= size)
168     src_len = size - 1;
169
170   memcpy (dst, src, src_len);
171   dst[src_len] = 0;
172
173   return (retval);
174 } /* }}} size_t c_strlcat */
175
176 int ds_list_from_rrd_file (char *file, /* {{{ */
177     size_t *ret_dses_num, char ***ret_dses)
178 {
179   char *rrd_argv[] = { "info", file, NULL };
180   int rrd_argc = (sizeof (rrd_argv) / sizeof (rrd_argv[0])) - 1;
181
182   rrd_info_t *info;
183   rrd_info_t *ptr;
184
185   char **dses = NULL;
186   size_t dses_num = 0;
187
188   info = rrd_info (rrd_argc, rrd_argv);
189   if (info == NULL)
190   {
191     printf ("%s: rrd_info (%s) failed.\n", __func__, file);
192     return (-1);
193   }
194
195   for (ptr = info; ptr != NULL; ptr = ptr->next)
196   {
197     size_t keylen;
198     size_t dslen;
199     char *ds;
200     char **tmp;
201
202     if (strncmp ("ds[", ptr->key, strlen ("ds[")) != 0)
203       continue;
204
205     keylen = strlen (ptr->key);
206     if (keylen < strlen ("ds[?].index"))
207       continue;
208
209     dslen = keylen - strlen ("ds[].index");
210     assert (dslen >= 1);
211
212     if (strcmp ("].index", ptr->key + (strlen ("ds[") + dslen)) != 0)
213       continue;
214
215     ds = malloc (dslen + 1);
216     if (ds == NULL)
217       continue;
218
219     memcpy (ds, ptr->key + strlen ("ds["), dslen);
220     ds[dslen] = 0;
221
222     tmp = realloc (dses, sizeof (*dses) * (dses_num + 1));
223     if (tmp == NULL)
224     {
225       free (ds);
226       continue;
227     }
228     dses = tmp;
229
230     dses[dses_num] = ds;
231     dses_num++;
232   }
233
234   rrd_info_free (info);
235
236   if (dses_num < 1)
237   {
238     assert (dses == NULL);
239     return (ENOENT);
240   }
241
242   *ret_dses_num = dses_num;
243   *ret_dses = dses;
244
245   return (0);
246 } /* }}} int ds_list_from_rrd_file */
247
248 /* vim: set sw=2 sts=2 et fdm=marker : */