LCOV - code coverage report
Current view: top level - src/server/protocol1 - backup_phase4.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 114 346 32.9 %
Date: 2020-07-31 05:59:47 Functions: 5 12 41.7 %

          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 "../child.h"
      17             : #include "../compress.h"
      18             : #include "../timestamp.h"
      19             : #include "blocklen.h"
      20             : #include "deleteme.h"
      21             : #include "fdirs.h"
      22             : #include "link.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_protocol1_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_protocol1_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_protocol1_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->protocol1->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(PROTO_1))
     556           0 :           || !(mb=sbuf_alloc(PROTO_1)))
     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, NULL)))
     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, NULL)))
     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(PROTO_1)))
     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, NULL))
     681             :                 {
     682             :                         case 0: break;
     683             :                         case 1: goto end;
     684             :                         default: goto error;
     685             :                 }
     686         200 :                 if(sb->protocol1->datapth.buf)
     687             :                 {
     688         182 :                         if(write_status(CNTR_STATUS_SHUFFLING,
     689          91 :                                 sb->protocol1->datapth.buf, get_cntr(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_protocol1(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(write_status(CNTR_STATUS_SHUFFLING, NULL, get_cntr(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(write_status(CNTR_STATUS_SHUFFLING,
     832             :                 "deleting temporary files", get_cntr(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             : }

Generated by: LCOV version 1.13