LCOV - code coverage report
Current view: top level - src/server/protocol2 - backup_phase4.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 270 407 66.3 %
Date: 2015-11-30 Functions: 12 15 80.0 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.h"
       3             : #include "../../bu.h"
       4             : #include "../../cmd.h"
       5             : #include "../../fsops.h"
       6             : #include "../../fzp.h"
       7             : #include "../../lock.h"
       8             : #include "../../log.h"
       9             : #include "../../prepend.h"
      10             : #include "../../protocol2/blk.h"
      11             : #include "../../sbuf.h"
      12             : #include "../../server/bu_get.h"
      13             : #include "../../server/manio.h"
      14             : #include "../../server/sdirs.h"
      15             : #include "champ_chooser/champ_chooser.h"
      16             : 
      17             : struct hooks
      18             : {
      19             :         char *path;
      20             :         uint64_t *fingerprints;
      21             :         size_t len;
      22             : };
      23             : 
      24          10 : static int hookscmp(struct hooks *a, struct hooks *b)
      25             : {
      26             :         size_t i;
      27          10 :         uint64_t *af=a->fingerprints;
      28          10 :         uint64_t *bf=b->fingerprints;
      29          13 :         for(i=0; i<a->len && i<b->len; i++)
      30             :         {
      31          12 :                 if(af[i]>bf[i]) return 1;
      32           8 :                 if(af[i]<bf[i]) return -1;
      33             :         }
      34           1 :         if(a->len>b->len) return 1;
      35           1 :         if(a->len<b->len) return -1;
      36           1 :         return 0;
      37             : }
      38             : 
      39          60 : static int hooks_alloc(struct hooks **hnew,
      40             :         char **path, uint64_t **fingerprints, size_t *len)
      41             : {
      42          60 :         if(!*path || !*fingerprints) return 0;
      43             : 
      44          16 :         if(!(*hnew=(struct hooks *)malloc_w(sizeof(struct hooks), __func__)))
      45           0 :                 return -1;
      46             :         
      47          16 :         (*hnew)->path=*path;
      48          16 :         (*hnew)->fingerprints=*fingerprints;
      49          16 :         (*hnew)->len=*len;
      50          16 :         *path=NULL;
      51          16 :         *fingerprints=NULL;
      52          16 :         *len=0;
      53          16 :         return 0;
      54             : }
      55             : 
      56             : // Return 0 for OK, -1 for error, 1 for finished reading the file.
      57          96 : static int get_next_set_of_hooks(struct hooks **hnew, struct sbuf *sb,
      58             :         struct fzp *spzp, char **path, uint64_t **fingerprints, size_t *len)
      59             : {
      60             :         struct blk blk;
      61             :         while(1)
      62             :         {
      63          96 :                 switch(sbuf_fill_from_file(sb, spzp, NULL, NULL))
      64             :                 {
      65           0 :                         case -1: goto error;
      66             :                         case 1:
      67             :                                 // Reached the end.
      68          44 :                                 if(hooks_alloc(hnew, path, fingerprints, len))
      69           0 :                                         goto error;
      70          44 :                                 return 1;
      71             :                 }
      72          52 :                 if(sb->path.cmd==CMD_MANIFEST)
      73             :                 {
      74          16 :                         if(hooks_alloc(hnew, path, fingerprints, len))
      75           0 :                                 break;
      76          16 :                         *path=sb->path.buf;
      77          16 :                         sb->path.buf=NULL;
      78          16 :                         sbuf_free_content(sb);
      79          16 :                         if(*hnew) return 0;
      80             :                 }
      81          36 :                 else if(sb->path.cmd==CMD_FINGERPRINT)
      82             :                 {
      83          72 :                         if(!(*fingerprints=(uint64_t *)realloc_w(*fingerprints,
      84          72 :                                 ((*len)+1)*sizeof(uint64_t), __func__)))
      85           0 :                                         goto error;
      86          36 :                         if(blk_set_from_iobuf_fingerprint(&blk, &sb->path))
      87           0 :                                 goto error;
      88          36 :                         (*fingerprints)[(*len)++]=blk.fingerprint;
      89          36 :                         sbuf_free_content(sb);
      90             :                 }
      91             :                 else
      92             :                 {
      93           0 :                         iobuf_log_unexpected(&sb->path, __func__);
      94           0 :                         break;
      95             :                 }
      96             :         }
      97             : 
      98             : error:
      99           0 :         sbuf_free_content(sb);
     100          48 :         return -1;
     101             : }
     102             : 
     103          15 : static int gzprintf_hooks(struct fzp *fzp, struct hooks *hooks)
     104             : {
     105             :         size_t i;
     106             :         fzp_printf(fzp, "%c%04lX%s\n", CMD_MANIFEST,
     107          15 :                 strlen(hooks->path), hooks->path);
     108          48 :         for(i=0; i<hooks->len; i++)
     109          33 :                 if(to_fzp_fingerprint(fzp, hooks->fingerprints[i]))
     110           0 :                         return -1;
     111          15 :         return 0;
     112             : }
     113             : 
     114          60 : static void hooks_free(struct hooks **hooks)
     115             : {
     116         120 :         if(!*hooks) return;
     117          16 :         free_w(&(*hooks)->path);
     118          16 :         free_v((void **)&(*hooks)->fingerprints);
     119          16 :         free_v((void **)hooks);
     120             : }
     121             : 
     122             : /* Merge two files of sorted sparse indexes into each other. */
     123             : #ifndef UTEST
     124             : static
     125             : #endif
     126           6 : int merge_sparse_indexes(const char *dst, const char *srca, const char *srcb)
     127             : {
     128             :         int fcmp;
     129           6 :         int ret=-1;
     130           6 :         struct sbuf *asb=NULL;
     131           6 :         struct sbuf *bsb=NULL;
     132           6 :         uint64_t *afingerprints=NULL;
     133           6 :         uint64_t *bfingerprints=NULL;
     134           6 :         size_t aflen=0;
     135           6 :         size_t bflen=0;
     136           6 :         struct fzp *azp=NULL;
     137           6 :         struct fzp *bzp=NULL;
     138           6 :         struct fzp *dzp=NULL;
     139           6 :         struct hooks *anew=NULL;
     140           6 :         struct hooks *bnew=NULL;
     141           6 :         char *apath=NULL;
     142           6 :         char *bpath=NULL;
     143             : 
     144          18 :         if(!(asb=sbuf_alloc(PROTO_2))
     145          12 :           || (srcb && !(bsb=sbuf_alloc(PROTO_2))))
     146           0 :                 goto end;
     147           6 :         if(build_path_w(dst))
     148           0 :                 goto end;
     149          12 :         if((srca && !(azp=fzp_gzopen(srca, "rb")))
     150           6 :           || (srcb && !(bzp=fzp_gzopen(srcb, "rb")))
     151          12 :           || !(dzp=fzp_gzopen(dst, "wb")))
     152           0 :                 goto end;
     153             : 
     154          27 :         while(azp || bzp || anew || bnew)
     155             :         {
     156          15 :                 if(azp
     157           9 :                   && asb
     158           9 :                   && !anew)
     159             :                 {
     160           8 :                         switch(get_next_set_of_hooks(&anew, asb, azp,
     161           8 :                                 &apath, &afingerprints, &aflen))
     162             :                         {
     163           0 :                                 case -1: goto end;
     164           6 :                                 case 1: fzp_close(&azp); // Finished OK.
     165             :                         }
     166             :                 }
     167             : 
     168          15 :                 if(bzp
     169          10 :                   && bsb
     170          10 :                   && !bnew)
     171             :                 {
     172           8 :                         switch(get_next_set_of_hooks(&bnew, bsb, bzp,
     173           8 :                                 &bpath, &bfingerprints, &bflen))
     174             :                         {
     175           0 :                                 case -1: goto end;
     176           6 :                                 case 1: fzp_close(&bzp); // Finished OK.
     177             :                         }
     178             :                 }
     179             : 
     180          15 :                 if(anew && !bnew)
     181             :                 {
     182           2 :                         if(gzprintf_hooks(dzp, anew)) goto end;
     183           2 :                         hooks_free(&anew);
     184             :                 }
     185          13 :                 else if(!anew && bnew)
     186             :                 {
     187           3 :                         if(gzprintf_hooks(dzp, bnew)) goto end;
     188           3 :                         hooks_free(&bnew);
     189             :                 }
     190          10 :                 else if(!anew && !bnew)
     191             :                 {
     192           0 :                         continue;
     193             :                 }
     194          10 :                 else if(!(fcmp=hookscmp(anew, bnew)))
     195             :                 {
     196             :                         // They were the same - write the new one.
     197           1 :                         if(gzprintf_hooks(dzp, bnew)) goto end;
     198           1 :                         hooks_free(&anew);
     199           1 :                         hooks_free(&bnew);
     200             :                 }
     201           9 :                 else if(fcmp<0)
     202             :                 {
     203           5 :                         if(gzprintf_hooks(dzp, anew)) goto end;
     204           5 :                         hooks_free(&anew);
     205             :                 }
     206             :                 else
     207             :                 {
     208           4 :                         if(gzprintf_hooks(dzp, bnew)) goto end;
     209           4 :                         hooks_free(&bnew);
     210             :                 }
     211             :         }
     212             : 
     213           6 :         if(fzp_close(&dzp))
     214             :         {
     215           0 :                 logp("Error closing %s in %s\n", tmpfile, __func__);
     216           0 :                 goto end;
     217             :         }
     218             : 
     219           6 :         ret=0;
     220             : end:
     221           6 :         fzp_close(&azp);
     222           6 :         fzp_close(&bzp);
     223           6 :         fzp_close(&dzp);
     224           6 :         sbuf_free(&asb);
     225           6 :         sbuf_free(&bsb);
     226           6 :         hooks_free(&anew);
     227           6 :         hooks_free(&bnew);
     228           6 :         free_v((void **)&afingerprints);
     229           6 :         free_v((void **)&bfingerprints);
     230           6 :         free_w(&apath);
     231           6 :         free_w(&bpath);
     232           6 :         return ret;
     233             : }
     234             : 
     235             : #ifndef UTEST
     236             : static 
     237             : #endif
     238          72 : int gzprintf_dindex(struct fzp *fzp, uint64_t *dindex)
     239             : {
     240             :         struct blk blk;
     241             :         struct iobuf wbuf;
     242          72 :         blk.savepath=*dindex;
     243          72 :         blk_to_iobuf_savepath(&blk, &wbuf);
     244          72 :         return iobuf_send_msg_fzp(&wbuf, fzp);
     245             : }
     246             : 
     247             : // Return 0 for OK, -1 for error, 1 for finished reading the file.
     248          38 : static int get_next_dindex(uint64_t **dnew, struct sbuf *sb, struct fzp *fzp)
     249             : {
     250             :         static struct blk blk;
     251             :         static struct iobuf rbuf;
     252             : 
     253          38 :         memset(&rbuf, 0, sizeof(rbuf));
     254             : 
     255          38 :         switch(iobuf_fill_from_fzp(&rbuf, fzp))
     256             :         {
     257           0 :                 case -1: goto error;
     258          12 :                 case 1: return 1; // Reached the end.
     259             :         }
     260          26 :         if(rbuf.cmd==CMD_SAVE_PATH)
     261             :         {
     262          26 :                 if(blk_set_from_iobuf_savepath(&blk, &rbuf))
     263           0 :                         goto error;
     264          26 :                 *dnew=(uint64_t *)malloc_w(sizeof(uint64_t), __func__);
     265          26 :                 **dnew=blk.savepath;
     266          26 :                 iobuf_free_content(&rbuf);
     267          26 :                 return 0;
     268             :         }
     269             :         else
     270           0 :                 iobuf_log_unexpected(&sb->path, __func__);
     271             : 
     272             : error:
     273           0 :         iobuf_free_content(&rbuf);
     274           0 :         return -1;
     275             : }
     276             : 
     277             : /* Merge two files of sorted dindexes into each other. */
     278           6 : int merge_dindexes(const char *dst, const char *srca, const char *srcb)
     279             : {
     280           6 :         int ret=-1;
     281           6 :         struct sbuf *asb=NULL;
     282           6 :         struct sbuf *bsb=NULL;
     283           6 :         struct fzp *azp=NULL;
     284           6 :         struct fzp *bzp=NULL;
     285           6 :         struct fzp *dzp=NULL;
     286           6 :         uint64_t *anew=NULL;
     287           6 :         uint64_t *bnew=NULL;
     288             : 
     289          18 :         if(!(asb=sbuf_alloc(PROTO_2))
     290          12 :           || (srcb && !(bsb=sbuf_alloc(PROTO_2))))
     291           0 :                 goto end;
     292           6 :         if(build_path_w(dst))
     293           0 :                 goto end;
     294          12 :         if((srca && !(azp=fzp_gzopen(srca, "rb")))
     295           6 :           || (srcb && !(bzp=fzp_gzopen(srcb, "rb")))
     296          12 :           || !(dzp=fzp_gzopen(dst, "wb")))
     297           0 :                 goto end;
     298             : 
     299          42 :         while(azp || bzp || anew || bnew)
     300             :         {
     301          30 :                 if(azp
     302          27 :                   && asb
     303          27 :                   && !anew)
     304             :                 {
     305          19 :                         switch(get_next_dindex(&anew, asb, azp))
     306             :                         {
     307           0 :                                 case -1: goto end;
     308           6 :                                 case 1: fzp_close(&azp); // Finished OK.
     309             :                         }
     310             :                 }
     311             : 
     312          30 :                 if(bzp
     313          26 :                   && bsb
     314          26 :                   && !bnew)
     315             :                 {
     316          19 :                         switch(get_next_dindex(&bnew, bsb, bzp))
     317             :                         {
     318           0 :                                 case -1: goto end;
     319           6 :                                 case 1: fzp_close(&bzp); // Finished OK.
     320             :                         }
     321             :                 }
     322             : 
     323          30 :                 if(anew && !bnew)
     324             :                 {
     325           4 :                         if(gzprintf_dindex(dzp, anew)) goto end;
     326           4 :                         free_v((void **)&anew);
     327             :                 }
     328          26 :                 else if(!anew && bnew)
     329             :                 {
     330           3 :                         if(gzprintf_dindex(dzp, bnew)) goto end;
     331           3 :                         free_v((void **)&bnew);
     332             :                 }
     333          23 :                 else if(!anew && !bnew)
     334             :                 {
     335           6 :                         continue;
     336             :                 }
     337          17 :                 else if(*anew==*bnew)
     338             :                 {
     339             :                         // They were the same - write the new one.
     340           2 :                         if(gzprintf_dindex(dzp, bnew)) goto end;
     341           2 :                         free_v((void **)&anew);
     342           2 :                         free_v((void **)&bnew);
     343             :                 }
     344          15 :                 else if(*anew<*bnew)
     345             :                 {
     346           7 :                         if(gzprintf_dindex(dzp, anew)) goto end;
     347           7 :                         free_v((void **)&anew);
     348             :                 }
     349             :                 else
     350             :                 {
     351           8 :                         if(gzprintf_dindex(dzp, bnew)) goto end;
     352           8 :                         free_v((void **)&bnew);
     353             :                 }
     354             :         }
     355             : 
     356           6 :         if(fzp_close(&dzp))
     357             :         {
     358           0 :                 logp("Error closing %s in %s\n", tmpfile, __func__);
     359           0 :                 goto end;
     360             :         }
     361             : 
     362           6 :         ret=0;
     363             : end:
     364           6 :         fzp_close(&azp);
     365           6 :         fzp_close(&bzp);
     366           6 :         fzp_close(&dzp);
     367           6 :         sbuf_free(&asb);
     368           6 :         sbuf_free(&bsb);
     369           6 :         free_v((void **)&anew);
     370           6 :         free_v((void **)&bnew);
     371           6 :         return ret;
     372             : }
     373             : 
     374          32 : static char *get_global_sparse_tmp(const char *global)
     375             : {
     376          32 :         return prepend_n(global, "tmp", strlen("tmp"), ".");
     377             : }
     378             : 
     379           0 : static int merge_into_global_sparse(const char *sparse, const char *global)
     380             : {
     381           0 :         int ret=-1;
     382           0 :         char *tmpfile=NULL;
     383             :         struct stat statp;
     384           0 :         struct lock *lock=NULL;
     385           0 :         const char *globalsrc=NULL;
     386             :         
     387           0 :         if(!(tmpfile=get_global_sparse_tmp(global)))
     388           0 :                 goto end;
     389             : 
     390           0 :         if(!(lock=try_to_get_sparse_lock(global)))
     391           0 :                 goto end;
     392             : 
     393           0 :         if(!lstat(global, &statp)) globalsrc=global;
     394             : 
     395           0 :         if(merge_sparse_indexes(tmpfile, globalsrc, sparse))
     396           0 :                 goto end;
     397             : 
     398             :         // FIX THIS: nasty race condition needs to be recoverable.
     399           0 :         if(do_rename(tmpfile, global)) goto end;
     400             : 
     401           0 :         ret=0;
     402             : end:
     403           0 :         lock_release(lock);
     404           0 :         lock_free(&lock);
     405           0 :         free_w(&tmpfile);
     406           0 :         return ret;
     407             : }
     408             : 
     409           7 : int merge_files_in_dir(const char *final, const char *fmanifest,
     410             :         const char *srcdir, uint64_t fcount,
     411             :         int merge(const char *dst, const char *srca, const char *srcb))
     412             : {
     413           7 :         int ret=-1;
     414           7 :         uint64_t i=0;
     415           7 :         uint64_t pass=0;
     416           7 :         char *m1dir=NULL;
     417           7 :         char *m2dir=NULL;
     418           7 :         char *srca=NULL;
     419           7 :         char *srcb=NULL;
     420           7 :         char *dst=NULL;
     421           7 :         char compa[32]="";
     422           7 :         char compb[32]="";
     423           7 :         char compd[32]="";
     424           7 :         char *fullsrcdir=NULL;
     425             : 
     426          21 :         if(!(m1dir=prepend_s(fmanifest, "m1"))
     427           7 :           || !(m2dir=prepend_s(fmanifest, "m2"))
     428          21 :           || !(fullsrcdir=prepend_s(fmanifest, srcdir)))
     429           0 :                 goto end;
     430          14 :         if(recursive_delete(m1dir)
     431           7 :           || recursive_delete(m2dir))
     432           0 :                 goto end;
     433             :         while(1)
     434             :         {
     435          13 :                 const char *srcdir=NULL;
     436          13 :                 const char *dstdir=NULL;
     437          13 :                 if(!pass)
     438             :                 {
     439           7 :                         srcdir=fullsrcdir;
     440           7 :                         dstdir=m1dir;
     441             :                 }
     442           6 :                 else if(pass%2)
     443             :                 {
     444           4 :                         srcdir=m1dir;
     445           4 :                         dstdir=m2dir;
     446             :                 }
     447             :                 else
     448             :                 {
     449           2 :                         srcdir=m2dir;
     450           2 :                         dstdir=m1dir;
     451             :                 }
     452          13 :                 pass++;
     453          33 :                 for(i=0; i<fcount; i+=2)
     454             :                 {
     455          20 :                         free_w(&srca);
     456          20 :                         free_w(&srcb);
     457          20 :                         free_w(&dst);
     458          20 :                         snprintf(compa, sizeof(compa), "%08"PRIX64, i);
     459          20 :                         snprintf(compb, sizeof(compb), "%08"PRIX64, i+1);
     460          20 :                         snprintf(compd, sizeof(compd), "%08"PRIX64, i/2);
     461          60 :                         if(!(srca=prepend_s(srcdir, compa))
     462          40 :                           || !(dst=prepend_s(dstdir, compd)))
     463           0 :                                 goto end;
     464          40 :                         if(i+1<fcount
     465          20 :                           && !(srcb=prepend_s(srcdir, compb)))
     466           0 :                                 goto end;
     467          20 :                         if(merge(dst, srca, srcb))
     468           0 :                                 goto end;
     469             :                 }
     470          13 :                 fcount=i/2;
     471          13 :                 if(fcount<2) break;
     472             :         }
     473             : 
     474             :         // FIX THIS: nasty race condition here needs to be automatically
     475             :         // recoverable.
     476           7 :         if(dst && do_rename(dst, final))
     477           0 :                 goto end;
     478          14 :         if(recursive_delete(m1dir)
     479           7 :           || recursive_delete(m2dir))
     480           0 :                 goto end;
     481             : 
     482           7 :         ret=0;
     483             : end:
     484           7 :         free_w(&m1dir);
     485           7 :         free_w(&m2dir);
     486           7 :         free_w(&srca);
     487           7 :         free_w(&srcb);
     488           7 :         free_w(&dst);
     489           7 :         free_w(&fullsrcdir);
     490          13 :         return ret;
     491             : }
     492             : 
     493           0 : int backup_phase4_server_protocol2(struct sdirs *sdirs, struct conf **confs)
     494             : {
     495           0 :         int ret=-1;
     496           0 :         char *dfiles=NULL;
     497           0 :         char *sparse=NULL;
     498           0 :         struct manio *newmanio=NULL;
     499           0 :         char *logpath=NULL;
     500           0 :         char *fmanifest=NULL; // FIX THIS: should be part of sdirs.
     501             : 
     502           0 :         if(!(logpath=prepend_s(sdirs->finishing, "log")))
     503           0 :                 goto end;
     504           0 :         if(log_fzp_set(logpath, confs))
     505           0 :                 goto end;
     506             : 
     507           0 :         logp("Begin phase4 (sparse generation)\n");
     508             : 
     509           0 :         if(!(fmanifest=prepend_s(sdirs->finishing, "manifest"))
     510           0 :           || !(newmanio=manio_open(fmanifest, "rb", PROTO_2))
     511           0 :           || manio_read_fcount(newmanio)
     512           0 :           || !(dfiles=prepend_s(fmanifest, "dfiles"))
     513           0 :           || !(sparse=prepend_s(fmanifest, "sparse")))
     514           0 :                 goto end;
     515             : 
     516           0 :         if(merge_files_in_dir(dfiles, fmanifest, "dindex",
     517             :                 newmanio->offset->fcount,
     518           0 :                 merge_dindexes))
     519           0 :                         goto end;
     520           0 :         if(merge_files_in_dir(sparse, fmanifest, "hooks",
     521             :                 newmanio->offset->fcount,
     522           0 :                 merge_sparse_indexes))
     523           0 :                         goto end;
     524             : 
     525           0 :         if(merge_into_global_sparse(sparse, sdirs->global_sparse))
     526           0 :                 goto end;
     527             : 
     528           0 :         logp("End phase4 (sparse generation)\n");
     529             : 
     530           0 :         ret=0;
     531             : end:
     532           0 :         manio_close(&newmanio);
     533           0 :         free_w(&sparse);
     534           0 :         free_w(&logpath);
     535           0 :         free_w(&fmanifest);
     536           0 :         return ret;
     537             : }
     538             : 
     539           0 : int regenerate_client_dindex(struct sdirs *sdirs)
     540             : {
     541           0 :         int ret=-1;
     542             :         struct bu *bu;
     543           0 :         struct bu *bu_list=NULL;
     544           0 :         char *newpath=NULL;
     545           0 :         char *oldpath=NULL;
     546           0 :         char tmp[16]="";
     547           0 :         int path_built=0;
     548           0 :         uint64_t last_index=0;
     549           0 :         char *dfiles_new=NULL;
     550             : 
     551           0 :         if(recursive_delete(sdirs->dindex)) goto end;
     552             : 
     553           0 :         if(bu_get_list(sdirs, &bu_list)) goto end;
     554             : 
     555           0 :         for(bu=bu_list; bu; bu=bu->next)
     556             :         {
     557           0 :                 snprintf(tmp, sizeof(tmp), "%08lu", bu->index-1);
     558           0 :                 if(!(newpath=prepend_s(sdirs->dindex, tmp))
     559           0 :                   || !(oldpath=prepend_s(bu->path, "manifest/dfiles")))
     560           0 :                         goto end;
     561           0 :                 if(!path_built)
     562             :                 {
     563           0 :                         if(build_path_w(newpath))
     564           0 :                                 goto end;
     565           0 :                         path_built++;
     566             :                 }
     567           0 :                 if(link(oldpath, newpath))
     568             :                 {
     569             :                         logp("%s could not hard link '%s' to '%s': %s\n",
     570           0 :                                 __func__, oldpath, newpath, strerror(errno));
     571           0 :                         goto end;
     572             :                 }
     573           0 :                 free_w(&newpath);
     574           0 :                 free_w(&oldpath);
     575           0 :                 last_index=(uint64_t)bu->index;
     576             :         }
     577             : 
     578           0 :         if(!(dfiles_new=prepend(sdirs->dfiles, ".new")))
     579           0 :                 goto end;
     580           0 :         if(merge_files_in_dir(dfiles_new, sdirs->client,
     581           0 :                 "dindex", last_index, merge_dindexes))
     582           0 :                         goto end;
     583             : 
     584           0 :         if(do_rename(dfiles_new, sdirs->dfiles))
     585           0 :                 goto end;
     586             : 
     587           0 :         if(recursive_delete(sdirs->dindex)) goto end;
     588             : 
     589           0 :         ret=0;
     590             : end:
     591           0 :         bu_list_free(&bu_list);
     592           0 :         free_w(&newpath);
     593           0 :         free_w(&oldpath);
     594           0 :         return ret;
     595             : }
     596             : 
     597          32 : int remove_from_global_sparse(const char *global_sparse,
     598             :         const char *candidate_str)
     599             : {
     600          32 :         int ret=-1;
     601          32 :         struct lock *lock=NULL;
     602          32 :         struct sbuf *asb=NULL;
     603          32 :         uint64_t *afingerprints=NULL;
     604          32 :         size_t aflen=0;
     605          32 :         size_t clen=0;
     606          32 :         struct fzp *azp=NULL;
     607          32 :         struct fzp *dzp=NULL;
     608          32 :         struct hooks *anew=NULL;
     609          32 :         char *apath=NULL;
     610          32 :         char *tmpfile=NULL;
     611             : 
     612          32 :         logp("Removing %s from %s\n", candidate_str, global_sparse);
     613          32 :         if(!(lock=try_to_get_sparse_lock(global_sparse)))
     614           0 :                 goto end;
     615             : 
     616          96 :         if(!(tmpfile=get_global_sparse_tmp(global_sparse))
     617          32 :           || !(azp=fzp_gzopen(global_sparse, "rb"))
     618          32 :           || !(dzp=fzp_gzopen(tmpfile, "wb"))
     619          96 :           || !(asb=sbuf_alloc(PROTO_2)))
     620           0 :                 goto end;
     621             : 
     622          32 :         clen=strlen(candidate_str);
     623             : 
     624          96 :         while(azp)
     625             :         {
     626          32 :                 switch(get_next_set_of_hooks(&anew, asb, azp,
     627          32 :                         &apath, &afingerprints, &aflen))
     628             :                 {
     629           0 :                         case -1: goto end;
     630          32 :                         case 1: fzp_close(&azp); // Finished OK.
     631             :                 }
     632             : 
     633          32 :                 if(!anew) continue;
     634             : 
     635           0 :                 if(!strncmp(anew->path, candidate_str, clen)
     636           0 :                   && *(anew->path+clen)=='/')
     637           0 :                         continue;
     638             : 
     639           0 :                 if(gzprintf_hooks(dzp, anew)) goto end;
     640           0 :                 hooks_free(&anew);
     641             :         }
     642             : 
     643          32 :         if(fzp_close(&dzp))
     644             :         {
     645           0 :                 logp("Error closing %s in %s\n", tmpfile, __func__);
     646           0 :                 goto end;
     647             :         }
     648             : 
     649             :         // FIX THIS: nasty race condition needs to be recoverable.
     650          32 :         if(do_rename(tmpfile, global_sparse)) goto end;
     651             : 
     652          32 :         ret=0;
     653             : end:
     654          32 :         fzp_close(&azp);
     655          32 :         fzp_close(&dzp);
     656          32 :         lock_release(lock);
     657          32 :         lock_free(&lock);
     658          32 :         sbuf_free(&asb);
     659          32 :         hooks_free(&anew);
     660          32 :         free_v((void **)&afingerprints);
     661          32 :         free_w(&apath);
     662          32 :         free_w(&tmpfile);
     663          32 :         return ret;
     664             : }

Generated by: LCOV version 1.10