"Fossies" - the Fresh Open Source Software Archive 
Member "vnstat-2.9/src/misc.c" (28 Dec 2021, 12966 Bytes) of package /linux/misc/vnstat-2.9.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "misc.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.8_vs_2.9.
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
20 int 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));
35 printe(PT_Error);
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
61 void 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 }
85 printe(PT_Info);
86 }
87 }
88
89 uint64_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));
99 printe(PT_Error);
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.");
121 printe(PT_Error);
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
148 char *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
189 int 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
203 char *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
222 const 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
238 const 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
256 uint64_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
269 int 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
282 char *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
308 int 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
320 int 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
336 void cursortocolumn(const int column)
337 {
338 printf("\033[%dG", column);
339 }
340
341 void cursorhide(void)
342 {
343 printf("\033[?25l");
344 }
345
346 void cursorshow(void)
347 {
348 printf("\033[?25h");
349 }
350
351 void eraseline(void)
352 {
353 printf("\033[2K");
354 }
355
356 /* validity of date or time itself isn't checked here as sqlite handles that */
357 int 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
403 int 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
453 uint64_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
493 void 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
553 int 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 }