Code

Merge branch 'ff/entropy' into collectd-4
[collectd.git] / src / common.c
1 /**
2  * collectd - src/common.c
3  * Copyright (C) 2005-2007  Florian octo Forster
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  *   Florian octo Forster <octo at verplant.org>
20  *   Niki W. Waibel <niki.waibel@gmx.net>
21 **/
23 #include "common.h"
24 #include "utils_debug.h"
26 #ifdef HAVE_MATH_H
27 #  include <math.h>
28 #endif
30 /* for ntohl and htonl */
31 #if HAVE_ARPA_INET_H
32 # include <arpa/inet.h>
33 #endif
35 extern int operating_mode;
37 #ifdef HAVE_LIBKSTAT
38 extern kstat_ctl_t *kc;
39 #endif
41 void sstrncpy (char *d, const char *s, int len)
42 {
43         strncpy (d, s, len);
44         d[len - 1] = '\0';
45 }
47 char *sstrdup (const char *s)
48 {
49         char *r;
51         if (s == NULL)
52                 return (NULL);
54         if((r = strdup (s)) == NULL)
55         {
56                 DBG ("Not enough memory.");
57                 exit(3);
58         }
60         return (r);
61 }
63 void *smalloc (size_t size)
64 {
65         void *r;
67         if ((r = malloc (size)) == NULL)
68         {
69                 DBG("Not enough memory.");
70                 exit(3);
71         }
73         return r;
74 }
76 #if 0
77 void sfree (void **ptr)
78 {
79         if (ptr == NULL)
80                 return;
82         if (*ptr != NULL)
83                 free (*ptr);
85         *ptr = NULL;
86 }
87 #endif
89 ssize_t sread (int fd, void *buf, size_t count)
90 {
91         char    *ptr;
92         size_t   nleft;
93         ssize_t  status;
95         ptr   = (char *) buf;
96         nleft = count;
98         while (nleft > 0)
99         {
100                 status = read (fd, (void *) ptr, nleft);
102                 if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
103                         continue;
105                 if (status < 0)
106                         return (status);
108                 if (status == 0)
109                 {
110                         DBG ("Received EOF from fd %i. "
111                                         "Closing fd and returning error.",
112                                         fd);
113                         close (fd);
114                         return (-1);
115                 }
117                 assert (nleft >= status);
119                 nleft = nleft - status;
120                 ptr   = ptr   + status;
121         }
123         return (0);
127 ssize_t swrite (int fd, const void *buf, size_t count)
129         const char *ptr;
130         size_t      nleft;
131         ssize_t     status;
133         ptr   = (const char *) buf;
134         nleft = count;
136         while (nleft > 0)
137         {
138                 status = write (fd, (const void *) ptr, nleft);
140                 if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
141                         continue;
143                 if (status < 0)
144                         return (status);
146                 nleft = nleft - status;
147                 ptr   = ptr   + status;
148         }
150         return (0);
153 int strsplit (char *string, char **fields, size_t size)
155         size_t i;
156         char *ptr;
158         i = 0;
159         ptr = string;
160         while ((fields[i] = strtok (ptr, " \t")) != NULL)
161         {
162                 ptr = NULL;
163                 i++;
165                 if (i >= size)
166                         break;
167         }
169         return (i);
172 int strjoin (char *dst, size_t dst_len,
173                 char **fields, size_t fields_num,
174                 const char *sep)
176         int field_len;
177         int sep_len;
178         int i;
180         memset (dst, '\0', dst_len);
182         if (fields_num <= 0)
183                 return (-1);
185         sep_len = 0;
186         if (sep != NULL)
187                 sep_len = strlen (sep);
189         for (i = 0; i < fields_num; i++)
190         {
191                 if ((i > 0) && (sep_len > 0))
192                 {
193                         if (dst_len <= sep_len)
194                                 return (-1);
196                         strncat (dst, sep, dst_len);
197                         dst_len -= sep_len;
198                 }
200                 field_len = strlen (fields[i]);
202                 if (dst_len <= field_len)
203                         return (-1);
205                 strncat (dst, fields[i], dst_len);
206                 dst_len -= field_len;
207         }
209         return (strlen (dst));
212 int strsubstitute (char *str, char c_from, char c_to)
214         int ret;
216         if (str == NULL)
217                 return (-1);
219         ret = 0;
220         while (*str != '\0')
221         {
222                 if (*str == c_from)
223                 {
224                         *str = c_to;
225                         ret++;
226                 }
227                 str++;
228         }
230         return (ret);
233 int escape_slashes (char *buf, int buf_len)
235         int i;
237         if (strcmp (buf, "/") == 0)
238         {
239                 if (buf_len < 5)
240                         return (-1);
242                 strncpy (buf, "root", buf_len);
243                 return (0);
244         }
246         /* Move one to the left */
247         memmove (buf, buf + 1, buf_len - 1);
249         for (i = 0; i < buf_len - 1; i++)
250         {
251                 if (buf[i] == '\0')
252                         break;
253                 else if (buf[i] == '/')
254                         buf[i] = '_';
255         }
256         buf[i] = '\0';
258         return (0);
261 int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret)
263         if ((tv0 == NULL) || (tv1 == NULL) || (ret == NULL))
264                 return (-2);
266         if ((tv0->tv_sec < tv1->tv_sec)
267                         || ((tv0->tv_sec == tv1->tv_sec) && (tv0->tv_usec < tv1->tv_usec)))
268                 return (-1);
270         ret->tv_sec  = tv0->tv_sec - tv1->tv_sec;
271         ret->tv_nsec = 1000 * ((long) (tv0->tv_usec - tv1->tv_usec));
273         if (ret->tv_nsec < 0)
274         {
275                 assert (ret->tv_sec > 0);
277                 ret->tv_nsec += 1000000000;
278                 ret->tv_sec  -= 1;
279         }
281         return (0);
284 int check_create_dir (const char *file_orig)
286         struct stat statbuf;
288         char  file_copy[512];
289         char  dir[512];
290         int   dir_len = 512;
291         char *fields[16];
292         int   fields_num;
293         char *ptr;
294         int   last_is_file = 1;
295         int   len;
296         int   i;
298         /*
299          * Sanity checks first
300          */
301         if (file_orig == NULL)
302                 return (-1);
304         if ((len = strlen (file_orig)) < 1)
305                 return (-1);
306         else if (len >= 512)
307                 return (-1);
309         /*
310          * If `file_orig' ends in a slash the last component is a directory,
311          * otherwise it's a file. Act accordingly..
312          */
313         if (file_orig[len - 1] == '/')
314                 last_is_file = 0;
316         /*
317          * Create a copy for `strtok' to destroy
318          */
319         strncpy (file_copy, file_orig, 512);
320         file_copy[511] = '\0';
322         /*
323          * Break into components. This will eat up several slashes in a row and
324          * remove leading and trailing slashes..
325          */
326         ptr = file_copy;
327         fields_num = 0;
328         while ((fields[fields_num] = strtok (ptr, "/")) != NULL)
329         {
330                 ptr = NULL;
331                 fields_num++;
333                 if (fields_num >= 16)
334                         break;
335         }
337         /*
338          * For each component, do..
339          */
340         for (i = 0; i < (fields_num - last_is_file); i++)
341         {
342                 /*
343                  * Do not create directories that start with a dot. This
344                  * prevents `../../' attacks and other likely malicious
345                  * behavior.
346                  */
347                 if (fields[i][0] == '.')
348                 {
349                         syslog (LOG_ERR, "Cowardly refusing to create a directory that begins with a `.' (dot): `%s'", file_orig);
350                         return (-2);
351                 }
353                 /*
354                  * Join the components together again
355                  */
356                 if (strjoin (dir, dir_len, fields, i + 1, "/") < 0)
357                 {
358                         syslog (LOG_ERR, "strjoin failed: `%s', component #%i", file_orig, i);
359                         return (-1);
360                 }
362                 if (stat (dir, &statbuf) == -1)
363                 {
364                         if (errno == ENOENT)
365                         {
366                                 if (mkdir (dir, 0755) == -1)
367                                 {
368                                         syslog (LOG_ERR, "mkdir (%s): %s", dir, strerror (errno));
369                                         return (-1);
370                                 }
371                         }
372                         else
373                         {
374                                 syslog (LOG_ERR, "stat (%s): %s", dir, strerror (errno));
375                                 return (-1);
376                         }
377                 }
378                 else if (!S_ISDIR (statbuf.st_mode))
379                 {
380                         syslog (LOG_ERR, "stat (%s): Not a directory!", dir);
381                         return (-1);
382                 }
383         }
385         return (0);
388 #ifdef HAVE_LIBKSTAT
389 int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name)
391         char ident[128];
392         
393         if (kc == NULL)
394                 return (-1);
396         snprintf (ident, 128, "%s,%i,%s", module, instance, name);
397         ident[127] = '\0';
399         if (*ksp_ptr == NULL)
400         {
401                 if ((*ksp_ptr = kstat_lookup (kc, module, instance, name)) == NULL)
402                 {
403                         syslog (LOG_ERR, "Cound not find kstat %s", ident);
404                         return (-1);
405                 }
407                 if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED)
408                 {
409                         syslog (LOG_WARNING, "kstat %s has wrong type", ident);
410                         *ksp_ptr = NULL;
411                         return (-1);
412                 }
413         }
415 #ifdef assert
416         assert (*ksp_ptr != NULL);
417         assert ((*ksp_ptr)->ks_type == KSTAT_TYPE_NAMED);
418 #endif
420         if (kstat_read (kc, *ksp_ptr, NULL) == -1)
421         {
422                 syslog (LOG_WARNING, "kstat %s could not be read", ident);
423                 return (-1);
424         }
426         if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED)
427         {
428                 syslog (LOG_WARNING, "kstat %s has wrong type", ident);
429                 return (-1);
430         }
432         return (0);
435 long long get_kstat_value (kstat_t *ksp, char *name)
437         kstat_named_t *kn;
438         long long retval = -1LL;
440 #ifdef assert
441         assert (ksp != NULL);
442         assert (ksp->ks_type == KSTAT_TYPE_NAMED);
443 #else
444         if (ksp == NULL)
445         {
446                 fprintf (stderr, "ERROR: %s:%i: ksp == NULL\n", __FILE__, __LINE__);
447                 return (-1LL);
448         }
449         else if (ksp->ks_type != KSTAT_TYPE_NAMED)
450         {
451                 fprintf (stderr, "ERROR: %s:%i: ksp->ks_type != KSTAT_TYPE_NAMED\n", __FILE__, __LINE__);
452                 return (-1LL);
453         }
454 #endif
456         if ((kn = (kstat_named_t *) kstat_data_lookup (ksp, name)) == NULL)
457                 return (retval);
459         if (kn->data_type == KSTAT_DATA_INT32)
460                 retval = (long long) kn->value.i32;
461         else if (kn->data_type == KSTAT_DATA_UINT32)
462                 retval = (long long) kn->value.ui32;
463         else if (kn->data_type == KSTAT_DATA_INT64)
464                 retval = (long long) kn->value.i64; /* According to ANSI C99 `long long' must hold at least 64 bits */
465         else if (kn->data_type == KSTAT_DATA_UINT64)
466                 retval = (long long) kn->value.ui64; /* XXX: Might overflow! */
467         else
468                 syslog (LOG_WARNING, "get_kstat_value: Not a numeric value: %s", name);
469                  
470         return (retval);
472 #endif /* HAVE_LIBKSTAT */
474 unsigned long long ntohll (unsigned long long n)
476 #if __BYTE_ORDER == __BIG_ENDIAN
477         return (n);
478 #else
479         return (((unsigned long long) ntohl (n)) << 32) + ntohl (n >> 32);
480 #endif
483 unsigned long long htonll (unsigned long long n)
485 #if __BYTE_ORDER == __BIG_ENDIAN
486         return (n);
487 #else
488         return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32);
489 #endif