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