LCOV - code coverage report
Current view: top level - src - rs_buf.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 100 161 62.1 %
Date: 2022-12-03 01:09:05 Functions: 6 11 54.5 %

          Line data    Source code
       1             : /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*-
       2             :  *
       3             :  * librsync -- the library for network deltas
       4             :  * $Id: buf.c,v 1.22 2003/12/16 00:10:55 abo Exp $
       5             :  * 
       6             :  * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org>
       7             :  * 
       8             :  * This program is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public License
      10             :  * as published by the Free Software Foundation; either version 2.1 of
      11             :  * the License, or (at your option) any later version.
      12             :  * 
      13             :  * This program is distributed in the hope that it will be useful, but
      14             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  * 
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with this program; if not, write to the Free Software
      20             :  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
      21             :  */
      22             : 
      23             :                               /*
      24             :                                | Pick a window, Jimmy, you're leaving.
      25             :                                |   -- Martin Schwenke, regularly
      26             :                                */
      27             : 
      28             : 
      29             : /*
      30             :  * buf.c -- Buffers that map between stdio file streams and librsync
      31             :  * streams.  As the stream consumes input and produces output, it is
      32             :  * refilled from appropriate input and output FILEs.  A dynamically
      33             :  * allocated buffer of configurable size is used as an intermediary.
      34             :  */
      35             : 
      36             : #include "burp.h"
      37             : #include "rs_buf.h"
      38             : #include "cmd.h"
      39             : #include "alloc.h"
      40             : #include "asfd.h"
      41             : #include "async.h"
      42             : #include "handy.h"
      43             : #include "iobuf.h"
      44             : #include "log.h"
      45             : #include "md5.h"
      46             : 
      47             : /* use fseeko instead of fseek for long file support if we have it */
      48             : #ifdef HAVE_FSEEKO
      49             : #define fseek fseeko
      50             : #endif
      51             : 
      52          24 : rs_filebuf_t *rs_filebuf_new(struct BFILE *bfd,
      53             :         struct fzp *fzp,
      54             :         struct asfd *asfd,
      55             :         size_t buf_len,
      56             :         size_t data_len)
      57             : {
      58          24 :         rs_filebuf_t *pf=NULL;
      59          24 :         if(!(pf=(struct rs_filebuf *)calloc_w(1,
      60             :                 sizeof(struct rs_filebuf), __func__))
      61          23 :           || !(pf->buf=(char *)calloc_w(1, buf_len, __func__))
      62          23 :           || !(pf->md5=md5_alloc(__func__)))
      63             :                 goto error;
      64          23 :         pf->buf_len=buf_len;
      65          23 :         pf->fzp=fzp;
      66          23 :         pf->bfd=bfd;
      67          23 :         pf->bytes=0;
      68          23 :         pf->data_len=data_len;
      69          23 :         if(data_len>0)
      70           9 :                 pf->do_known_byte_count=1;
      71             :         else
      72          14 :                 pf->do_known_byte_count=0;
      73          23 :         if(!md5_init(pf->md5))
      74             :         {
      75           0 :                 logp("md5_init() failed\n");
      76           0 :                 goto error;
      77             :         }
      78          23 :         pf->asfd=asfd;
      79          23 :         return pf;
      80             : error:
      81           1 :         rs_filebuf_free(&pf);
      82           1 :         return NULL;
      83             : }
      84             : 
      85      119322 : void rs_filebuf_free(rs_filebuf_t **fb) 
      86             : {
      87      119322 :         if(!fb || !*fb) return;
      88          23 :         md5_free(&((*fb)->md5));
      89          23 :         free_w(&((*fb)->buf));
      90          23 :         free_v((void **)fb);
      91             : }
      92             : 
      93             : /*
      94             :  * If the stream has no more data available, read some from F into
      95             :  * BUF, and let the stream use that.  On return, SEEN_EOF is true if
      96             :  * the end of file has passed into the stream.
      97             :  */
      98          14 : rs_result rs_infilebuf_fill(__attribute__ ((unused)) rs_job_t *job,
      99             :         rs_buffers_t *buf, void *opaque)
     100             : {
     101          14 :         int len=0;
     102          14 :         rs_filebuf_t *fb=(rs_filebuf_t *) opaque;
     103             : 
     104             :         //logp("rs_infilebuf_fill\n");
     105             : 
     106             :         /* This is only allowed if either the buf has no input buffer
     107             :          * yet, or that buffer could possibly be BUF. */
     108          14 :         if(buf->next_in)
     109             :         {
     110             :                 //logp("infilebuf avail_in %d buf_len %d\n",
     111             :                 //      buf->avail_in, fb->buf_len);
     112           5 :                 if(buf->avail_in > fb->buf_len)
     113             :                 {
     114           1 :                         logp("buf->avail_in > fb->buf_len (%lu > %lu) in %s\n",
     115             :                                 (unsigned long)buf->avail_in,
     116             :                                 (unsigned long)fb->buf_len, __func__);
     117           1 :                         return RS_IO_ERROR;
     118             :                 }
     119           4 :                 if(buf->next_in < fb->buf)
     120             :                 {
     121           1 :                         logp("buf->next_in < fb->buf in %s\n", __func__);
     122           1 :                         return RS_IO_ERROR;
     123             :                 }
     124           3 :                 if(buf->next_in > fb->buf + fb->buf_len)
     125             :                 {
     126           1 :                         logp("buf->next_in > fb->buf + fb->buf_len in %s\n",
     127             :                                 __func__);
     128           1 :                         return RS_IO_ERROR;
     129             :                 }
     130             :         }
     131             :         else
     132             :         {
     133           9 :                 if(buf->avail_in)
     134             :                 {
     135           1 :                         logp("buf->avail_in is %lu in %s\n",
     136             :                                 (unsigned long)buf->avail_in, __func__);
     137           1 :                         return RS_IO_ERROR;
     138             :                 }
     139             :         }
     140             : 
     141          10 :         if(buf->eof_in)
     142             :                 return RS_DONE;
     143             : 
     144           9 :         if(buf->avail_in)
     145             :                 /* Still some data remaining.  Perhaps we should read
     146             :                    anyhow? */
     147             :                 return RS_DONE;
     148             : 
     149           9 :         if(fb->asfd)
     150             :         {
     151             :                 static struct iobuf *rbuf=NULL;
     152           4 :                 rbuf=fb->asfd->rbuf;
     153             : 
     154           4 :                 switch(rbuf->cmd)
     155             :                 {
     156             :                         case CMD_APPEND:
     157           2 :                                 memcpy(fb->buf, rbuf->buf, rbuf->len);
     158           2 :                                 len=rbuf->len;
     159             :                                 break;
     160             :                         case CMD_END_FILE:
     161           2 :                                 buf->eof_in=1;
     162           2 :                                 return RS_DONE;
     163             :                         default:
     164           0 :                                 iobuf_log_unexpected(rbuf, __func__);
     165           0 :                                 return RS_IO_ERROR;
     166             :                 }
     167             :         }
     168           5 :         else if(fb->bfd)
     169             :         {
     170           2 :                 if(fb->do_known_byte_count)
     171             :                 {
     172           0 :                         if(fb->data_len>0)
     173             :                         {
     174           0 :                                 len=fb->bfd->read(fb->bfd, fb->buf,
     175           0 :                                         min(fb->buf_len, fb->data_len));
     176           0 :                                 fb->data_len-=len;
     177             :                         }
     178             :                         else
     179             :                         {
     180             :                                 // We have already read as much data as the VSS
     181             :                                 // header told us to, so set len=0 in order to
     182             :                                 // finish up.
     183             :                                 len=0;
     184             :                         }
     185             :                 }
     186             :                 else
     187           2 :                         len=fb->bfd->read(fb->bfd, fb->buf, fb->buf_len);
     188           2 :                 if(len==0)
     189             :                 {
     190             :                         //logp("bread: eof\n");
     191           2 :                         buf->eof_in=1;
     192           2 :                         return RS_DONE;
     193             :                 }
     194           0 :                 else if(len<0)
     195             :                 {
     196           0 :                         logp("rs_infilebuf_fill: error in bread: %s\n",
     197           0 :                                 strerror(errno));
     198           0 :                         return RS_IO_ERROR;
     199             :                 }
     200             :                 //logp("bread: ok: %d\n", len);
     201           0 :                 fb->bytes+=len;
     202           0 :                 if(!md5_update(fb->md5, fb->buf, len))
     203             :                 {
     204           0 :                         logp("rs_infilebuf_fill: md5_update() failed\n");
     205           0 :                         return RS_IO_ERROR;
     206             :                 }
     207             :         }
     208           3 :         else if(fb->fzp)
     209             :         {
     210           2 :                 if((len=fzp_read(fb->fzp, fb->buf, fb->buf_len))<=0)
     211             :                 {
     212             :                         // This will happen if file size is a multiple of
     213             :                         // input block len.
     214           2 :                         if(fzp_eof(fb->fzp))
     215             :                         {
     216           2 :                                 buf->eof_in=1;
     217           2 :                                 return RS_DONE;
     218             :                         }
     219             :                         else
     220             :                         {
     221           0 :                                 logp("rs_infilebuf_fill: got return %d when trying to read\n", len);
     222           0 :                                 return RS_IO_ERROR;
     223             :                         }
     224             :                 }
     225           0 :                 fb->bytes+=len;
     226           0 :                 if(!md5_update(fb->md5, fb->buf, len))
     227             :                 {
     228           0 :                         logp("rs_infilebuf_fill: md5_update() failed\n");
     229           0 :                         return RS_IO_ERROR;
     230             :                 }
     231             :         }
     232             : 
     233           3 :         buf->avail_in = len;
     234           3 :         buf->next_in = fb->buf;
     235             : 
     236           3 :         return RS_DONE;
     237             : }
     238             : 
     239             : /*
     240             :  * The buf is already using BUF for an output buffer, and probably
     241             :  * contains some buffered output now.  Write this out to F, and reset
     242             :  * the buffer cursor.
     243             :  */
     244          15 : rs_result rs_outfilebuf_drain(__attribute__ ((unused)) rs_job_t *job,
     245             :         rs_buffers_t *buf, void *opaque)
     246             : {
     247          15 :         rs_filebuf_t *fb=(rs_filebuf_t *)opaque;
     248             :         size_t wlen;
     249             : 
     250             :         //logp("in rs_outfilebuf_drain\n");
     251             : 
     252             :         /* This is only allowed if either the buf has no output buffer
     253             :          * yet, or that buffer could possibly be BUF. */
     254          15 :         if(!buf->next_out)
     255             :         {
     256           6 :                 if(buf->avail_out)
     257             :                 {
     258           1 :                         logp("buf->avail_out is %lu in %s\n",
     259             :                                 (unsigned long)buf->avail_out, __func__);
     260           1 :                         return RS_IO_ERROR;
     261             :                 }
     262           5 :                 buf->next_out = fb->buf;
     263           5 :                 buf->avail_out = fb->buf_len;
     264           5 :                 return RS_DONE;
     265             :         }
     266             : 
     267           9 :         if(buf->avail_out > fb->buf_len)
     268             :         {
     269           1 :                 logp("buf->avail_out > fb->buf_len (%lu > %lu) in %s\n",
     270             :                         (unsigned long)buf->avail_out,
     271             :                         (unsigned long)fb->buf_len, __func__);
     272           1 :                 return RS_IO_ERROR;
     273             :         }
     274           8 :         if(buf->next_out < fb->buf)
     275             :         {
     276           1 :                 logp("buf->next_out < fb->buf (%p < %p) in %s\n",
     277             :                         buf->next_out, fb->buf, __func__);
     278           1 :                 return RS_IO_ERROR;
     279             :         }
     280           7 :         if(buf->next_out > fb->buf + fb->buf_len)
     281             :         {
     282           1 :                 logp("buf->next_out > fb->buf + fb->buf_len in %s\n",
     283             :                         __func__);
     284           1 :                 return RS_IO_ERROR;
     285             :         }
     286             : 
     287           6 :         if((wlen=buf->next_out-fb->buf)>0)
     288             :         {
     289             :                 //logp("wlen: %d\n", wlen);
     290           6 :                 if(fb->asfd)
     291             :                 {
     292           6 :                         size_t w=wlen;
     293             :                         struct iobuf wbuf;
     294           6 :                         iobuf_set(&wbuf, CMD_APPEND, fb->buf, wlen);
     295           6 :                         switch(fb->asfd->append_all_to_write_buffer(
     296             :                                 fb->asfd, &wbuf))
     297             :                         {
     298             :                                 case APPEND_OK: break;
     299           0 :                                 case APPEND_BLOCKED: return RS_BLOCKED;
     300             :                                 case APPEND_ERROR:
     301           0 :                                 default: return RS_IO_ERROR;
     302             :                         }
     303           6 :                         fb->bytes+=w;
     304             :                 }
     305             :                 else
     306             :                 {
     307           0 :                         size_t result=0;
     308           0 :                         result=fzp_write(fb->fzp, fb->buf, wlen);
     309           0 :                         if(wlen!=result)
     310             :                         {
     311           0 :                                 logp("error draining buf to file: %s",
     312           0 :                                                 strerror(errno));
     313           0 :                                 return RS_IO_ERROR;
     314             :                         }
     315             :                 }
     316             :         }
     317             : 
     318           6 :         buf->next_out = fb->buf;
     319           6 :         buf->avail_out = fb->buf_len;
     320             : 
     321           6 :         return RS_DONE;
     322             : }
     323             : 
     324          14 : static rs_result rs_async_drive(rs_job_t *job, rs_buffers_t *rsbuf,
     325             :         rs_driven_cb in_cb, void *in_opaque,
     326             :         rs_driven_cb out_cb, void *out_opaque)
     327             : {
     328             :         rs_result result;
     329             :         rs_result iores;
     330             : 
     331          14 :         if(!rsbuf->eof_in && in_cb)
     332             :         {
     333           8 :                 iores=in_cb(job, rsbuf, in_opaque);
     334           8 :                 if(iores!=RS_DONE) return iores;
     335             :         }
     336             : 
     337          14 :         result=rs_job_iter(job, rsbuf);
     338          14 :         if(result!=RS_DONE && result!=RS_BLOCKED)
     339             :                 return result;
     340             : 
     341          14 :         if(out_cb)
     342             :         {
     343          10 :                 iores=(out_cb)(job, rsbuf, out_opaque);
     344          10 :                 if(iores!=RS_DONE) return iores;
     345             :         }
     346             : 
     347             :         return result;
     348             : }
     349             : 
     350          14 : rs_result rs_async(rs_job_t *job, rs_buffers_t *rsbuf,
     351             :         rs_filebuf_t *infb, rs_filebuf_t *outfb)
     352             : {
     353          14 :         return rs_async_drive(job, rsbuf,
     354             :                 infb ? rs_infilebuf_fill : NULL, infb,
     355             :                 outfb ? rs_outfilebuf_drain : NULL, outfb);
     356             : }
     357             : 
     358           0 : static rs_result rs_whole_gzrun(
     359             :         rs_job_t *job, struct fzp *in_file, struct fzp *out_file)
     360             : {
     361             :         rs_buffers_t buf;
     362             :         rs_result result;
     363           0 :         rs_filebuf_t *in_fb=NULL;
     364           0 :         rs_filebuf_t *out_fb=NULL;
     365             : 
     366           0 :         if(in_file)
     367           0 :                 in_fb=rs_filebuf_new(NULL,
     368             :                         in_file, NULL, ASYNC_BUF_LEN, -1);
     369           0 :         if(out_file)
     370           0 :                 out_fb=rs_filebuf_new(NULL,
     371             :                         out_file, NULL, ASYNC_BUF_LEN, -1);
     372             : 
     373           0 :         result=rs_job_drive(job, &buf,
     374             :                 in_fb ? rs_infilebuf_fill : NULL, in_fb,
     375             :                 out_fb ? rs_outfilebuf_drain : NULL, out_fb);
     376             : 
     377           0 :         rs_filebuf_free(&in_fb);
     378           0 :         rs_filebuf_free(&out_fb);
     379           0 :         return result;
     380             : }
     381             : 
     382           0 : rs_result rs_patch_gzfile(struct fzp *basis_file,
     383             :         struct fzp *delta_file, struct fzp *new_file)
     384             : {
     385             :         rs_job_t *job;
     386             :         rs_result r;
     387             : 
     388             :         // FIX THIS: Seems wrong to just pick out basis_file->fp.
     389             :         // Should probably pass a fp into rs_patch_gzfile.
     390             :         // Or, much better would be to investigate whether basis_file always
     391             :         // needs to be a FILE *. If I copy rs_file_copy_cb from librsync, and
     392             :         // rewrite it to use a struct fzp, maybe the callers to rs_patch_gzfile
     393             :         // do not need to mess around inflating files when they do not have
     394             :         // to.
     395           0 :         job=rs_patch_begin(rs_file_copy_cb, basis_file->fp);
     396           0 :         r=rs_whole_gzrun(job, delta_file, new_file);
     397           0 :         rs_job_free(job);
     398             : 
     399           0 :         return r;
     400             : }
     401             : 
     402           0 : rs_result rs_sig_gzfile(struct fzp *old_file, struct fzp *sig_file,
     403             :         size_t new_block_len, size_t strong_len,
     404             :         struct conf **confs)
     405             : {
     406             :         rs_job_t *job;
     407             :         rs_result r;
     408           0 :         job=
     409             :                 rs_sig_begin(new_block_len, strong_len
     410             : #ifndef RS_DEFAULT_STRONG_LEN
     411             :                         , rshash_to_magic_number(
     412             :                                 get_e_rshash(confs[OPT_RSHASH]))
     413             : #endif
     414             :                 );
     415             : 
     416           0 :         r=rs_whole_gzrun(job, old_file, sig_file);
     417           0 :         rs_job_free(job);
     418             : 
     419           0 :         return r;
     420             : }
     421             : 
     422           0 : rs_result rs_delta_gzfile(rs_signature_t *sig, struct fzp *new_file,
     423             :         struct fzp *delta_file)
     424             : {
     425             :         rs_job_t *job;
     426             :         rs_result r;
     427             : 
     428           0 :         job=rs_delta_begin(sig);
     429           0 :         r=rs_whole_gzrun(job, new_file, delta_file);
     430           0 :         rs_job_free(job);
     431             : 
     432           0 :         return r;
     433             : }
     434             : 
     435             : #ifndef RS_DEFAULT_STRONG_LEN
     436             : rs_magic_number rshash_to_magic_number(enum rshash r)
     437             : {
     438             :         switch(r)
     439             :         {
     440             :                 case RSHASH_BLAKE2:
     441             :                         return RS_BLAKE2_SIG_MAGIC;
     442             :                 default:
     443             :                         return RS_MD4_SIG_MAGIC;
     444             :         }
     445             : }
     446             : #endif
     447             : 
     448           0 : rs_result rs_loadsig_fzp(struct fzp *fzp, rs_signature_t **sig)
     449             : {
     450             :         rs_result r;
     451             :         rs_job_t *job;
     452             : 
     453           0 :         job=rs_loadsig_begin(sig);
     454           0 :         r=rs_whole_gzrun(job, fzp, NULL);
     455           0 :         rs_job_free(job);
     456             : 
     457           0 :         return r;
     458             : }

Generated by: LCOV version 1.13