"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(¤t);
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 }