"Fossies" - the Fresh Open Source Software Archive

Member "vnstat-2.9/src/dbaccess.c" (16 Sep 2019, 13309 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 "dbaccess.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.4_vs_2.5.

    1 #include "common.h"
    2 #include "dbsql.h"
    3 #include "dbaccess.h"
    4 
    5 int importlegacydb(const char *iface, const char *dirname)
    6 {
    7     DATA data;
    8 
    9     snprintf(errorstring, 1024, "Importing data from legacy database \"%s\".", iface);
   10     printe(PT_Infoless);
   11 
   12     if (db_getinterfacecountbyname(iface)) {
   13         return 0;
   14     }
   15 
   16     if (readdb(&data, iface, dirname, 0) != 0) {
   17         return 0;
   18     }
   19 
   20     if (!db_addinterface(iface)) {
   21         return 0;
   22     }
   23 
   24     if (!insertlegacydata(&data, iface)) {
   25         return 0;
   26     }
   27 
   28     return 1;
   29 }
   30 
   31 int insertlegacydata(DATA *data, const char *iface)
   32 {
   33     int i, year;
   34     time_t yeartime;
   35     struct tm *stm;
   36     uint64_t rx, tx;
   37 
   38     if (!db_begintransaction()) {
   39         return 0;
   40     }
   41 
   42     if (!db_setactive(iface, data->active)) {
   43         db_rollbacktransaction();
   44         return 0;
   45     }
   46     if (strcmp(iface, data->nick) != 0) {
   47         if (!db_setalias(iface, data->nick)) {
   48             db_rollbacktransaction();
   49             return 0;
   50         }
   51     }
   52     if (!db_setcounters(iface, data->currx, data->curtx)) {
   53         db_rollbacktransaction();
   54         return 0;
   55     }
   56     if (!db_setcreation(iface, data->created)) {
   57         db_rollbacktransaction();
   58         return 0;
   59     }
   60 
   61     for (i = 23; i >= 0; i--) {
   62         if (data->hour[i].date > 0 && (data->hour[i].rx > 0 || data->hour[i].tx > 0)) {
   63             if (!db_insertdata("hour", iface, data->hour[i].rx * 1024, data->hour[i].tx * 1024, (uint64_t)data->hour[i].date)) {
   64                 db_rollbacktransaction();
   65                 return 0;
   66             }
   67         }
   68     }
   69     for (i = 29; i >= 0; i--) {
   70         if (data->day[i].used) {
   71             if (!db_insertdata("day", iface, data->day[i].rx * 1024 * 1024 + (uint64_t)data->day[i].rxk * 1024, data->day[i].tx * 1024 * 1024 + (uint64_t)data->day[i].txk * 1024, (uint64_t)data->day[i].date)) {
   72                 db_rollbacktransaction();
   73                 return 0;
   74             }
   75         }
   76     }
   77     for (i = 11; i >= 0; i--) {
   78         if (data->month[i].used) {
   79             if (!db_insertdata("month", iface, data->month[i].rx * 1024 * 1024 + (uint64_t)data->month[i].rxk * 1024, data->month[i].tx * 1024 * 1024 + (uint64_t)data->month[i].txk * 1024, (uint64_t)data->month[i].month)) {
   80                 db_rollbacktransaction();
   81                 return 0;
   82             }
   83         }
   84     }
   85     for (i = 9; i >= 0; i--) {
   86         if (data->top10[i].used) {
   87             if (!db_insertdata("top", iface, data->top10[i].rx * 1024 * 1024 + (uint64_t)data->top10[i].rxk * 1024, data->top10[i].tx * 1024 * 1024 + (uint64_t)data->top10[i].txk * 1024, (uint64_t)data->top10[i].date)) {
   88                 db_rollbacktransaction();
   89                 return 0;
   90             }
   91         }
   92     }
   93 
   94     /* construct yearly data from legacy monthly data */
   95     rx = 0;
   96     tx = 0;
   97     year = 0;
   98     yeartime = 0;
   99     for (i = 11; i >= 0; i--) {
  100         if (!data->month[i].used) {
  101             continue;
  102         }
  103         stm = localtime(&data->month[i].month);
  104         /* sanity check for possible invalid data */
  105         if (stm->tm_year + 1900 <= 1980 || stm->tm_year + 1900 >= 2050) {
  106             continue;
  107         }
  108         if (stm->tm_year + 1900 != year) {
  109             if (year != 0 && (rx > 0 || tx > 0)) {
  110                 if (!db_insertdata("year", iface, rx, tx, (uint64_t)yeartime)) {
  111                     db_rollbacktransaction();
  112                     return 0;
  113                 }
  114             }
  115             year = stm->tm_year + 1900;
  116             yeartime = data->month[i].month;
  117             rx = 0;
  118             tx = 0;
  119         }
  120         rx += data->month[i].rx * 1024 * 1024 + (uint64_t)data->month[i].rxk * 1024;
  121         tx += data->month[i].tx * 1024 * 1024 + (uint64_t)data->month[i].txk * 1024;
  122     }
  123     if (year != 0 && (rx > 0 || tx > 0)) {
  124         if (!db_insertdata("year", iface, rx, tx, (uint64_t)yeartime)) {
  125             db_rollbacktransaction();
  126             return 0;
  127         }
  128     }
  129 
  130     if (!db_settotal(iface, data->totalrx * 1024 * 1024 + (uint64_t)data->totalrxk * 1024, data->totaltx * 1024 * 1024 + (uint64_t)data->totaltxk * 1024)) {
  131         db_rollbacktransaction();
  132         return 0;
  133     }
  134 
  135     return db_committransaction();
  136 }
  137 
  138 int readdb(DATA *data, const char *iface, const char *dirname, const int force)
  139 {
  140     FILE *legacydb;
  141     char file[512], backup[512];
  142 
  143     snprintf(file, 512, "%s/%s", dirname, iface);
  144     snprintf(backup, 512, "%s/.%s", dirname, iface);
  145 
  146     if ((legacydb = fopen(file, "r")) == NULL) {
  147         snprintf(errorstring, 1024, "Unable to read database \"%s\": %s", file, strerror(errno));
  148         printe(PT_Error);
  149 
  150         /* create new database template */
  151         initdb(data);
  152         strncpy_nt(data->interface, iface, 32);
  153         strncpy_nt(data->nick, data->interface, 32);
  154         return 1;
  155     }
  156 
  157     if (fread(data, sizeof(DATA), 1, legacydb) != 1 || ferror(legacydb)) {
  158         data->version = -1;
  159         if (debug) {
  160             printf("db: Database read failed for file \"%s\".\n", file);
  161         }
  162     } else {
  163         if (debug) {
  164             data->interface[sizeof(data->interface) - 1] = '\0';
  165             printf("db: Database loaded for interface \"%s\"...\n", data->interface);
  166         }
  167     }
  168     data->interface[sizeof(data->interface) - 1] = '\0';
  169     data->nick[sizeof(data->nick) - 1] = '\0';
  170 
  171     if (data->version == LEGACYDBVERSION) {
  172         if (!validatedb(data) && !force) {
  173             data->version = -1;
  174             if (debug) {
  175                 printf("db: Database for interface \"%s\" fails to validate, trying with backup\n", data->interface);
  176             }
  177         }
  178     }
  179 
  180     /* convert old database to new format if necessary */
  181     if (data->version < LEGACYDBVERSION) {
  182         if (data->version == -1) {
  183 
  184             /* close current db and try using backup if database conversion failed */
  185             fclose(legacydb);
  186             if ((legacydb = fopen(backup, "r")) == NULL) {
  187                 snprintf(errorstring, 1024, "Unable to open backup database \"%s\": %s", backup, strerror(errno));
  188                 printe(PT_Error);
  189                 if (noexit) {
  190                     return -1;
  191                 } else {
  192                     exit(EXIT_FAILURE);
  193                 }
  194             }
  195 
  196             if (fread(data, sizeof(DATA), 1, legacydb) != 1 || ferror(legacydb)) {
  197                 snprintf(errorstring, 1024, "Database load failed even when using backup (%s). Aborting.", strerror(errno));
  198                 printe(PT_Error);
  199                 fclose(legacydb);
  200 
  201                 if (noexit) {
  202                     return -1;
  203                 } else {
  204                     exit(EXIT_FAILURE);
  205                 }
  206             } else {
  207                 if (debug) {
  208                     data->interface[sizeof(data->interface) - 1] = '\0';
  209                     printf("db: Backup database loaded for interface \"%s\"...\n", data->interface);
  210                 }
  211             }
  212             data->interface[sizeof(data->interface) - 1] = '\0';
  213             data->nick[sizeof(data->nick) - 1] = '\0';
  214 
  215             if (data->version == LEGACYDBVERSION) {
  216                 if (!validatedb(data)) {
  217                     data->version = -1;
  218                     if (debug) {
  219                         printf("db: Backup database for interface \"%s\" fails to validate\n", data->interface);
  220                     }
  221                 }
  222             }
  223 
  224             if (data->version != LEGACYDBVERSION) {
  225                 if (data->version == -1) {
  226                     snprintf(errorstring, 1024, "Unable to use database \"%s\" or its backup.", file);
  227                     printe(PT_Error);
  228                     fclose(legacydb);
  229 
  230                     if (noexit) {
  231                         return -1;
  232                     } else {
  233                         exit(EXIT_FAILURE);
  234                     }
  235                 }
  236             }
  237             snprintf(errorstring, 1024, "Database possibly corrupted, using backup instead.");
  238             printe(PT_Info);
  239         }
  240 
  241     } else if (data->version > LEGACYDBVERSION) {
  242         snprintf(errorstring, 1024, "Downgrading database \"%s\" (v%d) is not supported.", file, data->version);
  243         printe(PT_Error);
  244         fclose(legacydb);
  245 
  246         if (noexit) {
  247             return -1;
  248         } else {
  249             exit(EXIT_FAILURE);
  250         }
  251     }
  252 
  253     fclose(legacydb);
  254 
  255     if (strcmp(data->interface, iface)) {
  256         snprintf(errorstring, 1024, "Warning:\nThe previous interface for this file was \"%s\".", data->interface);
  257         printe(PT_Multiline);
  258         snprintf(errorstring, 1024, "It has now been replaced with \"%s\".", iface);
  259         printe(PT_Multiline);
  260         snprintf(errorstring, 1024, "You can ignore this message if you renamed the filename.");
  261         printe(PT_Multiline);
  262         snprintf(errorstring, 1024, "Interface name mismatch, renamed \"%s\" -> \"%s\"", data->interface, iface);
  263         printe(PT_ShortMultiline);
  264         if (strcmp(data->interface, data->nick) == 0) {
  265             strncpy_nt(data->nick, iface, 32);
  266         }
  267         strncpy_nt(data->interface, iface, 32);
  268     }
  269 
  270     return 0;
  271 }
  272 
  273 void initdb(DATA *data)
  274 {
  275     int i;
  276     time_t current;
  277     struct tm *d;
  278 
  279     current = time(NULL);
  280     d = localtime(&current);
  281 
  282     /* set default values for a new database */
  283     data->version = LEGACYDBVERSION;
  284     data->active = 1;
  285     data->totalrx = 0;
  286     data->totaltx = 0;
  287     data->currx = 0;
  288     data->curtx = 0;
  289     data->totalrxk = 0;
  290     data->totaltxk = 0;
  291     data->lastupdated = current;
  292     data->created = current;
  293 
  294     /* days */
  295     for (i = 0; i <= 29; i++) {
  296         data->day[i].rx = 0;
  297         data->day[i].tx = 0;
  298         data->day[i].rxk = 0;
  299         data->day[i].txk = 0;
  300         data->day[i].date = 0;
  301         data->day[i].used = 0;
  302     }
  303 
  304     /* months */
  305     for (i = 0; i <= 11; i++) {
  306         data->month[i].rx = 0;
  307         data->month[i].tx = 0;
  308         data->month[i].rxk = 0;
  309         data->month[i].txk = 0;
  310         data->month[i].month = 0;
  311         data->month[i].used = 0;
  312     }
  313 
  314     /* top10 */
  315     for (i = 0; i <= 9; i++) {
  316         data->top10[i].rx = 0;
  317         data->top10[i].tx = 0;
  318         data->top10[i].rxk = 0;
  319         data->top10[i].txk = 0;
  320         data->top10[i].date = 0;
  321         data->top10[i].used = 0;
  322     }
  323 
  324     /* hours */
  325     for (i = 0; i <= 23; i++) {
  326         data->hour[i].rx = 0;
  327         data->hour[i].tx = 0;
  328         data->hour[i].date = 0;
  329     }
  330 
  331     data->day[0].used = data->month[0].used = 1;
  332     data->day[0].date = current;
  333 
  334     /* calculate new date for current month if current day is less
  335            than the set monthrotate value so that new databases begin
  336            from the right month */
  337     if (d->tm_mday < cfg.monthrotate) {
  338         d->tm_mday = cfg.monthrotate;
  339         d->tm_mon--;
  340         data->month[0].month = mktime(d);
  341     } else {
  342         data->month[0].month = current;
  343     }
  344 
  345     data->btime = MAX32;
  346 }
  347 
  348 int validatedb(DATA *data)
  349 {
  350     int i, used;
  351     uint64_t rxsum, txsum;
  352     const char *invaliddb = "Invalid database";
  353 
  354     if (debug) {
  355         printf("validating loaded database\n");
  356     }
  357 
  358     /* enforce string termination */
  359     data->interface[sizeof(data->interface) - 1] = '\0';
  360     data->nick[sizeof(data->nick) - 1] = '\0';
  361 
  362     if (data->version > LEGACYDBVERSION) {
  363         snprintf(errorstring, 1024, "%s: %s version: %d", data->interface, invaliddb, data->version);
  364         printe(PT_Error);
  365         return 0;
  366     }
  367 
  368     if (data->active < 0 || data->active > 1) {
  369         snprintf(errorstring, 1024, "%s: %s activity status: %d", data->interface, invaliddb, data->active);
  370         printe(PT_Error);
  371         return 0;
  372     }
  373 
  374     if (!strlen(data->interface)) {
  375         snprintf(errorstring, 1024, "%s interface string: %s", invaliddb, data->interface);
  376         printe(PT_Error);
  377         return 0;
  378     }
  379 
  380     if (!data->created || !data->lastupdated || !data->btime) {
  381         snprintf(errorstring, 1024, "%s: %s timestamp.", data->interface, invaliddb);
  382         printe(PT_Error);
  383         return 0;
  384     }
  385 
  386     rxsum = txsum = 0;
  387     used = 1;
  388     for (i = 0; i < 30; i++) {
  389         if (data->day[i].used < 0 || data->day[i].used > 1) {
  390             snprintf(errorstring, 1024, "%s: %s daily use information: %d %d", data->interface, invaliddb, i, data->day[i].used);
  391             printe(PT_Error);
  392             return 0;
  393         }
  394         if (data->day[i].rxk < 0 || data->day[i].txk < 0) {
  395             snprintf(errorstring, 1024, "%s: %s daily traffic: %d", data->interface, invaliddb, i);
  396             printe(PT_Error);
  397             return 0;
  398         }
  399         if (data->day[i].used && !used) {
  400             snprintf(errorstring, 1024, "%s: %s daily use order: %d", data->interface, invaliddb, i);
  401             printe(PT_Error);
  402             return 0;
  403         } else if (!data->day[i].used) {
  404             used = 0;
  405         }
  406         if (data->day[i].used) {
  407             rxsum += data->day[i].rx;
  408             txsum += data->day[i].tx;
  409         }
  410     }
  411 
  412     for (i = 1; i < 30; i++) {
  413         if (!data->day[i].used) {
  414             break;
  415         }
  416         if (data->day[i - 1].date < data->day[i].date) {
  417             snprintf(errorstring, 1024, "%s: %s daily date order: %u (%d) < %u (%d)", data->interface, invaliddb, (unsigned int)data->day[i - 1].date, i - 1, (unsigned int)data->day[i].date, i);
  418             printe(PT_Error);
  419             return 0;
  420         }
  421     }
  422 
  423     if (data->totalrx < rxsum || data->totaltx < txsum) {
  424         snprintf(errorstring, 1024, "%s: %s total traffic compared to daily usage.", data->interface, invaliddb);
  425         printe(PT_Error);
  426         return 0;
  427     }
  428 
  429     rxsum = txsum = 0;
  430     used = 1;
  431     for (i = 0; i < 12; i++) {
  432         if (data->month[i].used < 0 || data->month[i].used > 1) {
  433             snprintf(errorstring, 1024, "%s: %s monthly use information: %d %d", data->interface, invaliddb, i, data->month[i].used);
  434             printe(PT_Error);
  435             return 0;
  436         }
  437         if (data->month[i].rxk < 0 || data->month[i].txk < 0) {
  438             snprintf(errorstring, 1024, "%s: %s monthly traffic: %d", data->interface, invaliddb, i);
  439             printe(PT_Error);
  440             return 0;
  441         }
  442         if (data->month[i].used && !used) {
  443             snprintf(errorstring, 1024, "%s: %s monthly use order: %d", data->interface, invaliddb, i);
  444             printe(PT_Error);
  445             return 0;
  446         } else if (!data->month[i].used) {
  447             used = 0;
  448         }
  449         if (data->month[i].used) {
  450             rxsum += data->month[i].rx;
  451             txsum += data->month[i].tx;
  452         }
  453     }
  454 
  455     for (i = 1; i < 12; i++) {
  456         if (!data->month[i].used) {
  457             break;
  458         }
  459         if (data->month[i - 1].month < data->month[i].month) {
  460             snprintf(errorstring, 1024, "%s: %s monthly date order: %u (%d) < %u (%d)", data->interface, invaliddb, (unsigned int)data->month[i - 1].month, i - 1, (unsigned int)data->month[i].month, i);
  461             printe(PT_Error);
  462             return 0;
  463         }
  464     }
  465 
  466     if (data->totalrx < rxsum || data->totaltx < txsum) {
  467         snprintf(errorstring, 1024, "%s: %s total traffic compared to monthly usage.", data->interface, invaliddb);
  468         printe(PT_Error);
  469         return 0;
  470     }
  471 
  472     used = 1;
  473     for (i = 0; i < 10; i++) {
  474         if (data->top10[i].used < 0 || data->top10[i].used > 1) {
  475             snprintf(errorstring, 1024, "%s: %s top10 use information: %d %d", data->interface, invaliddb, i, data->top10[i].used);
  476             printe(PT_Error);
  477             return 0;
  478         }
  479         if (data->top10[i].rxk < 0 || data->top10[i].txk < 0) {
  480             snprintf(errorstring, 1024, "%s: %s top10 traffic: %d", data->interface, invaliddb, i);
  481             printe(PT_Error);
  482             return 0;
  483         }
  484         if (data->top10[i].used && !used) {
  485             snprintf(errorstring, 1024, "%s: %s top10 use order: %d", data->interface, invaliddb, i);
  486             printe(PT_Error);
  487             return 0;
  488         } else if (!data->top10[i].used) {
  489             used = 0;
  490         }
  491     }
  492 
  493     return 1;
  494 }