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