LCOV - code coverage report
Current view: top level - src/server - manio.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 308 382 80.6 %
Date: 2020-08-31 23:02:24 Functions: 34 35 97.1 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../cmd.h"
       4             : #include "../fsops.h"
       5             : #include "../fzp.h"
       6             : #include "../hexmap.h"
       7             : #include "../log.h"
       8             : #include "../msg.h"
       9             : #include "../prepend.h"
      10             : #include "../protocol2/blk.h"
      11             : #include "../sbuf.h"
      12             : #include "manio.h"
      13             : #include "protocol2/champ_chooser/champ_chooser.h"
      14             : #include "protocol2/dpth.h"
      15             : 
      16             : static void man_off_t_free_content(man_off_t *offset)
      17             : {
      18         246 :         if(!offset) return;
      19       15786 :         free_w(&offset->fpath);
      20       15786 :         free_w(&offset->ppath);
      21             : }
      22             : 
      23       15848 : void man_off_t_free(man_off_t **offset)
      24             : {
      25       15848 :         if(!offset || !*offset) return;
      26       31080 :         man_off_t_free_content(*offset);
      27       15540 :         free_v((void **)offset);
      28             : }
      29             : 
      30             : static man_off_t *man_off_t_alloc(void)
      31             : {
      32       15540 :         return (man_off_t *)calloc_w(1, sizeof(man_off_t), __func__);
      33             : }
      34             : 
      35          11 : static int init_write_hooks(struct manio *manio,
      36             :         const char *hook_dir, const char *rmanifest)
      37             : {
      38          11 :         if(!(manio->hook_dir=strdup_w(hook_dir, __func__))
      39          11 :           || !(manio->rmanifest=strdup_w(rmanifest, __func__))
      40          11 :           || !(manio->hook_sort=(uint64_t *)calloc_w(MANIFEST_SIG_MAX,
      41             :                 sizeof(uint64_t), __func__)))
      42             :                         return -1;
      43             :         return 0;
      44             : }
      45             : 
      46          11 : static int init_write_dindex(struct manio *manio, const char *dir)
      47             : {
      48          11 :         if(!(manio->dindex_dir=strdup_w(dir, __func__))
      49          11 :           || !(manio->dindex_sort=(uint64_t *)calloc_w(MANIFEST_SIG_MAX,
      50             :                 sizeof(uint64_t), __func__)))
      51             :                         return -1;
      52             :         return 0;
      53             : }
      54             : 
      55             : static int is_single_file(struct manio *manio)
      56             : {
      57        1710 :         return manio->protocol==PROTO_1 || manio->phase==1;
      58             : }
      59             : 
      60        1132 : static char *get_next_fpath(struct manio *manio, man_off_t *offset)
      61             : {
      62             :         static char tmp[32];
      63        2264 :         if(is_single_file(manio))
      64         484 :                 return strdup_w(manio->manifest, __func__);
      65         648 :         snprintf(tmp, sizeof(tmp), "%08" PRIX64, offset->fcount++);
      66         648 :         return prepend_s(manio->manifest, tmp);
      67             : }
      68             : 
      69        1032 : static int manio_open_next_fpath(struct manio *manio)
      70             : {
      71             :         static struct stat statp;
      72        1032 :         man_off_t *offset=manio->offset;
      73             : 
      74        1032 :         free_w(&offset->ppath);
      75        1032 :         offset->ppath=offset->fpath;
      76        1032 :         if(!(offset->fpath=get_next_fpath(manio, offset)))
      77             :                 return -1;
      78             : 
      79        1032 :         if(!strcmp(manio->mode, MANIO_MODE_READ)
      80        1226 :           && lstat(offset->fpath, &statp))
      81             :                 return 0;
      82             : 
      83         864 :         if(build_path_w(offset->fpath))
      84             :                 return -1;
      85         864 :         switch(manio->phase)
      86             :         {
      87             :                 case 2:
      88         676 :                         if(!(manio->fzp=fzp_open(offset->fpath,
      89         676 :                                 manio->mode))) return -1;
      90         676 :                         return 0;
      91             :                 case 1:
      92             :                 case 3:
      93             :                 default:
      94         188 :                         if(!(manio->fzp=fzp_gzopen(offset->fpath,
      95         188 :                                 manio->mode))) return -1;
      96         188 :                         return 0;
      97             :         }
      98             : }
      99             : 
     100          92 : static int manio_open_last_fpath(struct manio *manio)
     101             : {
     102          92 :         int max=-1;
     103         184 :         if(is_single_file(manio))
     104          56 :                 return manio_open_next_fpath(manio);
     105          36 :         if(get_highest_entry(manio->manifest, &max, 8))
     106             :                 return -1;
     107          36 :         if(max<0) max=0;
     108          36 :         manio->offset->fcount=(uint64_t)max;
     109          36 :         return manio_open_next_fpath(manio);
     110             : }
     111             : 
     112             : static struct manio *manio_alloc(void)
     113             : {
     114         806 :         return (struct manio *)calloc_w(1, sizeof(struct manio), __func__);
     115             : }
     116             : 
     117         806 : static struct manio *do_manio_open(const char *manifest, const char *mode,
     118             :         enum protocol protocol, int phase)
     119             : {
     120         806 :         struct manio *manio=NULL;
     121         806 :         if(!(manio=manio_alloc())
     122         806 :           || !(manio->manifest=strdup_w(manifest, __func__))
     123         806 :           || !(manio->mode=strdup_w(mode, __func__))
     124        1612 :           || !(manio->offset=man_off_t_alloc()))
     125             :                 goto error;
     126         806 :         manio->protocol=protocol;
     127         806 :         manio->phase=phase;
     128         806 :         if(!strcmp(manio->mode, MANIO_MODE_APPEND))
     129             :         {
     130          92 :                 if(manio->phase!=2)
     131             :                 {
     132           0 :                         logp("manio append mode only works for phase 2.\n");
     133           0 :                         logp("%s has phase: %d\n",
     134           0 :                                 manio->manifest, manio->phase);
     135           0 :                         goto error;
     136             :                 }
     137          92 :                 if(manio_open_last_fpath(manio))
     138             :                         goto error;
     139             :         }
     140             :         else
     141             :         {
     142         714 :                 if(manio_open_next_fpath(manio))
     143             :                         goto error;
     144             :         }
     145         806 :         return manio;
     146             : error:
     147           0 :         manio_close(&manio);
     148           0 :         return NULL;
     149             : }
     150             : 
     151          43 : struct manio *manio_open(const char *manifest, const char *mode,
     152             :         enum protocol protocol)
     153             : {
     154          43 :         return do_manio_open(manifest, mode, protocol, 0);
     155             : }
     156             : 
     157         144 : struct manio *manio_open_phase1(const char *manifest, const char *mode,
     158             :         enum protocol protocol)
     159             : {
     160         144 :         return do_manio_open(manifest, mode, protocol, 1);
     161             : }
     162             : 
     163         600 : struct manio *manio_open_phase2(const char *manifest, const char *mode,
     164             :         enum protocol protocol)
     165             : {
     166         600 :         return do_manio_open(manifest, mode, protocol, 2);
     167             : }
     168             : 
     169          19 : struct manio *manio_open_phase3(const char *manifest, const char *mode,
     170             :         enum protocol protocol, const char *rmanifest)
     171             : {
     172          19 :         struct manio *manio=NULL;
     173             : 
     174          19 :         if(!(manio=do_manio_open(manifest, mode, protocol, 3)))
     175             :                 goto end;
     176             : 
     177          19 :         if(protocol==PROTO_2 && rmanifest)
     178             :         {
     179          11 :                 char *hooksdir=NULL;
     180          11 :                 char *dindexdir=NULL;
     181          11 :                 if(!(hooksdir=prepend_s(manifest, "hooks"))
     182          11 :                   || !(dindexdir=prepend_s(manifest, "dindex"))
     183          11 :                   || init_write_hooks(manio, hooksdir, rmanifest)
     184          11 :                   || init_write_dindex(manio, dindexdir))
     185           0 :                         manio_close(&manio);
     186          11 :                 free_w(&hooksdir);
     187          11 :                 free_w(&dindexdir);
     188             :         }
     189             : 
     190             : end:
     191          19 :         return manio;
     192             : }
     193             : 
     194         806 : static void manio_free_content(struct manio *manio)
     195             : {
     196         806 :         if(!manio) return;
     197         806 :         man_off_t_free(&manio->offset);
     198         806 :         free_w(&manio->manifest);
     199         806 :         free_w(&manio->mode);
     200         806 :         free_w(&manio->rmanifest);
     201         806 :         free_w(&manio->hook_dir);
     202         806 :         free_v((void **)&manio->hook_sort);
     203         806 :         free_w(&manio->dindex_dir);
     204         806 :         free_v((void **)&manio->dindex_sort);
     205         806 :         memset(manio, 0, sizeof(struct manio));
     206             : }
     207             : 
     208             : #ifndef UTEST
     209             : static
     210             : #endif
     211          36 : int write_hook_header(struct fzp *fzp, const char *rmanifest, const char *msg)
     212             : {
     213          36 :         int ret=0;
     214          36 :         char *tmp=NULL;
     215          36 :         if(!(tmp=prepend_s(rmanifest, msg))
     216          36 :           || send_msg_fzp(fzp, CMD_MANIFEST, tmp, strlen(tmp)))
     217             :                 ret=-1;
     218          36 :         free_w(&tmp);
     219          36 :         return ret;
     220             : }
     221             : 
     222      377847 : static int uint64_t_sort(const void *a, const void *b)
     223             : {
     224      377847 :         uint64_t *x=(uint64_t *)a;
     225      377847 :         uint64_t *y=(uint64_t *)b;
     226      377847 :         if(*x>*y) return 1;
     227      185793 :         if(*x<*y) return -1;
     228           0 :         return 0;
     229             : }
     230             : 
     231             : static char *get_fcount_path(struct manio *manio)
     232             : {
     233          21 :         return prepend_s(manio->manifest, "fcount");
     234             : }
     235             : 
     236             : // Backup phase4 needs to know the fcount, so leave a file behind that
     237             : // contains it (otherwise phase4 will have to read and sort the directory
     238             : // contents).
     239          20 : static int manio_write_fcount(struct manio *manio)
     240             : {
     241          20 :         int ret=-1;
     242          20 :         struct fzp *fzp=NULL;
     243          20 :         char *path=NULL;
     244             : 
     245          40 :         if(!(path=get_fcount_path(manio))
     246          20 :           || !(fzp=fzp_open(path, "wb")))
     247             :                 goto end;
     248          20 :         if(fzp_printf(fzp, "%08" PRIX64 "\n", manio->offset->fcount)!=9)
     249             :         {
     250           0 :                 logp("Short write when writing to %s\n", path);
     251           0 :                 goto end;
     252             :         }
     253             :         ret=0;
     254             : end:
     255          20 :         if(fzp_close(&fzp))
     256             :         {
     257           0 :                 logp("Could not close file pointer to %s\n", path);
     258           0 :                 ret=-1;
     259             :         }
     260          20 :         free_w(&path);
     261          20 :         return ret;
     262             : }
     263             : 
     264           1 : int manio_read_fcount(struct manio *manio)
     265             : {
     266           1 :         int ret=-1;
     267             :         size_t s;
     268           1 :         struct fzp *fzp=NULL;
     269           1 :         char *path=NULL;
     270           1 :         char buf[16]="";
     271           2 :         if(!(path=get_fcount_path(manio))
     272           1 :           || !(fzp=fzp_open(path, "rb")))
     273             :                 goto end;
     274           1 :         if(!fzp_gets(fzp, buf, sizeof(buf)))
     275             :         {
     276           0 :                 logp("fzp_gets on %s failed\n", path);
     277           0 :                 goto end;
     278             :         }
     279           1 :         s=strlen(buf);
     280           1 :         if(s!=9)
     281             :         {
     282           0 :                 logp("data in %s is not the right length (%lu!=9)\n", path,
     283             :                         (unsigned long)s);
     284           0 :                 goto end;
     285             :         }
     286           1 :         manio->offset->fcount=strtoul(buf, NULL, 16);
     287           1 :         ret=0;
     288             : end:
     289           1 :         fzp_close(&fzp);
     290           1 :         free_w(&path);
     291           1 :         return ret;
     292             : }
     293             : 
     294        1135 : static int sort_and_write_hooks(struct manio *manio)
     295             : {
     296             :         int i;
     297        1135 :         int ret=-1;
     298        1135 :         struct fzp *fzp=NULL;
     299        1135 :         char msg[32]="";
     300        1135 :         char *path=NULL;
     301        1135 :         int hook_count=manio->hook_count;
     302        1135 :         uint64_t *hook_sort=manio->hook_sort;
     303        1135 :         if(!hook_sort) return 0;
     304             : 
     305          20 :         snprintf(msg, sizeof(msg), "%08" PRIX64, manio->offset->fcount-1);
     306          20 :         if(!(path=prepend_s(manio->hook_dir, msg))
     307          20 :           || build_path_w(path)
     308          20 :           || !(fzp=fzp_gzopen(path, MANIO_MODE_WRITE)))
     309             :                 goto end;
     310             : 
     311          20 :         qsort(hook_sort, hook_count, sizeof(uint64_t), uint64_t_sort);
     312             : 
     313          20 :         if(write_hook_header(fzp, manio->rmanifest, msg)) goto end;
     314        2208 :         for(i=0; i<hook_count; i++)
     315             :         {
     316             :                 // Do not bother with duplicates.
     317        2208 :                 if(i && hook_sort[i]==hook_sort[i-1])
     318           0 :                         continue;
     319             : 
     320        2208 :                 if(to_fzp_fingerprint(fzp, hook_sort[i]))
     321             :                         goto end;
     322             :         }
     323          20 :         if(fzp_close(&fzp))
     324             :         {
     325           0 :                 logp("Error closing %s in %s: %s\n",
     326           0 :                         path, __func__, strerror(errno));
     327           0 :                 goto end;
     328             :         }
     329          20 :         if(manio_write_fcount(manio)) goto end;
     330          20 :         manio->hook_count=0;
     331          20 :         ret=0;
     332             : end:
     333          20 :         fzp_close(&fzp);
     334          20 :         free_w(&path);
     335          20 :         return ret;
     336             : }
     337             : 
     338        1135 : static int sort_and_write_dindex(struct manio *manio)
     339             : {
     340             :         int i;
     341        1135 :         int ret=-1;
     342        1135 :         struct fzp *fzp=NULL;
     343        1135 :         char msg[32]="";
     344        1135 :         char *path=NULL;
     345             :         struct iobuf wbuf;
     346             :         struct blk blk;
     347        1135 :         int dindex_count=manio->dindex_count;
     348        1135 :         uint64_t *dindex_sort=manio->dindex_sort;
     349        1135 :         if(!dindex_sort) return 0;
     350             : 
     351          20 :         snprintf(msg, sizeof(msg), "%08" PRIX64, manio->offset->fcount-1);
     352          20 :         if(!(path=prepend_s(manio->dindex_dir, msg))
     353          20 :           || build_path_w(path)
     354          20 :           || !(fzp=fzp_gzopen(path, MANIO_MODE_WRITE)))
     355             :                 goto end;
     356             : 
     357          20 :         qsort(dindex_sort, dindex_count, sizeof(uint64_t), uint64_t_sort);
     358             : 
     359       34899 :         for(i=0; i<dindex_count; i++)
     360             :         {
     361             :                 // Do not bother with duplicates.
     362       34879 :                 if(i && dindex_sort[i]==dindex_sort[i-1])
     363           0 :                         continue;
     364             : 
     365       34879 :                 blk.savepath=dindex_sort[i];
     366       34879 :                 blk_to_iobuf_savepath(&blk, &wbuf);
     367       34879 :                 if(iobuf_send_msg_fzp(&wbuf, fzp)) return -1;
     368             :         }
     369          20 :         if(fzp_close(&fzp))
     370             :         {
     371           0 :                 logp("Error closing %s in %s: %s\n",
     372           0 :                         path, __func__, strerror(errno));
     373           0 :                 goto end;
     374             :         }
     375          20 :         manio->dindex_count=0;
     376          20 :         ret=0;
     377             : end:
     378          20 :         fzp_close(&fzp);
     379          20 :         free_w(&path);
     380          20 :         return ret;
     381             : }
     382             : 
     383        1135 : static int sort_and_write_hooks_and_dindex(struct manio *manio)
     384             : {
     385        1135 :         return sort_and_write_hooks(manio)
     386        1135 :           || sort_and_write_dindex(manio);
     387             : }
     388             : 
     389         954 : int manio_close(struct manio **manio)
     390             : {
     391         954 :         int ret=0;
     392             : //      int fd;
     393         954 :         if(!manio || !*manio) return ret;
     394         806 :         if(sort_and_write_hooks_and_dindex(*manio))
     395           0 :                 ret=-1;
     396             : /*
     397             :         There is no gzfileno()
     398             :         if((fd=fzp_fileno((*manio)->fzp))<0)
     399             :         {
     400             :                 logp("Could not get fileno in %s for %s: %s\n", __func__,
     401             :                         (*manio)->manifest, strerror(errno));
     402             :                 ret=-1;
     403             :         }
     404             :         // Should probably have a flush before fsync too.
     405             :         if(fsync(fd))
     406             :         {
     407             :                 logp("Error in fsync in %s for %s: %s\n", __func__,
     408             :                         (*manio)->manifest, strerror(errno));
     409             :                 ret=-1;
     410             :         }
     411             : */
     412         806 :         if(fzp_close(&((*manio)->fzp)))
     413           0 :                 ret=-1;
     414         806 :         sync();
     415         806 :         manio_free_content(*manio);
     416         806 :         free_v((void **)manio);
     417         806 :         return ret;
     418             : }
     419             : 
     420             : // Return -1 for error, 0 for stuff read OK, 1 for end of files.
     421      115440 : int manio_read_with_blk(struct manio *manio, struct sbuf *sb, struct blk *blk)
     422             : {
     423             :         while(1)
     424             :         {
     425      115598 :                 if(!manio->fzp)
     426             :                 {
     427         183 :                         if(manio_open_next_fpath(manio)) goto error;
     428         183 :                         if(!manio->fzp) return 1; // No more files to read.
     429             :                 }
     430             : 
     431      115463 :                 switch(sbuf_fill_from_file(sb, manio->fzp, blk))
     432             :                 {
     433             :                         case 0: return 0; // Got something.
     434             :                         case 1: break; // Keep going.
     435             :                         default: goto error; // Error.
     436             :                 }
     437             : 
     438             :                 // Reached the end of the current file.
     439             :                 // Maybe there is another file to continue with.
     440         286 :                 if(sort_and_write_hooks_and_dindex(manio)
     441         286 :                   || fzp_close(&manio->fzp)) goto error;
     442             : 
     443         572 :                 if(is_single_file(manio)) return 1;
     444             :         }
     445             : 
     446             : error:
     447             :         return -1;
     448             : }
     449             : 
     450       54948 : int manio_read(struct manio *manio, struct sbuf *sb)
     451             : {
     452       54948 :         return manio_read_with_blk(manio, sb, NULL);
     453             : }
     454             : 
     455          43 : static int reset_sig_count_and_close(struct manio *manio)
     456             : {
     457          43 :         if(sort_and_write_hooks_and_dindex(manio)) return -1;
     458          43 :         if(fzp_close(&manio->fzp)) return -1;
     459          43 :         manio->sig_count=0;
     460          43 :         if(manio_open_next_fpath(manio)) return -1;
     461          43 :         return 0;
     462             : }
     463             : 
     464             : #ifndef UTEST
     465             : static
     466             : #endif
     467        3574 : int manio_find_boundary(uint8_t *md5sum)
     468             : {
     469             :         int i;
     470             :         uint8_t x;
     471             :         uint8_t y;
     472        3574 :         uint8_t b4=0;
     473             : 
     474             :         // I am currently making it look for four of the same consecutive
     475             :         // characters in the md5sum.
     476       56854 :         for(i=0; i<MD5_DIGEST_LENGTH-1; i++)
     477             :         {
     478       53333 :                 x=md5sum[i]>>4;
     479       53333 :                 y=md5sum[i]&0x0F;
     480       53333 :                 if(x==y)
     481             :                 {
     482        3303 :                         if(x!=md5sum[i+1]>>4)
     483        3106 :                                 continue;
     484         197 :                         if(i && x==b4)
     485             :                                 return 1;
     486         175 :                         if(x==(md5sum[i+1]&0x0F))
     487             :                                 return 1;
     488             :                 }
     489             :                 b4=y;
     490             :         }
     491             :         return 0;
     492             : }
     493             : 
     494             : // After conditions are met, close the file currently being written to.
     495             : // Allow the number of signatures to be vary between MANIFEST_SIG_MIN and
     496             : // MANIFEST_SIG_MAX. This will hopefully allow fewer candidate manifests
     497             : // generated, since the boundary will be able to vary.
     498      187793 : static int check_sig_count(struct manio *manio, struct blk *blk)
     499             : {
     500      187793 :         manio->sig_count++;
     501             : 
     502      187793 :         if(manio->sig_count<MANIFEST_SIG_MIN)
     503             :                 return 0; // Not yet time to close.
     504             : 
     505        3558 :         if(manio->sig_count>=MANIFEST_SIG_MAX)
     506           0 :                 return reset_sig_count_and_close(manio); // Time to close.
     507             : 
     508             :         // At this point, dynamically decide based on the current msg.
     509        3558 :         if(manio_find_boundary(blk->md5sum))
     510          43 :                 return reset_sig_count_and_close(manio); // Time to close.
     511             :         return 0;
     512             : }
     513             : 
     514      187793 : static int write_sig_msg(struct manio *manio, struct blk *blk)
     515             : {
     516             :         struct iobuf wbuf;
     517      187793 :         if(!manio->fzp && manio_open_next_fpath(manio)) return -1;
     518      187793 :         blk_to_iobuf_sig_and_savepath(blk, &wbuf);
     519      187793 :         if(iobuf_send_msg_fzp(&wbuf, manio->fzp)) return -1;
     520      187793 :         return check_sig_count(manio, blk);
     521             : }
     522             : 
     523      187793 : int manio_write_sig_and_path(struct manio *manio, struct blk *blk)
     524             : {
     525      187793 :         if(manio->protocol==PROTO_1) return 0;
     526      187793 :         if(manio->hook_sort && blk_fingerprint_is_hook(blk))
     527             :         {
     528             :                 // Add to list of hooks for this manifest chunk.
     529        2208 :                 manio->hook_sort[manio->hook_count++]=blk->fingerprint;
     530             :         }
     531      187793 :         if(manio->dindex_sort)
     532             :         {
     533       35171 :                 uint64_t savepath=blk->savepath;
     534       35171 :                 savepath &= 0xFFFFFFFFFFFF0000ULL;
     535             :                 // Ignore obvious duplicates.
     536       35171 :                 if(!manio->dindex_count
     537       35152 :                   || manio->dindex_sort[manio->dindex_count-1]!=savepath)
     538             :                 {
     539             :                         // Add to list of dindexes for this manifest chunk.
     540       34879 :                         manio->dindex_sort[manio->dindex_count++]=savepath;
     541             :                 }
     542             :         }
     543      187793 :         return write_sig_msg(manio, blk);
     544             : }
     545             : 
     546       91874 : int manio_write_sbuf(struct manio *manio, struct sbuf *sb)
     547             : {
     548       91874 :         if(!manio->fzp && manio_open_next_fpath(manio)) return -1;
     549       91874 :         return sbuf_to_manifest(sb, manio->fzp);
     550             : }
     551             : 
     552       33804 : int manio_write_cntr(struct manio *manio, struct sbuf *sb,
     553             :         enum cntr_manio what)
     554             : {
     555       33804 :         if(!manio->fzp && manio_open_next_fpath(manio)) return -1;
     556       33804 :         return sbuf_to_manifest_cntr(sb, manio->fzp, what);
     557             : }
     558             : 
     559             : // Return -1 on error, 0 on OK, 1 for srcmanio finished.
     560          18 : int manio_copy_entry(struct sbuf *csb, struct sbuf *sb,
     561             :         struct manio *srcmanio, struct manio *dstmanio,
     562             :         const char *seed_src, const char *seed_dst)
     563             : {
     564             :         int ars;
     565             :         struct iobuf copy1;
     566             :         struct iobuf copy2;
     567             :         struct blk *blk;
     568          18 :         memset(&copy1, 0, sizeof(copy1));
     569          18 :         memset(&copy2, 0, sizeof(copy2));
     570          18 :         if(!(blk=blk_alloc()))
     571             :                 goto error;
     572             : 
     573             :         // Use the most recent stat for the new manifest.
     574          18 :         if(dstmanio)
     575             :         {
     576          18 :                 int e=0;
     577             :                 struct iobuf save1;
     578             :                 struct iobuf save2;
     579          18 :                 memset(&save1, 0, sizeof(save1));
     580          18 :                 memset(&save2, 0, sizeof(save2));
     581             :         
     582             :                 // When seeding, adjust the prefixes, but we need to remember
     583             :                 // the original too.
     584          18 :                 if(seed_src && seed_dst)
     585             :                 {
     586           0 :                         char *tmp=sb->path.buf+strlen(seed_src);
     587           0 :                         if(!(copy1.buf=strdup_w(seed_dst, __func__)))
     588             :                                 goto error;
     589           0 :                         if(astrcat(&copy1.buf, "/", __func__))
     590             :                                 goto error;
     591           0 :                         if(*tmp=='/')
     592           0 :                                 tmp++;
     593           0 :                         if(astrcat(&copy1.buf, tmp, __func__))
     594             :                                 goto error;
     595           0 :                         copy1.len=strlen(copy1.buf);
     596           0 :                         copy1.cmd=sb->path.cmd;
     597             : 
     598           0 :                         if(sb->protocol1 && sb->protocol1->datapth.buf
     599           0 :                           && !strncmp(sb->protocol1->datapth.buf,
     600             :                                 TREE_DIR, strlen(TREE_DIR)))
     601             :                         {
     602           0 :                                 tmp=sb->protocol1->datapth.buf
     603             :                                         +strlen(TREE_DIR)
     604           0 :                                         +strlen(seed_src);
     605           0 :                                 if(*tmp=='/')
     606           0 :                                         tmp++;
     607           0 :                                 if(!(copy2.buf=strdup_w(TREE_DIR, __func__)))
     608             :                                         goto error;
     609           0 :                                 if(*seed_dst!='/'
     610           0 :                                   && astrcat(&copy2.buf, "/", __func__))
     611             :                                         goto error;
     612           0 :                                 if(astrcat(&copy2.buf, seed_dst, __func__)
     613           0 :                                   || astrcat(&copy2.buf, "/", __func__)
     614           0 :                                   || astrcat(&copy2.buf, tmp, __func__))
     615             :                                         goto error;
     616           0 :                                 copy2.len=strlen(copy2.buf);
     617           0 :                                 copy2.cmd=sb->protocol1->datapth.cmd;
     618             :                         }
     619             : 
     620           0 :                         save1=sb->path;
     621           0 :                         sb->path=copy1;
     622             : 
     623           0 :                         if(copy2.buf)
     624             :                         {
     625           0 :                                 save2=sb->protocol1->datapth;
     626           0 :                                 sb->protocol1->datapth=copy2;
     627             :                         }
     628             :                 }
     629          18 :                 e=manio_write_sbuf(dstmanio, sb);
     630          18 :                 if(copy1.buf)
     631             :                 {
     632           0 :                         sb->path=save1;
     633           0 :                         iobuf_free_content(&copy1);
     634             :                 }
     635          18 :                 if(copy2.buf)
     636             :                 {
     637           0 :                         sb->protocol1->datapth=save2;
     638           0 :                         iobuf_free_content(&copy2);
     639             :                 }
     640          18 :                 if(e)
     641             :                         goto error;
     642             : 
     643          18 :                 if(dstmanio->protocol==PROTO_1)
     644             :                 {
     645           8 :                         sbuf_free_content(csb);
     646           8 :                         blk_free(&blk);
     647           8 :                         return 0;
     648             :                 }
     649             :         }
     650             : 
     651          10 :         copy1.len=csb->path.len;
     652          10 :         copy1.cmd=csb->path.cmd;
     653          10 :         if(!(copy1.buf=strdup_w(csb->path.buf, __func__)))
     654             :                 goto error;
     655             :         while(1)
     656             :         {
     657          30 :                 if((ars=manio_read_with_blk(srcmanio, csb, blk))<0)
     658             :                         goto error;
     659          30 :                 else if(ars>0)
     660             :                 {
     661             :                         // Finished.
     662           5 :                         sbuf_free_content(csb);
     663           5 :                         blk_free(&blk);
     664           5 :                         iobuf_free_content(&copy1);
     665           5 :                         return 1;
     666             :                 }
     667             : 
     668             :                 // Got something.
     669          25 :                 if(iobuf_pathcmp(&csb->path, &copy1))
     670             :                 {
     671             :                         // Found the next entry.
     672           5 :                         iobuf_free_content(&copy1);
     673           5 :                         blk_free(&blk);
     674           5 :                         return 0;
     675             :                 }
     676          20 :                 if(dstmanio)
     677             :                 {
     678          20 :                         if(!dstmanio->fzp
     679           0 :                           && manio_open_next_fpath(dstmanio))
     680             :                                 goto error;
     681             : 
     682          20 :                         if(csb->endfile.buf)
     683             :                         {
     684          10 :                                 if(iobuf_send_msg_fzp(&csb->endfile,
     685             :                                         dstmanio->fzp)) goto error;
     686             :                         }
     687             :                         else
     688             :                         {
     689             :                                 // Should have the next signature.
     690             :                                 // Write it to the destination manifest.
     691          10 :                                 if(manio_write_sig_and_path(dstmanio, blk))
     692             :                                         goto error;
     693             :                         }
     694             :                 }
     695             :         }
     696             : 
     697             : error:
     698           0 :         blk_free(&blk);
     699           0 :         iobuf_free_content(&copy1);
     700           0 :         iobuf_free_content(&copy2);
     701           0 :         return -1;
     702             : }
     703             : 
     704           0 : int manio_forward_through_sigs(struct sbuf *csb, struct manio *manio)
     705             : {
     706             :         // Call manio_copy_entry with nothing to write to, so
     707             :         // that we forward through the sigs in manio.
     708           0 :         return manio_copy_entry(csb, NULL, manio, NULL, NULL, NULL);
     709             : }
     710             : 
     711       14734 : man_off_t *manio_tell(struct manio *manio)
     712             : {
     713       14734 :         man_off_t *offset=NULL;
     714       14734 :         if(!manio->fzp)
     715             :         {
     716           0 :                 logp("%s called on null fzp\n", __func__);
     717           0 :                 if(manio->offset && manio->offset->fpath)
     718           0 :                         logp("manio->offset->fpath: %s\n",
     719             :                                 manio->offset->fpath);
     720             :                 goto error;
     721             :         }
     722       14734 :         if(!(offset=man_off_t_alloc())
     723       14734 :           || !(offset->fpath=strdup_w(manio->offset->fpath, __func__))
     724       14734 :           || (offset->offset=fzp_tell(manio->fzp))<0)
     725             :                 goto error;
     726       14734 :         offset->fcount=manio->offset->fcount;
     727       14734 :         return offset;
     728             : error:
     729           0 :         man_off_t_free(&offset);
     730           0 :         return NULL;
     731             : }
     732             : 
     733         246 : int manio_seek(struct manio *manio, man_off_t *offset)
     734             : {
     735         246 :         fzp_close(&manio->fzp);
     736         246 :         if(!(manio->fzp=fzp_gzopen(offset->fpath, manio->mode))
     737         246 :           || fzp_seek(manio->fzp, offset->offset, SEEK_SET))
     738             :                 return -1;
     739         492 :         man_off_t_free_content(manio->offset);
     740         246 :         if(!(manio->offset->fpath=strdup_w(offset->fpath, __func__)))
     741             :                 return -1;
     742         246 :         manio->offset->offset=offset->offset;
     743         246 :         manio->offset->fcount=offset->fcount;
     744         246 :         return 0;
     745             : }
     746             : 
     747         100 : static int remove_trailing_files(struct manio *manio, man_off_t *offset)
     748             : {
     749         100 :         int ret=-1;
     750         100 :         char *fpath=NULL;
     751             :         struct stat statp;
     752             :         while(1)
     753             :         {
     754         100 :                 free_w(&fpath);
     755         100 :                 if(!(fpath=get_next_fpath(manio, offset)))
     756             :                         goto end;
     757         200 :                 if(lstat(fpath, &statp)) break;
     758           0 :                 if(!S_ISREG(statp.st_mode))
     759             :                         goto end;
     760           0 :                 if(recursive_delete(fpath))
     761             :                         goto end;
     762             :         }
     763             :         ret=0;
     764             : end:
     765         100 :         free_w(&fpath);
     766         100 :         return ret;
     767             : }
     768             : 
     769         200 : int manio_close_and_truncate(struct manio **manio,
     770             :         man_off_t *offset, int compression)
     771             : {
     772         200 :         int ret=-1;
     773         200 :         errno=0;
     774         400 :         if(!is_single_file(*manio)
     775         100 :           && remove_trailing_files(*manio, offset))
     776             :                 goto end;
     777         200 :         if(manio_close(manio)) goto end;
     778         200 :         if(fzp_truncate(offset->fpath, FZP_FILE, offset->offset, compression))
     779             :         {
     780           0 :                 logp("Could not fzp_truncate %s in %s(): %s\n",
     781             :                         offset->fpath, __func__, strerror(errno));
     782           0 :                 goto end;
     783             :         }
     784             :         ret=0;
     785             : end:
     786         200 :         return ret;
     787             : }

Generated by: LCOV version 1.13