Line data Source code
1 : #include "burp.h"
2 : #include "alloc.h"
3 : #include "asfd.h"
4 : #include "async.h"
5 : #include "cmd.h"
6 : #include "cntr.h"
7 : #include "cstat.h"
8 : #include "fsops.h"
9 : #include "handy.h"
10 : #include "log.h"
11 :
12 : #include "server/monitor/json_output.h"
13 :
14 : #include <limits.h>
15 :
16 : #define CNTR_VERSION 3
17 : #define CNTR_PATH_BUF_LEN 256
18 :
19 0 : static void cntr_ent_free(struct cntr_ent *cntr_ent)
20 : {
21 0 : if(!cntr_ent) return;
22 0 : if(cntr_ent->field) free(cntr_ent->field);
23 0 : if(cntr_ent->label) free(cntr_ent->label);
24 : }
25 :
26 0 : struct cntr *cntr_alloc(void)
27 : {
28 0 : return (struct cntr *)calloc_w(1, sizeof(struct cntr), __func__);
29 : }
30 :
31 0 : static int add_cntr_ent(struct cntr *cntr, int flags,
32 : enum cmd cmd, const char *field, const char *label)
33 : {
34 0 : struct cntr_ent *cenew=NULL;
35 0 : if(!(cenew=(struct cntr_ent *)
36 : calloc_w(1, sizeof(struct cntr_ent), __func__))
37 0 : || !(cenew->field=strdup_w(field, __func__))
38 0 : || !(cenew->label=strdup_w(label, __func__)))
39 0 : goto error;
40 0 : cenew->flags=flags;
41 0 : cenew->cmd=cmd;
42 :
43 0 : if(cntr->list) cenew->next=cntr->list;
44 0 : cntr->list=cenew;
45 :
46 0 : cntr->ent[(uint8_t)cmd]=cenew;
47 0 : return 0;
48 : error:
49 0 : cntr_ent_free(cenew);
50 0 : return -1;
51 : }
52 :
53 0 : static size_t calc_max_str_len(struct cntr *cntr, const char *cname)
54 : {
55 0 : size_t slen=0;
56 : char ullmax[64];
57 0 : struct cntr_ent *e=NULL;
58 :
59 : // See cntr_to_str().
60 : // First section - name/version/status
61 0 : slen+=strlen(cname);
62 0 : slen+=16; // More than enough space.
63 :
64 : // Second section.
65 : snprintf(ullmax, sizeof(ullmax),
66 0 : " %"PRIu64 "\n", (uint64_t)ULLONG_MAX);
67 0 : for(e=cntr->list; e; e=e->next)
68 : {
69 0 : if(e->flags & CNTR_SINGLE_FIELD)
70 : // %c%llu\t
71 0 : slen+=strlen(ullmax)+2;
72 : else
73 : // %c%llu/%llu/%llu/%llu/%llu\t
74 0 : slen+=(strlen(ullmax)*5)+6;
75 : }
76 :
77 : // Fourth section - a path. Cannot know how long this might be. Guess.
78 0 : slen+=CNTR_PATH_BUF_LEN+3; // %c%s\t\n
79 :
80 0 : slen+=1; // Terminating character.
81 :
82 0 : return slen;
83 : }
84 :
85 0 : int cntr_init(struct cntr *cntr, const char *cname)
86 : {
87 0 : if(!cname)
88 : {
89 0 : logp("%s called with no client name\n", __func__);
90 0 : return -1;
91 : }
92 :
93 : // Add in reverse order, so that iterating over from the beginning
94 : // comes out in the right order.
95 0 : if(
96 : add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
97 0 : CMD_TIMESTAMP_END, "time_end", "End time")
98 0 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
99 0 : CMD_TIMESTAMP, "time_start", "Start time")
100 0 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
101 0 : CMD_BYTES_SENT, "bytes_sent", "Bytes sent")
102 0 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
103 0 : CMD_BYTES_RECV, "bytes_received", "Bytes received")
104 0 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
105 0 : CMD_BYTES, "bytes", "Bytes")
106 0 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
107 0 : CMD_BYTES_ESTIMATED, "bytes_estimated", "Bytes estimated")
108 0 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
109 0 : CMD_MESSAGE, "messages", "Messages")
110 0 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
111 0 : CMD_WARNING, "warnings", "Warnings")
112 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
113 0 : CMD_GRAND_TOTAL, "grand_total", "Grand total")
114 0 : || add_cntr_ent(cntr, 0,
115 0 : CMD_TOTAL, "total", "Total")
116 0 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
117 0 : CMD_ERROR, "errors", "Errors")
118 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
119 0 : CMD_DATA, "blocks", "Blocks")
120 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
121 0 : CMD_EFS_FILE, "efs_files", "EFS files")
122 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
123 0 : CMD_ENC_VSS_T, "vss_footers_encrypted", "VSS footers (enc)")
124 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
125 0 : CMD_VSS_T, "vss_footers", "VSS footers")
126 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
127 0 : CMD_ENC_VSS, "vss_headers_encrypted", "VSS headers (enc)")
128 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
129 0 : CMD_VSS, "vss_headers", "VSS headers")
130 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
131 0 : CMD_SPECIAL, "special_files", "Special files")
132 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
133 0 : CMD_SOFT_LINK, "hard_links", "Soft links")
134 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
135 0 : CMD_HARD_LINK, "soft_links", "Hard links")
136 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
137 0 : CMD_DIRECTORY, "directories", "Directories")
138 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
139 0 : CMD_ENC_METADATA, "meta_data_encrypted", "Meta data (enc)")
140 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
141 0 : CMD_METADATA, "meta_data", "Meta data")
142 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
143 0 : CMD_ENC_FILE, "files_encrypted", "Files (encrypted)")
144 0 : || add_cntr_ent(cntr, CNTR_TABULATE,
145 0 : CMD_FILE, "files", "Files")
146 : )
147 0 : return -1;
148 :
149 0 : cntr->ent[(uint8_t)CMD_TIMESTAMP]->count=(uint64_t)time(NULL);
150 :
151 0 : cntr->str_max_len=calc_max_str_len(cntr, cname);
152 0 : if(!(cntr->str=(char *)calloc_w(1, cntr->str_max_len, __func__))
153 0 : || !(cntr->cname=strdup_w(cname, __func__)))
154 0 : return -1;
155 :
156 0 : return 0;
157 : }
158 :
159 40 : void cntr_free(struct cntr **cntr)
160 : {
161 : struct cntr_ent *e;
162 40 : struct cntr_ent *l=NULL;
163 80 : if(!cntr || !*cntr) return;
164 0 : for(e=(*cntr)->list; e; e=l)
165 : {
166 0 : l=e->next;
167 0 : cntr_ent_free(e);
168 : }
169 0 : (*cntr)->list=NULL;
170 0 : free_w(&(*cntr)->str);
171 0 : free_v((void **)cntr);
172 : }
173 :
174 0 : const char *bytes_to_human(uint64_t counter)
175 : {
176 : static char ret[32]="";
177 0 : float div=(float)counter;
178 0 : char units[3]="";
179 :
180 0 : if(div<1024) return "";
181 :
182 0 : if((div/=1024)<1024)
183 0 : snprintf(units, sizeof(units), "KB");
184 0 : else if((div/=1024)<1024)
185 0 : snprintf(units, sizeof(units), "MB");
186 0 : else if((div/=1024)<1024)
187 0 : snprintf(units, sizeof(units), "GB");
188 0 : else if((div/=1024)<1024)
189 0 : snprintf(units, sizeof(units), "TB");
190 0 : else if((div/=1024)<1024)
191 0 : snprintf(units, sizeof(units), "EB");
192 : else
193 : {
194 0 : div/=1024;
195 0 : snprintf(units, sizeof(units), "PB");
196 : }
197 0 : snprintf(ret, sizeof(ret), " (%.2f %s)", div, units);
198 0 : return ret;
199 : }
200 :
201 0 : static void border(void)
202 : {
203 0 : logc("--------------------------------------------------------------------------------\n");
204 0 : }
205 :
206 0 : static void table_border(enum action act)
207 : {
208 0 : if(act==ACTION_BACKUP
209 0 : || act==ACTION_BACKUP_TIMED)
210 : {
211 0 : logc("% 18s ------------------------------------------------------------\n", "");
212 : }
213 0 : if(act==ACTION_RESTORE
214 0 : || act==ACTION_VERIFY)
215 : {
216 0 : logc("% 18s ------------------------------\n", "");
217 : }
218 0 : }
219 :
220 0 : static void incr_count_val(struct cntr *cntr, char ch, uint64_t val)
221 : {
222 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->count+=val;
223 0 : }
224 :
225 0 : static void incr_same_val(struct cntr *cntr, char ch, uint64_t val)
226 : {
227 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->same+=val;
228 0 : }
229 :
230 0 : static void incr_changed_val(struct cntr *cntr, char ch, uint64_t val)
231 : {
232 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->changed+=val;
233 0 : }
234 :
235 0 : static void incr_deleted_val(struct cntr *cntr, char ch, uint64_t val)
236 : {
237 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->deleted+=val;
238 0 : }
239 :
240 0 : static void incr_phase1_val(struct cntr *cntr, char ch, uint64_t val)
241 : {
242 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->phase1+=val;
243 0 : }
244 :
245 0 : static void incr_count(struct cntr *cntr, char ch)
246 : {
247 0 : return incr_count_val(cntr, ch, 1);
248 : }
249 :
250 0 : static void incr_same(struct cntr *cntr, char ch)
251 : {
252 0 : return incr_same_val(cntr, ch, 1);
253 : }
254 :
255 0 : static void incr_changed(struct cntr *cntr, char ch)
256 : {
257 0 : return incr_changed_val(cntr, ch, 1);
258 : }
259 :
260 0 : static void incr_deleted(struct cntr *cntr, char ch)
261 : {
262 0 : return incr_deleted_val(cntr, ch, 1);
263 : }
264 :
265 0 : static void incr_phase1(struct cntr *cntr, char ch)
266 : {
267 0 : return incr_phase1_val(cntr, ch, 1);
268 : }
269 :
270 0 : static void print_end(uint64_t val)
271 : {
272 0 : if(val) logc(" %"PRIu64 "\n", val);
273 0 : }
274 :
275 2 : void cntr_add(struct cntr *c, char ch, int print)
276 : {
277 : struct cntr_ent *grand_total_ent;
278 2 : if(!c) return;
279 0 : if(!(grand_total_ent=c->ent[CMD_GRAND_TOTAL])) return;
280 0 : if(print)
281 : {
282 0 : if(ch!=CMD_MESSAGE && ch!=CMD_WARNING)
283 0 : logc("%c", ch);
284 : }
285 0 : if(ch==CMD_FILE_CHANGED)
286 : {
287 0 : incr_changed(c, CMD_FILE);
288 0 : incr_changed(c, CMD_TOTAL);
289 0 : incr_changed(c, CMD_GRAND_TOTAL);
290 : }
291 : else
292 : {
293 0 : incr_count(c, ch);
294 0 : if(ch==CMD_WARNING || ch==CMD_MESSAGE) return;
295 0 : incr_count(c, CMD_TOTAL);
296 : }
297 :
298 0 : if(!((++grand_total_ent->count)%64) && print)
299 0 : print_end(grand_total_ent->count);
300 0 : fflush(stdout);
301 : }
302 :
303 0 : void cntr_add_phase1(struct cntr *c, char ch, int print)
304 : {
305 : static struct cntr_ent *total;
306 0 : incr_phase1(c, ch);
307 :
308 0 : total=c->ent[(uint8_t)CMD_GRAND_TOTAL];
309 0 : ++total->phase1;
310 0 : if(!print) return;
311 0 : if(total->phase1==1) logc("\n");
312 0 : logc("%c", ch);
313 0 : if(!((total->phase1)%64))
314 0 : print_end(total->phase1);
315 0 : fflush(stdout);
316 : }
317 :
318 0 : void cntr_add_val(struct cntr *c, char ch, uint64_t val, int print)
319 : {
320 0 : incr_count_val(c, ch, val);
321 0 : }
322 :
323 0 : void cntr_add_same(struct cntr *c, char ch)
324 : {
325 0 : incr_same(c, ch);
326 0 : incr_same(c, CMD_TOTAL);
327 0 : incr_same(c, CMD_GRAND_TOTAL);
328 0 : }
329 :
330 0 : void cntr_add_same_val(struct cntr *c, char ch, uint64_t val)
331 : {
332 0 : incr_same_val(c, ch, val);
333 0 : incr_same_val(c, CMD_TOTAL, val);
334 0 : incr_same_val(c, CMD_GRAND_TOTAL, val);
335 0 : }
336 :
337 0 : void cntr_add_changed(struct cntr *c, char ch)
338 : {
339 0 : incr_changed(c, ch);
340 0 : incr_changed(c, CMD_TOTAL);
341 0 : incr_changed(c, CMD_GRAND_TOTAL);
342 0 : }
343 :
344 0 : void cntr_add_changed_val(struct cntr *c, char ch, uint64_t val)
345 : {
346 0 : incr_changed_val(c, ch, val);
347 0 : incr_changed_val(c, CMD_TOTAL, val);
348 0 : incr_changed_val(c, CMD_GRAND_TOTAL, val);
349 0 : }
350 :
351 0 : void cntr_add_deleted(struct cntr *c, char ch)
352 : {
353 0 : incr_deleted(c, ch);
354 0 : incr_deleted(c, CMD_TOTAL);
355 0 : incr_deleted(c, CMD_GRAND_TOTAL);
356 0 : }
357 :
358 0 : void cntr_add_bytes(struct cntr *c, uint64_t bytes)
359 : {
360 0 : incr_count_val(c, CMD_BYTES, bytes);
361 0 : }
362 :
363 0 : void cntr_add_sentbytes(struct cntr *c, uint64_t bytes)
364 : {
365 0 : incr_count_val(c, CMD_BYTES_SENT, bytes);
366 0 : }
367 :
368 0 : void cntr_add_recvbytes(struct cntr *c, uint64_t bytes)
369 : {
370 0 : incr_count_val(c, CMD_BYTES_RECV, bytes);
371 0 : }
372 :
373 0 : static void quint_print(struct cntr_ent *ent, enum action act)
374 : {
375 : uint64_t a;
376 : uint64_t b;
377 : uint64_t c;
378 : uint64_t d;
379 : uint64_t e;
380 0 : if(!ent) return;
381 0 : a=ent->count;
382 0 : b=ent->changed;
383 0 : c=ent->same;
384 0 : d=ent->deleted;
385 0 : e=ent->phase1;
386 :
387 0 : if(!(ent->flags & CNTR_TABULATE)) return;
388 :
389 0 : if(!e && !a && !b && !c) return;
390 0 : logc("% 18s:", ent->label);
391 0 : if(act==ACTION_BACKUP
392 0 : || act==ACTION_BACKUP_TIMED)
393 : {
394 0 : logc("% 9llu ", a);
395 0 : logc("% 9llu ", b);
396 0 : logc("% 9llu ", c);
397 0 : logc("% 9llu ", d);
398 : }
399 0 : if(act==ACTION_RESTORE
400 0 : || act==ACTION_VERIFY)
401 : {
402 0 : logc("% 9s ", "");
403 : //logc("% 9s ", "");
404 : //logc("% 9s ", "");
405 : //logc("% 9s ", "");
406 : }
407 0 : if(act==ACTION_ESTIMATE)
408 : {
409 0 : logc("% 9s ", "");
410 0 : logc("% 9s ", "");
411 0 : logc("% 9llu\n", e);
412 : }
413 : else
414 : {
415 0 : logc("% 9llu |", a+b+c);
416 0 : logc("% 9llu\n", e);
417 : }
418 : }
419 :
420 0 : static uint64_t get_count(struct cntr_ent **ent, enum cmd cmd)
421 : {
422 0 : if(!ent[(uint8_t)cmd]) return 0;
423 0 : return ent[(uint8_t)cmd]->count;
424 : }
425 :
426 0 : static void bottom_part(struct cntr *c, enum action act)
427 : {
428 : uint64_t l;
429 0 : struct cntr_ent **e=c->ent;
430 0 : logc("\n");
431 0 : logc(" Messages: % 11llu\n", get_count(e, CMD_MESSAGE));
432 0 : logc(" Warnings: % 11llu\n", get_count(e, CMD_WARNING));
433 0 : logc("\n");
434 0 : logc(" Bytes estimated: % 11llu", get_count(e, CMD_BYTES_ESTIMATED));
435 0 : logc("%s\n", bytes_to_human(get_count(e, CMD_BYTES_ESTIMATED)));
436 :
437 0 : if(act==ACTION_ESTIMATE) return;
438 :
439 0 : if(act==ACTION_BACKUP
440 0 : || act==ACTION_BACKUP_TIMED)
441 : {
442 0 : l=get_count(e, CMD_BYTES);
443 0 : logc(" Bytes in backup: % 11llu", l);
444 0 : logc("%s\n", bytes_to_human(l));
445 : }
446 0 : if(act==ACTION_RESTORE)
447 : {
448 0 : l=get_count(e, CMD_BYTES);
449 0 : logc(" Bytes attempted: % 11llu", l);
450 0 : logc("%s\n", bytes_to_human(l));
451 : }
452 0 : if(act==ACTION_VERIFY)
453 : {
454 0 : l=get_count(e, CMD_BYTES);
455 0 : logc(" Bytes checked: % 11llu", l);
456 0 : logc("%s\n", bytes_to_human(l));
457 : }
458 :
459 0 : if(act==ACTION_BACKUP
460 0 : || act==ACTION_BACKUP_TIMED)
461 : {
462 0 : l=get_count(e, CMD_BYTES_RECV);
463 0 : logc(" Bytes received: % 11llu", l);
464 0 : logc("%s\n", bytes_to_human(l));
465 : }
466 0 : if(act==ACTION_BACKUP
467 0 : || act==ACTION_BACKUP_TIMED
468 0 : || act==ACTION_RESTORE)
469 : {
470 0 : l=get_count(e, CMD_BYTES_SENT);
471 0 : logc(" Bytes sent: % 11llu", l);
472 0 : logc("%s\n", bytes_to_human(l));
473 : }
474 : }
475 :
476 2 : void cntr_print(struct cntr *cntr, enum action act)
477 : {
478 : struct cntr_ent *e;
479 : time_t now;
480 : time_t start;
481 4 : if(!cntr) return;
482 0 : now=time(NULL);
483 0 : start=(time_t)cntr->ent[(uint8_t)CMD_TIMESTAMP]->count;
484 0 : cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count=(uint64_t)now;
485 :
486 0 : border();
487 0 : logc("Start time: %s\n", getdatestr(start));
488 0 : logc(" End time: %s\n", getdatestr(now));
489 0 : logc("Time taken: %s\n", time_taken(now-start));
490 0 : if(act==ACTION_BACKUP
491 0 : || act==ACTION_BACKUP_TIMED)
492 : {
493 : logc("% 18s % 9s % 9s % 9s % 9s % 9s |% 9s\n",
494 0 : " ", "New", "Changed", "Unchanged", "Deleted", "Total", "Scanned");
495 : }
496 0 : if(act==ACTION_RESTORE
497 0 : || act==ACTION_VERIFY)
498 : {
499 : logc("% 18s % 9s % 9s |% 9s\n",
500 0 : " ", "", "Attempted", "Expected");
501 : }
502 0 : if(act==ACTION_ESTIMATE)
503 : {
504 : logc("% 18s % 9s % 9s %9s\n",
505 0 : " ", "", "", "Scanned");
506 : }
507 0 : table_border(act);
508 :
509 0 : for(e=cntr->list; e; e=e->next)
510 0 : quint_print(e, act);
511 :
512 0 : table_border(act);
513 0 : bottom_part(cntr, act);
514 :
515 0 : border();
516 : }
517 :
518 : #ifndef HAVE_WIN32
519 :
520 0 : int cntr_stats_to_file(struct cntr *cntr,
521 : const char *directory, enum action act, struct conf **confs)
522 : {
523 0 : int ret=-1;
524 0 : int fd=-1;
525 0 : char *path=NULL;
526 0 : const char *fname=NULL;
527 0 : struct async *as=NULL;
528 0 : struct asfd *wfd=NULL;
529 0 : cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count
530 0 : =(uint64_t)time(NULL);
531 :
532 0 : if(act==ACTION_BACKUP
533 0 : || act==ACTION_BACKUP_TIMED)
534 0 : fname="backup_stats";
535 0 : else if(act==ACTION_RESTORE)
536 0 : fname="restore_stats";
537 0 : else if(act==ACTION_VERIFY)
538 0 : fname="verify_stats";
539 : else
540 0 : return 0;
541 :
542 0 : if(!(path=prepend_s(directory, fname)))
543 0 : goto end;
544 0 : if((fd=open(path, O_WRONLY|O_CREAT, 0666))<0)
545 : {
546 : logp("Could not open %s for writing in %s: %s\n",
547 0 : path, __func__, strerror(errno));
548 0 : goto end;
549 : }
550 : // FIX THIS:
551 : // Pretty heavy duty to set up all this async stuff just so that the
552 : // json stuff can write to a simple file.
553 0 : if(!(as=async_alloc())
554 0 : || as->init(as, 0)
555 0 : || !(wfd=asfd_alloc())
556 0 : || wfd->init(wfd, "stats file",
557 0 : as, fd, NULL, ASFD_STREAM_LINEBUF, confs))
558 0 : goto end;
559 0 : as->asfd_add(as, wfd);
560 0 : fd=-1;
561 0 : if(json_cntr_to_file(wfd, cntr))
562 0 : goto end;
563 :
564 : // FIX THIS: make this use the json output stuff.
565 : // Need to add the following few fields to the cntrs somehow.
566 : /*
567 : fprintf(fp, "client_version:%s\n",
568 : conf->peer_version?conf->peer_version:"");
569 : fprintf(fp, "server_version:%s\n", VERSION);
570 : fprintf(fp, "client_is_windows:%d\n", conf->client_is_windows);
571 : for(e=cntr->list; e; e=e->next)
572 : quint_print_to_file(fp, e, act);
573 : */
574 :
575 0 : ret=0;
576 : end:
577 0 : close_fd(&fd);
578 0 : free_w(&path);
579 0 : async_free(&as);
580 0 : asfd_free(&wfd);
581 0 : return ret;
582 : }
583 :
584 : #endif
585 :
586 2 : void cntr_print_end(struct cntr *cntr)
587 : {
588 : struct cntr_ent *grand_total_ent;
589 4 : if(!cntr) return;
590 0 : grand_total_ent=cntr->ent[CMD_GRAND_TOTAL];
591 0 : if(grand_total_ent)
592 : {
593 0 : print_end(grand_total_ent->count);
594 0 : logc("\n");
595 : }
596 : }
597 :
598 0 : void cntr_print_end_phase1(struct cntr *cntr)
599 : {
600 : struct cntr_ent *grand_total_ent;
601 0 : if(!cntr) return;
602 0 : grand_total_ent=cntr->ent[CMD_GRAND_TOTAL];
603 0 : if(grand_total_ent)
604 : {
605 0 : print_end(grand_total_ent->phase1);
606 0 : logc("\n");
607 : }
608 : }
609 :
610 : #ifndef HAVE_WIN32
611 : // Return string length.
612 0 : size_t cntr_to_str(struct cntr *cntr, const char *path)
613 : {
614 : static char tmp[CNTR_PATH_BUF_LEN+3]="";
615 0 : struct cntr_ent *e=NULL;
616 0 : char *str=cntr->str;
617 :
618 0 : cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count=time(NULL);
619 :
620 : snprintf(str, cntr->str_max_len-1, "%s\t%d\t%d\t",
621 0 : cntr->cname, CNTR_VERSION, cntr->cntr_status);
622 :
623 0 : for(e=cntr->list; e; e=e->next)
624 : {
625 0 : if(e->flags & CNTR_SINGLE_FIELD)
626 : snprintf(tmp, sizeof(tmp),
627 0 : "%c%"PRIu64"\t", e->cmd, e->count);
628 : else
629 : snprintf(tmp, sizeof(tmp),
630 : "%c%"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64"\t",
631 : e->cmd, e->count, e->same,
632 0 : e->changed, e->deleted, e->phase1);
633 0 : strcat(str, tmp);
634 : }
635 :
636 : // Abuse CMD_DATAPTH.
637 0 : snprintf(tmp, sizeof(tmp), "%c%s\t\n", CMD_DATAPTH, path?path:"");
638 0 : strcat(str, tmp);
639 :
640 0 : return strlen(str);
641 : }
642 : #endif
643 :
644 0 : static int extract_ul(const char *value, struct cntr_ent *ent)
645 : {
646 0 : char *as=NULL;
647 0 : char *bs=NULL;
648 0 : char *cs=NULL;
649 0 : char *ds=NULL;
650 0 : char *es=NULL;
651 0 : char *copy=NULL;
652 0 : if(!value || !(copy=strdup_w(value, __func__))) return -1;
653 :
654 : // Do not want to use strtok, just in case I end up running more
655 : // than one at a time.
656 0 : as=copy;
657 0 : if((bs=strchr(as, '/')))
658 : {
659 0 : *bs='\0';
660 0 : ent->count=strtoull(as, NULL, 10);
661 0 : if((cs=strchr(++bs, '/')))
662 : {
663 0 : *cs='\0';
664 0 : ent->changed=strtoull(bs, NULL, 10);
665 0 : if((ds=strchr(++cs, '/')))
666 : {
667 0 : *ds='\0';
668 0 : ent->same=strtoull(cs, NULL, 10);
669 0 : if((es=strchr(++ds, '/')))
670 : {
671 0 : ent->deleted=strtoull(ds, NULL, 10);
672 0 : *es='\0';
673 0 : es++;
674 0 : ent->phase1=strtoull(es, NULL, 10);
675 : }
676 : }
677 : }
678 : }
679 : else
680 : {
681 : // Single field.
682 0 : ent->count=strtoull(as, NULL, 10);
683 : }
684 0 : free(copy);
685 0 : return 0;
686 : }
687 :
688 : /*
689 : static char *get_backup_str(const char *s, int *deletable)
690 : {
691 : static char str[32]="";
692 : const char *cp=NULL;
693 : const char *dp=NULL;
694 : if(!s || !*s) return NULL;
695 : if(!(cp=strchr(s, ' '))
696 : || !(dp=strchr(cp+1, ' ')))
697 : snprintf(str, sizeof(str), "never");
698 : else
699 : {
700 : uint64_t backupnum=0;
701 : backupnum=strtoul(s, NULL, 10);
702 : snprintf(str, sizeof(str),
703 : "%07lu %s", backupnum, getdatestr(atol(dp+1)));
704 : if(*(cp+1)=='1') *deletable=1;
705 : }
706 : return str;
707 : }
708 : */
709 :
710 : /*
711 : static int add_to_backup_list(struct strlist **backups, const char *tok)
712 : {
713 : int deletable=0;
714 : const char *str=NULL;
715 : if(!(str=get_backup_str(tok, &deletable))) return 0;
716 : if(strlist_add(backups, (char *)str, deletable)) return -1;
717 : return 0;
718 : }
719 : */
720 :
721 0 : static int extract_cntrs(struct cstat *cstat, char **path)
722 : {
723 : char *tok;
724 0 : struct cntr *cntr=cstat->cntr;
725 0 : while((tok=strtok(NULL, "\t\n")))
726 : {
727 0 : switch(tok[0])
728 : {
729 : case CMD_DATAPTH:
730 0 : free_w(path);
731 0 : if(!(*path=strdup_w(tok+1, __func__)))
732 0 : return -1;
733 0 : break;
734 : default:
735 0 : if(cntr->ent[(uint8_t)tok[0]]
736 0 : && extract_ul(tok+1,
737 0 : cntr->ent[(uint8_t)tok[0]]))
738 0 : return -1;
739 0 : break;
740 : }
741 : }
742 0 : return 0;
743 : }
744 :
745 0 : int str_to_cntr(const char *str, struct cstat *cstat, char **path)
746 : {
747 0 : int ret=-1;
748 0 : char *tok=NULL;
749 0 : char *copy=NULL;
750 :
751 0 : if(!(copy=strdup_w(str, __func__)))
752 0 : return -1;
753 :
754 0 : if((tok=strtok(copy, "\t\n")))
755 : {
756 0 : char *tmp=NULL;
757 : // First token is the client name. Do not need that here.
758 : // Second is the cntr version.
759 0 : if(!(tmp=strtok(NULL, "\t\n")))
760 : {
761 : logp("Parsing problem in %s: null version\n",
762 0 : __func__);
763 0 : goto end;
764 : }
765 0 : if(atoi(tmp)!=CNTR_VERSION)
766 : {
767 0 : ret=0;
768 0 : goto end;
769 : }
770 : // Third is cstat_status.
771 0 : if(!(tmp=strtok(NULL, "\t\n")))
772 : {
773 : logp("Parsing problem in %s: null cstat_status\n",
774 0 : __func__);
775 0 : goto end;
776 : }
777 0 : cstat->cntr->cntr_status=(enum cntr_status)atoi(tmp);
778 :
779 0 : if(extract_cntrs(cstat, path)) goto end;
780 : }
781 :
782 0 : ret=0;
783 : end:
784 0 : free_w(©);
785 0 : return ret;
786 : }
787 :
788 : #ifndef HAVE_WIN32
789 0 : int cntr_send(struct cntr *cntr)
790 : {
791 : /*
792 : size_t l;
793 : char buf[4096]="";
794 : l=cntr_to_str(get_cntr(confs[OPT_CNTR]), STATUS_RUNNING, " ");
795 : if(async_write_strn(CMD_GEN, buf, l))
796 : {
797 : logp("Error when sending counters to client.\n");
798 : return -1;
799 : }
800 : */
801 0 : return 0;
802 : }
803 : #endif
804 :
805 0 : static enum asl_ret cntr_recv_func(struct asfd *asfd,
806 : struct conf **confs, void *param)
807 : {
808 : /*
809 : if(str_to_cntr(asfd->rbuf->buf, NULL, NULL, NULL, NULL,
810 : conf->p1cntr, get_cntr(confs[OPT_CNTR]), NULL))
811 : return ASL_END_ERROR;
812 : */
813 0 : return ASL_END_OK;
814 : }
815 :
816 0 : int cntr_recv(struct asfd *asfd, struct conf **confs)
817 : {
818 0 : return asfd->simple_loop(asfd, confs, NULL, __func__, cntr_recv_func);
819 : }
820 :
821 0 : const char *cntr_status_to_str(struct cntr *cntr)
822 : {
823 0 : switch(cntr->cntr_status)
824 : {
825 0 : case CNTR_STATUS_SCANNING: return CNTR_STATUS_STR_SCANNING;
826 0 : case CNTR_STATUS_BACKUP: return CNTR_STATUS_STR_BACKUP;
827 0 : case CNTR_STATUS_MERGING: return CNTR_STATUS_STR_MERGING;
828 0 : case CNTR_STATUS_SHUFFLING: return CNTR_STATUS_STR_SHUFFLING;
829 0 : case CNTR_STATUS_LISTING: return CNTR_STATUS_STR_LISTING;
830 0 : case CNTR_STATUS_RESTORING: return CNTR_STATUS_STR_RESTORING;
831 0 : case CNTR_STATUS_VERIFYING: return CNTR_STATUS_STR_VERIFYING;
832 0 : case CNTR_STATUS_DELETING: return CNTR_STATUS_STR_DELETING;
833 0 : case CNTR_STATUS_DIFFING: return CNTR_STATUS_STR_DIFFING;
834 0 : default: return "unknown";
835 : }
836 : }
837 :
838 0 : enum cntr_status cntr_str_to_status(const char *str)
839 : {
840 0 : if(!strcmp(str, CNTR_STATUS_STR_SCANNING))
841 0 : return CNTR_STATUS_SCANNING;
842 0 : else if(!strcmp(str, CNTR_STATUS_STR_BACKUP))
843 0 : return CNTR_STATUS_BACKUP;
844 0 : else if(!strcmp(str, CNTR_STATUS_STR_MERGING))
845 0 : return CNTR_STATUS_MERGING;
846 0 : else if(!strcmp(str, CNTR_STATUS_STR_SHUFFLING))
847 0 : return CNTR_STATUS_SHUFFLING;
848 0 : else if(!strcmp(str, CNTR_STATUS_STR_LISTING))
849 0 : return CNTR_STATUS_LISTING;
850 0 : else if(!strcmp(str, CNTR_STATUS_STR_RESTORING))
851 0 : return CNTR_STATUS_RESTORING;
852 0 : else if(!strcmp(str, CNTR_STATUS_STR_VERIFYING))
853 0 : return CNTR_STATUS_VERIFYING;
854 0 : else if(!strcmp(str, CNTR_STATUS_STR_DELETING))
855 0 : return CNTR_STATUS_DELETING;
856 0 : else if(!strcmp(str, CNTR_STATUS_STR_DIFFING))
857 0 : return CNTR_STATUS_DIFFING;
858 0 : return CNTR_STATUS_UNSET;
859 : }
|