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