LCOV - code coverage report
Current view: top level - src/protocol1 - rs_buf.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 2 190 1.1 %
Date: 2015-10-31 Functions: 1 13 7.7 %

          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 "../cntr.h"
      43             : #include "../handy.h"
      44             : #include "../iobuf.h"
      45             : #include "../log.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           0 : void *rs_alloc(size_t size)
      53             : {
      54           0 :         return calloc_w(1, size, __func__);
      55             : }
      56             : 
      57           0 : rs_filebuf_t *rs_filebuf_new(struct asfd *asfd,
      58             :         BFILE *bfd, struct fzp *fzp, int fd,
      59             :         size_t buf_len, size_t data_len, struct cntr *cntr)
      60             : {
      61           0 :         rs_filebuf_t *pf=NULL;
      62           0 :         if(!(pf=(struct rs_filebuf *)calloc_w(1,
      63           0 :                 sizeof(struct rs_filebuf), __func__))) return NULL;
      64             : 
      65           0 :         if(!(pf->buf=(char *)calloc_w(1, buf_len, __func__)))
      66           0 :                 goto error;
      67           0 :         pf->buf_len=buf_len;
      68           0 :         pf->fzp=fzp;
      69           0 :         pf->fd=fd;
      70           0 :         pf->bfd=bfd;
      71           0 :         pf->bytes=0;
      72           0 :         pf->data_len=data_len;
      73           0 :         if(data_len>0)
      74           0 :                 pf->do_known_byte_count=1;
      75             :         else
      76           0 :                 pf->do_known_byte_count=0;
      77           0 :         pf->cntr=cntr;
      78           0 :         if(!MD5_Init(&(pf->md5)))
      79             :         {
      80           0 :                 logp("MD5_Init() failed\n");
      81           0 :                 goto error;
      82             :         }
      83           0 :         pf->asfd=asfd;
      84           0 :         return pf;
      85             : error:
      86           0 :         rs_filebuf_free(&pf);
      87           0 :         return NULL;
      88             : }
      89             : 
      90      116666 : void rs_filebuf_free(rs_filebuf_t **fb) 
      91             : {
      92      233332 :         if(!fb || !*fb) return;
      93           0 :         free_w(&((*fb)->buf));
      94           0 :         free_v((void **)fb);
      95             : }
      96             : 
      97             : /*
      98             :  * If the stream has no more data available, read some from F into
      99             :  * BUF, and let the stream use that.  On return, SEEN_EOF is true if
     100             :  * the end of file has passed into the stream.
     101             :  */
     102           0 : rs_result rs_infilebuf_fill(rs_job_t *job, rs_buffers_t *buf, void *opaque)
     103             : {
     104           0 :         int len=0;
     105           0 :         rs_filebuf_t *fb=(rs_filebuf_t *) opaque;
     106             :         struct cntr *cntr;
     107           0 :         int fd=fb->fd;
     108           0 :         cntr=fb->cntr;
     109             : 
     110             :         //logp("rs_infilebuf_fill\n");
     111             : 
     112             :         /* This is only allowed if either the buf has no input buffer
     113             :          * yet, or that buffer could possibly be BUF. */
     114           0 :         if(buf->next_in)
     115             :         {
     116             :                 //logp("infilebuf avail_in %d buf_len %d\n",
     117             :                 //      buf->avail_in, fb->buf_len);
     118           0 :                 if(buf->avail_in > fb->buf_len)
     119             :                 {
     120             :                         logp("buf->avail_in > fb->buf_len (%d > %d) in %s\n",
     121           0 :                                 buf->avail_in, fb->buf_len, __func__);
     122           0 :                         return RS_IO_ERROR;
     123             :                 }
     124           0 :                 if(buf->next_in < fb->buf)
     125             :                 {
     126           0 :                         logp("buf->next_in < fb->buf in %s\n", __func__);
     127           0 :                         return RS_IO_ERROR;
     128             :                 }
     129           0 :                 if(buf->next_in > fb->buf + fb->buf_len)
     130             :                 {
     131             :                         logp("buf->next_in > fb->buf + fb->buf_len in %s\n",
     132           0 :                                 __func__);
     133           0 :                         return RS_IO_ERROR;
     134             :                 }
     135             :         }
     136             :         else
     137             :         {
     138           0 :                 if(buf->avail_in)
     139             :                 {
     140             :                         logp("buf->avail_in is %d in %s\n",
     141           0 :                                 buf->avail_in, __func__);
     142           0 :                         return RS_IO_ERROR;
     143             :                 }
     144             :         }
     145             : 
     146           0 :         if(buf->eof_in) return RS_DONE;
     147             : 
     148           0 :         if(buf->avail_in)
     149             :                 /* Still some data remaining.  Perhaps we should read
     150             :                    anyhow? */
     151           0 :                 return RS_DONE;
     152             : 
     153           0 :         if(fd>=0)
     154             :         {
     155             :                 static struct iobuf *rbuf=NULL;
     156           0 :                 rbuf=fb->asfd->rbuf;
     157             : 
     158           0 :                 if(fb->asfd->read(fb->asfd)) return RS_IO_ERROR;
     159           0 :                 if(rbuf->cmd==CMD_APPEND)
     160             :                 {
     161             :                         //logp("got '%c' in fd infilebuf: %d\n",
     162             :                         //      CMD_APPEND, rbuf->len);
     163           0 :                         memcpy(fb->buf, rbuf->buf, rbuf->len);
     164           0 :                         len=rbuf->len;
     165           0 :                         iobuf_free_content(rbuf);
     166             :                 }
     167           0 :                 else if(rbuf->cmd==CMD_END_FILE)
     168             :                 {
     169           0 :                         iobuf_free_content(rbuf);
     170             :                         //logp("got %c in fd infilebuf\n", CMD_END_FILE);
     171           0 :                         buf->eof_in=1;
     172           0 :                         return RS_DONE;
     173             :                 }
     174           0 :                 else if(rbuf->cmd==CMD_WARNING)
     175             :                 {
     176           0 :                         logp("WARNING: %s\n", rbuf->buf);
     177           0 :                         cntr_add(cntr, rbuf->cmd, 0);
     178           0 :                         iobuf_free_content(rbuf);
     179           0 :                         return RS_DONE;
     180             :                 }
     181             :                 else
     182             :                 {
     183           0 :                         iobuf_log_unexpected(rbuf, __func__);
     184           0 :                         iobuf_free_content(rbuf);
     185           0 :                         return RS_IO_ERROR;
     186             :                 }
     187             :         }
     188           0 :         else if(fb->bfd)
     189             :         {
     190           0 :                 if(fb->do_known_byte_count)
     191             :                 {
     192           0 :                         if(fb->data_len>0)
     193             :                         {
     194             :                                 len=fb->bfd->read(fb->bfd, fb->buf,
     195           0 :                                         min(fb->buf_len, fb->data_len));
     196           0 :                                 fb->data_len-=len;
     197             :                         }
     198             :                         else
     199             :                         {
     200             :                                 // We have already read as much data as the VSS
     201             :                                 // header told us to, so set len=0 in order to
     202             :                                 // finish up.
     203           0 :                                 len=0;
     204             :                         }
     205             :                 }
     206             :                 else
     207           0 :                         len=fb->bfd->read(fb->bfd, fb->buf, fb->buf_len);
     208           0 :                 if(len==0)
     209             :                 {
     210             :                         //logp("bread: eof\n");
     211           0 :                         buf->eof_in=1;
     212           0 :                         return RS_DONE;
     213             :                 }
     214           0 :                 else if(len<0)
     215             :                 {
     216           0 :                         logp("rs_infilebuf_fill: error in bread\n");
     217           0 :                         return RS_IO_ERROR;
     218             :                 }
     219             :                 //logp("bread: ok: %d\n", len);
     220           0 :                 fb->bytes+=len;
     221           0 :                 if(!MD5_Update(&(fb->md5), fb->buf, len))
     222             :                 {
     223           0 :                         logp("rs_infilebuf_fill: MD5_Update() failed\n");
     224           0 :                         return RS_IO_ERROR;
     225             :                 }
     226             :         }
     227           0 :         else if(fb->fzp)
     228             :         {
     229           0 :                 if((len=fzp_read(fb->fzp, fb->buf, fb->buf_len))<=0)
     230             :                 {
     231             :                         // This will happen if file size is a multiple of
     232             :                         // input block len.
     233           0 :                         if(fzp_eof(fb->fzp))
     234             :                         {
     235           0 :                                 buf->eof_in=1;
     236           0 :                                 return RS_DONE;
     237             :                         }
     238             :                         else
     239             :                         {
     240           0 :                                 logp("rs_infilebuf_fill: got return %d when trying to read\n", len);
     241           0 :                                 return RS_IO_ERROR;
     242             :                         }
     243             :                 }
     244           0 :                 fb->bytes+=len;
     245           0 :                 if(!MD5_Update(&(fb->md5), fb->buf, len))
     246             :                 {
     247           0 :                         logp("rs_infilebuf_fill: MD5_Update() failed\n");
     248           0 :                         return RS_IO_ERROR;
     249             :                 }
     250             :         }
     251             : 
     252           0 :         buf->avail_in = len;
     253           0 :         buf->next_in = fb->buf;
     254             : 
     255           0 :         return RS_DONE;
     256             : }
     257             : 
     258             : /*
     259             :  * The buf is already using BUF for an output buffer, and probably
     260             :  * contains some buffered output now.  Write this out to F, and reset
     261             :  * the buffer cursor.
     262             :  */
     263           0 : rs_result rs_outfilebuf_drain(rs_job_t *job, rs_buffers_t *buf, void *opaque)
     264             : {
     265           0 :         rs_filebuf_t *fb=(rs_filebuf_t *)opaque;
     266           0 :         int fd=fb->fd;
     267             :         size_t wlen;
     268             : 
     269             :         //logp("in rs_outfilebuf_drain\n");
     270             : 
     271             :         /* This is only allowed if either the buf has no output buffer
     272             :          * yet, or that buffer could possibly be BUF. */
     273           0 :         if(!buf->next_out)
     274             :         {
     275           0 :                 if(buf->avail_out)
     276             :                 {
     277             :                         logp("buf->avail_out is %d in %s\n",
     278           0 :                                 buf->avail_out, __func__);
     279           0 :                         return RS_IO_ERROR;
     280             :                 }
     281           0 :                 buf->next_out = fb->buf;
     282           0 :                 buf->avail_out = fb->buf_len;
     283           0 :                 return RS_DONE;
     284             :         }
     285             : 
     286           0 :         if(buf->avail_out > fb->buf_len)
     287             :         {
     288             :                 logp("buf->avail_out > fb->buf_len (%d > %d) in %s\n",
     289           0 :                         buf->avail_out, fb->buf_len, __func__);
     290           0 :                 return RS_IO_ERROR;
     291             :         }
     292           0 :         if(buf->next_out < fb->buf)
     293             :         {
     294             :                 logp("buf->next_out < fb->buf (%p < %p) in %s\n",
     295           0 :                         buf->next_out, fb->buf, __func__);
     296           0 :                 return RS_IO_ERROR;
     297             :         }
     298           0 :         if(buf->next_out > fb->buf + fb->buf_len)
     299             :         {
     300             :                 logp("buf->next_out > fb->buf + fb->buf_len in %s\n",
     301           0 :                         __func__);
     302           0 :                 return RS_IO_ERROR;
     303             :         }
     304             : 
     305           0 :         if((wlen=buf->next_out-fb->buf)>0)
     306             :         {
     307             :                 //logp("wlen: %d\n", wlen);
     308           0 :                 if(fd>0)
     309             :                 {
     310           0 :                         size_t w=wlen;
     311             :                         static struct iobuf *wbuf=NULL;
     312           0 :                         if(!wbuf && !(wbuf=iobuf_alloc())) return RS_IO_ERROR;
     313           0 :                         wbuf->cmd=CMD_APPEND;
     314           0 :                         wbuf->buf=fb->buf;
     315           0 :                         wbuf->len=wlen;
     316           0 :                         switch(fb->asfd->append_all_to_write_buffer(
     317           0 :                                 fb->asfd, wbuf))
     318             :                         {
     319           0 :                                 case APPEND_OK: break;
     320           0 :                                 case APPEND_BLOCKED: return RS_BLOCKED;
     321             :                                 case APPEND_ERROR:
     322           0 :                                 default: return RS_IO_ERROR;
     323             :                         }
     324           0 :                         fb->bytes+=w;
     325             :                 }
     326             :                 else
     327             :                 {
     328           0 :                         size_t result=0;
     329           0 :                         result=fzp_write(fb->fzp, fb->buf, wlen);
     330           0 :                         if(wlen!=result)
     331             :                         {
     332             :                                 logp("error draining buf to file: %s",
     333           0 :                                                 strerror(errno));
     334           0 :                                 return RS_IO_ERROR;
     335             :                         }
     336             :                 }
     337             :         }
     338             : 
     339           0 :         buf->next_out = fb->buf;
     340           0 :         buf->avail_out = fb->buf_len;
     341             : 
     342           0 :         return RS_DONE;
     343             : }
     344             : 
     345           0 : static rs_result rs_async_drive(rs_job_t *job, rs_buffers_t *rsbuf,
     346             :              rs_driven_cb in_cb, void *in_opaque,
     347             :              rs_driven_cb out_cb, void *out_opaque)
     348             : {
     349             :         rs_result result;
     350             :         rs_result iores;
     351             : 
     352           0 :         if(!rsbuf->eof_in && in_cb)
     353             :         {
     354           0 :                 iores=in_cb(job, rsbuf, in_opaque);
     355           0 :                 if(iores!=RS_DONE) return iores;
     356             :         }
     357             : 
     358           0 :         result=rs_job_iter(job, rsbuf);
     359           0 :         if(result!=RS_DONE && result!=RS_BLOCKED)
     360           0 :                 return result;
     361             : 
     362           0 :         if(out_cb)
     363             :         {
     364           0 :                 iores=(out_cb)(job, rsbuf, out_opaque);
     365           0 :                 if(iores!=RS_DONE) return iores;
     366             :         }
     367             : 
     368           0 :         return result;
     369             : }
     370             : 
     371           0 : rs_result rs_async(rs_job_t *job, rs_buffers_t *rsbuf,
     372             :         rs_filebuf_t *infb, rs_filebuf_t *outfb)
     373             : {
     374             :         return rs_async_drive(job, rsbuf,
     375             :                 infb ? rs_infilebuf_fill : NULL, infb,
     376           0 :                 outfb ? rs_outfilebuf_drain : NULL, outfb);
     377             : }
     378             : 
     379           0 : static rs_result rs_whole_gzrun(struct asfd *asfd,
     380             :         rs_job_t *job, struct fzp *in_file, struct fzp *out_file,
     381             :         struct cntr *cntr)
     382             : {
     383             :         rs_buffers_t buf;
     384             :         rs_result result;
     385           0 :         rs_filebuf_t *in_fb=NULL;
     386           0 :         rs_filebuf_t *out_fb=NULL;
     387             : 
     388           0 :         if(in_file)
     389             :                 in_fb=rs_filebuf_new(asfd, NULL,
     390           0 :                         in_file, -1, ASYNC_BUF_LEN, -1, cntr);
     391           0 :         if(out_file)
     392             :                 out_fb=rs_filebuf_new(asfd, NULL,
     393           0 :                         out_file, -1, ASYNC_BUF_LEN, -1, cntr);
     394             : 
     395             :         result=rs_job_drive(job, &buf,
     396             :                 in_fb ? rs_infilebuf_fill : NULL, in_fb,
     397           0 :                 out_fb ? rs_outfilebuf_drain : NULL, out_fb);
     398             : 
     399           0 :         rs_filebuf_free(&in_fb);
     400           0 :         rs_filebuf_free(&out_fb);
     401           0 :         return result;
     402             : }
     403             : 
     404           0 : rs_result rs_patch_gzfile(struct asfd *asfd, struct fzp *basis_file,
     405             :         struct fzp *delta_file, struct fzp *new_file,
     406             :         struct cntr *cntr)
     407             : {
     408             :         rs_job_t *job;
     409             :         rs_result r;
     410             : 
     411             :         // FIX THIS: Seems wrong to just pick out basis_file->fp.
     412             :         // Should probably pass a fp into rs_patch_gzfile.
     413             :         // Or, much better would be to investigate whether basis_file always
     414             :         // needs to be a FILE *. If I copy rs_file_copy_cb from librsync, and
     415             :         // rewrite it to use a struct fzp, maybe the callers to rs_patch_gzfile
     416             :         // do not need to mess around inflating files when they do not have
     417             :         // to.
     418           0 :         job=rs_patch_begin(rs_file_copy_cb, basis_file->fp);
     419           0 :         r=rs_whole_gzrun(asfd, job, delta_file, new_file, cntr);
     420           0 :         rs_job_free(job);
     421             : 
     422           0 :         return r;
     423             : }
     424             : 
     425           0 : rs_result rs_sig_gzfile(struct asfd *asfd,
     426             :         struct fzp *old_file, struct fzp *sig_file,
     427             :         size_t new_block_len, size_t strong_len,
     428             :         struct conf **confs)
     429             : {
     430             :         rs_job_t *job;
     431             :         rs_result r;
     432             :         job=
     433             :                 rs_sig_begin(new_block_len, strong_len
     434             : #ifndef RS_DEFAULT_STRONG_LEN
     435             :                         , rshash_to_magic_number(
     436             :                                 get_e_rshash(confs[OPT_RSHASH]))
     437             : #endif
     438           0 :                 );
     439             : 
     440           0 :         r=rs_whole_gzrun(asfd, job, old_file, sig_file, get_cntr(confs));
     441           0 :         rs_job_free(job);
     442             : 
     443           0 :         return r;
     444             : }
     445             : 
     446           0 : rs_result rs_delta_gzfile(struct asfd *asfd,
     447             :         rs_signature_t *sig, struct fzp *new_file,
     448             :         struct fzp *delta_file,
     449             :         struct cntr *cntr)
     450             : {
     451             :         rs_job_t *job;
     452             :         rs_result r;
     453             : 
     454           0 :         job=rs_delta_begin(sig);
     455           0 :         r=rs_whole_gzrun(asfd, job, new_file, delta_file, cntr);
     456           0 :         rs_job_free(job);
     457             : 
     458           0 :         return r;
     459             : }
     460             : 
     461             : #ifndef RS_DEFAULT_STRONG_LEN
     462             : rs_magic_number rshash_to_magic_number(enum rshash r)
     463             : {
     464             :         switch(r)
     465             :         {
     466             :                 case RSHASH_BLAKE2: return RS_BLAKE2_SIG_MAGIC;
     467             :                 default: return RS_MD4_SIG_MAGIC;
     468             :         }
     469             : }
     470             : #endif
     471             : 
     472           0 : rs_result rs_loadsig_fzp(struct fzp *fzp,
     473             :         rs_signature_t **sig, rs_stats_t *stats)
     474             : {
     475           0 :         return rs_loadsig_file(fzp->fp, sig, stats);
     476             : }
     477             : 
     478           0 : rs_result rs_loadsig_network_run(struct asfd *asfd,
     479             :         rs_job_t *job, struct cntr *cntr)
     480             : {
     481             :         rs_buffers_t buf;
     482             :         rs_result result;
     483           0 :         rs_filebuf_t *in_fb=NULL;
     484             : 
     485           0 :         if(!(in_fb=rs_filebuf_new(asfd, NULL,
     486           0 :                 NULL, asfd->fd, ASYNC_BUF_LEN, -1, cntr)))
     487             :         {
     488           0 :                 result=RS_MEM_ERROR;
     489           0 :                 goto end;
     490             :         }
     491             : 
     492           0 :         result=rs_job_drive(job, &buf, rs_infilebuf_fill, in_fb, NULL, NULL);
     493             : 
     494             : end:
     495           0 :         rs_filebuf_free(&in_fb);
     496           0 :         return result;
     497             : }

Generated by: LCOV version 1.10