2 * copyright (c) 2007-2014 Emil Mikulic.
4 * daylog.c: daily usage log
6 * You may use, modify and redistribute this file under the terms of the
7 * GNU General Public License version 2. (see COPYING.GPL)
10 #define _GNU_SOURCE 1 /* for O_NOFOLLOW on Linux */
26 static const char *daylog_fn
= NULL
;
27 static time_t today_real
, tomorrow_real
;
28 static uint64_t bytes_in
, bytes_out
, pkts_in
, pkts_out
;
30 #define DAYLOG_DATE_LEN 26 /* strlen("1900-01-01 00:00:00 +1234") + 1 */
31 static char datebuf
[DAYLOG_DATE_LEN
];
33 static char *fmt_date(time_t when
) {
36 "%Y-%m-%d %H:%M:%S %z",
37 localtime(&when
)) == 0)
38 errx(1, "strftime() failed in fmt_date()");
42 /* Given some time today, find the first second of tomorrow. */
43 static time_t tomorrow(time_t t_before
) {
47 lt
= localtime(&t_before
);
48 memcpy(&tm
, lt
, sizeof(tm
));
52 tm
.tm_mday
= lt
->tm_mday
+ 1; /* tomorrow */
53 t_after
= mktime(&tm
);
54 assert(t_after
> t_before
);
59 static void daylog_write(const char *format
, ...) _printflike_(1, 2);
60 static void daylog_write(const char *format
, ...) {
66 assert(daylog_fn
!= NULL
);
67 fd
= open(daylog_fn
, O_WRONLY
| O_APPEND
| O_CREAT
| O_NOFOLLOW
, 0600);
69 warn("daylog_write: couldn't open '%s' for append", daylog_fn
);
75 str_vappendf(buf
, format
, va
);
78 wr
= str_write(buf
, fd
);
80 warn("daylog_write: couldn't write to '%s'", daylog_fn
);
81 else if (wr
!= (ssize_t
)str_len(buf
))
82 warnx("daylog_write: truncated write to '%s': wrote %d of %d bytes",
90 static void daylog_emit(void) {
91 daylog_write("%s|%qu|%qu|%qu|%qu|%qu\n",
100 void daylog_init(const char *filename
) {
101 daylog_fn
= filename
;
102 today_real
= now_real();
103 tomorrow_real
= tomorrow(today_real
);
104 verbosef("today is %llu, tomorrow is %llu",
107 bytes_in
= bytes_out
= pkts_in
= pkts_out
= 0;
109 daylog_write("# logging started at %s (%qu)\n",
110 fmt_date(today_real
), (qu
)today_real
);
113 void daylog_free(void) {
114 today_real
= now_real();
115 daylog_emit(); /* Emit what's currently accumulated before we exit. */
116 daylog_write("# logging stopped at %s (%qu)\n",
117 fmt_date(today_real
), (qu
)today_real
);
120 void daylog_acct(uint64_t amount
, enum graph_dir dir
) {
121 if (daylog_fn
== NULL
)
122 return; /* daylogging disabled */
124 /* Check if we need to update the log. */
125 if (now_real() >= tomorrow_real
) {
128 today_real
= now_real();
129 tomorrow_real
= tomorrow(today_real
);
130 bytes_in
= bytes_out
= pkts_in
= pkts_out
= 0;
131 verbosef("updated daylog, tomorrow = %llu", (llu
)tomorrow_real
);
135 if (dir
== GRAPH_IN
) {
139 assert(dir
== GRAPH_OUT
);
145 /* vim:set ts=3 sw=3 tw=78 et: */