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 "../cstat.h"
11 : #include "../fsops.h"
12 : #include "../handy.h"
13 : #include "../iobuf.h"
14 : #include "../log.h"
15 : #include "../sbuf.h"
16 : #include "backup_phase2.h"
17 : #include "blocklen.h"
18 : #include "child.h"
19 : #include "compress.h"
20 : #include "dpth.h"
21 : #include "link.h"
22 : #include "manios.h"
23 : #include "resume.h"
24 :
25 : static size_t treepathlen=0;
26 :
27 0 : static int path_length_warn(struct iobuf *path, struct conf **cconfs)
28 : {
29 0 : if(get_int(cconfs[OPT_PATH_LENGTH_WARN]))
30 0 : logw(NULL, get_cntr(cconfs), "Path too long for tree - will save in data structure instead: %s\n", path->buf);
31 0 : return 1;
32 : }
33 :
34 4 : static int path_too_long(struct iobuf *path, struct conf **cconfs)
35 : {
36 4 : const char *cp;
37 4 : const char *cp1;
38 4 : size_t len;
39 :
40 4 : if(treepathlen+path->len+1>fs_full_path_max)
41 : {
42 : // FIX THIS:
43 : // Cannot warn down the asfd to the client, because it can
44 : // arrive after the client has disconnected, which causes
45 : // an error on the server side.
46 : // Would need to change the way that "backupphase2end" works
47 : // to be able to fix it.
48 0 : return path_length_warn(path, cconfs);
49 : }
50 : // We have to check every part in the path to ensure it less then fs_name_max
51 : // minimum windows case is c:/a, nix case is /
52 : // usual: c:/users, /home
53 4 : cp = strchr(path->buf, '/');
54 4 : if( !cp ) // very strange
55 0 : return strlen(path->buf) > fs_name_max ? path_length_warn(path, cconfs):0;
56 18 : while(cp && *cp)
57 : {
58 14 : cp++;
59 14 : cp1 = strchr(cp, '/');
60 14 : len = cp1? cp1-cp : strlen(cp);
61 14 : if( len > fs_name_max )
62 0 : return path_length_warn(path, cconfs);
63 : cp = cp1;
64 : }
65 : return 0;
66 : }
67 :
68 4 : static int treedata(struct sbuf *sb, struct conf **cconfs)
69 : {
70 : // Windows is sending directory data as if it is file data - this
71 : // cannot be saved in a tree structure.
72 4 : if(S_ISDIR(sb->statp.st_mode)) return 0;
73 :
74 4 : if(sb->path.cmd!=CMD_FILE
75 4 : && sb->path.cmd!=CMD_ENC_FILE
76 0 : && sb->path.cmd!=CMD_EFS_FILE)
77 : return 0;
78 :
79 4 : return !path_too_long(&sb->path, cconfs);
80 : }
81 :
82 4 : static char *set_new_datapth(struct sdirs *sdirs, struct conf **cconfs,
83 : struct sbuf *sb, struct dpth *dpth, int *istreedata)
84 : {
85 4 : char *tmp=NULL;
86 4 : char *rpath=NULL;
87 4 : if(get_int(cconfs[OPT_DIRECTORY_TREE]))
88 4 : *istreedata=treedata(sb, cconfs);
89 :
90 4 : if(*istreedata)
91 : {
92 : // We want to place this file in a directory structure like
93 : // the directory structure on the original client.
94 4 : if(!(tmp=prepend_s(TREE_DIR, sb->path.buf)))
95 : {
96 0 : log_out_of_memory(__func__);
97 0 : return NULL;
98 : }
99 : }
100 : else
101 : {
102 0 : if(!(tmp=strdup_w(dpth_mk(dpth, sb->compression,
103 : sb->path.cmd), __func__))) return NULL;
104 : }
105 4 : iobuf_from_str(&sb->datapth, CMD_DATAPTH, tmp);
106 4 : if(build_path(sdirs->datadirtmp,
107 4 : sb->datapth.buf, &rpath, sdirs->datadirtmp))
108 : {
109 0 : logp("build path failed");
110 0 : return NULL;
111 : }
112 4 : return rpath;
113 : }
114 :
115 4 : static int start_to_receive_new_file(struct asfd *asfd,
116 : struct sdirs *sdirs, struct conf **cconfs,
117 : struct sbuf *sb, struct dpth *dpth)
118 : {
119 4 : int ret=-1;
120 4 : char *rpath=NULL;
121 4 : int istreedata=0;
122 :
123 : //logp("start to receive: %s\n", iobuf_to_printable(&sb->path));
124 :
125 4 : if(!(rpath=set_new_datapth(sdirs, cconfs, sb, dpth, &istreedata)))
126 0 : goto end;
127 :
128 4 : if(!(sb->fzp=fzp_open(rpath, "wb")))
129 : {
130 0 : log_and_send(asfd, "make file failed");
131 0 : goto end;
132 : }
133 4 : if(!istreedata) dpth_incr(dpth);
134 : ret=0;
135 4 : end:
136 4 : free_w(&rpath);
137 4 : return ret;
138 : }
139 :
140 : enum processed_e
141 : {
142 : P_ERROR=-1,
143 : P_DONE_NEW=0,
144 : P_DONE_CHANGED=1,
145 : P_DONE_UNCHANGED=2,
146 : P_DONE_DELETED=3,
147 : P_NEW=4,
148 : P_CHANGED=5
149 : };
150 :
151 : #include <librsync.h>
152 :
153 2 : static enum processed_e process_changed_file(struct asfd *asfd,
154 : struct conf **cconfs,
155 : struct sbuf *cb, struct sbuf *p1b,
156 : const char *adir)
157 : {
158 2 : int ret=P_ERROR;
159 2 : size_t blocklen=0;
160 2 : char *curpath=NULL;
161 : //logp("need to process changed file: %s (%s)\n",
162 : // cb->path, cb->datapth);
163 :
164 : // Move datapth onto p1b.
165 2 : iobuf_move(&p1b->datapth, &cb->datapth);
166 :
167 2 : if(!(curpath=prepend_s(adir, p1b->datapth.buf)))
168 : {
169 0 : log_out_of_memory(__func__);
170 0 : goto end;
171 : }
172 2 : if(dpth_is_compressed(cb->compression, curpath))
173 0 : p1b->sigfzp=fzp_gzopen(curpath, "rb");
174 : else
175 2 : p1b->sigfzp=fzp_open(curpath, "rb");
176 2 : if(!p1b->sigfzp)
177 : {
178 0 : logp("could not open %s: %s\n", curpath, strerror(errno));
179 0 : goto end;
180 : }
181 :
182 2 : blocklen=get_librsync_block_len(cb->endfile.buf);
183 2 : if(!(p1b->sigjob=
184 2 : rs_sig_begin(blocklen, PROTO1_RS_STRONG_LEN
185 : #ifndef RS_DEFAULT_STRONG_LEN
186 : , rshash_to_magic_number(get_e_rshash(cconfs[OPT_RSHASH]))
187 : #endif
188 : )
189 : ))
190 : {
191 0 : logp("could not start signature job.\n");
192 0 : goto end;
193 : }
194 : //logp("sig begin: %s\n", iobuf_to_printable(p1b->datapth));
195 2 : if(!(p1b->infb=rs_filebuf_new(NULL,
196 : p1b->sigfzp,
197 : NULL, blocklen, -1)))
198 : {
199 0 : logp("could not rs_filebuf_new for infb.\n");
200 0 : goto end;
201 : }
202 2 : if(!(p1b->outfb=rs_filebuf_new(NULL, NULL,
203 : asfd, ASYNC_BUF_LEN, -1)))
204 : {
205 0 : logp("could not rs_filebuf_new for in_outfb.\n");
206 0 : goto end;
207 : }
208 :
209 : // Flag the things that need to be sent (to the client)
210 2 : p1b->flags |= SBUF_SEND_DATAPTH;
211 2 : p1b->flags |= SBUF_SEND_STAT;
212 2 : p1b->flags |= SBUF_SEND_PATH;
213 :
214 : //logp("sending sig for %s\n", p1b->path);
215 : //logp("(%s)\n", p1b->datapth);
216 :
217 2 : ret=P_CHANGED;
218 2 : end:
219 2 : free_w(&curpath);
220 2 : return ret;
221 : }
222 :
223 68 : static enum processed_e new_non_file(struct sbuf *p1b,
224 : struct manios *manios, struct conf **cconfs)
225 : {
226 : // Is something that does not need more data backed up.
227 : // Like a directory or a link or something like that.
228 : // Goes into the unchanged file, so that it does not end up out of
229 : // order with normal files, which has to wait around for their data
230 : // to turn up.
231 68 : if(manio_write_sbuf(manios->unchanged, p1b))
232 : return P_ERROR;
233 : // No actual data saved - goes in counters_n.
234 68 : if(manio_write_cntr(manios->counters_n, p1b, CNTR_MANIO_NEW))
235 : return P_ERROR;
236 68 : cntr_add(get_cntr(cconfs), p1b->path.cmd, 0);
237 68 : return P_DONE_NEW;
238 : }
239 :
240 0 : static enum processed_e changed_non_file(struct sbuf *p1b,
241 : struct manios *manios,
242 : enum cmd cmd, struct conf **cconfs)
243 : {
244 : // As new_non_file.
245 0 : if(manio_write_sbuf(manios->unchanged, p1b))
246 : return P_ERROR;
247 : // No actual data saved - goes in counters_n.
248 0 : if(manio_write_cntr(manios->counters_n, p1b, CNTR_MANIO_CHANGED))
249 : return P_ERROR;
250 0 : cntr_add_changed(get_cntr(cconfs), cmd);
251 0 : return P_DONE_CHANGED;
252 : }
253 :
254 122 : static enum processed_e process_new(struct conf **cconfs,
255 : struct sbuf *p1b, struct manios *manios)
256 : {
257 122 : if(sbuf_is_filedata(p1b)
258 68 : || sbuf_is_vssdata(p1b))
259 : {
260 : //logp("need to process new file: %s\n", p1b->path);
261 : // Flag the things that need to be sent (to the client)
262 54 : p1b->flags |= SBUF_SEND_STAT;
263 54 : p1b->flags |= SBUF_SEND_PATH;
264 54 : return P_NEW;
265 : }
266 68 : return new_non_file(p1b, manios, cconfs);
267 : }
268 :
269 6 : static enum processed_e process_unchanged_file(
270 : struct sbuf *p1b, struct sbuf *cb,
271 : struct manios *manios,
272 : struct conf **cconfs)
273 : {
274 : // Need to re-encode the p1b attribs to include compression and
275 : // other bits and pieces that are recorded on cb.
276 6 : iobuf_move(&p1b->datapth, &cb->datapth);
277 6 : iobuf_move(&p1b->endfile, &cb->endfile);
278 6 : p1b->salt=cb->salt;
279 6 : p1b->compression=cb->compression;
280 6 : p1b->encryption=cb->encryption;
281 : // Need to free attr so that it is reallocated, because it may get
282 : // longer than what the client told us in phase1.
283 6 : iobuf_free_content(&p1b->attr);
284 6 : if(attribs_encode(p1b))
285 : return P_ERROR;
286 6 : if(manio_write_sbuf(manios->unchanged, p1b))
287 : return P_ERROR;
288 : // No actual data saved - goes in counters_n.
289 6 : if(manio_write_cntr(manios->counters_n, p1b, CNTR_MANIO_SAME))
290 : return P_ERROR;
291 6 : cntr_add_same(get_cntr(cconfs), p1b->path.cmd);
292 6 : if(p1b->endfile.buf) cntr_add_bytes(get_cntr(cconfs),
293 0 : strtoull(p1b->endfile.buf, NULL, 10));
294 : return P_DONE_UNCHANGED;
295 : }
296 :
297 5 : static int open_previous_manifest(struct manio **manio, struct sdirs *sdirs)
298 : {
299 5 : struct stat statp;
300 5 : if(!lstat(sdirs->cmanifest, &statp)
301 1 : && !(*manio=manio_open(sdirs->cmanifest, "rb")))
302 : {
303 0 : logp("could not open old manifest %s\n", sdirs->cmanifest);
304 0 : return -1;
305 : }
306 : return 0;
307 : }
308 :
309 0 : static int get_hardlink_master_from_hmanio(
310 : struct manio **hmanio,
311 : struct sdirs *sdirs,
312 : struct sbuf *cb,
313 : struct sbuf *hb
314 : ) {
315 0 : int passes=0;
316 0 : while(1)
317 : {
318 0 : sbuf_free_content(hb);
319 0 : switch(manio_read(*hmanio, hb))
320 : {
321 : case 0: // Keep going.
322 0 : break;
323 0 : case 1: // Finished OK.
324 0 : manio_close(hmanio);
325 : // Might have already been part way down the
326 : // manifest when we started. If we get to the
327 : // end, go back to the beginning once.
328 0 : if(!passes)
329 : {
330 0 : if(open_previous_manifest(hmanio,
331 : sdirs)) return -1;
332 0 : passes++;
333 0 : continue;
334 : }
335 : return 0;
336 : default: // Error;
337 : return -1;
338 : }
339 0 : if(hb->path.cmd!=CMD_FILE
340 0 : && hb->path.cmd!=CMD_ENC_FILE)
341 0 : continue;
342 0 : if(!strcmp(hb->path.buf, cb->link.buf)
343 0 : && hb->datapth.buf)
344 : return 1; // Found it.
345 : }
346 : return -1;
347 : }
348 :
349 0 : static int relink_deleted_hardlink_master(
350 : struct dpth *dpth,
351 : struct manio **hmanio,
352 : struct sdirs *sdirs,
353 : struct sbuf *p1b,
354 : struct sbuf *cb,
355 : struct conf **cconfs
356 : ) {
357 0 : int ret=-1;
358 0 : char *newdatapth_full=NULL;
359 0 : char *olddatapth_full=NULL;
360 0 : char *newdatapth=NULL;
361 0 : char *relinkpath_full=NULL;
362 0 : struct stat statp;
363 0 : struct sbuf *hb=NULL;
364 0 : int istreedata=0;
365 :
366 0 : if(!(hb=sbuf_alloc()))
367 0 : goto end;
368 :
369 0 : switch(get_hardlink_master_from_hmanio(hmanio, sdirs, cb, hb))
370 : {
371 : case 0: // Did not find it.
372 : return 0;
373 : case 1: // Found it.
374 0 : break;
375 0 : default: // Error.
376 0 : goto end;
377 : }
378 :
379 : // Protect against the old file being encrypted, and the new file not
380 : // being encrypted - and vice versa.
381 0 : if(p1b->path.cmd!=hb->path.cmd)
382 : return 0;
383 :
384 0 : if(!(newdatapth_full=set_new_datapth(sdirs,
385 : cconfs, p1b, dpth, &istreedata)))
386 0 : goto end;
387 0 : if(!istreedata) dpth_incr(dpth);
388 0 : if(!(relinkpath_full=prepend_s(sdirs->relink,
389 0 : p1b->datapth.buf)))
390 0 : goto end;
391 0 : if(!(newdatapth=strdup_w(p1b->datapth.buf, __func__)))
392 0 : goto end;
393 : /*
394 : printf("newdatapth_full: %s\n", newdatapth_full);
395 : printf("relinkpath_full: %s\n", relinkpath_full);
396 : printf("newdatapth: %s\n", newdatapth);
397 : printf("hbdatapth: %s\n", iobuf_to_printable(&hb->datapth));
398 : printf("sdirs->currentdata: %s\n", sdirs->currentdata);
399 : */
400 :
401 0 : if(!(olddatapth_full=prepend_s(sdirs->currentdata,
402 0 : hb->datapth.buf)))
403 0 : goto end;
404 0 : if(lstat(olddatapth_full, &statp) || !S_ISREG(statp.st_mode))
405 : {
406 0 : logw(NULL, get_cntr(cconfs),
407 : "Did not find path for relink: %s\n", olddatapth_full);
408 0 : ret=0;
409 0 : goto end;
410 : }
411 0 : if(build_path_w(relinkpath_full))
412 0 : goto end;
413 0 : if(do_link(olddatapth_full, relinkpath_full,
414 : &statp, cconfs, /*overwrite*/0))
415 0 : goto end;
416 :
417 0 : iobuf_free_content(&cb->datapth);
418 :
419 0 : iobuf_from_str(&hb->datapth, CMD_DATAPTH,
420 : p1b->datapth.buf);
421 0 : p1b->datapth.buf=NULL;
422 0 : iobuf_from_str(&cb->datapth, CMD_DATAPTH, newdatapth);
423 0 : newdatapth=NULL;
424 0 : iobuf_move(&cb->endfile, &hb->endfile);
425 :
426 0 : ret=1;
427 0 : end:
428 0 : free_w(&newdatapth_full);
429 0 : free_w(&olddatapth_full);
430 0 : free_w(&newdatapth);
431 0 : free_w(&relinkpath_full);
432 0 : sbuf_free(&hb);
433 0 : return ret;
434 : }
435 :
436 4 : static int librsync_enabled(struct sbuf *p1b,
437 : struct sbuf *cb,
438 : struct conf **cconfs)
439 : {
440 4 : off_t max_size;
441 4 : if(!get_int(cconfs[OPT_LIBRSYNC]))
442 : return 0;
443 4 : max_size=(off_t)get_uint64_t(cconfs[OPT_LIBRSYNC_MAX_SIZE]);
444 4 : if(!max_size)
445 : return 1;
446 0 : return max_size >= cb->statp.st_size && max_size >= p1b->statp.st_size;
447 : }
448 :
449 10 : static enum processed_e maybe_do_delta_stuff(struct asfd *asfd,
450 : struct dpth *dpth,
451 : struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
452 : struct manios *manios, struct manio **hmanio,
453 : struct conf **cconfs)
454 : {
455 10 : int oldcompressed=0;
456 10 : int compression=p1b->compression;
457 :
458 : // If the file type changed, I think it is time to back it up again
459 : // (for example, EFS changing to normal file, or back again).
460 10 : if(cb->path.cmd!=p1b->path.cmd)
461 : {
462 0 : if(hmanio && *hmanio
463 0 : && cb->path.cmd==CMD_HARD_LINK
464 0 : && (p1b->path.cmd==CMD_FILE
465 0 : || p1b->path.cmd==CMD_ENC_FILE))
466 : {
467 0 : struct stat *p1statp=&p1b->statp;
468 0 : struct stat *cstatp=&cb->statp;
469 : // A hardlink changed into a file. It is possible that
470 : // The file that the hardlink was pointing to got
471 : // deleted. Maybe we can reuse the previous file.
472 0 : if(p1statp->st_dev==cstatp->st_dev
473 0 : && p1statp->st_ino==cstatp->st_ino
474 0 : && p1statp->st_mtime==cstatp->st_mtime)
475 : {
476 0 : switch(relink_deleted_hardlink_master(
477 : dpth, hmanio, sdirs,
478 : p1b, cb, cconfs))
479 : {
480 : case 0:
481 : break;
482 0 : case 1:
483 0 : return process_unchanged_file(
484 : p1b, cb, manios,
485 : cconfs);
486 : default:
487 : return P_ERROR;
488 : }
489 : }
490 : }
491 0 : return process_new(cconfs, p1b, manios);
492 : }
493 :
494 : // file is encrypted with an outdated scheme
495 : // and should be backed up again to update encryption
496 10 : if(get_int(cconfs[OPT_FORCE_UPDATE_ENCRYPTION])
497 0 : && cb->path.cmd!=CMD_EFS_FILE
498 0 : && sbuf_is_encrypted(cb)
499 0 : && cb->encryption<ENCRYPTION_LATEST)
500 : {
501 0 : return process_new(cconfs, p1b, manios);
502 : }
503 :
504 : // mtime is the actual file data.
505 : // ctime is the attributes or meta data.
506 10 : if(cb->statp.st_mtime==p1b->statp.st_mtime
507 6 : && cb->statp.st_ctime==p1b->statp.st_ctime)
508 : {
509 : // got an unchanged file
510 : //logp("got unchanged file: %s %c\n",
511 : // iobuf_to_printable(&cb->path), p1b->path.cmd);
512 6 : return process_unchanged_file(p1b, cb, manios, cconfs);
513 : }
514 :
515 4 : if(cb->statp.st_mtime==p1b->statp.st_mtime
516 0 : && cb->statp.st_ctime!=p1b->statp.st_ctime)
517 : {
518 : // File data stayed the same, but attributes or meta data
519 : // changed. We already have the attributes, but may need to get
520 : // extra meta data.
521 : // FIX THIS horrible mess.
522 0 : if(cb->path.cmd==CMD_ENC_METADATA
523 0 : || p1b->path.cmd==CMD_ENC_METADATA
524 0 : || cb->path.cmd==CMD_EFS_FILE
525 0 : || p1b->path.cmd==CMD_EFS_FILE
526 : // FIX THIS: make unencrypted metadata use the librsync
527 0 : || cb->path.cmd==CMD_METADATA
528 0 : || p1b->path.cmd==CMD_METADATA
529 0 : || sbuf_is_vssdata(cb)
530 0 : || sbuf_is_vssdata(p1b))
531 0 : return process_new(cconfs, p1b, manios);
532 : // On Windows, we have to back up the whole file if ctime
533 : // changed, otherwise things like permission changes do not get
534 : // noticed. So, in that case, fall through to the changed stuff
535 : // below.
536 : // Non-Windows clients finish here.
537 0 : else if(!get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
538 0 : return process_unchanged_file(p1b, cb, manios, cconfs);
539 : }
540 :
541 4 : if(!sbuf_is_filedata(p1b)
542 0 : && !sbuf_is_vssdata(p1b))
543 0 : return changed_non_file(p1b, manios, p1b->path.cmd, cconfs);
544 :
545 : // Got a changed file.
546 : //logp("got changed file: %s\n", iobuf_to_printable(&p1b->path));
547 :
548 : // If either old or new is encrypted, or librsync is off, we need to
549 : // get a new file.
550 : // FIX THIS horrible mess.
551 4 : if(!librsync_enabled(p1b, cb, cconfs)
552 : // FIX THIS: make unencrypted metadata use the librsync
553 4 : || cb->path.cmd==CMD_METADATA
554 4 : || p1b->path.cmd==CMD_METADATA
555 4 : || sbuf_is_encrypted(cb)
556 2 : || sbuf_is_encrypted(p1b)
557 2 : || sbuf_is_vssdata(cb)
558 2 : || sbuf_is_vssdata(p1b))
559 2 : return process_new(cconfs, p1b, manios);
560 :
561 : // Get new files if they have switched between compression on or off.
562 2 : if(cb->datapth.buf
563 2 : && dpth_is_compressed(cb->compression,
564 : cb->datapth.buf))
565 2 : oldcompressed=1;
566 2 : if( ( oldcompressed && !compression)
567 2 : || (!oldcompressed && compression))
568 0 : return process_new(cconfs, p1b, manios);
569 :
570 : // Otherwise, do the delta stuff (if possible).
571 2 : return process_changed_file(asfd, cconfs, cb, p1b,
572 2 : sdirs->currentdata);
573 : }
574 :
575 2 : static enum processed_e deleted_file(struct sbuf *cb,
576 : struct manios *manios, struct conf **cconfs)
577 : {
578 : // Only goes in the non-data counter list so that ordering in the
579 : // changed lists are not messed up.
580 : // No actual data saved - goes in counters_n.
581 2 : if(manio_write_cntr(manios->counters_n, cb, CNTR_MANIO_DELETED))
582 : return P_ERROR;
583 2 : cntr_add_deleted(get_cntr(cconfs), cb->path.cmd);
584 2 : return P_DONE_DELETED;
585 : }
586 :
587 : // return 1 to say that a file was processed
588 12 : static enum processed_e maybe_process_file(struct asfd *asfd,
589 : struct dpth *dpth,
590 : struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
591 : struct manios *manios, struct manio **hmanio,
592 : struct conf **cconfs)
593 : {
594 12 : int pcmp;
595 12 : if(p1b)
596 : {
597 11 : if(!(pcmp=sbuf_pathcmp(cb, p1b)))
598 10 : return maybe_do_delta_stuff(asfd, dpth,sdirs, cb, p1b,
599 : manios, hmanio, cconfs);
600 1 : else if(pcmp>0)
601 : {
602 : //logp("ahead: %s\n", iobuf_to_printable(&p1b->path));
603 : // ahead - need to get the whole file
604 0 : return process_new(cconfs, p1b, manios);
605 : }
606 : }
607 : //logp("behind: %s\n", iobuf_to_printable(&p1b->path));
608 : // Behind - need to read more from the old manifest.
609 : // Count a deleted file - it was in the old manifest
610 : // but not the new.
611 2 : return deleted_file(cb, manios, cconfs);
612 : }
613 :
614 : enum sts_e
615 : {
616 : STS_ERROR=-1,
617 : STS_OK=0,
618 : STS_BLOCKED=1
619 : };
620 :
621 : // Return 1 if there is still stuff needing to be sent.
622 : // FIX THIS: lots of repeated code.
623 63 : static enum sts_e do_stuff_to_send(struct asfd *asfd,
624 : struct sbuf *p1b, char **last_requested)
625 : {
626 63 : static struct iobuf wbuf;
627 63 : if(p1b->flags & SBUF_SEND_DATAPTH)
628 : {
629 2 : iobuf_copy(&wbuf, &p1b->datapth);
630 2 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
631 : {
632 2 : case APPEND_OK: break;
633 : case APPEND_BLOCKED: return STS_BLOCKED;
634 : default: return STS_ERROR;
635 : }
636 2 : p1b->flags &= ~SBUF_SEND_DATAPTH;
637 : }
638 63 : if(p1b->flags & SBUF_SEND_STAT)
639 : {
640 56 : iobuf_copy(&wbuf, &p1b->attr);
641 56 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
642 : {
643 56 : case APPEND_OK: break;
644 : case APPEND_BLOCKED: return STS_BLOCKED;
645 : default: return STS_ERROR;
646 : }
647 56 : p1b->flags &= ~SBUF_SEND_STAT;
648 : }
649 63 : if(p1b->flags & SBUF_SEND_PATH)
650 : {
651 56 : iobuf_copy(&wbuf, &p1b->path);
652 56 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
653 : {
654 56 : case APPEND_OK: break;
655 : case APPEND_BLOCKED: return STS_BLOCKED;
656 : default: return STS_ERROR;
657 : }
658 56 : p1b->flags &= ~SBUF_SEND_PATH;
659 56 : free_w(last_requested);
660 56 : if(!(*last_requested=strdup_w(p1b->path.buf, __func__)))
661 : return STS_ERROR;
662 : }
663 63 : if(p1b->sigjob && !(p1b->flags & SBUF_SEND_ENDOFSIG))
664 : {
665 4 : rs_result sigresult;
666 :
667 4 : switch((sigresult=rs_async(p1b->sigjob,
668 : &(p1b->rsbuf),
669 : p1b->infb, p1b->outfb)))
670 : {
671 2 : case RS_DONE:
672 2 : p1b->flags |= SBUF_SEND_ENDOFSIG;
673 2 : break;
674 : case RS_BLOCKED:
675 : case RS_RUNNING:
676 : // keep going round the loop.
677 : return STS_BLOCKED;
678 0 : default:
679 0 : logp("error in rs_async: %d %s\n",
680 : sigresult, rs_strerror(sigresult));
681 0 : return STS_ERROR;
682 : }
683 : }
684 61 : if(p1b->flags & SBUF_SEND_ENDOFSIG)
685 : {
686 2 : iobuf_from_str(&wbuf, CMD_END_FILE, (char *)"endfile");
687 2 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
688 : {
689 2 : case APPEND_OK: break;
690 : case APPEND_BLOCKED: return STS_BLOCKED;
691 : default: return STS_ERROR;
692 : }
693 2 : p1b->flags &= ~SBUF_SEND_ENDOFSIG;
694 : }
695 : return STS_OK;
696 : }
697 :
698 4 : static int start_to_receive_delta(struct sdirs *sdirs, struct sbuf *rb)
699 : {
700 4 : if(rb->compression)
701 : {
702 0 : if(!(rb->fzp=fzp_gzopen(sdirs->deltmppath,
703 0 : comp_level(rb->compression))))
704 : return -1;
705 : }
706 : else
707 : {
708 4 : if(!(rb->fzp=fzp_open(sdirs->deltmppath, "wb")))
709 : return -1;
710 : }
711 4 : rb->flags |= SBUF_RECV_DELTA;
712 :
713 4 : return 0;
714 : }
715 :
716 4 : static int finish_delta(struct sdirs *sdirs, struct sbuf *rb)
717 : {
718 4 : int ret=0;
719 4 : char *deltmp=NULL;
720 4 : char *delpath=NULL;
721 4 : if(!(deltmp=prepend_s("deltas.forward", rb->datapth.buf))
722 4 : || !(delpath=prepend_s(sdirs->working, deltmp))
723 4 : || mkpath(&delpath, sdirs->working)
724 : // Rename race condition is of no consequence here, as delpath will
725 : // just get recreated.
726 4 : || do_rename(sdirs->deltmppath, delpath))
727 : ret=-1;
728 4 : free_w(&delpath);
729 4 : free_w(&deltmp);
730 4 : return ret;
731 : }
732 :
733 8 : static int deal_with_receive_end_file(struct asfd *asfd, struct sdirs *sdirs,
734 : struct sbuf *rb, struct manios *manios,
735 : struct conf **cconfs, char **last_requested)
736 : {
737 8 : int ret=-1;
738 8 : static char *cp=NULL;
739 8 : static struct iobuf *rbuf;
740 8 : struct cntr *cntr=get_cntr(cconfs);
741 8 : rbuf=asfd->rbuf;
742 : // Finished the file.
743 : // Write it to the phase2 file, and free the buffers.
744 :
745 8 : if(fzp_close(&rb->fzp))
746 : {
747 0 : logp("error closing delta for %s in receive\n",
748 : iobuf_to_printable(&rb->path));
749 0 : goto end;
750 : }
751 8 : iobuf_move(&rb->endfile, rbuf);
752 8 : if(rb->flags & SBUF_RECV_DELTA && finish_delta(sdirs, rb))
753 0 : goto end;
754 :
755 8 : if(manio_write_sbuf(manios->changed, rb))
756 0 : goto end;
757 :
758 8 : if(rb->flags & SBUF_RECV_DELTA)
759 : {
760 : // Data has been saved - goes in counters_d, or the counters
761 : // will be out of sequence.
762 4 : if(manio_write_cntr(manios->counters_d, rb, CNTR_MANIO_CHANGED))
763 : return P_ERROR;
764 4 : cntr_add_changed(cntr, rb->path.cmd);
765 : }
766 : else
767 : {
768 : // Data has been saved - goes in counters_d, or the counters
769 : // will be out of sequence.
770 4 : if(manio_write_cntr(manios->counters_d, rb, CNTR_MANIO_NEW))
771 : return P_ERROR;
772 4 : cntr_add(cntr, rb->path.cmd, 0);
773 : }
774 :
775 8 : if(*last_requested && !strcmp(rb->path.buf, *last_requested))
776 2 : free_w(last_requested);
777 :
778 8 : cp=strchr(rb->endfile.buf, ':');
779 8 : if(rb->endfile.buf)
780 8 : cntr_add_bytes(cntr, strtoull(rb->endfile.buf, NULL, 10));
781 8 : if(cp)
782 : {
783 : // checksum stuff goes here
784 8 : }
785 :
786 8 : ret=0;
787 8 : end:
788 8 : sbuf_free_content(rb);
789 8 : return ret;
790 : }
791 :
792 8 : static int deal_with_receive_append(struct asfd *asfd, struct sbuf *rb)
793 : {
794 8 : int app=0;
795 8 : static struct iobuf *rbuf;
796 8 : rbuf=asfd->rbuf;
797 : //logp("rbuf->len: %d\n", rbuf->len);
798 :
799 8 : if(rb->fzp)
800 8 : app=fzp_write(rb->fzp, rbuf->buf, rbuf->len);
801 :
802 8 : if(app>0) return 0;
803 0 : logp("error when appending: %d\n", app);
804 0 : asfd->write_str(asfd, CMD_ERROR, "write failed");
805 0 : return -1;
806 : }
807 :
808 8 : static int deal_with_filedata(struct asfd *asfd,
809 : struct sdirs *sdirs, struct sbuf *rb,
810 : struct iobuf *rbuf, struct dpth *dpth, struct conf **cconfs)
811 : {
812 8 : iobuf_move(&rb->path, rbuf);
813 :
814 8 : if(rb->datapth.buf)
815 : {
816 : // Receiving a delta.
817 4 : if(start_to_receive_delta(sdirs, rb))
818 : {
819 0 : logp("error in start_to_receive_delta\n");
820 0 : return -1;
821 : }
822 : return 0;
823 : }
824 :
825 : // Receiving a whole new file.
826 4 : if(start_to_receive_new_file(asfd, sdirs, cconfs, rb, dpth))
827 : {
828 0 : logp("error in start_to_receive_new_file\n");
829 0 : return -1;
830 : }
831 : return 0;
832 : }
833 :
834 : enum str_e
835 : {
836 : STR_ERROR=-1,
837 : STR_OK=0,
838 : STR_FINISHED=1
839 : };
840 :
841 : // returns 1 for finished ok.
842 85 : static enum str_e do_stuff_to_receive(struct asfd *asfd,
843 : struct sdirs *sdirs, struct conf **cconfs,
844 : struct sbuf *rb, struct manios *manios,
845 : struct dpth *dpth, char **last_requested)
846 : {
847 85 : struct iobuf *rbuf=asfd->rbuf;
848 :
849 85 : if(rbuf->cmd==CMD_MESSAGE
850 85 : || rbuf->cmd==CMD_WARNING)
851 : {
852 0 : struct cntr *cntr=NULL;
853 0 : if(cconfs) cntr=get_cntr(cconfs);
854 0 : log_recvd(rbuf, cntr, 0);
855 0 : return STR_OK;
856 : }
857 :
858 85 : if(rb->fzp)
859 : {
860 : // Currently writing a file (or meta data)
861 16 : switch(rbuf->cmd)
862 : {
863 8 : case CMD_APPEND:
864 8 : if(deal_with_receive_append(asfd, rb))
865 0 : goto error;
866 : return STR_OK;
867 8 : case CMD_END_FILE:
868 8 : if(deal_with_receive_end_file(asfd, sdirs, rb,
869 : manios, cconfs, last_requested))
870 0 : goto error;
871 : return STR_OK;
872 0 : case CMD_INTERRUPT:
873 0 : if(*last_requested
874 0 : && !strcmp(rbuf->buf, *last_requested))
875 0 : free_w(last_requested);
876 0 : fzp_close(&(rb->fzp));
877 0 : sbuf_free_content(rb);
878 0 : return STR_OK;
879 0 : default:
880 0 : iobuf_log_unexpected(rbuf, __func__);
881 0 : goto error;
882 : }
883 : }
884 :
885 : // Otherwise, expecting to be told of a file to save.
886 69 : switch(rbuf->cmd)
887 : {
888 4 : case CMD_DATAPTH:
889 4 : if(iobuf_relative_path_attack(rbuf))
890 0 : goto error;
891 4 : iobuf_move(&rb->datapth, rbuf);
892 4 : return STR_OK;
893 8 : case CMD_ATTRIBS:
894 8 : iobuf_move(&rb->attr, rbuf);
895 8 : attribs_decode(rb);
896 8 : return STR_OK;
897 5 : case CMD_GEN:
898 5 : if(!strcmp(rbuf->buf, "okbackupphase2end"))
899 5 : goto end_phase2;
900 0 : iobuf_log_unexpected(rbuf, __func__);
901 0 : goto error;
902 44 : case CMD_INTERRUPT:
903 : // Interrupt - forget about the last requested
904 : // file if it matches. Otherwise, we can get
905 : // stuck on the select in the async stuff,
906 : // waiting for something that will never arrive.
907 44 : if(*last_requested
908 44 : && !strcmp(rbuf->buf, *last_requested))
909 1 : free_w(last_requested);
910 : return STR_OK;
911 : default:
912 8 : break;
913 : }
914 8 : if(iobuf_is_filedata(rbuf)
915 0 : || iobuf_is_vssdata(rbuf))
916 : {
917 8 : if(deal_with_filedata(asfd, sdirs, rb, rbuf, dpth, cconfs))
918 0 : goto error;
919 : return STR_OK;
920 : }
921 0 : iobuf_log_unexpected(rbuf, __func__);
922 :
923 : error:
924 : return STR_ERROR;
925 5 : end_phase2:
926 5 : return STR_FINISHED;
927 : }
928 :
929 5 : static int vss_opts_changed(struct sdirs *sdirs, struct conf **cconfs,
930 : const char *incexc)
931 : {
932 5 : int ret=-1;
933 5 : struct conf **oldconfs;
934 5 : struct conf **newconfs;
935 5 : if(!(oldconfs=confs_alloc())
936 5 : || !(newconfs=confs_alloc()))
937 0 : goto end;
938 5 : confs_init(oldconfs);
939 5 : confs_init(newconfs);
940 :
941 : // Figure out the old config, which is in the incexc file left
942 : // in the current backup directory on the server.
943 5 : if(is_reg_lstat(sdirs->cincexc)<=0
944 1 : || conf_parse_incexcs_path(oldconfs, sdirs->cincexc))
945 : {
946 : // Assume that the file did not exist, and therefore
947 : // the old split_vss setting is 0.
948 4 : set_int(oldconfs[OPT_SPLIT_VSS], 0);
949 4 : set_int(oldconfs[OPT_STRIP_VSS], 0);
950 : }
951 :
952 : // Figure out the new config, which is either in the incexc file from
953 : // the client, or in the cconf on the server.
954 5 : if(incexc)
955 : {
956 0 : if(conf_parse_incexcs_buf(newconfs, incexc))
957 : {
958 : // Should probably not got here.
959 0 : set_int(newconfs[OPT_SPLIT_VSS], 0);
960 0 : set_int(newconfs[OPT_STRIP_VSS], 0);
961 : }
962 : }
963 : else
964 : {
965 5 : set_int(newconfs[OPT_SPLIT_VSS],
966 5 : get_int(cconfs[OPT_SPLIT_VSS]));
967 5 : set_int(newconfs[OPT_STRIP_VSS],
968 5 : get_int(cconfs[OPT_STRIP_VSS]));
969 : }
970 :
971 5 : if(get_int(newconfs[OPT_SPLIT_VSS])!=get_int(oldconfs[OPT_SPLIT_VSS]))
972 : {
973 0 : logp("split_vss=%d (changed since last backup)\n",
974 0 : get_int(newconfs[OPT_SPLIT_VSS]));
975 0 : ret=1; goto end;
976 : }
977 5 : if(get_int(newconfs[OPT_STRIP_VSS])!=get_int(oldconfs[OPT_STRIP_VSS]))
978 : {
979 0 : logp("strip_vss=%d (changed since last backup)\n",
980 0 : get_int(newconfs[OPT_STRIP_VSS]));
981 0 : ret=1; goto end;
982 : }
983 : ret=0;
984 : end:
985 0 : if(ret==1) logp("All files will be treated as new\n");
986 5 : confs_free(&oldconfs);
987 5 : confs_free(&newconfs);
988 5 : return ret;
989 : }
990 :
991 135 : static int process_next_file_from_manios(struct asfd *asfd,
992 : struct dpth *dpth,
993 : struct sdirs *sdirs,
994 : struct manios *manios,
995 : struct manio **hmanio,
996 : struct sbuf **p1b,
997 : struct sbuf *cb,
998 : struct conf **cconfs)
999 : {
1000 135 : if(!(*p1b=sbuf_alloc()))
1001 0 : goto error;
1002 135 : switch(manio_read(manios->phase1, *p1b))
1003 : {
1004 : case 0:
1005 : break;
1006 5 : case 1:
1007 5 : manio_close(&manios->phase1);
1008 5 : if(asfd->write_str(asfd, CMD_GEN, "backupphase2end"))
1009 0 : goto error;
1010 5 : sbuf_free(p1b);
1011 5 : break;
1012 0 : case -1:
1013 0 : goto error;
1014 : }
1015 :
1016 135 : if(!manios->current)
1017 : {
1018 120 : if(!*p1b) return 0;
1019 : // No old manifest, need to ask for a new file.
1020 117 : switch(process_new(cconfs, *p1b, manios))
1021 : {
1022 : case P_NEW:
1023 : return 0;
1024 65 : case P_DONE_NEW:
1025 65 : goto p1b_done;
1026 0 : default:
1027 0 : goto error;
1028 : }
1029 : }
1030 :
1031 : // Have an old manifest, look for it there.
1032 :
1033 : // Might already have it, or be ahead in the old
1034 : // manifest.
1035 15 : if(cb->path.buf)
1036 : {
1037 2 : switch(maybe_process_file(asfd, dpth,
1038 : sdirs, cb, *p1b, manios, hmanio, cconfs))
1039 : {
1040 : case P_NEW:
1041 : return 0;
1042 0 : case P_CHANGED:
1043 : // Free cb content for things like encrypted
1044 : // files, which we only pretend are new.
1045 0 : sbuf_free_content(cb);
1046 0 : return 0;
1047 0 : case P_DONE_NEW:
1048 0 : goto p1b_done;
1049 0 : case P_DONE_CHANGED:
1050 : case P_DONE_UNCHANGED:
1051 0 : sbuf_free_content(cb);
1052 0 : goto p1b_done;
1053 2 : case P_DONE_DELETED:
1054 2 : sbuf_free_content(cb);
1055 2 : break;
1056 0 : case P_ERROR:
1057 0 : goto error;
1058 : }
1059 : }
1060 :
1061 15 : while(1)
1062 : {
1063 15 : sbuf_free_content(cb);
1064 15 : switch(manio_read(manios->current, cb))
1065 : {
1066 : case 0: break;
1067 5 : case 1: manio_close(&manios->current);
1068 5 : if(*p1b) switch(process_new(cconfs,
1069 : *p1b, manios))
1070 : {
1071 : case P_NEW:
1072 : return 0;
1073 3 : case P_DONE_NEW:
1074 3 : goto p1b_done;
1075 0 : default:
1076 0 : goto error;
1077 : }
1078 : return 0;
1079 0 : case -1: goto error;
1080 : }
1081 10 : switch(maybe_process_file(asfd, dpth, sdirs,
1082 : cb, *p1b, manios, hmanio, cconfs))
1083 : {
1084 : case P_NEW:
1085 : return 0;
1086 2 : case P_CHANGED:
1087 : // Free cb content for things like encrypted
1088 : // files, which we only pretend are new.
1089 2 : sbuf_free_content(cb);
1090 2 : return 0;
1091 0 : case P_DONE_NEW:
1092 0 : goto p1b_done;
1093 6 : case P_DONE_CHANGED:
1094 : case P_DONE_UNCHANGED:
1095 6 : sbuf_free_content(cb);
1096 6 : goto p1b_done;
1097 0 : case P_DONE_DELETED:
1098 0 : sbuf_free_content(cb);
1099 0 : continue;
1100 0 : case P_ERROR:
1101 0 : goto error;
1102 : }
1103 : }
1104 : error:
1105 : return -1;
1106 74 : p1b_done:
1107 74 : sbuf_free(p1b);
1108 74 : return 0;
1109 : }
1110 :
1111 10 : static int maybe_move_seed_dir(struct sdirs *sdirs, struct conf **cconfs)
1112 : {
1113 10 : int ret=-1;
1114 10 : char *fullsrc=NULL;
1115 10 : char *fulldst=NULL;
1116 10 : char *seed_src=NULL;
1117 10 : char *seed_dst=NULL;
1118 10 : if(!sdirs || !cconfs)
1119 : return 0;
1120 6 : seed_src=get_string(cconfs[OPT_SEED_SRC]);
1121 6 : seed_dst=get_string(cconfs[OPT_SEED_DST]);
1122 6 : if(!seed_src || !seed_dst)
1123 : return 0;
1124 :
1125 : // Need to move the data from the client to the correct
1126 : // location.
1127 0 : if(!(fullsrc=prepend_s(sdirs->datadirtmp, TREE_DIR))
1128 0 : || !(fulldst=prepend_s(sdirs->datadirtmp, TREE_DIR))
1129 0 : || astrcat(&fullsrc, seed_src, __func__))
1130 0 : goto end;
1131 0 : if(*seed_dst!='/'
1132 0 : && astrcat(&fulldst, "/", __func__))
1133 0 : goto end;
1134 0 : if(astrcat(&fulldst, seed_dst, __func__))
1135 0 : goto end;
1136 0 : if(build_path_w(fulldst))
1137 0 : goto end;
1138 0 : if(do_rename(fullsrc, fulldst))
1139 0 : goto end;
1140 :
1141 : ret=0;
1142 0 : end:
1143 0 : free_w(&fullsrc);
1144 0 : free_w(&fulldst);
1145 0 : return ret;
1146 : }
1147 :
1148 10 : int backup_phase2_server_all(struct async *as, struct sdirs *sdirs,
1149 : const char *incexc, int resume, struct conf **cconfs)
1150 : {
1151 10 : int ret=0;
1152 10 : man_off_t *pos_phase1=NULL;
1153 10 : man_off_t *pos_current=NULL;
1154 10 : struct dpth *dpth=NULL;
1155 10 : char *last_requested=NULL;
1156 10 : struct manio *hmanio=NULL; // to look up deleted hardlinks
1157 10 : struct manios *manios=NULL;
1158 10 : struct sbuf *cb=NULL; // file list in current manifest
1159 10 : struct sbuf *p1b=NULL; // file list from client
1160 10 : struct sbuf *rb=NULL; // receiving file from client
1161 10 : struct asfd *asfd=NULL;
1162 10 : int breaking=0;
1163 10 : int breakcount=0;
1164 10 : struct cntr *cntr=NULL;
1165 10 : struct cntr_ent *warn_ent=NULL;
1166 10 : int fail_on_warning=0;
1167 :
1168 10 : if(!as)
1169 : {
1170 1 : logp("async not provided to %s()\n", __func__);
1171 1 : goto error;
1172 : }
1173 9 : if(!sdirs)
1174 : {
1175 2 : logp("sdirs not provided to %s()\n", __func__);
1176 2 : goto error;
1177 : }
1178 7 : if(!cconfs)
1179 : {
1180 1 : logp("cconfs not provided to %s()\n", __func__);
1181 1 : goto error;
1182 : }
1183 6 : asfd=as->asfd;
1184 6 : if(!asfd)
1185 : {
1186 1 : logp("asfd not provided to %s()\n", __func__);
1187 1 : goto error;
1188 : }
1189 5 : cntr=get_cntr(cconfs);
1190 5 : fail_on_warning=get_int(cconfs[OPT_FAIL_ON_WARNING]);
1191 5 : if(cntr)
1192 0 : warn_ent=cntr->ent[CMD_WARNING];
1193 :
1194 5 : if(get_int(cconfs[OPT_BREAKPOINT])>=2000
1195 0 : && get_int(cconfs[OPT_BREAKPOINT])<3000)
1196 : {
1197 0 : breaking=get_int(cconfs[OPT_BREAKPOINT]);
1198 0 : breakcount=breaking-2000;
1199 : }
1200 :
1201 5 : logp("Begin phase2 (receive file data)\n");
1202 :
1203 5 : if(!(dpth=dpth_alloc())
1204 5 : || dpth_init(dpth, sdirs->currentdata,
1205 : get_int(cconfs[OPT_MAX_STORAGE_SUBDIRS])))
1206 0 : goto error;
1207 :
1208 : // If the first file that others hardlink to has been deleted, we will
1209 : // need to look through the previous manifest to find the information
1210 : // for that original file, in order to not have to copy all the data
1211 : // across again.
1212 5 : if(open_previous_manifest(&hmanio, sdirs))
1213 0 : goto error;
1214 :
1215 5 : if(get_int(cconfs[OPT_DIRECTORY_TREE]))
1216 : {
1217 : // Need to make sure we do not try to create a path that is
1218 : // too long.
1219 5 : if(build_path_w(sdirs->treepath)) goto error;
1220 5 : mkdir(sdirs->treepath, 0777);
1221 5 : treepathlen=strlen(sdirs->treepath);
1222 5 : if(init_fs_max(sdirs->treepath))
1223 0 : goto error;
1224 : }
1225 :
1226 5 : if(resume)
1227 : {
1228 0 : if(do_resume(&pos_phase1, &pos_current,
1229 : sdirs, dpth, cconfs))
1230 0 : goto error;
1231 0 : if(cntr_send_sdirs(asfd, sdirs, cconfs, CNTR_STATUS_BACKUP))
1232 0 : goto error;
1233 : }
1234 :
1235 5 : if(!(manios=manios_open_phase2(sdirs, pos_phase1, pos_current)))
1236 0 : goto error;
1237 : // If the split_vss setting changed between the previous backup and the
1238 : // new backup, close the previous manifest. This will have the effect
1239 : // of making the client back up everything fresh. Need to do this,
1240 : // otherwise toggling split_vss on and off will result in backups that
1241 : // do not work.
1242 5 : if(vss_opts_changed(sdirs, cconfs, incexc))
1243 0 : manio_close(&manios->current);
1244 :
1245 5 : if(!(cb=sbuf_alloc())
1246 5 : || !(p1b=sbuf_alloc())
1247 5 : || !(rb=sbuf_alloc()))
1248 0 : goto error;
1249 :
1250 921 : while(1)
1251 : {
1252 921 : if(check_fail_on_warning(fail_on_warning, warn_ent))
1253 0 : goto error;
1254 :
1255 921 : if(breaking && breakcount--==0)
1256 0 : return breakpoint(breaking, __func__);
1257 :
1258 921 : if(timed_operation(CNTR_STATUS_BACKUP,
1259 921 : rb->path.buf?rb->path.buf:"", asfd, sdirs, cconfs))
1260 0 : goto error;
1261 921 : if(last_requested
1262 220 : || !manios->phase1
1263 16 : || asfd->writebuflen)
1264 : {
1265 905 : iobuf_free_content(asfd->rbuf);
1266 905 : if(asfd->as->read_write(asfd->as))
1267 : {
1268 0 : logp("error in %s\n", __func__);
1269 0 : goto error;
1270 : }
1271 :
1272 905 : if(asfd->rbuf->buf)
1273 85 : switch(do_stuff_to_receive(asfd, sdirs,
1274 : cconfs, rb, manios,
1275 : dpth, &last_requested))
1276 : {
1277 : case STR_OK:
1278 : break;
1279 5 : case STR_FINISHED:
1280 5 : if(check_fail_on_warning(
1281 : fail_on_warning, warn_ent))
1282 0 : goto error;
1283 5 : goto end;
1284 0 : case STR_ERROR:
1285 0 : goto error;
1286 : }
1287 : }
1288 :
1289 916 : if(p1b) switch(do_stuff_to_send(asfd, p1b, &last_requested))
1290 : {
1291 61 : case STS_OK:
1292 61 : sbuf_free(&p1b);
1293 61 : break;
1294 2 : case STS_BLOCKED:
1295 2 : continue;
1296 0 : case STS_ERROR:
1297 0 : goto error;
1298 : }
1299 :
1300 914 : if(manios->phase1
1301 135 : && process_next_file_from_manios(asfd, dpth, sdirs,
1302 : manios, &hmanio, &p1b, cb, cconfs))
1303 0 : goto error;
1304 : }
1305 :
1306 5 : error:
1307 5 : ret=-1;
1308 5 : if(p1b)
1309 0 : logp(" last tried file: %s\n",
1310 : iobuf_to_printable(&p1b->path));
1311 5 : end:
1312 10 : if(manios_close(&manios))
1313 : {
1314 0 : logp("error closing manios in %s\n", __func__);
1315 0 : ret=-1;
1316 : }
1317 10 : if(maybe_move_seed_dir(sdirs, cconfs))
1318 : {
1319 0 : logp("error moving seed dir\n");
1320 0 : ret=-1;
1321 : }
1322 10 : free_w(&last_requested);
1323 10 : sbuf_free(&cb);
1324 10 : sbuf_free(&p1b);
1325 10 : sbuf_free(&rb);
1326 10 : manio_close(&hmanio);
1327 10 : dpth_free(&dpth);
1328 10 : man_off_t_free(&pos_phase1);
1329 10 : man_off_t_free(&pos_current);
1330 10 : if(!ret && sdirs)
1331 5 : unlink(sdirs->phase1data);
1332 :
1333 10 : logp("End phase2 (receive file data)\n");
1334 :
1335 10 : return ret;
1336 : }
|