X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fdaemon%2Futils_time.c;h=86476ea63b4cd95728cfd843a48b52d26859d979;hb=a5377cf935630082f2eac2e5f4a538844cc06c8d;hp=6603c15e89f161afc832a5e2cd8ef08b335564ea;hpb=b286b677bb54a3192a4121c2aa0857a133fd0603;p=collectd.git diff --git a/src/daemon/utils_time.c b/src/daemon/utils_time.c index 6603c15e..86476ea6 100644 --- a/src/daemon/utils_time.c +++ b/src/daemon/utils_time.c @@ -1,6 +1,6 @@ /** * collectd - src/utils_time.c - * Copyright (C) 2010 Florian octo Forster + * Copyright (C) 2010-2015 Florian octo Forster * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,15 +21,28 @@ * DEALINGS IN THE SOFTWARE. * * Authors: - * Florian octo Forster + * Florian octo Forster **/ #include "collectd.h" + #include "utils_time.h" #include "plugin.h" #include "common.h" -#if HAVE_CLOCK_GETTIME +#ifndef DEFAULT_MOCK_TIME +# define DEFAULT_MOCK_TIME 1542455354518929408ULL +#endif + +#ifdef MOCK_TIME +cdtime_t cdtime_mock = (cdtime_t) MOCK_TIME; + +cdtime_t cdtime (void) +{ + return cdtime_mock; +} +#else /* !MOCK_TIME */ +# if HAVE_CLOCK_GETTIME cdtime_t cdtime (void) /* {{{ */ { int status; @@ -46,7 +59,7 @@ cdtime_t cdtime (void) /* {{{ */ return (TIMESPEC_TO_CDTIME_T (&ts)); } /* }}} cdtime_t cdtime */ -#else +# else /* !HAVE_CLOCK_GETTIME */ /* Work around for Mac OS X which doesn't have clock_gettime(2). *sigh* */ cdtime_t cdtime (void) /* {{{ */ { @@ -64,41 +77,95 @@ cdtime_t cdtime (void) /* {{{ */ return (TIMEVAL_TO_CDTIME_T (&tv)); } /* }}} cdtime_t cdtime */ +# endif #endif -size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t) /* {{{ */ +/* format_zone reads time zone information from "extern long timezone", exported + * by , and formats it according to RFC 3339. This differs from + * strftime()'s "%z" format by including a colon between hour and minute. */ +static int format_zone (char *buffer, size_t buffer_size, struct tm const *tm) /* {{{ */ +{ + char tmp[7]; + size_t sz; + + if ((buffer == NULL) || (buffer_size < 7)) + return EINVAL; + + sz = strftime (tmp, sizeof (tmp), "%z", tm); + if (sz == 0) + return ENOMEM; + if (sz != 5) + { + DEBUG ("format_zone: strftime(\"%%z\") = \"%s\", want \"+hhmm\"", tmp); + sstrncpy (buffer, tmp, buffer_size); + return 0; + } + + buffer[0] = tmp[0]; + buffer[1] = tmp[1]; + buffer[2] = tmp[2]; + buffer[3] = ':'; + buffer[4] = tmp[3]; + buffer[5] = tmp[4]; + buffer[6] = 0; + + return 0; +} /* }}} int format_zone */ + +static int format_rfc3339 (char *buffer, size_t buffer_size, cdtime_t t, _Bool print_nano) /* {{{ */ { struct timespec t_spec; struct tm t_tm; - + char base[20]; /* 2006-01-02T15:04:05 */ + char nano[11]; /* .999999999 */ + char zone[7]; /* +00:00 */ + char *fields[] = {base, nano, zone}; size_t len; + int status; CDTIME_T_TO_TIMESPEC (t, &t_spec); NORMALIZE_TIMESPEC (t_spec); - if (localtime_r ((time_t *)&t_spec.tv_sec, &t_tm) == NULL) { + if (localtime_r (&t_spec.tv_sec, &t_tm) == NULL) { char errbuf[1024]; - ERROR ("cdtime_to_iso8601: localtime_r failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return (0); + status = errno; + ERROR ("format_rfc3339: localtime_r failed: %s", + sstrerror (status, errbuf, sizeof (errbuf))); + return (status); } - len = strftime (s, max, "%Y-%m-%dT%H:%M:%S", &t_tm); + len = strftime (base, sizeof (base), "%Y-%m-%dT%H:%M:%S", &t_tm); if (len == 0) - return 0; + return ENOMEM; - if (max - len > 2) { - int n = snprintf (s + len, max - len, ".%09i", (int)t_spec.tv_nsec); - len += (n < max - len) ? n : max - len; - } + if (print_nano) + ssnprintf (nano, sizeof (nano), ".%09ld", (long) t_spec.tv_nsec); + else + sstrncpy (nano, "", sizeof (nano)); - if (max - len > 3) { - int n = strftime (s + len, max - len, "%z", &t_tm); - len += (n < max - len) ? n : max - len; - } + status = format_zone (zone, sizeof (zone), &t_tm); + if (status != 0) + return status; + + if (strjoin (buffer, buffer_size, fields, STATIC_ARRAY_SIZE (fields), "") < 0) + return ENOMEM; + return 0; +} /* }}} int format_rfc3339 */ + +int rfc3339 (char *buffer, size_t buffer_size, cdtime_t t) /* {{{ */ +{ + if (buffer_size < RFC3339_SIZE) + return ENOMEM; + + return format_rfc3339 (buffer, buffer_size, t, 0); +} /* }}} size_t cdtime_to_rfc3339 */ + +int rfc3339nano (char *buffer, size_t buffer_size, cdtime_t t) /* {{{ */ +{ + if (buffer_size < RFC3339NANO_SIZE) + return ENOMEM; - s[max - 1] = '\0'; - return len; -} /* }}} size_t cdtime_to_iso8601 */ + return format_rfc3339 (buffer, buffer_size, t, 1); +} /* }}} size_t cdtime_to_rfc3339nano */ /* vim: set sw=2 sts=2 et fdm=marker : */