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 :
16 2 : static int rs_loadsig_network_run(struct asfd *asfd,
17 : rs_job_t *job, struct cntr *cntr)
18 : {
19 2 : int ret=-1;
20 : rs_buffers_t buf;
21 : rs_result result;
22 2 : rs_filebuf_t *in_fb=NULL;
23 : memset(&buf, 0, sizeof(buf));
24 :
25 2 : if(!(in_fb=rs_filebuf_new(NULL,
26 2 : NULL, asfd, ASYNC_BUF_LEN, -1)))
27 : {
28 : result=RS_MEM_ERROR;
29 : goto end;
30 : }
31 :
32 : while(1)
33 : {
34 4 : iobuf_free_content(asfd->rbuf);
35 4 : if(asfd->read(asfd)) goto end;
36 4 : if(asfd->rbuf->cmd==CMD_MESSAGE
37 4 : || asfd->rbuf->cmd==CMD_WARNING)
38 : {
39 0 : log_recvd(asfd->rbuf, cntr, 0);
40 0 : continue;
41 : }
42 4 : switch((result=rs_async(job, &buf, in_fb, NULL)))
43 : {
44 : case RS_BLOCKED:
45 : case RS_RUNNING:
46 : continue;
47 : case RS_DONE:
48 : ret=0;
49 : goto end;
50 : default:
51 : logp("error in rs_async for sig: %d\n",
52 0 : result);
53 0 : goto end;
54 : }
55 : }
56 :
57 : end:
58 2 : iobuf_free_content(asfd->rbuf);
59 2 : rs_filebuf_free(&in_fb);
60 2 : return ret;
61 : }
62 :
63 2 : static int load_signature(struct asfd *asfd,
64 : rs_signature_t **sumset, struct cntr *cntr)
65 : {
66 : rs_job_t *job;
67 :
68 2 : if(!(job=rs_loadsig_begin(sumset)))
69 : {
70 0 : logp("could not start sig job.\n");
71 0 : return -1;
72 : }
73 2 : if(rs_loadsig_network_run(asfd, job, cntr))
74 : return -1;
75 2 : if(rs_build_hash_table(*sumset))
76 : return -1;
77 2 : rs_job_free(job);
78 2 : return 0;
79 : }
80 :
81 2 : static int load_signature_and_send_delta(struct asfd *asfd,
82 : BFILE *bfd, uint64_t *bytes, uint64_t *sentbytes,
83 : struct cntr *cntr)
84 : {
85 2 : int ret=-1;
86 2 : rs_job_t *job=NULL;
87 2 : rs_signature_t *sumset=NULL;
88 : uint8_t checksum[MD5_DIGEST_LENGTH];
89 2 : rs_filebuf_t *infb=NULL;
90 2 : rs_filebuf_t *outfb=NULL;
91 : rs_buffers_t rsbuf;
92 : memset(&rsbuf, 0, sizeof(rsbuf));
93 :
94 2 : if(load_signature(asfd, &sumset, cntr))
95 : goto end;
96 :
97 2 : if(!(job=rs_delta_begin(sumset)))
98 : {
99 0 : logp("could not start delta job.\n");
100 0 : goto end;
101 : }
102 :
103 2 : if(!(infb=rs_filebuf_new(bfd,
104 2 : NULL, NULL, ASYNC_BUF_LEN, bfd->datalen))
105 4 : || !(outfb=rs_filebuf_new(NULL,
106 2 : NULL, asfd, ASYNC_BUF_LEN, -1)))
107 : {
108 0 : logp("could not rs_filebuf_new for delta\n");
109 0 : goto end;
110 : }
111 :
112 : while(1)
113 : {
114 : rs_result result;
115 6 : switch((result=rs_async(job, &rsbuf, infb, outfb)))
116 : {
117 : case RS_DONE:
118 2 : *bytes=infb->bytes;
119 2 : *sentbytes=outfb->bytes;
120 2 : if(!MD5_Final(checksum, &(infb->md5)))
121 : {
122 0 : logp("MD5_Final() failed\n");
123 0 : goto end;
124 : }
125 2 : if(write_endfile(asfd, *bytes, checksum))
126 : goto end;
127 2 : ret=0;
128 2 : goto end;
129 : case RS_BLOCKED:
130 : case RS_RUNNING:
131 : // FIX ME: get it to read stuff here too.
132 : // (errors, for example)
133 4 : if(asfd->as->write(asfd->as))
134 : goto end;
135 : continue;
136 : default:
137 : logp("error in rs_async for delta: %d\n",
138 0 : result);
139 0 : goto end;
140 : }
141 : }
142 : end:
143 2 : rs_filebuf_free(&infb);
144 2 : rs_filebuf_free(&outfb);
145 2 : if(job) rs_job_free(job);
146 2 : if(sumset) rs_free_sumset(sumset);
147 2 : return ret;
148 : }
149 :
150 6 : static int send_whole_file_w(struct asfd *asfd,
151 : struct sbuf *sb, const char *datapth,
152 : int quick_read, uint64_t *bytes, const char *encpassword,
153 : struct cntr *cntr, int compression, BFILE *bfd,
154 : const char *extrameta, size_t elen)
155 : {
156 6 : if((compression || encpassword) && sb->path.cmd!=CMD_EFS_FILE)
157 : return send_whole_file_gzl(asfd,
158 : sb->path.buf, datapth, quick_read, bytes,
159 0 : encpassword, cntr, compression, bfd, extrameta, elen);
160 : else
161 : return send_whole_filel(asfd,
162 : sb->path.cmd, datapth, quick_read, bytes,
163 6 : 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 8 : if(sb->path.cmd!=CMD_FILE
188 8 : && sb->path.cmd!=CMD_ENC_FILE
189 8 : && sb->path.cmd!=CMD_EFS_FILE)
190 : return 0;
191 16 : if(get_uint64_t(confs[OPT_MIN_FILE_SIZE])
192 8 : && (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: %c:%s\n", sb->path.cmd, sb->path.buf);
195 0 : return -1;
196 : }
197 16 : if(get_uint64_t(confs[OPT_MAX_FILE_SIZE])
198 8 : && (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: %c:%s\n", sb->path.cmd, sb->path.buf);
201 0 : return -1;
202 : }
203 : return 0;
204 : }
205 :
206 14 : static int deal_with_data(struct asfd *asfd, struct sbuf *sb,
207 : 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 : 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 8 : if(sb->path.cmd!=CMD_METADATA
240 8 : && sb->path.cmd!=CMD_ENC_METADATA)
241 : {
242 8 : if(bfd->open_for_send(bfd, asfd,
243 : sb->path.buf, sb->winattr,
244 8 : 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 8 : 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, bfd,
264 0 : sb, &extrameta, &elen, cntr))
265 : {
266 : logw(asfd, cntr,
267 0 : "Meta data error for %s\n", sb->path.buf);
268 0 : goto end;
269 : }
270 0 : if(extrameta)
271 : {
272 : #ifdef HAVE_WIN32
273 : if(get_int(confs[OPT_STRIP_VSS]))
274 : {
275 : free_w(&extrameta);
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 8 : if(sb->path.cmd==CMD_FILE
289 4 : && sb->protocol1->datapth.buf)
290 : {
291 2 : uint64_t sentbytes=0;
292 : // Need to do sig/delta stuff.
293 4 : if(asfd->write(asfd, &(sb->protocol1->datapth))
294 2 : || asfd->write(asfd, &sb->attr)
295 2 : || asfd->write(asfd, &sb->path)
296 4 : || load_signature_and_send_delta(asfd, bfd,
297 2 : &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 2 : cntr_add(get_cntr(confs), CMD_FILE_CHANGED, 1);
306 2 : cntr_add_bytes(get_cntr(confs), bytes);
307 2 : cntr_add_sentbytes(get_cntr(confs), sentbytes);
308 2 : }
309 : }
310 : else
311 : {
312 : //logp("need to send whole file: %s\n", sb.path);
313 : // send the whole file.
314 :
315 12 : if((asfd->write(asfd, &sb->attr)
316 6 : || asfd->write(asfd, &sb->path))
317 12 : || send_whole_file_w(asfd, sb, NULL, 0, &bytes,
318 6 : get_string(confs[OPT_ENCRYPTION_PASSWORD]),
319 : cntr, sb->compression,
320 12 : bfd, extrameta, elen))
321 : goto end;
322 : else
323 : {
324 6 : cntr_add(get_cntr(confs), sb->path.cmd, 1);
325 6 : cntr_add_bytes(get_cntr(confs), bytes);
326 6 : cntr_add_sentbytes(get_cntr(confs), bytes);
327 : }
328 : }
329 :
330 : end:
331 : 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 8 : bfd->close(bfd, asfd);
341 : #endif
342 8 : sbuf_free_content(sb);
343 8 : free_w(&extrameta);
344 8 : return ret;
345 : }
346 :
347 19 : static int parse_rbuf(struct asfd *asfd, struct sbuf *sb,
348 : BFILE *bfd, struct conf **confs)
349 : {
350 : static struct iobuf *rbuf;
351 19 : rbuf=asfd->rbuf;
352 : //printf("now %d: %c:%s\n", rbuf->len, rbuf->cmd, rbuf->buf);
353 19 : if(rbuf->cmd==CMD_DATAPTH)
354 : {
355 2 : iobuf_move(&(sb->protocol1->datapth), rbuf);
356 : }
357 17 : 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 18 : else if(iobuf_is_filedata(rbuf)
365 9 : || iobuf_is_vssdata(rbuf))
366 : {
367 8 : if(deal_with_data(asfd, sb, bfd, confs))
368 : 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 : return 0;
383 : }
384 :
385 6 : static int do_backup_phase2_client(struct asfd *asfd,
386 : struct conf **confs, int resume)
387 : {
388 6 : 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 6 : BFILE *bfd=NULL;
393 6 : struct sbuf *sb=NULL;
394 6 : struct iobuf *rbuf=NULL;
395 6 : struct cntr *cntr=NULL;
396 6 : if(confs) cntr=get_cntr(confs);
397 :
398 6 : if(!asfd)
399 : {
400 1 : logp("%s() called without asfd!\n", __func__);
401 1 : goto end;
402 : }
403 5 : rbuf=asfd->rbuf;
404 :
405 10 : if(!(bfd=bfile_alloc())
406 5 : || !(sb=sbuf_alloc(PROTO_1)))
407 : goto end;
408 5 : bfile_init(bfd, 0, cntr);
409 :
410 5 : if(!resume)
411 : {
412 : // Only do this bit if the server did not tell us to resume.
413 10 : if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
414 5 : || asfd_read_expect(asfd, CMD_GEN, "ok"))
415 : 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 24 : iobuf_free_content(rbuf);
426 24 : if(asfd->read(asfd)) goto end;
427 23 : else if(!rbuf->buf) continue;
428 :
429 23 : if(rbuf->cmd==CMD_GEN && !strcmp(rbuf->buf, "backupphase2end"))
430 : {
431 4 : if(asfd->write_str(asfd, CMD_GEN, "okbackupphase2end"))
432 : goto end;
433 4 : ret=0;
434 4 : break;
435 : }
436 :
437 19 : if(parse_rbuf(asfd, sb, bfd, confs))
438 : goto end;
439 : }
440 :
441 : end:
442 : // It is possible for a bfd to still be open.
443 6 : if(bfd) bfd->close(bfd, asfd);
444 6 : bfile_free(&bfd);
445 6 : iobuf_free_content(rbuf);
446 6 : sbuf_free(&sb);
447 6 : return ret;
448 : }
449 :
450 6 : int backup_phase2_client_protocol1(struct asfd *asfd,
451 : struct conf **confs, int resume)
452 : {
453 6 : int ret=0;
454 6 : struct cntr *cntr=NULL;
455 6 : if(confs) cntr=get_cntr(confs);
456 :
457 6 : logp("Phase 2 begin (send backup data)\n");
458 6 : logf("\n");
459 :
460 6 : ret=do_backup_phase2_client(asfd, confs, resume);
461 :
462 6 : cntr_print_end(cntr);
463 6 : cntr_print(cntr, ACTION_BACKUP);
464 :
465 6 : if(ret) logp("Error in phase 2\n");
466 6 : logp("Phase 2 end (send file data)\n");
467 :
468 6 : return ret;
469 : }
|