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