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 int 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: %c:%s\n", sb->path.cmd, sb->path.buf);
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: %c:%s\n", sb->path.cmd, sb->path.buf);
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 12 : || send_whole_file_w(asfd, sb, NULL, 0, &bytes,
318 6 : get_string(confs[OPT_ENCRYPTION_PASSWORD]),
319 : cntr, sb->compression,
320 : bfd, extrameta, elen))
321 : goto end;
322 6 : cntr_add(cntr, sb->path.cmd, 1);
323 : }
324 8 : cntr_add_bytes(cntr, bytes);
325 :
326 : end:
327 : ret=0;
328 : error:
329 : #ifdef HAVE_WIN32
330 : // If using Windows do not close bfd - it needs
331 : // to stay open to read VSS/file data/VSS.
332 : // It will get closed either when given a
333 : // different file path, or when this function
334 : // exits.
335 : #else
336 8 : bfd->close(bfd, asfd);
337 : #endif
338 8 : sbuf_free_content(sb);
339 8 : free_w(&extrameta);
340 8 : return ret;
341 : }
342 :
343 19 : static int parse_rbuf(struct asfd *asfd, struct sbuf *sb,
344 : struct BFILE *bfd, struct conf **confs)
345 : {
346 : static struct iobuf *rbuf;
347 19 : rbuf=asfd->rbuf;
348 : //printf("now %d: %c:%s\n", rbuf->len, rbuf->cmd, rbuf->buf);
349 19 : if(rbuf->cmd==CMD_DATAPTH)
350 : {
351 2 : iobuf_move(&(sb->protocol1->datapth), rbuf);
352 : }
353 17 : else if(rbuf->cmd==CMD_ATTRIBS)
354 : {
355 : // Ignore the stat data - we will fill it
356 : // in again. Some time may have passed by now,
357 : // and it is best to make it as fresh as
358 : // possible.
359 : }
360 9 : else if(iobuf_is_filedata(rbuf)
361 1 : || iobuf_is_vssdata(rbuf))
362 : {
363 8 : if(deal_with_data(asfd, sb, bfd, confs))
364 : return -1;
365 : }
366 2 : else if(rbuf->cmd==CMD_MESSAGE
367 1 : || rbuf->cmd==CMD_WARNING)
368 : {
369 1 : struct cntr *cntr=NULL;
370 1 : if(confs) cntr=get_cntr(confs);
371 1 : log_recvd(rbuf, cntr, 0);
372 : }
373 : else
374 : {
375 0 : iobuf_log_unexpected(rbuf, __func__);
376 0 : return -1;
377 : }
378 : return 0;
379 : }
380 :
381 6 : static int do_backup_phase2_client(struct asfd *asfd,
382 : struct conf **confs, int resume)
383 : {
384 6 : int ret=-1;
385 : // For efficiency, open Windows files for the VSS data, and do not
386 : // close them until another time around the loop, when the actual
387 : // data is read.
388 6 : struct BFILE *bfd=NULL;
389 6 : struct sbuf *sb=NULL;
390 6 : struct iobuf *rbuf=NULL;
391 6 : struct cntr *cntr=NULL;
392 6 : if(confs) cntr=get_cntr(confs);
393 :
394 6 : if(!asfd)
395 : {
396 1 : logp("%s() called without asfd!\n", __func__);
397 1 : goto end;
398 : }
399 5 : rbuf=asfd->rbuf;
400 :
401 5 : if(!(bfd=bfile_alloc())
402 5 : || !(sb=sbuf_alloc(PROTO_1)))
403 : goto end;
404 5 : bfile_init(bfd, 0, cntr);
405 :
406 5 : if(!resume)
407 : {
408 : // Only do this bit if the server did not tell us to resume.
409 5 : if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
410 5 : || asfd_read_expect(asfd, CMD_GEN, "ok"))
411 : goto end;
412 : }
413 : else
414 : {
415 : // On resume, the server might update the client with cntr.
416 0 : if(cntr_recv(asfd, confs))
417 : 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 : logfmt("\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, asfd);
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 : }
|