Line data Source code
1 : #include "../burp.h"
2 : #include "../action.h"
3 : #include "../alloc.h"
4 : #include "../asfd.h"
5 : #include "../async.h"
6 : #include "../attribs.h"
7 : #include "../cmd.h"
8 : #include "../cntr.h"
9 : #include "../conf.h"
10 : #include "../handy_extra.h"
11 : #include "../log.h"
12 : #include "../md5.h"
13 : #include "../transfer.h"
14 : #include "extrameta.h"
15 : #include "find.h"
16 : #include "backup_phase2.h"
17 :
18 2 : static int rs_loadsig_network_run(struct asfd *asfd,
19 : rs_job_t *job, struct cntr *cntr)
20 : {
21 2 : int ret=-1;
22 : rs_buffers_t buf;
23 : rs_result result;
24 2 : rs_filebuf_t *in_fb=NULL;
25 2 : memset(&buf, 0, sizeof(buf));
26 :
27 2 : if(!(in_fb=rs_filebuf_new(NULL,
28 : NULL, asfd, ASYNC_BUF_LEN, -1)))
29 : goto end;
30 :
31 : while(1)
32 : {
33 4 : iobuf_free_content(asfd->rbuf);
34 4 : if(asfd->read(asfd)) goto end;
35 8 : if(asfd->rbuf->cmd==CMD_MESSAGE
36 4 : || asfd->rbuf->cmd==CMD_WARNING)
37 : {
38 0 : log_recvd(asfd->rbuf, cntr, 0);
39 0 : continue;
40 : }
41 4 : switch((result=rs_async(job, &buf, in_fb, NULL)))
42 : {
43 : case RS_BLOCKED:
44 : case RS_RUNNING:
45 2 : continue;
46 : case RS_DONE:
47 : ret=0;
48 : goto end;
49 : default:
50 0 : logp("error in rs_async for sig: %d\n",
51 : result);
52 0 : goto end;
53 : }
54 : }
55 :
56 : end:
57 2 : iobuf_free_content(asfd->rbuf);
58 2 : rs_filebuf_free(&in_fb);
59 2 : return ret;
60 : }
61 :
62 2 : static int load_signature(struct asfd *asfd,
63 : rs_signature_t **sumset, struct cntr *cntr)
64 : {
65 : rs_job_t *job;
66 :
67 2 : if(!(job=rs_loadsig_begin(sumset)))
68 : {
69 0 : logp("could not start sig job.\n");
70 0 : return -1;
71 : }
72 2 : if(rs_loadsig_network_run(asfd, job, cntr))
73 : return -1;
74 2 : if(rs_build_hash_table(*sumset))
75 : return -1;
76 2 : rs_job_free(job);
77 2 : return 0;
78 : }
79 :
80 2 : static int load_signature_and_send_delta(struct asfd *asfd,
81 : struct BFILE *bfd, uint64_t *bytes, uint64_t *sentbytes,
82 : struct cntr *cntr)
83 : {
84 2 : int ret=-1;
85 2 : rs_job_t *job=NULL;
86 2 : rs_signature_t *sumset=NULL;
87 : uint8_t checksum[MD5_DIGEST_LENGTH];
88 2 : rs_filebuf_t *infb=NULL;
89 2 : rs_filebuf_t *outfb=NULL;
90 : rs_buffers_t rsbuf;
91 2 : memset(&rsbuf, 0, sizeof(rsbuf));
92 :
93 2 : if(load_signature(asfd, &sumset, cntr))
94 : goto end;
95 :
96 2 : if(!(job=rs_delta_begin(sumset)))
97 : {
98 0 : logp("could not start delta job.\n");
99 0 : goto end;
100 : }
101 :
102 2 : if(!(infb=rs_filebuf_new(bfd,
103 : NULL, NULL, ASYNC_BUF_LEN, bfd->datalen))
104 2 : || !(outfb=rs_filebuf_new(NULL,
105 : NULL, asfd, ASYNC_BUF_LEN, -1)))
106 : {
107 0 : logp("could not rs_filebuf_new for delta\n");
108 0 : goto end;
109 : }
110 :
111 : while(1)
112 4 : {
113 : rs_result result;
114 6 : switch((result=rs_async(job, &rsbuf, infb, outfb)))
115 : {
116 : case RS_DONE:
117 2 : *bytes=infb->bytes;
118 2 : *sentbytes=outfb->bytes;
119 2 : if(!md5_final(infb->md5, checksum))
120 : {
121 0 : logp("md5_final() failed\n");
122 0 : goto end;
123 : }
124 2 : if(write_endfile(asfd, *bytes, checksum))
125 : goto end;
126 2 : ret=0;
127 2 : goto end;
128 : case RS_BLOCKED:
129 : case RS_RUNNING:
130 : // FIX ME: get it to read stuff here too.
131 : // (errors, for example)
132 4 : if(asfd->as->write(asfd->as))
133 : goto end;
134 4 : continue;
135 : default:
136 0 : logp("error in rs_async for delta: %d\n",
137 : result);
138 0 : goto end;
139 : }
140 : }
141 : end:
142 2 : rs_filebuf_free(&infb);
143 2 : rs_filebuf_free(&outfb);
144 2 : if(job) rs_job_free(job);
145 2 : if(sumset) rs_free_sumset(sumset);
146 2 : return ret;
147 : }
148 :
149 6 : static enum send_e send_whole_file_w(struct asfd *asfd,
150 : struct sbuf *sb, const char *datapth,
151 : int quick_read, uint64_t *bytes, const char *encpassword,
152 : struct cntr *cntr, int compression, struct BFILE *bfd,
153 : const char *extrameta, size_t elen)
154 : {
155 6 : if((compression || encpassword) && sb->path.cmd!=CMD_EFS_FILE)
156 : {
157 0 : int key_deriv=sb->encryption;
158 0 : return send_whole_file_gzl(asfd, datapth, quick_read, bytes,
159 : encpassword, cntr, compression, bfd, extrameta, elen,
160 : key_deriv, sb->salt);
161 : }
162 : else
163 6 : return send_whole_filel(asfd,
164 : #ifdef HAVE_WIN32
165 : sb->path.cmd,
166 : #endif
167 : datapth, quick_read, bytes,
168 : cntr, bfd, extrameta, elen);
169 : }
170 :
171 0 : static int forget_file(struct asfd *asfd, struct sbuf *sb, struct conf **confs)
172 : {
173 : // Tell the server to forget about this
174 : // file, otherwise it might get stuck
175 : // on a select waiting for it to arrive.
176 0 : if(asfd->write_str(asfd, CMD_INTERRUPT, sb->path.buf))
177 : return 0;
178 :
179 0 : if(sb->path.cmd==CMD_FILE && sb->datapth.buf)
180 : {
181 0 : rs_signature_t *sumset=NULL;
182 : // The server will be sending us a signature.
183 : // Munch it up then carry on.
184 0 : if(load_signature(asfd, &sumset, get_cntr(confs))) return -1;
185 0 : else rs_free_sumset(sumset);
186 : }
187 : return 0;
188 : }
189 :
190 8 : static int size_checks(struct asfd *asfd, struct sbuf *sb, struct conf **confs)
191 : {
192 16 : if(sb->path.cmd!=CMD_FILE
193 8 : && sb->path.cmd!=CMD_ENC_FILE
194 0 : && sb->path.cmd!=CMD_EFS_FILE)
195 : return 0;
196 8 : if(get_uint64_t(confs[OPT_MIN_FILE_SIZE])
197 0 : && (uint64_t)sb->statp.st_size<get_uint64_t(confs[OPT_MIN_FILE_SIZE]))
198 : {
199 0 : logw(asfd, get_cntr(confs), "File size decreased below min_file_size after initial scan: %s\n", iobuf_to_printable(&sb->path));
200 0 : return -1;
201 : }
202 8 : if(get_uint64_t(confs[OPT_MAX_FILE_SIZE])
203 0 : && (uint64_t)sb->statp.st_size>get_uint64_t(confs[OPT_MAX_FILE_SIZE]))
204 : {
205 0 : logw(asfd, get_cntr(confs), "File size increased above max_file_size after initial scan: %s\n", iobuf_to_printable(&sb->path));
206 0 : return -1;
207 : }
208 : return 0;
209 : }
210 :
211 8 : static int deal_with_data(struct asfd *asfd, struct sbuf *sb,
212 : struct BFILE *bfd, struct conf **confs)
213 : {
214 8 : int ret=-1;
215 8 : int forget=0;
216 8 : size_t elen=0;
217 8 : char *extrameta=NULL;
218 8 : uint64_t bytes=0;
219 8 : int conf_compression=get_int(confs[OPT_COMPRESSION]);
220 8 : struct cntr *cntr=get_cntr(confs);
221 8 : const char *enc_password=get_string(confs[OPT_ENCRYPTION_PASSWORD]);
222 :
223 8 : sb->compression=conf_compression;
224 8 : if(enc_password)
225 : {
226 0 : sb->encryption=ENCRYPTION_KEY_DERIVED_AES_CBC_256;
227 0 : if(!RAND_bytes((uint8_t *)&sb->salt, 8))
228 : {
229 0 : logp("RAND_bytes() failed\n");
230 0 : return -1;
231 : }
232 : }
233 :
234 8 : iobuf_copy(&sb->path, asfd->rbuf);
235 8 : iobuf_init(asfd->rbuf);
236 :
237 : #ifdef HAVE_WIN32
238 : if(win32_lstat(sb->path.buf, &sb->statp, &sb->winattr))
239 : #else
240 16 : if(lstat(sb->path.buf, &sb->statp))
241 : #endif
242 : {
243 0 : logw(asfd, cntr, "Path has vanished: %s\n",
244 : iobuf_to_printable(&sb->path));
245 0 : forget++;
246 0 : goto end;
247 : }
248 :
249 8 : if(size_checks(asfd, sb, confs))
250 : {
251 : forget++;
252 : goto end;
253 : }
254 :
255 8 : sb->compression=in_exclude_comp(get_strlist(confs[OPT_EXCOM]),
256 8 : sb->path.buf, conf_compression);
257 8 : if(attribs_encode(sb)) goto error;
258 :
259 16 : if(sb->path.cmd!=CMD_METADATA
260 8 : && sb->path.cmd!=CMD_ENC_METADATA)
261 : {
262 24 : if(bfd->open_for_send(bfd, asfd,
263 16 : sb->path.buf, sb->winattr,
264 : get_int(confs[OPT_ATIME]), cntr))
265 : {
266 : forget++;
267 : goto end;
268 : }
269 : }
270 :
271 16 : if(sb->path.cmd==CMD_METADATA
272 : || sb->path.cmd==CMD_ENC_METADATA
273 8 : || sb->path.cmd==CMD_VSS
274 8 : || sb->path.cmd==CMD_ENC_VSS
275 : #ifdef HAVE_WIN32
276 : || get_int(confs[OPT_STRIP_VSS])
277 : #endif
278 : )
279 : {
280 0 : if(get_extrameta(asfd,
281 : #ifdef HAVE_WIN32
282 : bfd,
283 : #endif
284 0 : sb->path.buf,
285 0 : S_ISDIR(sb->statp.st_mode),
286 : &extrameta, &elen, cntr))
287 : {
288 0 : logw(asfd, cntr,
289 : "Meta data error for %s\n",
290 : iobuf_to_printable(&sb->path));
291 0 : forget++;
292 0 : goto end;
293 : }
294 0 : if(extrameta)
295 : {
296 : #ifdef HAVE_WIN32
297 : if(get_int(confs[OPT_STRIP_VSS]))
298 : {
299 : free_w(&extrameta);
300 : elen=0;
301 : }
302 : #endif
303 : }
304 : else
305 : {
306 0 : logw(asfd, cntr,
307 : "No meta data after all: %s\n",
308 : iobuf_to_printable(&sb->path));
309 0 : forget++;
310 0 : goto end;
311 : }
312 : }
313 :
314 8 : if(sb->path.cmd==CMD_FILE
315 4 : && sb->datapth.buf)
316 2 : {
317 2 : uint64_t sentbytes=0;
318 : // Need to do sig/delta stuff.
319 2 : if(asfd->write(asfd, &(sb->datapth))
320 2 : || asfd->write(asfd, &sb->attr)
321 2 : || asfd->write(asfd, &sb->path)
322 2 : || load_signature_and_send_delta(asfd, bfd,
323 : &bytes, &sentbytes, cntr))
324 : {
325 0 : logp("error in sig/delta for %s (%s)\n",
326 : iobuf_to_printable(&sb->path),
327 : iobuf_to_printable(&sb->datapth));
328 0 : forget++;
329 0 : goto end;
330 : }
331 2 : cntr_add(cntr, CMD_FILE_CHANGED, 1);
332 : }
333 : else
334 : {
335 : //logp("need to send whole file: %s\n", sb.path);
336 : // send the whole file.
337 :
338 6 : if(asfd->write(asfd, &sb->attr)
339 6 : || asfd->write(asfd, &sb->path))
340 : goto end;
341 :
342 6 : switch(send_whole_file_w(asfd, sb, NULL, 0, &bytes,
343 : enc_password,
344 : cntr, sb->compression,
345 : bfd, extrameta, elen))
346 : {
347 : case SEND_OK:
348 : break;
349 : case SEND_ERROR:
350 0 : forget++;
351 0 : break;
352 : case SEND_FATAL:
353 : default:
354 : goto error;
355 : }
356 6 : cntr_add(cntr, sb->path.cmd, 1);
357 : }
358 8 : cntr_add_bytes(cntr, bytes);
359 :
360 : end:
361 8 : ret=0;
362 8 : if(forget && forget_file(asfd, sb, confs))
363 0 : ret=-1;
364 : error:
365 : #ifdef HAVE_WIN32
366 : // If using Windows do not close bfd - it needs
367 : // to stay open to read VSS/file data/VSS.
368 : // It will get closed either when given a
369 : // different file path, or when this function
370 : // exits.
371 : #else
372 8 : bfd->close(bfd, asfd);
373 : #endif
374 8 : sbuf_free_content(sb);
375 8 : free_w(&extrameta);
376 8 : return ret;
377 : }
378 :
379 19 : static int parse_rbuf(struct asfd *asfd, struct sbuf *sb,
380 : struct BFILE *bfd, struct conf **confs)
381 : {
382 : static struct iobuf *rbuf;
383 19 : rbuf=asfd->rbuf;
384 19 : if(rbuf->cmd==CMD_DATAPTH)
385 : {
386 2 : iobuf_move(&(sb->datapth), rbuf);
387 : }
388 17 : else if(rbuf->cmd==CMD_ATTRIBS)
389 : {
390 : // Ignore the stat data - we will fill it
391 : // in again. Some time may have passed by now,
392 : // and it is best to make it as fresh as
393 : // possible.
394 : }
395 9 : else if(iobuf_is_filedata(rbuf)
396 1 : || iobuf_is_vssdata(rbuf))
397 : {
398 8 : if(deal_with_data(asfd, sb, bfd, confs))
399 : return -1;
400 : }
401 2 : else if(rbuf->cmd==CMD_MESSAGE
402 1 : || rbuf->cmd==CMD_WARNING)
403 : {
404 1 : struct cntr *cntr=NULL;
405 1 : if(confs) cntr=get_cntr(confs);
406 1 : log_recvd(rbuf, cntr, 0);
407 : }
408 : else
409 : {
410 0 : iobuf_log_unexpected(rbuf, __func__);
411 0 : return -1;
412 : }
413 : return 0;
414 : }
415 :
416 6 : static int do_backup_phase2_client(struct asfd *asfd,
417 : struct conf **confs, int resume)
418 : {
419 6 : int ret=-1;
420 : // For efficiency, open Windows files for the VSS data, and do not
421 : // close them until another time around the loop, when the actual
422 : // data is read.
423 6 : struct BFILE *bfd=NULL;
424 6 : struct sbuf *sb=NULL;
425 6 : struct iobuf *rbuf=NULL;
426 6 : struct cntr *cntr=NULL;
427 6 : if(confs) cntr=get_cntr(confs);
428 :
429 6 : if(!asfd)
430 : {
431 1 : logp("%s() called without asfd!\n", __func__);
432 1 : goto end;
433 : }
434 5 : rbuf=asfd->rbuf;
435 :
436 5 : if(!(bfd=bfile_alloc())
437 5 : || !(sb=sbuf_alloc()))
438 : goto end;
439 5 : bfile_init(bfd, 0, cntr);
440 :
441 5 : if(!resume)
442 : {
443 : // Only do this bit if the server did not tell us to resume.
444 5 : if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
445 5 : || asfd_read_expect(asfd, CMD_GEN, "ok"))
446 : goto end;
447 : }
448 : else
449 : {
450 : // On resume, the server might update the client with cntr.
451 0 : if(cntr_recv(asfd, confs))
452 : goto end;
453 : }
454 :
455 : while(1)
456 : {
457 24 : iobuf_free_content(rbuf);
458 24 : if(asfd->read(asfd)) goto end;
459 23 : else if(!rbuf->buf) continue;
460 :
461 23 : if(rbuf->cmd==CMD_GEN && !strcmp(rbuf->buf, "backupphase2end"))
462 : {
463 4 : if(asfd->write_str(asfd, CMD_GEN, "okbackupphase2end"))
464 : goto end;
465 4 : ret=0;
466 4 : break;
467 : }
468 :
469 19 : if(parse_rbuf(asfd, sb, bfd, confs))
470 : goto end;
471 : }
472 :
473 : end:
474 : // It is possible for a bfd to still be open.
475 6 : if(bfd) bfd->close(bfd, asfd);
476 6 : bfile_free(&bfd);
477 6 : iobuf_free_content(rbuf);
478 6 : sbuf_free(&sb);
479 6 : return ret;
480 : }
481 :
482 6 : int backup_phase2_client(struct asfd *asfd,
483 : struct conf **confs, int resume)
484 : {
485 6 : int ret=0;
486 6 : struct cntr *cntr=NULL;
487 6 : if(confs) cntr=get_cntr(confs);
488 :
489 6 : logp("Phase 2 begin (send backup data)\n");
490 6 : logfmt("\n");
491 :
492 6 : ret=do_backup_phase2_client(asfd, confs, resume);
493 :
494 6 : cntr_print_end(cntr);
495 6 : cntr_set_bytes(cntr, asfd);
496 6 : cntr_print(cntr, ACTION_BACKUP);
497 :
498 6 : if(ret) logp("Error in phase 2\n");
499 6 : logp("Phase 2 end (send file data)\n");
500 :
501 6 : return ret;
502 : }
|