X-Git-Url: https://unix4lyfe.org/gitweb/darkstat-debian/blobdiff_plain/a1e8056c92203d02860d719abb1d562453896da8..3c6b3682c70be84db86e70c191016913a9836c31:/daylog.c diff --git a/daylog.c b/daylog.c index a0b517e..080f11f 100644 --- a/daylog.c +++ b/daylog.c @@ -1,5 +1,5 @@ /* darkstat 3 - * copyright (c) 2007-2011 Emil Mikulic. + * copyright (c) 2007-2014 Emil Mikulic. * * daylog.c: daily usage log * @@ -9,143 +9,126 @@ #define _GNU_SOURCE 1 /* for O_NOFOLLOW on Linux */ -#include +#include "cdefs.h" +#include "err.h" +#include "daylog.h" +#include "str.h" +#include "now.h" + #include #include +#include #include #include +#include #include -#include "err.h" -#include "daylog.h" -#include "str.h" -#include "now.h" - static const char *daylog_fn = NULL; -static time_t today_time, tomorrow_time; +static time_t today_real, tomorrow_real; static uint64_t bytes_in, bytes_out, pkts_in, pkts_out; #define DAYLOG_DATE_LEN 26 /* strlen("1900-01-01 00:00:00 +1234") + 1 */ static char datebuf[DAYLOG_DATE_LEN]; -static char * -fmt_date(const time_t when) -{ - time_t tmp = when; - if (strftime(datebuf, DAYLOG_DATE_LEN, - "%Y-%m-%d %H:%M:%S %z", localtime(&tmp) ) == 0) +static char *fmt_date(time_t when) { + if (strftime(datebuf, + DAYLOG_DATE_LEN, + "%Y-%m-%d %H:%M:%S %z", + localtime(&when)) == 0) errx(1, "strftime() failed in fmt_date()"); - return (datebuf); + return datebuf; } /* Given some time today, find the first second of tomorrow. */ -static time_t -tomorrow(const time_t today) -{ - time_t tmp = today; +static time_t tomorrow(time_t t_before) { + time_t t_after; struct tm tm, *lt; - lt = localtime(&tmp); + lt = localtime(&t_before); memcpy(&tm, lt, sizeof(tm)); tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour = 0; tm.tm_mday = lt->tm_mday + 1; /* tomorrow */ - return mktime(&tm); -} - -static int -daylog_open(void) -{ - return open(daylog_fn, O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW, 0600); -} - -static void -daylog_emit(void) -{ - int fd = daylog_open(); - - if (fd != -1) { - struct str *buf = str_make(); - char *s; - size_t len; - str_appendf(buf, "%s|%u|%qu|%qu|%qu|%qu\n", - fmt_date(today_time), (unsigned int)today_time, - bytes_in, bytes_out, pkts_in, pkts_out); - str_extract(buf, &len, &s); - - (void)write(fd, s, len); /* ignore write errors */ - close(fd); - free(s); - } + t_after = mktime(&tm); + assert(t_after > t_before); + return t_after; } -void -daylog_init(const char *filename) -{ +/* Warns on error. */ +static void daylog_write(const char *format, ...) _printflike_(1, 2); +static void daylog_write(const char *format, ...) { int fd; + ssize_t wr; + va_list va; struct str *buf; - char *s; - size_t len; - - daylog_fn = filename; - today_time = time(NULL); - tomorrow_time = tomorrow(today_time); - verbosef("today is %u, tomorrow is %u", - (unsigned int)today_time, (unsigned int)tomorrow_time); - bytes_in = bytes_out = pkts_in = pkts_out = 0; - fd = daylog_open(); - if (fd == -1) - err(1, "couldn't open(\"%s\") for append", filename); + assert(daylog_fn != NULL); + fd = open(daylog_fn, O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW, 0600); + if (fd == -1) { + warn("daylog_write: couldn't open '%s' for append", daylog_fn); + return; + } buf = str_make(); - str_appendf(buf, "# logging started at %s (%u)\n", - fmt_date(today_time), (unsigned int)today_time); - str_extract(buf, &len, &s); - (void)write(fd, s, len); /* ignore write errors */ + va_start(va, format); + str_vappendf(buf, format, va); + va_end(va); + + wr = str_write(buf, fd); + if (wr == -1) + warn("daylog_write: couldn't write to '%s'", daylog_fn); + else if (wr != (ssize_t)str_len(buf)) + warnx("daylog_write: truncated write to '%s': wrote %d of %d bytes", + daylog_fn, + (int)wr, + (int)str_len(buf)); close(fd); - free(s); + str_free(buf); } -void daylog_free(void) -{ - int fd; - struct str *buf; - char *s; - size_t len; - - today_time = time(NULL); +static void daylog_emit(void) { + daylog_write("%s|%qu|%qu|%qu|%qu|%qu\n", + fmt_date(today_real), + (qu)today_real, + (qu)bytes_in, + (qu)bytes_out, + (qu)pkts_in, + (qu)pkts_out); +} - /* Emit what's currently accumulated. */ - daylog_emit(); +void daylog_init(const char *filename) { + daylog_fn = filename; + today_real = now_real(); + tomorrow_real = tomorrow(today_real); + verbosef("today is %llu, tomorrow is %llu", + (llu)today_real, + (llu)tomorrow_real); + bytes_in = bytes_out = pkts_in = pkts_out = 0; - fd = daylog_open(); - if (fd == -1) return; + daylog_write("# logging started at %s (%qu)\n", + fmt_date(today_real), (qu)today_real); +} - buf = str_make(); - str_appendf(buf, "# logging stopped at %s (%u)\n", - fmt_date(today_time), (unsigned int)today_time); - str_extract(buf, &len, &s); - (void)write(fd, s, len); /* ignore write errors */ - close(fd); - free(s); +void daylog_free(void) { + today_real = now_real(); + daylog_emit(); /* Emit what's currently accumulated before we exit. */ + daylog_write("# logging stopped at %s (%qu)\n", + fmt_date(today_real), (qu)today_real); } -void -daylog_acct(uint64_t amount, enum graph_dir dir) -{ - if (daylog_fn == NULL) return; /* disabled */ +void daylog_acct(uint64_t amount, enum graph_dir dir) { + if (daylog_fn == NULL) + return; /* daylogging disabled */ - /* Check if we need to rotate. */ - if (now >= tomorrow_time) { + /* Check if we need to update the log. */ + if (now_real() >= tomorrow_real) { daylog_emit(); - today_time = now; - tomorrow_time = tomorrow(today_time); + today_real = now_real(); + tomorrow_real = tomorrow(today_real); bytes_in = bytes_out = pkts_in = pkts_out = 0; - verbosef("rotated daylog, tomorrow = %u", - (unsigned int)tomorrow_time); + verbosef("updated daylog, tomorrow = %llu", (llu)tomorrow_real); } /* Accounting. */