vnstat  2.9
About: vnStat is a console-based network traffic monitor (using the /proc filesystem).
  Fossies Dox: vnstat-2.9.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

misc.c
Go to the documentation of this file.
1#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__APPLE__) && !defined(__FreeBSD_kernel__)
2#if defined(__clang__)
3#pragma clang diagnostic push
4#pragma clang diagnostic ignored "-Wreserved-id-macro"
5#endif
6#define _XOPEN_SOURCE 600
7#if defined(__clang__)
8#pragma clang diagnostic pop
9#endif
10#endif
11/* enable wcswidth on kFreeBSD */
12#if defined(__FreeBSD_kernel__) && defined(__GLIBC__)
13#define __USE_XOPEN
14#define _XOPEN_SOURCE
15#endif
16#include "common.h"
17#include "misc.h"
18#include <wchar.h>
19
20int spacecheck(const char *path)
21{
22 struct statvfs buf;
23 uint64_t free;
24
25 /* do space check only when configured for it */
26 if (!cfg.spacecheck) {
27 return 1;
28 }
29
30 if (statvfs(path, &buf)) {
31 if (noexit) {
32 return 0;
33 } else {
34 snprintf(errorstring, 1024, "Free diskspace check failed: %s", strerror(errno));
36 exit(EXIT_FAILURE);
37 }
38 }
39
40 free = (uint64_t)((double)buf.f_bavail / (double)1024) * buf.f_bsize;
41
42 if (debug) {
43 printf("bsize %d\n", (int)buf.f_bsize);
44 printf("blocks %lu\n", (unsigned long int)buf.f_blocks);
45 printf("bfree %lu\n", (unsigned long int)buf.f_bfree);
46 printf("bavail %lu\n", (unsigned long int)buf.f_bavail);
47 printf("ffree %lu\n", (unsigned long int)buf.f_ffree);
48 printf("%" PRIu64 " free space left\n", free);
49 }
50
51 /* the database is likely to be less than 200 kiB but let's require */
52 /* 1 MiB to be on the safe side, anyway, the filesystem should */
53 /* always have more free space than that */
54 if (free <= 1024) {
55 return 0;
56 } else {
57 return 1;
58 }
59}
60
61void sighandler(int sig)
62{
63 /* set signal */
64 intsignal = sig;
65
66 if (debug) {
67 switch (sig) {
68
69 case SIGHUP:
70 snprintf(errorstring, 1024, "DEBUG: SIGHUP (%d)", sig);
71 break;
72
73 case SIGTERM:
74 snprintf(errorstring, 1024, "DEBUG: SIGTERM (%d)", sig);
75 break;
76
77 case SIGINT:
78 snprintf(errorstring, 1024, "DEBUG: SIGINT (%d)", sig);
79 break;
80
81 default:
82 snprintf(errorstring, 1024, "DEBUG: Unknown signal %d", sig);
83 break;
84 }
86 }
87}
88
89uint64_t getbtime(void)
90{
91 uint64_t result = 0;
92#if defined(__linux__)
93 FILE *fp;
94 int check;
95 char temp[64], statline[128];
96
97 if ((fp = fopen("/proc/stat", "r")) == NULL) {
98 snprintf(errorstring, 1024, "Unable to read /proc/stat: %s", strerror(errno));
100 if (noexit) {
101 return 0;
102 } else {
103 exit(1);
104 }
105 }
106
107 check = 0;
108 while (fgets(statline, 128, fp) != NULL) {
109 sscanf(statline, "%63s", temp);
110 if (strcmp(temp, "btime") == 0) {
111 /* if (debug)
112 printf("\n%s\n",statline); */
113 check = 1;
114 break;
115 }
116 }
117 fclose(fp);
118
119 if (check == 0) {
120 snprintf(errorstring, 1024, "btime missing from /proc/stat.");
122 if (noexit) {
123 return 0;
124 } else {
125 exit(1);
126 }
127 }
128
129 result = strtoull(statline + 6, (char **)NULL, 0);
130
131#elif defined(BSD_VNSTAT)
132 struct timeval btm;
133 size_t len = sizeof(btm);
134 int mib[2] = {CTL_KERN, KERN_BOOTTIME};
135
136 if (sysctl(mib, 2, &btm, &len, NULL, 0) < 0) {
137 if (debug)
138 printf("sysctl(kern.boottime) failed.\n");
139 return 0;
140 }
141
142 result = (uint64_t)btm.tv_sec;
143#endif
144
145 return result;
146}
147
148char *getvalue(const uint64_t bytes, const int len, const RequestType type)
149{
150 static char buffer[64];
151 int i, declen = cfg.defaultdecimals, p = 1024;
152 uint64_t limit;
153
154 if (type == RT_ImageScale) {
155 declen = 0;
156 }
157
158 if (cfg.unitmode == 2) {
159 p = 1000;
160 }
161
162 if ((type == RT_Estimate) && (bytes == 0)) {
163 declen = len - (int)strlen(getunitprefix(2)) - 2;
164 if (declen < 2) {
165 declen = 2;
166 }
167 snprintf(buffer, 64, "%*s %*s", declen, "--", (int)strlen(getunitprefix(2)), " ");
168 } else {
169 for (i = UNITPREFIXCOUNT - 1; i > 0; i--) {
170 limit = (uint64_t)(pow(p, i - 1)) * 1000;
171 if (bytes >= limit) {
172 if (i > 1) {
173 snprintf(buffer, 64, "%" DECCONV "*.*f %s", getunitspacing(len, 5), declen, (double)bytes / (double)(getunitdivisor(cfg.unitmode, i + 1)), getunitprefix(i + 1));
174 } else {
175 if (type == RT_Estimate) {
176 declen = 0;
177 }
178 snprintf(buffer, 64, "%" DECCONV "*.*f %s", getunitspacing(len, 2), declen, (double)bytes / (double)(getunitdivisor(cfg.unitmode, i + 1)), getunitprefix(i + 1));
179 }
180 return buffer;
181 }
182 }
183 snprintf(buffer, 64, "%" DECCONV "*" PRIu64 " %s", getunitspacing(len, 1), bytes, getunitprefix(1));
184 }
185
186 return buffer;
187}
188
189int getunitspacing(const int len, const int index)
190{
191 int l = len;
192
193 /* tune spacing according to unit */
194 /* +1 for space between number and unit */
195 l -= (int)strlen(getunitprefix(index)) + 1;
196 if (l < 0) {
197 l = 1;
198 }
199
200 return l;
201}
202
203char *gettrafficrate(const uint64_t bytes, const time_t interval, const int len)
204{
205 static char buffer[64];
206 int declen = cfg.defaultdecimals;
207 uint64_t b = bytes;
208
209 if (interval == 0) {
210 snprintf(buffer, 64, "%*s", len, "n/a");
211 return buffer;
212 }
213
214 /* convert to proper unit */
215 if (cfg.rateunit == 1) {
216 b *= 8;
217 }
218
219 return getratestring(b / (uint64_t)interval, len, declen);
220}
221
222const char *getunitprefix(const int index)
223{
224 /* clang-format off */
225 static const char *unitprefix[] = { "na",
226 "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", /* IEC - 1024^n */
227 "B", "KB", "MB", "GB", "TB", "PB", "EB", /* JEDEC - 1024^n */
228 "B", "kB", "MB", "GB", "TB", "PB", "EB" }; /* SI - 1000^n */
229 /* clang-format on */
230
231 if (index > UNITPREFIXCOUNT) {
232 return unitprefix[0];
233 } else {
234 return unitprefix[(cfg.unitmode * UNITPREFIXCOUNT) + index];
235 }
236}
237
238const char *getrateunitprefix(const int unitmode, const int index)
239{
240 /* clang-format off */
241 static const char *rateunitprefix[] = { "na",
242 "B/s", "KiB/s", "MiB/s", "GiB/s", "TiB/s", "PiB/s", "EiB/s", /* IEC - 1024^n */
243 "B/s", "KB/s", "MB/s", "GB/s", "TB/s", "PB/s", "EB/s", /* JEDEC - 1024^n */
244 "B/s", "kB/s", "MB/s", "GB/s", "TB/s", "PB/s", "EB/s", /* SI - 1000^n */
245 "bit/s", "Kibit/s", "Mibit/s", "Gibit/s", "Tibit/s", "Pibit/s", "Eibit/s", /* IEC - 1024^n */
246 "bit/s", "kbit/s", "Mbit/s", "Gbit/s", "Tbit/s", "Pbit/s", "Ebit/s" }; /* SI - 1000^n */
247 /* clang-format on */
248
249 if (index > UNITPREFIXCOUNT) {
250 return rateunitprefix[0];
251 } else {
252 return rateunitprefix[(unitmode * UNITPREFIXCOUNT) + index];
253 }
254}
255
256uint64_t getunitdivisor(const int unitmode, const int index)
257{
258 if (index > UNITPREFIXCOUNT) {
259 return 1;
260 } else {
261 if (unitmode == 2 || unitmode == 4) {
262 return (uint64_t)(pow(1000, index - 1));
263 } else {
264 return (uint64_t)(pow(1024, index - 1));
265 }
266 }
267}
268
269int getunit(void)
270{
271 int unit;
272
273 if (cfg.rateunit == 0) {
274 unit = cfg.unitmode;
275 } else {
276 unit = 3 + cfg.rateunitmode;
277 }
278
279 return unit;
280}
281
282char *getratestring(const uint64_t rate, const int len, const int declen)
283{
284 int l, i, unit, p = 1024;
285 static char buffer[64];
286 uint64_t limit;
287
288 unit = getunit();
289
290 if (unit == 2 || unit == 4) {
291 p = 1000;
292 }
293
294 for (i = UNITPREFIXCOUNT - 1; i > 0; i--) {
295 limit = (uint64_t)(pow(p, i - 1)) * 1000;
296 if (rate >= limit) {
297 l = getratespacing(len, unit, i + 1);
298 snprintf(buffer, 64, "%" DECCONV "*.*f %s", l, declen, (double)rate / (double)(getunitdivisor(unit, i + 1)), getrateunitprefix(unit, i + 1));
299 return buffer;
300 }
301 }
302
303 l = getratespacing(len, unit, 1);
304 snprintf(buffer, 64, "%" DECCONV "*.0f %s", l, (double)rate / (double)(getunitdivisor(unit, 1)), getrateunitprefix(unit, 1));
305 return buffer;
306}
307
308int getratespacing(const int len, const int unitmode, const int unitindex)
309{
310 int l = len;
311
312 l -= (int)strlen(getrateunitprefix(unitmode, unitindex)) + 1;
313 if (l < 0) {
314 l = 1;
315 }
316
317 return l;
318}
319
320int getpadding(const int len, const char *str)
321{
322#if defined(HAVE_MBSTOWCS) && defined(HAVE_WCSWIDTH)
323 wchar_t wbuffer[64];
324 if (!cfg.utflocale) {
325 return len;
326 }
327 if ((int)mbstowcs(wbuffer, str, 64) < 0) {
328 return len;
329 }
330 return len + ((int)strlen(str) - wcswidth(wbuffer, 64));
331#else
332 return len;
333#endif
334}
335
336void cursortocolumn(const int column)
337{
338 printf("\033[%dG", column);
339}
340
341void cursorhide(void)
342{
343 printf("\033[?25l");
344}
345
346void cursorshow(void)
347{
348 printf("\033[?25h");
349}
350
351void eraseline(void)
352{
353 printf("\033[2K");
354}
355
356/* validity of date or time itself isn't checked here as sqlite handles that */
357int validatedatetime(const char *str)
358{
359 short valid;
360 unsigned int len, i, t;
361 const char *templates[] = {"dddd-dd-dd dd:dd", "dddd-dd-dd"};
362
363 len = (unsigned int)strlen(str);
364 if (strcmp(str, "today") == 0) {
365 return 1;
366 }
367
368 if (len > strlen(templates[0])) {
369 return 0;
370 }
371
372 for (t = 0; t < 2; t++) {
373 if (len != strlen(templates[t])) {
374 continue;
375 }
376 valid = 1;
377 for (i = 0; i < strlen(templates[t]); i++) {
378 switch (templates[t][i]) {
379 case 'd':
380 if (!isdigit(str[i])) {
381 valid = 0;
382 }
383 break;
384 default:
385 if (str[i] != templates[t][i]) {
386 valid = 0;
387 }
388 break;
389 }
390 if (!valid) {
391 break;
392 }
393 }
394 if (!valid) {
395 continue;
396 }
397 return 1;
398 }
399
400 return 0;
401}
402
403int issametimeslot(const ListType listtype, const time_t entry, const time_t updated)
404{
405 struct tm e, u;
406
407 if (updated < entry) {
408 return 0;
409 }
410
411 if (entry == updated) {
412 return 1;
413 }
414
415 if (localtime_r(&entry, &e) == NULL || localtime_r(&updated, &u) == NULL) {
416 return 0;
417 }
418
419 switch (listtype) {
420 case LT_5min:
421 if ((entry - (entry % 300)) == (updated - (updated % 300))) {
422 return 1;
423 }
424 break;
425 case LT_Hour:
426 if (e.tm_year == u.tm_year && e.tm_yday == u.tm_yday && e.tm_hour == u.tm_hour) {
427 return 1;
428 }
429 break;
430 case LT_Top:
431 case LT_Day:
432 if (e.tm_year == u.tm_year && e.tm_yday == u.tm_yday) {
433 return 1;
434 }
435 break;
436 case LT_Month:
437 if (e.tm_year == u.tm_year && e.tm_mon == u.tm_mon) {
438 return 1;
439 }
440 break;
441 case LT_Year:
442 if (e.tm_year == u.tm_year) {
443 return 1;
444 }
445 break;
446 case LT_None:
447 return 0;
448 }
449
450 return 0;
451}
452
453uint64_t getperiodseconds(const ListType listtype, const time_t entry, const time_t updated, const short isongoing)
454{
455 struct tm e, u;
456 uint64_t seconds = 0;
457
458 if (localtime_r(&entry, &e) == NULL || localtime_r(&updated, &u) == NULL) {
459 return 0;
460 }
461
462 if (isongoing) {
463 if (listtype == LT_Day) {
464 seconds = (uint64_t)u.tm_sec + (uint64_t)u.tm_min * 60 + (uint64_t)u.tm_hour * 3600;
465 } else if (listtype == LT_Month) {
466 seconds = (uint64_t)mosecs(entry, updated);
467 } else if (listtype == LT_Year) {
468 seconds = (uint64_t)u.tm_yday * 86400 + (uint64_t)u.tm_sec + (uint64_t)u.tm_min * 60 + (uint64_t)u.tm_hour * 3600;
469 } else if (listtype == LT_Top) {
470 seconds = 86400;
471 } else if (listtype == LT_Hour) {
472 seconds = (uint64_t)u.tm_sec + (uint64_t)u.tm_min * 60;
473 } else if (listtype == LT_5min) {
474 seconds = (uint64_t)u.tm_sec + (uint64_t)u.tm_min % 5 * 60;
475 }
476 } else {
477 if (listtype == LT_Day || listtype == LT_Top) {
478 seconds = 86400;
479 } else if (listtype == LT_Month) {
480 seconds = (uint64_t)dmonth(e.tm_mon) * 86400;
481 } else if (listtype == LT_Year) {
482 seconds = (uint64_t)(365 + isleapyear(e.tm_year + 1900)) * 86400;
483 } else if (listtype == LT_Hour) {
484 seconds = 3600;
485 } else if (listtype == LT_5min) {
486 seconds = 300;
487 }
488 }
489
490 return seconds;
491}
492
493void getestimates(uint64_t *rx, uint64_t *tx, const ListType listtype, const time_t updated, dbdatalist **dbdata)
494{
495 struct tm u;
496 uint64_t div = 0, mult = 0;
497 dbdatalist *datalist_i = *dbdata;
498
499 *rx = *tx = 0;
500
501 if (datalist_i == NULL) {
502 return;
503 }
504
505 if (localtime_r(&updated, &u) == NULL) {
506 return;
507 }
508
509 /* last entry on the list is the most recent entry */
510 while (datalist_i->next != NULL) {
511 datalist_i = datalist_i->next;
512 }
513
514 if (datalist_i->rx == 0 || datalist_i->tx == 0) {
515 return;
516 }
517
518 /* LT_5min and LT_Hour don't have the estimate line visible in outputs */
519 /* but are used by BarColumnShowsRate which requires "past" values for */
520 /* full hours / 5 minutes for the bar to show correctly */
521 if (listtype == LT_5min) {
522 div = ((uint64_t)u.tm_min % 5 * 60) + (uint64_t)u.tm_sec;
523 if (div == 0) {
524 div = 1;
525 mult = 1;
526 } else {
527 mult = 300;
528 }
529 } else if (listtype == LT_Hour) {
530 div = (uint64_t)u.tm_min * 60 + (uint64_t)u.tm_sec;
531 if (div == 0) {
532 div = 1;
533 mult = 1;
534 } else {
535 mult = 3600;
536 }
537 } else if (listtype == LT_Day) {
538 div = (uint64_t)u.tm_hour * 3600 + (uint64_t)u.tm_min * 60 + (uint64_t)u.tm_sec;
539 mult = 86400;
540 } else if (listtype == LT_Month) {
541 div = (uint64_t)mosecs(datalist_i->timestamp, updated);
542 mult = (uint64_t)dmonth(u.tm_mon) * 86400;
543 } else if (listtype == LT_Year) {
544 div = (uint64_t)u.tm_yday * 1440 + (uint64_t)u.tm_hour * 60 + (uint64_t)u.tm_min;
545 mult = (uint64_t)(365 + isleapyear(u.tm_year + 1900)) * 1440;
546 }
547 if (div > 0) {
548 *rx = (uint64_t)((double)datalist_i->rx / (double)div) * mult;
549 *tx = (uint64_t)((double)datalist_i->tx / (double)div) * mult;
550 }
551}
552
553int ishelprequest(const char *arg)
554{
555 if (strlen(arg) == 0) {
556 return 0;
557 }
558
559 if (strlen(arg) == 1 && arg[0] == '?') {
560 return 1;
561 } else if ((strcmp(arg, "-?") == 0) || (strcmp(arg, "--help") == 0)) {
562 return 1;
563 }
564
565 return 0;
566}
int noexit
Definition: common.c:9
time_t mosecs(time_t month, time_t updated)
Definition: common.c:209
int intsignal
Definition: common.c:10
int isleapyear(const int year)
Definition: common.c:197
int dmonth(const int month)
Definition: common.c:177
char errorstring[1024]
Definition: common.c:6
int printe(const PrintType type)
Definition: common.c:14
int debug
Definition: common.c:8
CFG cfg
Definition: common.c:4
@ PT_Info
Definition: common.h:350
@ PT_Error
Definition: common.h:353
#define DECCONV
Definition: common.h:41
int ishelprequest(const char *arg)
Definition: misc.c:553
const char * getrateunitprefix(const int unitmode, const int index)
Definition: misc.c:238
uint64_t getperiodseconds(const ListType listtype, const time_t entry, const time_t updated, const short isongoing)
Definition: misc.c:453
void cursortocolumn(const int column)
Definition: misc.c:336
void getestimates(uint64_t *rx, uint64_t *tx, const ListType listtype, const time_t updated, dbdatalist **dbdata)
Definition: misc.c:493
int validatedatetime(const char *str)
Definition: misc.c:357
uint64_t getbtime(void)
Definition: misc.c:89
void cursorshow(void)
Definition: misc.c:346
int getunit(void)
Definition: misc.c:269
int issametimeslot(const ListType listtype, const time_t entry, const time_t updated)
Definition: misc.c:403
void eraseline(void)
Definition: misc.c:351
char * getvalue(const uint64_t bytes, const int len, const RequestType type)
Definition: misc.c:148
const char * getunitprefix(const int index)
Definition: misc.c:222
int getunitspacing(const int len, const int index)
Definition: misc.c:189
char * getratestring(const uint64_t rate, const int len, const int declen)
Definition: misc.c:282
int getpadding(const int len, const char *str)
Definition: misc.c:320
void cursorhide(void)
Definition: misc.c:341
uint64_t getunitdivisor(const int unitmode, const int index)
Definition: misc.c:256
void sighandler(int sig)
Definition: misc.c:61
char * gettrafficrate(const uint64_t bytes, const time_t interval, const int len)
Definition: misc.c:203
int spacecheck(const char *path)
Definition: misc.c:20
int getratespacing(const int len, const int unitmode, const int unitindex)
Definition: misc.c:308
#define UNITPREFIXCOUNT
Definition: misc.h:4
ListType
Definition: misc.h:14
@ LT_5min
Definition: misc.h:16
@ LT_Hour
Definition: misc.h:17
@ LT_Year
Definition: misc.h:20
@ LT_Day
Definition: misc.h:18
@ LT_None
Definition: misc.h:15
@ LT_Top
Definition: misc.h:21
@ LT_Month
Definition: misc.h:19
RequestType
Definition: misc.h:8
@ RT_ImageScale
Definition: misc.h:11
@ RT_Estimate
Definition: misc.h:10
int32_t defaultdecimals
Definition: common.h:316
int32_t rateunitmode
Definition: common.h:314
int32_t spacecheck
Definition: common.h:315
int32_t utflocale
Definition: common.h:322
int32_t unitmode
Definition: common.h:314
int32_t rateunit
Definition: common.h:314
time_t timestamp
Definition: dbsql.h:8
struct dbdatalist * next
Definition: dbsql.h:11
uint64_t rx
Definition: dbsql.h:10
uint64_t tx
Definition: dbsql.h:10