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