2 * collection4 - filesystem.c
3 * Copyright (C) 2010 Florian octo Forster
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA
21 * Florian octo Forster <ff at octo.it>
30 #include <sys/types.h>
34 #include "filesystem.h"
36 struct fs_scan_dir_data_s /* {{{ */
38 fs_ident_cb_t callback;
43 char *plugin_instance;
47 typedef struct fs_scan_dir_data_s fs_scan_dir_data_t;
49 typedef int (*callback_type_t) (const char *type, void *user_data);
50 typedef int (*callback_plugin_t) (const char *base_dir,
51 const char *plugin, void *user_data);
52 typedef int (*callback_host_t) (const char *base_dir,
53 const char *host, void *user_data);
56 * Directory and file walking functions
58 static int foreach_rrd_file (const char *dir, /* {{{ */
59 int (*callback) (const char *, void *),
73 while ((entry = readdir (dh)) != NULL)
76 char abspath[PATH_MAX + 1];
79 if (entry->d_name[0] == '.')
82 d_name_len = strlen (entry->d_name);
86 if (strcasecmp (".rrd", entry->d_name + (d_name_len - 4)) != 0)
89 snprintf (abspath, sizeof (abspath), "%s/%s", dir, entry->d_name);
90 abspath[sizeof (abspath) - 1] = 0;
92 memset (&statbuf, 0, sizeof (statbuf));
94 status = stat (abspath, &statbuf);
98 if (!S_ISREG (statbuf.st_mode))
101 entry->d_name[d_name_len - 4] = 0;
103 status = (*callback) (entry->d_name, user_data);
106 } /* while (readdir) */
110 } /* }}} int foreach_rrd_file */
112 static int foreach_type (const char *host, const char *plugin, /* {{{ */
113 callback_type_t callback, void *user_data)
115 char abspath[PATH_MAX + 1];
117 if ((host == NULL) || (plugin == NULL))
120 snprintf (abspath, sizeof (abspath), "%s/%s/%s", DATA_DIR, host, plugin);
121 abspath[sizeof (abspath) - 1] = 0;
123 return (foreach_rrd_file (abspath, callback, user_data));
124 } /* }}} int foreach_type */
126 static int foreach_plugin (const char *host, /* {{{ */
127 callback_plugin_t callback,
130 char abspath[PATH_MAX + 1];
135 snprintf (abspath, sizeof (abspath), "%s/%s", DATA_DIR, host);
136 abspath[sizeof (abspath) - 1] = 0;
138 return (fs_foreach_dir (abspath, callback, user_data));
139 } /* }}} int foreach_plugin */
141 static int foreach_host (callback_host_t callback, /* {{{ */
144 return (fs_foreach_dir (DATA_DIR, callback, user_data));
145 } /* }}} int foreach_host */
148 * Functions building "fs_scan_dir_data_t" and calling the user-supplied
149 * callback eventually.
151 static int scan_type (const char *type, void *user_data) /* {{{ */
153 fs_scan_dir_data_t *data = user_data;
154 graph_ident_t *ident;
157 if ((type == NULL) || (data == NULL))
160 if ((data->type != NULL) || (data->type_instance != NULL))
163 data->type = strdup (type);
164 if (data->type == NULL)
167 data->type_instance = strchr (data->type, '-');
168 if (data->type_instance != NULL)
170 *data->type_instance = 0;
171 data->type_instance++;
175 data->type_instance = data->type + strlen (data->type);
178 ident = ident_create (data->host,
179 data->plugin, data->plugin_instance,
180 data->type, data->type_instance);
187 status = (*data->callback) (ident, data->user_data);
188 ident_destroy (ident);
193 data->type_instance = NULL;
196 } /* }}} int scan_type */
198 static int scan_plugin (__attribute__((unused)) const char *base_dir, /* {{{ */
199 const char *plugin, void *user_data)
201 fs_scan_dir_data_t *data = user_data;
204 if ((plugin == NULL) || (data == NULL))
207 if ((data->plugin != NULL) || (data->plugin_instance != NULL))
210 data->plugin = strdup (plugin);
211 if (data->plugin == NULL)
214 data->plugin_instance = strchr (data->plugin, '-');
215 if (data->plugin_instance != NULL)
217 *data->plugin_instance = 0;
218 data->plugin_instance++;
222 data->plugin_instance = data->plugin + strlen (data->plugin);
225 status = foreach_type (data->host, plugin, scan_type, data);
229 data->plugin_instance = NULL;
232 } /* }}} int scan_plugin */
234 static int scan_host (__attribute__((unused)) const char *base_dir, /* {{{ */
235 const char *host, void *user_data)
237 fs_scan_dir_data_t *data = user_data;
240 if ((host == NULL) || (data == NULL))
243 if (data->host != NULL)
246 data->host = strdup (host);
247 if (data->host == NULL)
250 status = foreach_plugin (host, scan_plugin, data);
256 } /* }}} int scan_host */
261 int fs_foreach_dir (const char *base_dir, /* {{{ */
262 int (*callback) (const char *base_dir, const char *entry, void *),
266 struct dirent *entry;
269 if (callback == NULL)
272 dh = opendir (base_dir);
276 while ((entry = readdir (dh)) != NULL)
279 char abspath[PATH_MAX + 1];
281 if (entry->d_name[0] == '.')
284 snprintf (abspath, sizeof (abspath), "%s/%s", base_dir, entry->d_name);
285 abspath[sizeof (abspath) - 1] = 0;
287 memset (&statbuf, 0, sizeof (statbuf));
289 status = stat (abspath, &statbuf);
293 if (!S_ISDIR (statbuf.st_mode))
296 status = (*callback) (base_dir, entry->d_name, user_data);
299 } /* while (readdir) */
303 } /* }}} int fs_foreach_dir */
305 int fs_foreach_file (const char *base_dir, /* {{{ */
306 int (*callback) (const char *base_dir, const char *entry, void *),
310 struct dirent *entry;
313 if (callback == NULL)
316 dh = opendir (base_dir);
320 while ((entry = readdir (dh)) != NULL)
323 char abspath[PATH_MAX + 1];
325 if (entry->d_name[0] == '.')
328 snprintf (abspath, sizeof (abspath), "%s/%s", base_dir, entry->d_name);
329 abspath[sizeof (abspath) - 1] = 0;
331 memset (&statbuf, 0, sizeof (statbuf));
333 status = stat (abspath, &statbuf);
337 if (!S_ISREG (statbuf.st_mode))
340 status = (*callback) (base_dir, entry->d_name, user_data);
343 } /* while (readdir) */
347 } /* }}} int fs_foreach_file */
349 int fs_scan (fs_ident_cb_t callback, void *user_data) /* {{{ */
351 fs_scan_dir_data_t data;
353 memset (&data, 0, sizeof (data));
354 data.callback = callback;
355 data.user_data = user_data;
359 data.plugin_instance = NULL;
361 data.type_instance = NULL;
363 foreach_host (scan_host, &data);
366 } /* }}} int fs_scan */
368 /* vim: set sw=2 sts=2 et fdm=marker : */