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

Generated by: LCOV version 1.10