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

Generated by: LCOV version 1.10