Line data Source code
1 : #include "../burp.h"
2 : #include "../alloc.h"
3 : #include "../asfd.h"
4 : #include "../async.h"
5 : #include "../cmd.h"
6 : #include "../cntr.h"
7 : #include "../conf.h"
8 : #include "../cstat.h"
9 : #include "../fsops.h"
10 : #include "../fzp.h"
11 : #include "../handy.h"
12 : #include "../log.h"
13 : #include "../prepend.h"
14 : #include "../sbuf.h"
15 : #include "../strlist.h"
16 : #include "blocklen.h"
17 : #include "deleteme.h"
18 : #include "fdirs.h"
19 : #include "child.h"
20 : #include "compress.h"
21 : #include "link.h"
22 : #include "timestamp.h"
23 : #include "zlibio.h"
24 : #include "backup_phase4.h"
25 :
26 : #include <librsync.h>
27 :
28 : // Also used by restore.c.
29 : // FIX THIS: This stuff is very similar to make_rev_delta, can maybe share
30 : // some code.
31 0 : int do_patch(const char *dst, const char *del,
32 : const char *upd, bool gzupd, int compression)
33 : {
34 0 : struct fzp *dstp=NULL;
35 0 : struct fzp *delfzp=NULL;
36 0 : struct fzp *upfzp=NULL;
37 0 : rs_result result=RS_IO_ERROR;
38 :
39 0 : if(!(dstp=fzp_open(dst, "rb"))) goto end;
40 :
41 0 : if(!(delfzp=fzp_gzopen(del, "rb")))
42 : goto end;
43 :
44 0 : if(gzupd)
45 0 : upfzp=fzp_gzopen(upd, comp_level(compression));
46 : else
47 0 : upfzp=fzp_open(upd, "wb");
48 :
49 0 : if(!upfzp) goto end;
50 :
51 0 : if((result=rs_patch_gzfile(dstp, delfzp, upfzp))!=RS_DONE)
52 : {
53 0 : logp("rs_patch_gzfile returned %d %s\n",
54 : result, rs_strerror(result));
55 : }
56 : end:
57 0 : fzp_close(&dstp);
58 0 : fzp_close(&delfzp);
59 0 : if(fzp_close(&upfzp))
60 : {
61 0 : logp("error closing %s in %s\n", upd, __func__);
62 0 : result=RS_IO_ERROR;
63 : }
64 0 : return result;
65 : }
66 :
67 0 : static int make_rev_sig(const char *dst, const char *sig, const char *endfile,
68 : int compression, struct conf **confs)
69 : {
70 0 : int ret=-1;
71 : rs_result result;
72 0 : struct fzp *dstfzp=NULL;
73 0 : struct fzp *sigp=NULL;
74 : //logp("make rev sig: %s %s\n", dst, sig);
75 :
76 0 : if(dpth_is_compressed(compression, dst))
77 0 : dstfzp=fzp_gzopen(dst, "rb");
78 : else
79 0 : dstfzp=fzp_open(dst, "rb");
80 :
81 0 : if(!dstfzp
82 0 : || !(sigp=fzp_open(sig, "wb")))
83 : goto end;
84 :
85 0 : if((result=rs_sig_gzfile(dstfzp, sigp,
86 : get_librsync_block_len(endfile),
87 0 : PROTO1_RS_STRONG_LEN, confs)!=RS_DONE))
88 : {
89 0 : logp("rs_sig_gzfile returned %d %s\n",
90 : result, rs_strerror(result));
91 0 : goto end;
92 : }
93 : ret=0;
94 : end:
95 : //logp("end of make rev sig\n");
96 0 : fzp_close(&dstfzp);
97 0 : if(fzp_close(&sigp))
98 : {
99 0 : logp("error closing %s in %s\n", sig, __func__);
100 0 : return -1;
101 : }
102 : return ret;
103 : }
104 :
105 0 : static int make_rev_delta(const char *src, const char *sig, const char *del,
106 : int compression, struct conf **cconfs)
107 : {
108 0 : int ret=-1;
109 : rs_result result;
110 0 : struct fzp *srcfzp=NULL;
111 0 : struct fzp *delfzp=NULL;
112 0 : struct fzp *sigp=NULL;
113 0 : rs_signature_t *sumset=NULL;
114 :
115 : //logp("make rev delta: %s %s %s\n", src, sig, del);
116 0 : if(!(sigp=fzp_open(sig, "rb"))) goto end;
117 :
118 0 : if((result=rs_loadsig_fzp(sigp, &sumset))!=RS_DONE)
119 : {
120 0 : logp("rs_loadsig_fzp returned %d %s\n",
121 : result, rs_strerror(result));
122 0 : goto end;
123 : }
124 0 : if((result=rs_build_hash_table(sumset))!=RS_DONE)
125 : {
126 0 : logp("rs_build_hash_table returned %d %s\n",
127 : result, rs_strerror(result));
128 0 : goto end;
129 : }
130 :
131 : //logp("make rev deltb: %s %s %s\n", src, sig, del);
132 :
133 0 : if(dpth_is_compressed(compression, src))
134 0 : srcfzp=fzp_gzopen(src, "rb");
135 : else
136 0 : srcfzp=fzp_open(src, "rb");
137 :
138 0 : if(!srcfzp) goto end;
139 :
140 0 : if(get_int(cconfs[OPT_COMPRESSION]))
141 0 : delfzp=fzp_gzopen(del,
142 0 : comp_level(get_int(cconfs[OPT_COMPRESSION])));
143 : else
144 0 : delfzp=fzp_open(del, "wb");
145 0 : if(!delfzp) goto end;
146 :
147 0 : if((result=rs_delta_gzfile(sumset, srcfzp, delfzp))!=RS_DONE)
148 : {
149 0 : logp("rs_delta_gzfile returned %d %s\n",
150 : result, rs_strerror(result));
151 0 : goto end;
152 : }
153 : ret=0;
154 : end:
155 0 : if(sumset) rs_free_sumset(sumset);
156 0 : fzp_close(&srcfzp);
157 0 : fzp_close(&sigp);
158 0 : if(fzp_close(&delfzp))
159 : {
160 0 : logp("error closing delfzp %s in %s\n", del, __func__);
161 0 : ret=-1;
162 : }
163 0 : return ret;
164 : }
165 :
166 0 : static int gen_rev_delta(const char *sigpath, const char *deltadir,
167 : const char *oldpath, const char *finpath, const char *path,
168 : struct sbuf *sb, struct conf **cconfs)
169 : {
170 0 : int ret=-1;
171 0 : char *delpath=NULL;
172 0 : if(!(delpath=prepend_s(deltadir, path)))
173 : {
174 0 : log_out_of_memory(__func__);
175 : goto end;
176 : }
177 : //logp("Generating reverse delta...\n");
178 : /*
179 : logp("delpath: %s\n", delpath);
180 : logp("finpath: %s\n", finpath);
181 : logp("sigpath: %s\n", sigpath);
182 : logp("oldpath: %s\n", oldpath);
183 : */
184 0 : if(mkpath(&delpath, deltadir))
185 : {
186 0 : logp("could not mkpaths for: %s\n", delpath);
187 : goto end;
188 : }
189 0 : else if(make_rev_sig(finpath, sigpath,
190 0 : sb->endfile.buf, sb->compression, cconfs))
191 : {
192 0 : logp("could not make signature from: %s\n", finpath);
193 : goto end;
194 : }
195 0 : else if(make_rev_delta(oldpath, sigpath,
196 : delpath, sb->compression, cconfs))
197 : {
198 0 : logp("could not make delta from: %s\n", oldpath);
199 : goto end;
200 : }
201 0 : else unlink(sigpath);
202 :
203 0 : ret=0;
204 : end:
205 0 : free_w(&delpath);
206 0 : return ret;
207 : }
208 :
209 0 : static int inflate_oldfile(const char *opath, const char *infpath,
210 : struct stat *statp, struct cntr *cntr)
211 : {
212 0 : int ret=0;
213 :
214 0 : if(!statp->st_size)
215 : {
216 0 : struct fzp *dest=NULL;
217 : // Empty file - cannot inflate.
218 : // just close the destination and we have duplicated a
219 : // zero length file.
220 0 : if(!(dest=fzp_open(infpath, "wb"))) goto end;
221 0 : logp("asked to inflate zero length file: %s\n", opath);
222 0 : if(fzp_close(&dest))
223 0 : logp("error closing %s in %s\n", infpath, __func__);
224 : }
225 0 : else if(zlib_inflate(NULL, opath, infpath, cntr))
226 : {
227 0 : logp("zlib_inflate returned error\n");
228 0 : ret=-1;
229 : }
230 : end:
231 0 : return ret;
232 : }
233 :
234 0 : static int inflate_or_link_oldfile(const char *oldpath, const char *infpath,
235 : int compression, struct conf **cconfs)
236 : {
237 : struct stat statp;
238 :
239 0 : if(lstat(oldpath, &statp))
240 : {
241 0 : logp("could not lstat %s\n", oldpath);
242 0 : return -1;
243 : }
244 :
245 0 : if(dpth_is_compressed(compression, oldpath))
246 0 : return inflate_oldfile(oldpath, infpath, &statp,
247 : get_cntr(cconfs));
248 :
249 : // If it was not a compressed file, just hard link it.
250 : // It is possible that infpath already exists, if the server
251 : // was interrupted on a previous run just after this point.
252 0 : return do_link(oldpath, infpath, &statp, cconfs,
253 : 1 /* allow overwrite of infpath */);
254 : }
255 :
256 0 : static int forward_patch_and_reverse_diff(
257 : struct fdirs *fdirs,
258 : struct fzp **delfp,
259 : const char *deltabdir,
260 : const char *deltafdir,
261 : const char *deltafpath,
262 : const char *sigpath,
263 : const char *oldpath,
264 : const char *newpath,
265 : const char *datapth,
266 : const char *finpath,
267 : int hardlinked_current,
268 : struct sbuf *sb,
269 : struct conf **cconfs
270 : )
271 : {
272 : int lrs;
273 0 : int ret=-1;
274 0 : char *infpath=NULL;
275 :
276 : // Got a forward patch to do.
277 : // First, need to gunzip the old file, otherwise the librsync patch
278 : // will take forever, because it will be doing seeks all over the
279 : // place, and gzseeks are slow.
280 0 : if(!(infpath=prepend_s(deltafdir, "inflate")))
281 : {
282 0 : log_out_of_memory(__func__);
283 : goto end;
284 : }
285 :
286 : //logp("Fixing up: %s\n", datapth);
287 0 : if(inflate_or_link_oldfile(oldpath, infpath, sb->compression, cconfs))
288 : {
289 0 : logp("error when inflating old file: %s\n", oldpath);
290 : goto end;
291 : }
292 :
293 0 : if((lrs=do_patch(infpath, deltafpath, newpath,
294 : sb->compression, sb->compression /* from manifest */)))
295 : {
296 0 : logp("WARNING: librsync error when patching %s: %d\n",
297 : oldpath, lrs);
298 0 : cntr_add(get_cntr(cconfs), CMD_WARNING, 1);
299 : // Try to carry on with the rest of the backup regardless.
300 : // Remove anything that got written.
301 0 : unlink(newpath);
302 :
303 : // First, note that we want to remove this entry from
304 : // the manifest.
305 0 : if(!*delfp
306 0 : && !(*delfp=fzp_open(fdirs->deletionsfile, "ab")))
307 : {
308 : // Could not mark this file as deleted. Fatal.
309 : goto end;
310 : }
311 0 : if(sbuf_to_manifest(sb, *delfp))
312 : goto end;
313 0 : if(fzp_flush(*delfp))
314 : {
315 0 : logp("error fflushing deletions file in %s: %s\n",
316 0 : __func__, strerror(errno));
317 : goto end;
318 : }
319 : ret=0;
320 : goto end;
321 : }
322 :
323 : // Need to generate a reverse diff, unless we are keeping a hardlinked
324 : // archive.
325 0 : if(!hardlinked_current)
326 : {
327 0 : if(gen_rev_delta(sigpath, deltabdir,
328 : oldpath, newpath, datapth, sb, cconfs))
329 : goto end;
330 : }
331 :
332 : // Power interruptions should be recoverable. If it happens before this
333 : // point, the data jiggle for this file has to be done again.
334 : // Once finpath is in place, no more jiggle is required.
335 :
336 : // Use the fresh new file.
337 : // Rename race condition is of no consequence, because finpath will
338 : // just get recreated automatically.
339 0 : if(do_rename(newpath, finpath))
340 : goto end;
341 :
342 : // Remove the forward delta, as it is no longer needed. There is a
343 : // reverse diff and the finished finished file is in place.
344 : //logp("Deleting delta.forward...\n");
345 0 : unlink(deltafpath);
346 :
347 : // Remove the old file. If a power cut happens just before this, the
348 : // old file will hang around forever.
349 : // FIX THIS: maybe put in something to detect this.
350 : // ie, both a reverse delta and the old file exist.
351 0 : if(!hardlinked_current)
352 : {
353 : //logp("Deleting oldpath...\n");
354 0 : unlink(oldpath);
355 : }
356 :
357 : ret=0;
358 : end:
359 0 : if(infpath)
360 : {
361 0 : unlink(infpath);
362 0 : free_w(&infpath);
363 : }
364 0 : return ret;
365 : }
366 :
367 91 : static int jiggle(struct sdirs *sdirs, struct fdirs *fdirs, struct sbuf *sb,
368 : int hardlinked_current, const char *deltabdir, const char *deltafdir,
369 : const char *sigpath, struct fzp **delfp, struct conf **cconfs)
370 : {
371 91 : int ret=-1;
372 : struct stat statp;
373 91 : char *oldpath=NULL;
374 91 : char *newpath=NULL;
375 91 : char *finpath=NULL;
376 91 : char *deltafpath=NULL;
377 91 : char *relinkpath=NULL;
378 91 : const char *datapth=sb->datapth.buf;
379 :
380 : // If the previous backup was a hardlinked_archive, there will not be
381 : // a currentdup directory - just directly use the file in the previous
382 : // backup.
383 91 : if(!(oldpath=prepend_s(hardlinked_current?
384 : sdirs->currentdata:fdirs->currentdupdata, datapth))
385 91 : || !(newpath=prepend_s(fdirs->datadirtmp, datapth))
386 91 : || !(finpath=prepend_s(fdirs->datadir, datapth))
387 91 : || !(deltafpath=prepend_s(deltafdir, datapth)))
388 : goto end;
389 :
390 182 : if(!lstat(finpath, &statp) && S_ISREG(statp.st_mode))
391 : {
392 : // Looks like an interrupted jiggle did this file already.
393 : static int donemsg=0;
394 6 : if(!unlink(deltafpath))
395 0 : logp("deleted unneeded forward delta: %s\n",
396 : deltafpath);
397 6 : if(!donemsg)
398 : {
399 1 : logp("skipping already present file: %s\n", finpath);
400 1 : logp("to save log space, skips of other already present files will not be logged\n");
401 1 : donemsg++;
402 : }
403 : ret=0;
404 : goto end;
405 : }
406 :
407 85 : if(mkpath(&finpath, fdirs->datadir))
408 : {
409 0 : logp("could not create path for: %s\n", finpath);
410 : goto end;
411 : }
412 :
413 170 : if(!lstat(deltafpath, &statp) && S_ISREG(statp.st_mode))
414 : {
415 0 : if(mkpath(&newpath, fdirs->datadirtmp))
416 : {
417 0 : logp("could not create path for: %s\n", newpath);
418 : goto end;
419 : }
420 0 : ret=forward_patch_and_reverse_diff(
421 : fdirs,
422 : delfp,
423 : deltabdir,
424 : deltafdir,
425 : deltafpath,
426 : sigpath,
427 : oldpath,
428 : newpath,
429 : datapth,
430 : finpath,
431 : hardlinked_current,
432 : sb,
433 : cconfs
434 : );
435 : goto end;
436 : }
437 :
438 170 : if(!lstat(newpath, &statp) && S_ISREG(statp.st_mode))
439 : {
440 : // Use the fresh new file.
441 : // This needs to happen after checking
442 : // for the forward delta, because the
443 : // patching stuff writes to newpath.
444 :
445 : // Rename race condition is of no consequence, because finpath
446 : // will just get recreated automatically.
447 :
448 : //logp("Using newly received file\n");
449 85 : ret=do_rename(newpath, finpath);
450 : goto end;
451 : }
452 :
453 0 : if(!lstat(oldpath, &statp) && S_ISREG(statp.st_mode))
454 : {
455 : // Use the old unchanged file.
456 : // Hard link it first.
457 : //logp("Hard linking to old file: %s\n", datapth);
458 0 : if(do_link(oldpath, finpath, &statp, cconfs,
459 : 0 /* do not overwrite finpath (should never need to) */))
460 : goto end;
461 : else
462 : {
463 : // If we are not keeping a hardlinked
464 : // archive, delete the old link.
465 0 : if(!hardlinked_current)
466 : {
467 : //logp("Unlinking old file: %s\n", oldpath);
468 0 : unlink(oldpath);
469 : }
470 : }
471 : ret=0;
472 : goto end;
473 : }
474 :
475 0 : if(!(relinkpath=prepend_s(sdirs->relink, datapth)))
476 : goto end;
477 0 : if(!lstat(relinkpath, &statp) && S_ISREG(statp.st_mode))
478 : {
479 : // Use the relinked path - something that used to be a hardlink
480 : // but is now the original file because the file that we
481 : // originally hardlinked to has been deleted.
482 0 : ret=do_rename(relinkpath, finpath);
483 : goto end;
484 : }
485 :
486 0 : logp("could not find: %s\n", oldpath);
487 : end:
488 91 : free_w(&oldpath);
489 91 : free_w(&newpath);
490 91 : free_w(&finpath);
491 91 : free_w(&deltafpath);
492 91 : free_w(&relinkpath);
493 91 : return ret;
494 : }
495 :
496 : /* If OPT_HARDLINKED_ARCHIVE set, hardlink everything.
497 : If unset and there is more than one 'keep' value, periodically hardlink,
498 : based on the first 'keep' value. This is so that we have more choice
499 : of backups to delete than just the oldest.
500 : */
501 2 : static int need_hardlinked_archive(struct conf **cconfs, uint64_t bno)
502 : {
503 2 : int kp=0;
504 2 : int ret=0;
505 2 : struct strlist *keep=get_strlist(cconfs[OPT_KEEP]);
506 2 : if(get_int(cconfs[OPT_HARDLINKED_ARCHIVE]))
507 : {
508 0 : logp("New backup is a hardlinked_archive\n");
509 0 : return 1;
510 : }
511 2 : if(!keep || !keep->next)
512 : {
513 2 : logp("New backup is not a hardlinked_archive\n");
514 2 : return 0;
515 : }
516 :
517 : // If they have specified more than one 'keep' value, need to
518 : // periodically hardlink, based on the first 'keep' value.
519 0 : kp=keep->flag;
520 :
521 0 : logp("First keep value: %d, backup: %" PRIu64 " (%" PRIu64 "-1=%" PRIu64 ")\n",
522 : kp, bno, bno, bno-1);
523 :
524 0 : ret=(bno-1)%kp;
525 0 : logp("New backup is %sa hardlinked_archive (%" PRIu64 "%%%d=%d)\n",
526 : ret?"not ":"", bno-1, kp, ret);
527 :
528 0 : return !ret;
529 : }
530 :
531 2 : static int maybe_delete_files_from_manifest(const char *manifesttmp,
532 : struct fdirs *fdirs, struct conf **cconfs)
533 : {
534 2 : int ars=0;
535 2 : int ret=-1;
536 2 : int pcmp=0;
537 2 : struct fzp *dfp=NULL;
538 2 : struct fzp *nmzp=NULL;
539 2 : struct fzp *omzp=NULL;
540 2 : struct sbuf *db=NULL;
541 2 : struct sbuf *mb=NULL;
542 : struct stat statp;
543 :
544 4 : if(lstat(fdirs->deletionsfile, &statp)) // No deletions, no problem.
545 : return 0;
546 0 : logp("Performing deletions on manifest\n");
547 :
548 0 : if(!(manifesttmp=get_tmp_filename(fdirs->manifest)))
549 : goto end;
550 :
551 0 : if(!(dfp=fzp_open(fdirs->deletionsfile, "rb"))
552 0 : || !(omzp=fzp_gzopen(fdirs->manifest, "rb"))
553 0 : || !(nmzp=fzp_gzopen(manifesttmp,
554 0 : comp_level(get_int(cconfs[OPT_COMPRESSION]))))
555 0 : || !(db=sbuf_alloc())
556 0 : || !(mb=sbuf_alloc()))
557 : goto end;
558 :
559 0 : while(omzp || dfp)
560 : {
561 0 : if(dfp && !db->path.buf
562 0 : && (ars=sbuf_fill_from_file(db, dfp)))
563 : {
564 0 : if(ars<0) goto end;
565 : // ars==1 means it ended ok.
566 0 : fzp_close(&dfp);
567 : }
568 0 : if(omzp && !mb->path.buf
569 0 : && (ars=sbuf_fill_from_file(mb, omzp)))
570 : {
571 0 : if(ars<0) goto end;
572 : // ars==1 means it ended ok.
573 0 : fzp_close(&omzp);
574 : }
575 :
576 0 : if(mb->path.buf && !db->path.buf)
577 : {
578 0 : if(sbuf_to_manifest(mb, nmzp)) goto end;
579 0 : sbuf_free_content(mb);
580 : }
581 0 : else if(!mb->path.buf && db->path.buf)
582 : {
583 0 : sbuf_free_content(db);
584 : }
585 0 : else if(!mb->path.buf && !db->path.buf)
586 : {
587 0 : continue;
588 : }
589 0 : else if(!(pcmp=sbuf_pathcmp(mb, db)))
590 : {
591 : // They were the same - do not write.
592 0 : sbuf_free_content(mb);
593 0 : sbuf_free_content(db);
594 : }
595 0 : else if(pcmp<0)
596 : {
597 : // Behind in manifest. Write.
598 0 : if(sbuf_to_manifest(mb, nmzp)) goto end;
599 0 : sbuf_free_content(mb);
600 : }
601 : else
602 : {
603 : // Behind in deletions file. Do not write.
604 0 : sbuf_free_content(db);
605 : }
606 : }
607 :
608 : ret=0;
609 : end:
610 0 : if(fzp_close(&nmzp))
611 : {
612 0 : logp("error closing %s in %s\n", manifesttmp, __func__);
613 0 : ret=-1;
614 : }
615 :
616 0 : fzp_close(&dfp);
617 0 : fzp_close(&omzp);
618 0 : sbuf_free(&db);
619 0 : sbuf_free(&mb);
620 0 : if(!ret)
621 : {
622 0 : unlink(fdirs->deletionsfile);
623 : // The rename race condition is not a problem here, as long
624 : // as manifesttmp is the same path as that generated in the
625 : // atomic data jiggle.
626 0 : if(do_rename(manifesttmp, fdirs->manifest))
627 : return -1;
628 : }
629 0 : if(manifesttmp) unlink(manifesttmp);
630 : return ret;
631 : }
632 :
633 : /* Need to make all the stuff that this does atomic so that existing backups
634 : never get broken, even if somebody turns the power off on the server. */
635 2 : static int atomic_data_jiggle(struct sdirs *sdirs, struct fdirs *fdirs,
636 : int hardlinked_current, struct conf **cconfs)
637 : {
638 2 : int ret=-1;
639 2 : char *datapth=NULL;
640 2 : char *tmpman=NULL;
641 : struct stat statp;
642 :
643 2 : char *deltabdir=NULL;
644 2 : char *deltafdir=NULL;
645 2 : char *sigpath=NULL;
646 2 : struct fzp *zp=NULL;
647 2 : struct sbuf *sb=NULL;
648 :
649 2 : struct fzp *delfp=NULL;
650 :
651 2 : logp("Doing the atomic data jiggle...\n");
652 :
653 2 : if(!(tmpman=get_tmp_filename(fdirs->manifest)))
654 : goto error;
655 4 : if(lstat(fdirs->manifest, &statp))
656 : {
657 : // Manifest does not exist - maybe the server was killed before
658 : // it could be renamed.
659 0 : logp("%s did not exist - trying %s\n", fdirs->manifest, tmpman);
660 : // Rename race condition is of no consequence, because manifest
661 : // already does not exist.
662 0 : do_rename(tmpman, fdirs->manifest);
663 : }
664 2 : if(!(zp=fzp_gzopen(fdirs->manifest, "rb")))
665 : goto error;
666 :
667 2 : if(!(deltabdir=prepend_s(fdirs->currentdup, "deltas.reverse"))
668 2 : || !(deltafdir=prepend_s(sdirs->finishing, "deltas.forward"))
669 2 : || !(sigpath=prepend_s(fdirs->currentdup, "sig.tmp"))
670 2 : || !(sb=sbuf_alloc()))
671 : {
672 0 : log_out_of_memory(__func__);
673 0 : goto error;
674 : }
675 :
676 2 : mkdir(fdirs->datadir, 0777);
677 :
678 : while(1)
679 : {
680 402 : switch(sbuf_fill_from_file(sb, zp))
681 : {
682 : case 0: break;
683 : case 1: goto end;
684 : default: goto error;
685 : }
686 200 : if(sb->datapth.buf)
687 : {
688 91 : if(timed_operation_status_only(CNTR_STATUS_SHUFFLING,
689 : sb->datapth.buf, cconfs)
690 91 : || jiggle(sdirs, fdirs, sb, hardlinked_current,
691 : deltabdir, deltafdir,
692 : sigpath, &delfp, cconfs))
693 : goto error;
694 : }
695 200 : sbuf_free_content(sb);
696 : }
697 :
698 : end:
699 2 : if(fzp_close(&delfp))
700 : {
701 0 : logp("error closing %s in atomic_data_jiggle\n",
702 : fdirs->deletionsfile);
703 0 : goto error;
704 : }
705 :
706 2 : if(maybe_delete_files_from_manifest(tmpman, fdirs, cconfs))
707 : goto error;
708 :
709 : // Remove the temporary data directory, we have probably removed
710 : // useful files from it.
711 2 : recursive_delete_dirs_only(deltafdir);
712 :
713 2 : ret=0;
714 : error:
715 2 : fzp_close(&zp);
716 2 : fzp_close(&delfp);
717 2 : sbuf_free(&sb);
718 2 : free_w(&deltabdir);
719 2 : free_w(&deltafdir);
720 2 : free_w(&sigpath);
721 2 : free_w(&datapth);
722 2 : free_w(&tmpman);
723 2 : return ret;
724 : }
725 :
726 2 : int backup_phase4_server_all(struct sdirs *sdirs, struct conf **cconfs)
727 : {
728 2 : int ret=-1;
729 : struct stat statp;
730 2 : char realcurrent[256]="";
731 2 : uint64_t bno=0;
732 2 : int hardlinked_current=0;
733 2 : char tstmp[64]="";
734 2 : int previous_backup=0;
735 2 : struct fdirs *fdirs=NULL;
736 :
737 2 : readlink_w(sdirs->current, realcurrent, sizeof(realcurrent));
738 :
739 2 : if(!(fdirs=fdirs_alloc())
740 2 : || fdirs_init(fdirs, sdirs, realcurrent))
741 : goto end;
742 :
743 2 : if(log_fzp_set(fdirs->logpath, cconfs))
744 : goto end;
745 :
746 2 : logp("Begin phase4 (shuffle files)\n");
747 :
748 2 : if(timed_operation_status_only(CNTR_STATUS_SHUFFLING, NULL, cconfs))
749 : goto end;
750 :
751 4 : if(!lstat(sdirs->current, &statp)) // Had a previous backup.
752 : {
753 0 : previous_backup++;
754 :
755 0 : if(lstat(fdirs->hlinkedcurrent, &statp))
756 : {
757 0 : hardlinked_current=0;
758 0 : logp("Previous backup is not a hardlinked_archive\n");
759 0 : logp(" will generate reverse deltas\n");
760 : }
761 : else
762 : {
763 0 : hardlinked_current=1;
764 0 : logp("Previous backup is a hardlinked_archive\n");
765 0 : logp(" will not generate reverse deltas\n");
766 : }
767 :
768 : // If current was not a hardlinked_archive, need to duplicate
769 : // it.
770 0 : if(!hardlinked_current && lstat(fdirs->currentdup, &statp))
771 : {
772 : // Have not duplicated the current backup yet.
773 0 : if(!lstat(fdirs->currentduptmp, &statp))
774 : {
775 0 : logp("Removing previous directory: %s\n",
776 0 : fdirs->currentduptmp);
777 0 : if(recursive_delete(fdirs->currentduptmp))
778 : {
779 0 : logp("Could not delete %s\n",
780 0 : fdirs->currentduptmp);
781 0 : goto end;
782 : }
783 : }
784 0 : logp("Duplicating current backup.\n");
785 0 : if(recursive_hardlink(sdirs->current,
786 0 : fdirs->currentduptmp, cconfs)
787 : // The rename race condition is of no consequence here
788 : // because currentdup does not exist.
789 0 : || do_rename(fdirs->currentduptmp, fdirs->currentdup))
790 : goto end;
791 : }
792 : }
793 :
794 2 : if(timestamp_read(fdirs->timestamp, tstmp, sizeof(tstmp)))
795 : {
796 0 : logp("could not read timestamp file: %s\n",
797 0 : fdirs->timestamp);
798 0 : goto end;
799 : }
800 : // Get the backup number.
801 2 : bno=strtoull(tstmp, NULL, 10);
802 :
803 : // Determine whether the new backup should be a hardlinked
804 : // archive or not, from the confs and the backup number...
805 2 : if(need_hardlinked_archive(cconfs, bno))
806 : {
807 : // Create a file to indicate that the previous backup
808 : // does not have others depending on it.
809 0 : struct fzp *hfp=NULL;
810 0 : if(!(hfp=fzp_open(fdirs->hlinked, "wb"))) goto end;
811 :
812 : // Stick the next backup timestamp in it. It might
813 : // be useful one day when wondering when the next
814 : // backup, now deleted, was made.
815 0 : fzp_printf(hfp, "%s\n", tstmp);
816 0 : if(fzp_close(&hfp))
817 : {
818 0 : logp("error closing hardlinked indication\n");
819 0 : goto end;
820 : }
821 : }
822 : else
823 2 : unlink(fdirs->hlinked);
824 :
825 2 : if(atomic_data_jiggle(sdirs, fdirs, hardlinked_current, cconfs))
826 : {
827 0 : logp("could not finish up backup.\n");
828 0 : goto end;
829 : }
830 :
831 2 : if(timed_operation_status_only(CNTR_STATUS_SHUFFLING,
832 : "deleting temporary files", cconfs))
833 : goto end;
834 :
835 : // Remove the temporary data directory, we have now removed
836 : // everything useful from it.
837 2 : recursive_delete(fdirs->datadirtmp);
838 :
839 : // Clean up the currentdata directory - this is now the 'old'
840 : // currentdata directory. Any files that were deleted from
841 : // the client will be left in there, so call recursive_delete
842 : // with the option that makes it not delete files.
843 : // This will have the effect of getting rid of unnecessary
844 : // directories.
845 2 : recursive_delete_dirs_only_no_warnings(fdirs->currentdupdata);
846 2 : recursive_delete_dirs_only_no_warnings(sdirs->relink);
847 :
848 : // Rename the old current to something that we know to delete.
849 2 : if(previous_backup && !hardlinked_current)
850 : {
851 0 : if(deleteme_move(sdirs,
852 0 : fdirs->fullrealcurrent, realcurrent)
853 : // I have tested that potential race conditions on the
854 : // rename() are automatically recoverable here.
855 0 : || do_rename(fdirs->currentdup, fdirs->fullrealcurrent))
856 : goto end;
857 : }
858 :
859 2 : if(deleteme_maybe_delete(cconfs, sdirs))
860 : goto end;
861 :
862 2 : logp("End phase4 (shuffle files)\n");
863 :
864 2 : ret=0;
865 : end:
866 2 : fdirs_free(&fdirs);
867 2 : return ret;
868 : }
|