"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.

    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 }