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