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: 0 388 0.0 %
Date: 2015-10-31 Functions: 0 11 0.0 %

          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             : }

Generated by: LCOV version 1.10