Line data Source code
1 : #include "../../burp.h"
2 : #include "../../alloc.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 "../../conffile.h"
10 : #include "../../fsops.h"
11 : #include "../../handy.h"
12 : #include "../../iobuf.h"
13 : #include "../../log.h"
14 : #include "../../sbuf.h"
15 : #include "../child.h"
16 : #include "../compress.h"
17 : #include "../resume.h"
18 : #include "blocklen.h"
19 : #include "dpth.h"
20 : #include "backup_phase2.h"
21 :
22 : static size_t treepathlen=0;
23 :
24 0 : static int path_length_warn(struct iobuf *path, struct conf **cconfs)
25 : {
26 0 : if(get_int(cconfs[OPT_PATH_LENGTH_WARN]))
27 0 : logw(NULL, get_cntr(cconfs), "Path too long for tree - will save in data structure instead: %s\n", path->buf);
28 0 : return 1;
29 : }
30 :
31 4 : static int path_too_long(struct iobuf *path, struct conf **cconfs)
32 : {
33 : static const char *cp;
34 4 : if(treepathlen+path->len+1>fs_full_path_max)
35 : {
36 : // FIX THIS:
37 : // Cannot warn down the asfd to the client, because it can
38 : // arrive after the client has disconnected, which causes
39 : // an error on the server side.
40 : // Would need to change the way that "backupphase2end" works
41 : // to be able to fix it.
42 0 : return path_length_warn(path, cconfs);
43 : }
44 4 : if((cp=strrchr(path->buf, '/'))) cp++;
45 0 : else cp=path->buf;
46 4 : if(strlen(cp)>fs_name_max) return path_length_warn(path, cconfs);
47 : return 0;
48 : }
49 :
50 4 : static int treedata(struct sbuf *sb, struct conf **cconfs)
51 : {
52 : // Windows is sending directory data as if it is file data - this
53 : // cannot be saved in a tree structure.
54 4 : if(S_ISDIR(sb->statp.st_mode)) return 0;
55 :
56 8 : if(sb->path.cmd!=CMD_FILE
57 4 : && sb->path.cmd!=CMD_ENC_FILE
58 0 : && sb->path.cmd!=CMD_EFS_FILE)
59 : return 0;
60 :
61 4 : return !path_too_long(&sb->path, cconfs);
62 : }
63 :
64 4 : static char *set_new_datapth(struct asfd *asfd,
65 : struct sdirs *sdirs, struct conf **cconfs,
66 : struct sbuf *sb, struct dpth *dpth, int *istreedata)
67 : {
68 4 : char *tmp=NULL;
69 4 : char *rpath=NULL;
70 4 : if(get_int(cconfs[OPT_DIRECTORY_TREE]))
71 4 : *istreedata=treedata(sb, cconfs);
72 :
73 4 : if(*istreedata)
74 : {
75 : // We want to place this file in a directory structure like
76 : // the directory structure on the original client.
77 4 : if(!(tmp=prepend_s(TREE_DIR, sb->path.buf)))
78 : {
79 0 : log_and_send_oom(asfd);
80 : return NULL;
81 : }
82 : }
83 : else
84 : {
85 0 : if(!(tmp=strdup_w(dpth_protocol1_mk(dpth, sb->compression,
86 : sb->path.cmd), __func__))) return NULL;
87 : }
88 4 : iobuf_from_str(&sb->protocol1->datapth, CMD_DATAPTH, tmp);
89 4 : if(build_path(sdirs->datadirtmp,
90 4 : sb->protocol1->datapth.buf, &rpath, sdirs->datadirtmp))
91 : {
92 0 : log_and_send(asfd, "build path failed");
93 : return NULL;
94 : }
95 4 : return rpath;
96 : }
97 :
98 4 : static int start_to_receive_new_file(struct asfd *asfd,
99 : struct sdirs *sdirs, struct conf **cconfs,
100 : struct sbuf *sb, struct dpth *dpth)
101 : {
102 4 : int ret=-1;
103 4 : char *rpath=NULL;
104 4 : int istreedata=0;
105 :
106 : //logp("start to receive: %s\n", sb->path.buf);
107 :
108 4 : if(!(rpath=set_new_datapth(asfd,
109 : sdirs, cconfs, sb, dpth, &istreedata)))
110 : goto end;
111 :
112 4 : if(!(sb->protocol1->fzp=fzp_open(rpath, "wb")))
113 : {
114 0 : log_and_send(asfd, "make file failed");
115 0 : goto end;
116 : }
117 4 : if(!istreedata) dpth_incr(dpth);
118 : ret=0;
119 : end:
120 4 : free_w(&rpath);
121 4 : return ret;
122 : }
123 :
124 : enum processed_e
125 : {
126 : P_ERROR=-1,
127 : P_DONE_NEW=0,
128 : P_DONE_CHANGED=1,
129 : P_DONE_UNCHANGED=2,
130 : P_DONE_DELETED=3,
131 : P_NEW=4,
132 : P_CHANGED=5
133 : };
134 :
135 : #include <librsync.h>
136 :
137 2 : static enum processed_e process_changed_file(struct asfd *asfd,
138 : struct conf **cconfs,
139 : struct sbuf *cb, struct sbuf *p1b,
140 : const char *adir)
141 : {
142 2 : int ret=P_ERROR;
143 2 : size_t blocklen=0;
144 2 : char *curpath=NULL;
145 : //logp("need to process changed file: %s (%s)\n",
146 : // cb->path, cb->datapth);
147 :
148 : // Move datapth onto p1b.
149 2 : iobuf_move(&p1b->protocol1->datapth, &cb->protocol1->datapth);
150 :
151 2 : if(!(curpath=prepend_s(adir, p1b->protocol1->datapth.buf)))
152 : {
153 0 : log_out_of_memory(__func__);
154 : goto end;
155 : }
156 2 : if(dpth_protocol1_is_compressed(cb->compression, curpath))
157 0 : p1b->protocol1->sigfzp=fzp_gzopen(curpath, "rb");
158 : else
159 2 : p1b->protocol1->sigfzp=fzp_open(curpath, "rb");
160 2 : if(!p1b->protocol1->sigfzp)
161 : {
162 0 : logp("could not open %s: %s\n", curpath, strerror(errno));
163 : goto end;
164 : }
165 :
166 2 : blocklen=get_librsync_block_len(cb->endfile.buf);
167 4 : if(!(p1b->protocol1->sigjob=
168 : #ifdef RS_DEFAULT_STRONG_LEN
169 2 : rs_sig_begin(blocklen, RS_DEFAULT_STRONG_LEN)
170 : #else
171 : // This is for librsync-1.0.0. RS_DEFAULT_STRONG_LEN was 8 in
172 : // librsync-0.9.7.
173 : rs_sig_begin(blocklen, 8,
174 : rshash_to_magic_number(get_e_rshash(cconfs[OPT_RSHASH])))
175 : #endif
176 : ))
177 : {
178 0 : logp("could not start signature job.\n");
179 : goto end;
180 : }
181 : //logp("sig begin: %s\n", p1b->protocol1->datapth.buf);
182 2 : if(!(p1b->protocol1->infb=rs_filebuf_new(NULL,
183 2 : p1b->protocol1->sigfzp,
184 : NULL, blocklen, -1)))
185 : {
186 0 : logp("could not rs_filebuf_new for infb.\n");
187 : goto end;
188 : }
189 2 : if(!(p1b->protocol1->outfb=rs_filebuf_new(NULL, NULL,
190 : asfd, ASYNC_BUF_LEN, -1)))
191 : {
192 0 : logp("could not rs_filebuf_new for in_outfb.\n");
193 : goto end;
194 : }
195 :
196 : // Flag the things that need to be sent (to the client)
197 2 : p1b->flags |= SBUF_SEND_DATAPTH;
198 2 : p1b->flags |= SBUF_SEND_STAT;
199 2 : p1b->flags |= SBUF_SEND_PATH;
200 :
201 : //logp("sending sig for %s\n", p1b->path);
202 : //logp("(%s)\n", p1b->datapth);
203 :
204 2 : ret=P_CHANGED;
205 : end:
206 2 : free_w(&curpath);
207 2 : return ret;
208 : }
209 :
210 68 : static enum processed_e new_non_file(struct sbuf *p1b,
211 : struct manio *ucmanio, struct conf **cconfs)
212 : {
213 : // Is something that does not need more data backed up.
214 : // Like a directory or a link or something like that.
215 : // Goes into the unchanged file, so that it does not end up out of
216 : // order with normal files, which has to wait around for their data
217 : // to turn up.
218 68 : if(manio_write_sbuf(ucmanio, p1b))
219 : return P_ERROR;
220 68 : cntr_add(get_cntr(cconfs), p1b->path.cmd, 0);
221 68 : return P_DONE_NEW;
222 : }
223 :
224 0 : static enum processed_e changed_non_file(struct sbuf *p1b,
225 : struct manio *ucmanio, enum cmd cmd, struct conf **cconfs)
226 : {
227 : // As new_non_file.
228 0 : if(manio_write_sbuf(ucmanio, p1b))
229 : return P_ERROR;
230 0 : cntr_add_changed(get_cntr(cconfs), cmd);
231 0 : return P_DONE_CHANGED;
232 : }
233 :
234 122 : static enum processed_e process_new(struct conf **cconfs,
235 : struct sbuf *p1b, struct manio *ucmanio)
236 : {
237 122 : if(sbuf_is_filedata(p1b)
238 68 : || sbuf_is_vssdata(p1b))
239 : {
240 : //logp("need to process new file: %s\n", p1b->path);
241 : // Flag the things that need to be sent (to the client)
242 54 : p1b->flags |= SBUF_SEND_STAT;
243 54 : p1b->flags |= SBUF_SEND_PATH;
244 54 : return P_NEW;
245 : }
246 68 : return new_non_file(p1b, ucmanio, cconfs);
247 : }
248 :
249 6 : static enum processed_e process_unchanged_file(struct sbuf *p1b, struct sbuf *cb,
250 : struct manio *ucmanio, struct conf **cconfs)
251 : {
252 : // Need to re-encode the p1b attribs to include compression and
253 : // other bits and pieces that are recorded on cb.
254 6 : iobuf_move(&p1b->protocol1->datapth, &cb->protocol1->datapth);
255 6 : iobuf_move(&p1b->endfile, &cb->endfile);
256 6 : p1b->compression=cb->compression;
257 : // Why is winattr not getting sent in phase1?
258 6 : p1b->winattr=cb->winattr;
259 : // Need to free attr so that it is reallocated, because it may get
260 : // longer than what the client told us in phase1.
261 6 : iobuf_free_content(&p1b->attr);
262 6 : if(attribs_encode(p1b))
263 : return P_ERROR;
264 6 : if(manio_write_sbuf(ucmanio, p1b))
265 : return P_ERROR;
266 6 : cntr_add_same(get_cntr(cconfs), p1b->path.cmd);
267 6 : if(p1b->endfile.buf) cntr_add_bytes(get_cntr(cconfs),
268 0 : strtoull(p1b->endfile.buf, NULL, 10));
269 : return P_DONE_UNCHANGED;
270 : }
271 :
272 10 : static enum processed_e maybe_do_delta_stuff(struct asfd *asfd,
273 : struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
274 : struct manio *ucmanio, struct conf **cconfs)
275 : {
276 10 : int oldcompressed=0;
277 10 : int compression=p1b->compression;
278 :
279 : // If the file type changed, I think it is time to back it up again
280 : // (for example, EFS changing to normal file, or back again).
281 10 : if(cb->path.cmd!=p1b->path.cmd)
282 0 : return process_new(cconfs, p1b, ucmanio);
283 :
284 : // mtime is the actual file data.
285 : // ctime is the attributes or meta data.
286 10 : if(cb->statp.st_mtime==p1b->statp.st_mtime
287 6 : && cb->statp.st_ctime==p1b->statp.st_ctime)
288 : {
289 : // got an unchanged file
290 : //logp("got unchanged file: %s %c %c\n",
291 : // cb->path.buf, cb->path.cmd, p1b->path.cmd);
292 6 : return process_unchanged_file(p1b, cb, ucmanio, cconfs);
293 : }
294 :
295 4 : if(cb->statp.st_mtime==p1b->statp.st_mtime
296 0 : && cb->statp.st_ctime!=p1b->statp.st_ctime)
297 : {
298 : // File data stayed the same, but attributes or meta data
299 : // changed. We already have the attributes, but may need to get
300 : // extra meta data.
301 : // FIX THIS horrible mess.
302 0 : if(cb->path.cmd==CMD_ENC_METADATA
303 0 : || p1b->path.cmd==CMD_ENC_METADATA
304 0 : || cb->path.cmd==CMD_EFS_FILE
305 0 : || p1b->path.cmd==CMD_EFS_FILE
306 : // FIX THIS: make unencrypted metadata use the librsync
307 0 : || cb->path.cmd==CMD_METADATA
308 0 : || p1b->path.cmd==CMD_METADATA
309 0 : || sbuf_is_vssdata(cb)
310 0 : || sbuf_is_vssdata(p1b))
311 0 : return process_new(cconfs, p1b, ucmanio);
312 : // On Windows, we have to back up the whole file if ctime
313 : // changed, otherwise things like permission changes do not get
314 : // noticed. So, in that case, fall through to the changed stuff
315 : // below.
316 : // Non-Windows clients finish here.
317 0 : else if(!get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
318 0 : return process_unchanged_file(p1b,
319 : cb, ucmanio, cconfs);
320 : }
321 :
322 : // Got a changed file.
323 : //logp("got changed file: %s\n", p1b->path.buf);
324 :
325 : // If either old or new is encrypted, or librsync is off, we need to
326 : // get a new file.
327 : // FIX THIS horrible mess.
328 4 : if(!get_int(cconfs[OPT_LIBRSYNC])
329 : // FIX THIS: make unencrypted metadata use the librsync
330 4 : || cb->path.cmd==CMD_METADATA
331 4 : || p1b->path.cmd==CMD_METADATA
332 4 : || sbuf_is_encrypted(cb)
333 2 : || sbuf_is_encrypted(p1b)
334 2 : || sbuf_is_vssdata(cb)
335 2 : || sbuf_is_vssdata(p1b))
336 2 : return process_new(cconfs, p1b, ucmanio);
337 :
338 : // Get new files if they have switched between compression on or off.
339 2 : if(cb->protocol1->datapth.buf
340 2 : && dpth_protocol1_is_compressed(cb->compression,
341 : cb->protocol1->datapth.buf))
342 0 : oldcompressed=1;
343 2 : if( ( oldcompressed && !compression)
344 2 : || (!oldcompressed && compression))
345 0 : return process_new(cconfs, p1b, ucmanio);
346 :
347 : // Otherwise, do the delta stuff (if possible).
348 2 : if(sbuf_is_filedata(p1b)
349 0 : || sbuf_is_vssdata(p1b))
350 2 : return process_changed_file(asfd, cconfs, cb, p1b,
351 2 : sdirs->currentdata);
352 0 : return changed_non_file(p1b, ucmanio, p1b->path.cmd, cconfs);
353 : }
354 :
355 : static enum processed_e process_deleted_file(struct sbuf *cb,
356 : struct conf **cconfs)
357 : {
358 0 : cntr_add_deleted(get_cntr(cconfs), cb->path.cmd);
359 : return P_DONE_DELETED;
360 : }
361 :
362 : // return 1 to say that a file was processed
363 10 : static enum processed_e maybe_process_file(struct asfd *asfd,
364 0 : struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
365 : struct manio *ucmanio, struct conf **cconfs)
366 : {
367 : int pcmp;
368 10 : if(p1b)
369 : {
370 10 : if(!(pcmp=sbuf_pathcmp(cb, p1b)))
371 10 : return maybe_do_delta_stuff(asfd, sdirs, cb, p1b,
372 : ucmanio, cconfs);
373 0 : else if(pcmp>0)
374 : {
375 : //logp("ahead: %s\n", p1b->path);
376 : // ahead - need to get the whole file
377 0 : return process_new(cconfs, p1b, ucmanio);
378 : }
379 : }
380 : //logp("behind: %s\n", p1b->path);
381 : // Behind - need to read more from the old manifest.
382 : // Count a deleted file - it was in the old manifest
383 : // but not the new.
384 0 : return process_deleted_file(cb, cconfs);
385 : }
386 :
387 : enum sts_e
388 : {
389 : STS_ERROR=-1,
390 : STS_OK=0,
391 : STS_BLOCKED=1
392 : };
393 :
394 : // Return 1 if there is still stuff needing to be sent.
395 : // FIX THIS: lots of repeated code.
396 63 : static enum sts_e do_stuff_to_send(struct asfd *asfd,
397 : struct sbuf *p1b, char **last_requested)
398 : {
399 : static struct iobuf wbuf;
400 63 : if(p1b->flags & SBUF_SEND_DATAPTH)
401 : {
402 2 : iobuf_copy(&wbuf, &p1b->protocol1->datapth);
403 2 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
404 : {
405 : case APPEND_OK: break;
406 : case APPEND_BLOCKED: return STS_BLOCKED;
407 0 : default: return STS_ERROR;
408 : }
409 2 : p1b->flags &= ~SBUF_SEND_DATAPTH;
410 : }
411 63 : if(p1b->flags & SBUF_SEND_STAT)
412 : {
413 56 : iobuf_copy(&wbuf, &p1b->attr);
414 56 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
415 : {
416 : case APPEND_OK: break;
417 : case APPEND_BLOCKED: return STS_BLOCKED;
418 0 : default: return STS_ERROR;
419 : }
420 56 : p1b->flags &= ~SBUF_SEND_STAT;
421 : }
422 63 : if(p1b->flags & SBUF_SEND_PATH)
423 : {
424 56 : iobuf_copy(&wbuf, &p1b->path);
425 56 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
426 : {
427 : case APPEND_OK: break;
428 : case APPEND_BLOCKED: return STS_BLOCKED;
429 0 : default: return STS_ERROR;
430 : }
431 56 : p1b->flags &= ~SBUF_SEND_PATH;
432 56 : free_w(last_requested);
433 56 : if(!(*last_requested=strdup_w(p1b->path.buf, __func__)))
434 : return STS_ERROR;
435 : }
436 63 : if(p1b->protocol1->sigjob && !(p1b->flags & SBUF_SEND_ENDOFSIG))
437 : {
438 : rs_result sigresult;
439 :
440 4 : switch((sigresult=rs_async(p1b->protocol1->sigjob,
441 : &(p1b->protocol1->rsbuf),
442 : p1b->protocol1->infb, p1b->protocol1->outfb)))
443 : {
444 : case RS_DONE:
445 2 : p1b->flags |= SBUF_SEND_ENDOFSIG;
446 2 : break;
447 : case RS_BLOCKED:
448 : case RS_RUNNING:
449 : // keep going round the loop.
450 : return STS_BLOCKED;
451 : default:
452 0 : logp("error in rs_async: %d\n", sigresult);
453 0 : return STS_ERROR;
454 : }
455 : }
456 61 : if(p1b->flags & SBUF_SEND_ENDOFSIG)
457 : {
458 2 : iobuf_from_str(&wbuf, CMD_END_FILE, (char *)"endfile");
459 2 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
460 : {
461 : case APPEND_OK: break;
462 : case APPEND_BLOCKED: return STS_BLOCKED;
463 0 : default: return STS_ERROR;
464 : }
465 2 : p1b->flags &= ~SBUF_SEND_ENDOFSIG;
466 : }
467 : return STS_OK;
468 : }
469 :
470 4 : static int start_to_receive_delta(struct sdirs *sdirs, struct sbuf *rb)
471 : {
472 4 : if(rb->compression)
473 : {
474 0 : if(!(rb->protocol1->fzp=fzp_gzopen(sdirs->deltmppath,
475 0 : comp_level(rb->compression))))
476 : return -1;
477 : }
478 : else
479 : {
480 4 : if(!(rb->protocol1->fzp=fzp_open(sdirs->deltmppath, "wb")))
481 : return -1;
482 : }
483 4 : rb->flags |= SBUF_RECV_DELTA;
484 :
485 : return 0;
486 : }
487 :
488 4 : static int finish_delta(struct sdirs *sdirs, struct sbuf *rb)
489 : {
490 4 : int ret=0;
491 4 : char *deltmp=NULL;
492 4 : char *delpath=NULL;
493 4 : if(!(deltmp=prepend_s("deltas.forward", rb->protocol1->datapth.buf))
494 4 : || !(delpath=prepend_s(sdirs->working, deltmp))
495 4 : || mkpath(&delpath, sdirs->working)
496 : // Rename race condition is of no consequence here, as delpath will
497 : // just get recreated.
498 4 : || do_rename(sdirs->deltmppath, delpath))
499 : ret=-1;
500 4 : free_w(&delpath);
501 4 : free_w(&deltmp);
502 4 : return ret;
503 : }
504 :
505 8 : static int deal_with_receive_end_file(struct asfd *asfd, struct sdirs *sdirs,
506 4 : struct sbuf *rb, struct manio *chmanio, struct conf **cconfs,
507 : char **last_requested)
508 : {
509 8 : int ret=-1;
510 : static char *cp=NULL;
511 : static struct iobuf *rbuf;
512 8 : struct cntr *cntr=get_cntr(cconfs);
513 8 : rbuf=asfd->rbuf;
514 : // Finished the file.
515 : // Write it to the phase2 file, and free the buffers.
516 :
517 8 : if(fzp_close(&(rb->protocol1->fzp)))
518 : {
519 0 : logp("error closing delta for %s in receive\n", rb->path.buf);
520 : goto end;
521 : }
522 8 : iobuf_move(&rb->endfile, rbuf);
523 12 : if(rb->flags & SBUF_RECV_DELTA && finish_delta(sdirs, rb))
524 : goto end;
525 :
526 8 : if(manio_write_sbuf(chmanio, rb))
527 : goto end;
528 :
529 8 : if(rb->flags & SBUF_RECV_DELTA)
530 4 : cntr_add_changed(cntr, rb->path.cmd);
531 : else
532 4 : cntr_add(cntr, rb->path.cmd, 0);
533 :
534 8 : if(*last_requested && !strcmp(rb->path.buf, *last_requested))
535 2 : free_w(last_requested);
536 :
537 8 : cp=strchr(rb->endfile.buf, ':');
538 8 : if(rb->endfile.buf)
539 8 : cntr_add_bytes(cntr, strtoull(rb->endfile.buf, NULL, 10));
540 : if(cp)
541 : {
542 : // checksum stuff goes here
543 : }
544 :
545 : ret=0;
546 : end:
547 8 : sbuf_free_content(rb);
548 8 : return ret;
549 : }
550 :
551 8 : static int deal_with_receive_append(struct asfd *asfd, struct sbuf *rb)
552 : {
553 8 : int app=0;
554 : static struct iobuf *rbuf;
555 8 : rbuf=asfd->rbuf;
556 : //logp("rbuf->len: %d\n", rbuf->len);
557 :
558 8 : if(rb->protocol1->fzp)
559 8 : app=fzp_write(rb->protocol1->fzp, rbuf->buf, rbuf->len);
560 :
561 8 : if(app>0) return 0;
562 0 : logp("error when appending: %d\n", app);
563 0 : asfd->write_str(asfd, CMD_ERROR, "write failed");
564 : return -1;
565 : }
566 :
567 8 : static int deal_with_filedata(struct asfd *asfd,
568 : struct sdirs *sdirs, struct sbuf *rb,
569 : struct iobuf *rbuf, struct dpth *dpth, struct conf **cconfs)
570 : {
571 8 : iobuf_move(&rb->path, rbuf);
572 :
573 8 : if(rb->protocol1->datapth.buf)
574 : {
575 : // Receiving a delta.
576 4 : if(start_to_receive_delta(sdirs, rb))
577 : {
578 0 : logp("error in start_to_receive_delta\n");
579 0 : return -1;
580 : }
581 : return 0;
582 : }
583 :
584 : // Receiving a whole new file.
585 4 : if(start_to_receive_new_file(asfd, sdirs, cconfs, rb, dpth))
586 : {
587 0 : logp("error in start_to_receive_new_file\n");
588 0 : return -1;
589 : }
590 : return 0;
591 : }
592 :
593 : enum str_e
594 : {
595 : STR_ERROR=-1,
596 : STR_OK=0,
597 : STR_FINISHED=1
598 : };
599 :
600 : // returns 1 for finished ok.
601 85 : static enum str_e do_stuff_to_receive(struct asfd *asfd,
602 : struct sdirs *sdirs, struct conf **cconfs,
603 : struct sbuf *rb, struct manio *chmanio,
604 : struct dpth *dpth, char **last_requested)
605 : {
606 85 : struct iobuf *rbuf=asfd->rbuf;
607 :
608 170 : if(rbuf->cmd==CMD_MESSAGE
609 85 : || rbuf->cmd==CMD_WARNING)
610 : {
611 0 : struct cntr *cntr=NULL;
612 0 : if(cconfs) cntr=get_cntr(cconfs);
613 0 : log_recvd(rbuf, cntr, 0);
614 0 : return STR_OK;
615 : }
616 :
617 85 : if(rb->protocol1->fzp)
618 : {
619 : // Currently writing a file (or meta data)
620 16 : switch(rbuf->cmd)
621 : {
622 : case CMD_APPEND:
623 8 : if(deal_with_receive_append(asfd, rb))
624 : goto error;
625 : return STR_OK;
626 : case CMD_END_FILE:
627 8 : if(deal_with_receive_end_file(asfd, sdirs, rb,
628 : chmanio, cconfs, last_requested))
629 : goto error;
630 : return STR_OK;
631 : default:
632 0 : iobuf_log_unexpected(rbuf, __func__);
633 0 : goto error;
634 : }
635 : }
636 :
637 : // Otherwise, expecting to be told of a file to save.
638 69 : switch(rbuf->cmd)
639 : {
640 : case CMD_DATAPTH:
641 4 : iobuf_move(&rb->protocol1->datapth, rbuf);
642 4 : return STR_OK;
643 : case CMD_ATTRIBS:
644 8 : iobuf_move(&rb->attr, rbuf);
645 8 : attribs_decode(rb);
646 8 : return STR_OK;
647 : case CMD_GEN:
648 5 : if(!strcmp(rbuf->buf, "okbackupphase2end"))
649 : goto end_phase2;
650 0 : iobuf_log_unexpected(rbuf, __func__);
651 0 : goto error;
652 : case CMD_INTERRUPT:
653 : // Interrupt - forget about the last requested
654 : // file if it matches. Otherwise, we can get
655 : // stuck on the select in the async stuff,
656 : // waiting for something that will never arrive.
657 44 : if(*last_requested
658 44 : && !strcmp(rbuf->buf, *last_requested))
659 1 : free_w(last_requested);
660 : return STR_OK;
661 : default:
662 : break;
663 : }
664 8 : if(iobuf_is_filedata(rbuf)
665 0 : || iobuf_is_vssdata(rbuf))
666 : {
667 8 : if(deal_with_filedata(asfd, sdirs, rb, rbuf, dpth, cconfs))
668 : goto error;
669 : return STR_OK;
670 : }
671 0 : iobuf_log_unexpected(rbuf, __func__);
672 :
673 : error:
674 : return STR_ERROR;
675 : end_phase2:
676 : return STR_FINISHED;
677 : }
678 :
679 1 : static int vss_opts_changed(struct sdirs *sdirs, struct conf **cconfs,
680 : const char *incexc)
681 : {
682 1 : int ret=-1;
683 : struct conf **oldconfs;
684 : struct conf **newconfs;
685 1 : if(!(oldconfs=confs_alloc())
686 1 : || !(newconfs=confs_alloc()))
687 : goto end;
688 1 : confs_init(oldconfs);
689 1 : confs_init(newconfs);
690 :
691 : // Figure out the old config, which is in the incexc file left
692 : // in the current backup directory on the server.
693 1 : if(conf_parse_incexcs_path(oldconfs, sdirs->cincexc))
694 : {
695 : // Assume that the file did not exist, and therefore
696 : // the old split_vss setting is 0.
697 0 : set_int(oldconfs[OPT_SPLIT_VSS], 0);
698 0 : set_int(oldconfs[OPT_STRIP_VSS], 0);
699 : }
700 :
701 : // Figure out the new config, which is either in the incexc file from
702 : // the client, or in the cconf on the server.
703 1 : if(incexc)
704 : {
705 0 : if(conf_parse_incexcs_buf(newconfs, incexc))
706 : {
707 : // Should probably not got here.
708 0 : set_int(newconfs[OPT_SPLIT_VSS], 0);
709 0 : set_int(newconfs[OPT_STRIP_VSS], 0);
710 : }
711 : }
712 : else
713 : {
714 1 : set_int(newconfs[OPT_SPLIT_VSS],
715 1 : get_int(cconfs[OPT_SPLIT_VSS]));
716 1 : set_int(newconfs[OPT_STRIP_VSS],
717 1 : get_int(cconfs[OPT_STRIP_VSS]));
718 : }
719 :
720 1 : if(get_int(newconfs[OPT_SPLIT_VSS])!=get_int(oldconfs[OPT_SPLIT_VSS]))
721 : {
722 0 : logp("split_vss=%d (changed since last backup)\n",
723 0 : get_int(newconfs[OPT_SPLIT_VSS]));
724 0 : ret=1; goto end;
725 : }
726 1 : if(get_int(newconfs[OPT_STRIP_VSS])!=get_int(oldconfs[OPT_STRIP_VSS]))
727 : {
728 0 : logp("strip_vss=%d (changed since last backup)\n",
729 0 : get_int(newconfs[OPT_STRIP_VSS]));
730 0 : ret=1; goto end;
731 : }
732 : ret=0;
733 : end:
734 1 : if(ret==1) logp("All files will be treated as new\n");
735 1 : confs_free(&oldconfs);
736 1 : confs_free(&newconfs);
737 1 : return ret;
738 : }
739 :
740 : // Open the previous (current) manifest.
741 : // If the split_vss setting changed between the previous backup and the new
742 : // backup, do not open the previous manifest. This will have the effect of
743 : // making the client back up everything fresh. Need to do this, otherwise
744 : // toggling split_vss on and off will result in backups that do not work.
745 5 : static int open_previous_manifest(struct manio **cmanio,
746 : struct sdirs *sdirs, const char *incexc, struct conf **cconfs)
747 : {
748 : struct stat statp;
749 10 : if(!lstat(sdirs->cmanifest, &statp)
750 1 : && !vss_opts_changed(sdirs, cconfs, incexc)
751 1 : && !(*cmanio=manio_open(sdirs->cmanifest, "rb", PROTO_1)))
752 : {
753 0 : logp("could not open old manifest %s\n", sdirs->cmanifest);
754 0 : return -1;
755 : }
756 : return 0;
757 : }
758 :
759 135 : static int process_next_file_from_manios(struct asfd *asfd,
760 : struct sdirs *sdirs,
761 : struct manio **p1manio,
762 : struct manio **cmanio,
763 : struct manio *ucmanio,
764 : struct sbuf **p1b,
765 : struct sbuf *cb,
766 : struct conf **cconfs)
767 : {
768 135 : if(!(*p1b=sbuf_alloc(PROTO_1)))
769 : goto error;
770 135 : switch(manio_read(*p1manio, *p1b))
771 : {
772 : case 0:
773 : break;
774 : case 1:
775 5 : manio_close(p1manio);
776 5 : if(asfd->write_str(asfd, CMD_GEN, "backupphase2end"))
777 : goto error;
778 5 : sbuf_free(p1b);
779 5 : break;
780 : case -1:
781 : goto error;
782 : }
783 :
784 135 : if(!*cmanio)
785 : {
786 124 : if(!*p1b) return 0;
787 : // No old manifest, need to ask for a new file.
788 120 : switch(process_new(cconfs, *p1b, ucmanio))
789 : {
790 : case P_NEW:
791 : return 0;
792 : case P_DONE_NEW:
793 : goto p1b_done;
794 : default:
795 : goto error;
796 : }
797 : }
798 :
799 : // Have an old manifest, look for it there.
800 :
801 : // Might already have it, or be ahead in the old
802 : // manifest.
803 11 : if(cb->path.buf)
804 : {
805 0 : switch(maybe_process_file(asfd,
806 : sdirs, cb, *p1b, ucmanio, cconfs))
807 : {
808 : case P_NEW:
809 : case P_CHANGED:
810 : // Free cb content for things like encrypted
811 : // files, which we only pretend are new.
812 0 : sbuf_free_content(cb);
813 0 : return 0;
814 : case P_DONE_NEW:
815 : goto p1b_done;
816 : case P_DONE_CHANGED:
817 : case P_DONE_UNCHANGED:
818 0 : sbuf_free_content(cb);
819 0 : goto p1b_done;
820 : case P_DONE_DELETED:
821 0 : sbuf_free_content(cb);
822 0 : break;
823 : case P_ERROR:
824 : goto error;
825 : }
826 : }
827 :
828 : while(1)
829 : {
830 11 : sbuf_free_content(cb);
831 11 : switch(manio_read(*cmanio, cb))
832 : {
833 : case 0: break;
834 1 : case 1: manio_close(cmanio);
835 1 : if(*p1b) switch(process_new(cconfs,
836 : *p1b, ucmanio))
837 : {
838 : case P_NEW:
839 : return 0;
840 : case P_DONE_NEW:
841 : goto p1b_done;
842 : default:
843 : goto error;
844 : }
845 : return 0;
846 : case -1: goto error;
847 : }
848 10 : switch(maybe_process_file(asfd, sdirs,
849 : cb, *p1b, ucmanio, cconfs))
850 : {
851 : case P_NEW:
852 : case P_CHANGED:
853 : // Free cb content for things like encrypted
854 : // files, which we only pretend are new.
855 4 : sbuf_free_content(cb);
856 4 : return 0;
857 : case P_DONE_NEW:
858 : goto p1b_done;
859 : case P_DONE_CHANGED:
860 : case P_DONE_UNCHANGED:
861 6 : sbuf_free_content(cb);
862 6 : goto p1b_done;
863 : case P_DONE_DELETED:
864 0 : sbuf_free_content(cb);
865 0 : continue;
866 : case P_ERROR:
867 : goto error;
868 : }
869 : }
870 : error:
871 : return -1;
872 : p1b_done:
873 74 : sbuf_free(p1b);
874 74 : return 0;
875 : }
876 :
877 10 : int backup_phase2_server_protocol1(struct async *as, struct sdirs *sdirs,
878 : const char *incexc, int resume, struct conf **cconfs)
879 : {
880 10 : int ret=0;
881 10 : man_off_t *p1pos=NULL;
882 10 : struct manio *p1manio=NULL;
883 10 : struct dpth *dpth=NULL;
884 10 : char *deltmppath=NULL;
885 10 : char *last_requested=NULL;
886 10 : struct manio *chmanio=NULL; // changed data
887 10 : struct manio *ucmanio=NULL; // unchanged data
888 10 : struct manio *cmanio=NULL; // previous (current) manifest.
889 10 : struct sbuf *cb=NULL; // file list in current manifest
890 10 : struct sbuf *p1b=NULL; // file list from client
891 10 : struct sbuf *rb=NULL; // receiving file from client
892 10 : struct asfd *asfd=NULL;
893 10 : int breaking=0;
894 10 : int breakcount=0;
895 10 : struct cntr *cntr=NULL;
896 :
897 10 : if(!as)
898 : {
899 1 : logp("async not provided to %s()\n", __func__);
900 1 : goto error;
901 : }
902 9 : if(!sdirs)
903 : {
904 2 : logp("sdirs not provided to %s()\n", __func__);
905 2 : goto error;
906 : }
907 7 : if(!cconfs)
908 : {
909 1 : logp("cconfs not provided to %s()\n", __func__);
910 1 : goto error;
911 : }
912 6 : asfd=as->asfd;
913 6 : if(!asfd)
914 : {
915 1 : logp("asfd not provided to %s()\n", __func__);
916 1 : goto error;
917 : }
918 5 : cntr=get_cntr(cconfs);
919 :
920 5 : if(get_int(cconfs[OPT_BREAKPOINT])>=2000
921 0 : && get_int(cconfs[OPT_BREAKPOINT])<3000)
922 : {
923 0 : breaking=get_int(cconfs[OPT_BREAKPOINT]);
924 0 : breakcount=breaking-2000;
925 : }
926 :
927 5 : logp("Begin phase2 (receive file data)\n");
928 :
929 5 : if(!(dpth=dpth_alloc())
930 5 : || dpth_protocol1_init(dpth, sdirs->currentdata,
931 : get_int(cconfs[OPT_MAX_STORAGE_SUBDIRS])))
932 : goto error;
933 :
934 5 : if(open_previous_manifest(&cmanio, sdirs, incexc, cconfs))
935 : goto error;
936 :
937 5 : if(get_int(cconfs[OPT_DIRECTORY_TREE]))
938 : {
939 : // Need to make sure we do not try to create a path that is
940 : // too long.
941 5 : if(build_path_w(sdirs->treepath)) goto error;
942 5 : mkdir(sdirs->treepath, 0777);
943 5 : treepathlen=strlen(sdirs->treepath);
944 5 : if(init_fs_max(sdirs->treepath))
945 : goto error;
946 : }
947 :
948 5 : if(resume)
949 : {
950 0 : if(!(p1pos=do_resume(sdirs, dpth, cconfs)))
951 : goto error;
952 0 : if(cntr_send_sdirs(asfd, sdirs, cconfs))
953 : goto error;
954 : }
955 :
956 5 : if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", PROTO_1))
957 5 : || (resume && manio_seek(p1manio, p1pos)))
958 : goto error;
959 5 : if(!(cb=sbuf_alloc(PROTO_1))
960 5 : || !(p1b=sbuf_alloc(PROTO_1))
961 5 : || !(rb=sbuf_alloc(PROTO_1)))
962 : goto error;
963 :
964 : // Unchanged and changed should now be truncated correctly, we just
965 : // have to open them for appending.
966 : // Data is not getting written to a compressed file.
967 : // This is important for recovery if the power goes.
968 5 : if(!(ucmanio=manio_open_phase2(sdirs->unchanged, "ab", PROTO_1))
969 5 : || !(chmanio=manio_open_phase2(sdirs->changed, "ab", PROTO_1)))
970 : goto error;
971 :
972 : while(1)
973 : {
974 921 : if(breaking && breakcount--==0)
975 0 : return breakpoint(breaking, __func__);
976 :
977 921 : if(write_status(CNTR_STATUS_BACKUP,
978 921 : rb->path.buf?rb->path.buf:"", cntr))
979 : goto error;
980 1842 : if(last_requested
981 921 : || !p1manio
982 16 : || asfd->writebuflen)
983 : {
984 905 : iobuf_free_content(asfd->rbuf);
985 905 : if(asfd->as->read_write(asfd->as))
986 : {
987 0 : logp("error in %s\n", __func__);
988 0 : goto error;
989 : }
990 :
991 905 : if(asfd->rbuf->buf)
992 85 : switch(do_stuff_to_receive(asfd, sdirs,
993 : cconfs, rb, chmanio, dpth, &last_requested))
994 : {
995 : case STR_OK:
996 : break;
997 : case STR_FINISHED:
998 : goto end;
999 : case STR_ERROR:
1000 : goto error;
1001 : }
1002 : }
1003 :
1004 916 : if(p1b) switch(do_stuff_to_send(asfd, p1b, &last_requested))
1005 : {
1006 : case STS_OK:
1007 61 : sbuf_free(&p1b);
1008 61 : break;
1009 : case STS_BLOCKED:
1010 2 : continue;
1011 : case STS_ERROR:
1012 : goto error;
1013 : }
1014 :
1015 914 : if(p1manio
1016 135 : && process_next_file_from_manios(asfd, sdirs,
1017 : &p1manio, &cmanio, ucmanio, &p1b, cb, cconfs))
1018 : goto error;
1019 : }
1020 :
1021 : error:
1022 : ret=-1;
1023 : end:
1024 10 : if(manio_close(&chmanio))
1025 : {
1026 0 : logp("error closing %s in %s\n", sdirs->changed, __func__);
1027 0 : ret=-1;
1028 : }
1029 10 : if(manio_close(&ucmanio))
1030 : {
1031 0 : logp("error closing %s in %s\n", sdirs->unchanged, __func__);
1032 0 : ret=-1;
1033 : }
1034 10 : free_w(&deltmppath);
1035 10 : free_w(&last_requested);
1036 10 : sbuf_free(&cb);
1037 10 : sbuf_free(&p1b);
1038 10 : sbuf_free(&rb);
1039 10 : manio_close(&p1manio);
1040 10 : manio_close(&cmanio);
1041 10 : dpth_free(&dpth);
1042 10 : man_off_t_free(&p1pos);
1043 10 : if(!ret && sdirs)
1044 5 : unlink(sdirs->phase1data);
1045 :
1046 10 : logp("End phase2 (receive file data)\n");
1047 :
1048 10 : return ret;
1049 : }
|