LCOV - code coverage report
Current view: top level - src/client/protocol1 - backup_phase2.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 157 200 78.5 %
Date: 2016-07-02 Functions: 9 10 90.0 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../action.h"
       3             : #include "../../alloc.h"
       4             : #include "../../asfd.h"
       5             : #include "../../async.h"
       6             : #include "../../attribs.h"
       7             : #include "../../cmd.h"
       8             : #include "../../cntr.h"
       9             : #include "../../conf.h"
      10             : #include "../../log.h"
      11             : #include "../../protocol1/handy.h"
      12             : #include "../../protocol1/msg.h"
      13             : #include "../extrameta.h"
      14             : #include "../find.h"
      15             : 
      16           2 : static int rs_loadsig_network_run(struct asfd *asfd,
      17             :         rs_job_t *job, struct cntr *cntr)
      18             : {
      19           2 :         int ret=-1;
      20             :         rs_buffers_t buf;
      21             :         rs_result result;
      22           2 :         rs_filebuf_t *in_fb=NULL;
      23             :         memset(&buf, 0, sizeof(buf));
      24             : 
      25           2 :         if(!(in_fb=rs_filebuf_new(NULL,
      26           2 :                 NULL, asfd, ASYNC_BUF_LEN, -1)))
      27             :                 goto end;
      28             : 
      29             :         while(1)
      30             :         {
      31           4 :                 iobuf_free_content(asfd->rbuf);
      32           4 :                 if(asfd->read(asfd)) goto end;
      33           4 :                 if(asfd->rbuf->cmd==CMD_MESSAGE
      34           4 :                   || asfd->rbuf->cmd==CMD_WARNING)
      35             :                 {
      36           0 :                         log_recvd(asfd->rbuf, cntr, 0);
      37           0 :                         continue;
      38             :                 }
      39           4 :                 switch((result=rs_async(job, &buf, in_fb, NULL)))
      40             :                 {
      41             :                         case RS_BLOCKED:
      42             :                         case RS_RUNNING:
      43             :                                 continue;
      44             :                         case RS_DONE:
      45             :                                 ret=0;
      46             :                                 goto end;
      47             :                         default:
      48             :                                 logp("error in rs_async for sig: %d\n",
      49           0 :                                         result);
      50           0 :                                 goto end;
      51             :                 }
      52             :         }
      53             : 
      54             : end:
      55           2 :         iobuf_free_content(asfd->rbuf);
      56           2 :         rs_filebuf_free(&in_fb);
      57           2 :         return ret;
      58             : }
      59             : 
      60           2 : static int load_signature(struct asfd *asfd,
      61             :         rs_signature_t **sumset, struct cntr *cntr)
      62             : {
      63             :         rs_job_t *job;
      64             : 
      65           2 :         if(!(job=rs_loadsig_begin(sumset)))
      66             :         {
      67           0 :                 logp("could not start sig job.\n");
      68           0 :                 return -1;
      69             :         }
      70           2 :         if(rs_loadsig_network_run(asfd, job, cntr))
      71             :                 return -1;
      72           2 :         if(rs_build_hash_table(*sumset))
      73             :                 return -1;
      74           2 :         rs_job_free(job);
      75           2 :         return 0;
      76             : }
      77             : 
      78           2 : static int load_signature_and_send_delta(struct asfd *asfd,
      79             :         BFILE *bfd, uint64_t *bytes, uint64_t *sentbytes,
      80             :         struct cntr *cntr)
      81             : {
      82           2 :         int ret=-1;
      83           2 :         rs_job_t *job=NULL;
      84           2 :         rs_signature_t *sumset=NULL;
      85             :         uint8_t checksum[MD5_DIGEST_LENGTH];
      86           2 :         rs_filebuf_t *infb=NULL;
      87           2 :         rs_filebuf_t *outfb=NULL;
      88             :         rs_buffers_t rsbuf;
      89             :         memset(&rsbuf, 0, sizeof(rsbuf));
      90             : 
      91           2 :         if(load_signature(asfd, &sumset, cntr))
      92             :                 goto end;
      93             : 
      94           2 :         if(!(job=rs_delta_begin(sumset)))
      95             :         {
      96           0 :                 logp("could not start delta job.\n");
      97           0 :                 goto end;
      98             :         }
      99             : 
     100           2 :         if(!(infb=rs_filebuf_new(bfd,
     101           2 :                 NULL, NULL, ASYNC_BUF_LEN, bfd->datalen))
     102           4 :           || !(outfb=rs_filebuf_new(NULL,
     103           2 :                 NULL, asfd, ASYNC_BUF_LEN, -1)))
     104             :         {
     105           0 :                 logp("could not rs_filebuf_new for delta\n");
     106           0 :                 goto end;
     107             :         }
     108             : 
     109             :         while(1)
     110             :         {
     111             :                 rs_result result;
     112           6 :                 switch((result=rs_async(job, &rsbuf, infb, outfb)))
     113             :                 {
     114             :                         case RS_DONE:
     115           2 :                                 *bytes=infb->bytes;
     116           2 :                                 *sentbytes=outfb->bytes;
     117           2 :                                 if(!MD5_Final(checksum, &(infb->md5)))
     118             :                                 {
     119           0 :                                         logp("MD5_Final() failed\n");
     120           0 :                                         goto end;
     121             :                                 }
     122           2 :                                 if(write_endfile(asfd, *bytes, checksum))
     123             :                                         goto end;
     124           2 :                                 ret=0;
     125           2 :                                 goto end;
     126             :                         case RS_BLOCKED:
     127             :                         case RS_RUNNING:
     128             :                                 // FIX ME: get it to read stuff here too.
     129             :                                 // (errors, for example)
     130           4 :                                 if(asfd->as->write(asfd->as))
     131             :                                         goto end;
     132             :                                 continue;
     133             :                         default:
     134             :                                 logp("error in rs_async for delta: %d\n",
     135           0 :                                         result);
     136           0 :                                 goto end;
     137             :                 }
     138             :         }
     139             : end:
     140           2 :         rs_filebuf_free(&infb);
     141           2 :         rs_filebuf_free(&outfb);
     142           2 :         if(job) rs_job_free(job);
     143           2 :         if(sumset) rs_free_sumset(sumset);
     144           2 :         return ret;
     145             : }
     146             : 
     147           6 : static int send_whole_file_w(struct asfd *asfd,
     148             :         struct sbuf *sb, const char *datapth,
     149             :         int quick_read, uint64_t *bytes, const char *encpassword,
     150             :         struct cntr *cntr, int compression, BFILE *bfd,
     151             :         const char *extrameta, size_t elen)
     152             : {
     153           6 :         if((compression || encpassword) && sb->path.cmd!=CMD_EFS_FILE)
     154             :                 return send_whole_file_gzl(asfd,
     155             :                   sb->path.buf, datapth, quick_read, bytes,
     156           0 :                   encpassword, cntr, compression, bfd, extrameta, elen);
     157             :         else
     158             :                 return send_whole_filel(asfd,
     159             :                   sb->path.cmd, datapth, quick_read, bytes,
     160           6 :                   cntr, bfd, extrameta, elen);
     161             : }
     162             : 
     163           0 : static int forget_file(struct asfd *asfd, struct sbuf *sb, struct conf **confs)
     164             : {
     165             :         // Tell the server to forget about this
     166             :         // file, otherwise it might get stuck
     167             :         // on a select waiting for it to arrive.
     168           0 :         if(asfd->write_str(asfd, CMD_INTERRUPT, sb->path.buf))
     169             :                 return 0;
     170             : 
     171           0 :         if(sb->path.cmd==CMD_FILE && sb->protocol1->datapth.buf)
     172             :         {
     173           0 :                 rs_signature_t *sumset=NULL;
     174             :                 // The server will be sending us a signature.
     175             :                 // Munch it up then carry on.
     176           0 :                 if(load_signature(asfd, &sumset, get_cntr(confs))) return -1;
     177           0 :                 else rs_free_sumset(sumset);
     178             :         }
     179             :         return 0;
     180             : }
     181             : 
     182           8 : static int size_checks(struct asfd *asfd, struct sbuf *sb, struct conf **confs)
     183             : {
     184           8 :         if(sb->path.cmd!=CMD_FILE
     185           8 :           && sb->path.cmd!=CMD_ENC_FILE
     186           8 :           && sb->path.cmd!=CMD_EFS_FILE)
     187             :                 return 0;
     188          16 :         if(get_uint64_t(confs[OPT_MIN_FILE_SIZE])
     189           8 :           && (uint64_t)sb->statp.st_size<get_uint64_t(confs[OPT_MIN_FILE_SIZE]))
     190             :         {
     191           0 :                 logw(asfd, get_cntr(confs), "File size decreased below min_file_size after initial scan: %c:%s\n", sb->path.cmd, sb->path.buf);
     192           0 :                 return -1;
     193             :         }
     194          16 :         if(get_uint64_t(confs[OPT_MAX_FILE_SIZE])
     195           8 :           && (uint64_t)sb->statp.st_size>get_uint64_t(confs[OPT_MAX_FILE_SIZE]))
     196             :         {
     197           0 :                 logw(asfd, get_cntr(confs), "File size increased above max_file_size after initial scan: %c:%s\n", sb->path.cmd, sb->path.buf);
     198           0 :                 return -1;
     199             :         }
     200             :         return 0;
     201             : }
     202             : 
     203          14 : static int deal_with_data(struct asfd *asfd, struct sbuf *sb,
     204             :         BFILE *bfd, struct conf **confs)
     205             : {
     206           8 :         int ret=-1;
     207           8 :         int forget=0;
     208           8 :         size_t elen=0;
     209           8 :         char *extrameta=NULL;
     210           8 :         uint64_t bytes=0;
     211           8 :         int conf_compression=get_int(confs[OPT_COMPRESSION]);
     212           8 :         struct cntr *cntr=get_cntr(confs);
     213             : 
     214           8 :         sb->compression=conf_compression;
     215             : 
     216           8 :         iobuf_copy(&sb->path, asfd->rbuf);
     217           8 :         iobuf_init(asfd->rbuf);
     218             : 
     219             : #ifdef HAVE_WIN32
     220             :         if(win32_lstat(sb->path.buf, &sb->statp, &sb->winattr))
     221             : #else
     222          16 :         if(lstat(sb->path.buf, &sb->statp))
     223             : #endif
     224             :         {
     225           0 :                 logw(asfd, cntr, "Path has vanished: %s\n", sb->path.buf);
     226           0 :                 if(forget_file(asfd, sb, confs)) goto error;
     227             :                 goto end;
     228             :         }
     229             : 
     230           8 :         if(size_checks(asfd, sb, confs)) forget++;
     231             : 
     232             :         sb->compression=in_exclude_comp(get_strlist(confs[OPT_EXCOM]),
     233           8 :                 sb->path.buf, conf_compression);
     234           8 :         if(attribs_encode(sb)) goto error;
     235             : 
     236           8 :         if(sb->path.cmd!=CMD_METADATA
     237           8 :           && sb->path.cmd!=CMD_ENC_METADATA)
     238             :         {
     239           8 :                 if(bfd->open_for_send(bfd, asfd,
     240             :                         sb->path.buf, sb->winattr,
     241           8 :                         get_int(confs[OPT_ATIME]), cntr, PROTO_1))
     242           0 :                                 forget++;
     243             :         }
     244             : 
     245           8 :         if(forget)
     246             :         {
     247           0 :                 if(forget_file(asfd, sb, confs)) goto error;
     248             :                 goto end;
     249             :         }
     250             : 
     251           8 :         if(sb->path.cmd==CMD_METADATA
     252             :           || sb->path.cmd==CMD_ENC_METADATA
     253           8 :           || sb->path.cmd==CMD_VSS
     254           8 :           || sb->path.cmd==CMD_ENC_VSS
     255             : #ifdef HAVE_WIN32
     256             :           || get_int(confs[OPT_STRIP_VSS])
     257             : #endif
     258             :           )
     259             :         {
     260           0 :                 if(get_extrameta(asfd, bfd, sb->path.buf,
     261           0 :                         S_ISDIR(sb->statp.st_mode),
     262           0 :                         &extrameta, &elen, cntr))
     263             :                 {
     264             :                         logw(asfd, cntr,
     265           0 :                                 "Meta data error for %s\n", sb->path.buf);
     266           0 :                         goto end;
     267             :                 }
     268           0 :                 if(extrameta)
     269             :                 {
     270             : #ifdef HAVE_WIN32
     271             :                         if(get_int(confs[OPT_STRIP_VSS]))
     272             :                         {
     273             :                                 free_w(&extrameta);
     274             :                                 elen=0;
     275             :                         }
     276             : #endif
     277             :                 }
     278             :                 else
     279             :                 {
     280             :                         logw(asfd, cntr,
     281           0 :                                 "No meta data after all: %s\n", sb->path.buf);
     282           0 :                         goto end;
     283             :                 }
     284             :         }
     285             : 
     286           8 :         if(sb->path.cmd==CMD_FILE
     287           4 :           && sb->protocol1->datapth.buf)
     288             :         {
     289           2 :                 uint64_t sentbytes=0;
     290             :                 // Need to do sig/delta stuff.
     291           4 :                 if(asfd->write(asfd, &(sb->protocol1->datapth))
     292           2 :                   || asfd->write(asfd, &sb->attr)
     293           2 :                   || asfd->write(asfd, &sb->path)
     294           4 :                   || load_signature_and_send_delta(asfd, bfd,
     295           2 :                         &bytes, &sentbytes, cntr))
     296             :                 {
     297             :                         logp("error in sig/delta for %s (%s)\n",
     298           0 :                                 sb->path.buf, sb->protocol1->datapth.buf);
     299           0 :                         goto end;
     300             :                 }
     301             :                 else
     302             :                 {
     303           2 :                         cntr_add(get_cntr(confs), CMD_FILE_CHANGED, 1);
     304           2 :                         cntr_add_bytes(get_cntr(confs), bytes);
     305           2 :                         cntr_add_sentbytes(get_cntr(confs), sentbytes);
     306           2 :                 }
     307             :         }
     308             :         else
     309             :         {
     310             :                 //logp("need to send whole file: %s\n", sb.path);
     311             :                 // send the whole file.
     312             : 
     313          12 :                 if((asfd->write(asfd, &sb->attr)
     314           6 :                   || asfd->write(asfd, &sb->path))
     315          12 :                   || send_whole_file_w(asfd, sb, NULL, 0, &bytes,
     316           6 :                         get_string(confs[OPT_ENCRYPTION_PASSWORD]),
     317             :                         cntr, sb->compression,
     318          12 :                         bfd, extrameta, elen))
     319             :                                 goto end;
     320             :                 else
     321             :                 {
     322           6 :                         cntr_add(get_cntr(confs), sb->path.cmd, 1);
     323           6 :                         cntr_add_bytes(get_cntr(confs), bytes);
     324           6 :                         cntr_add_sentbytes(get_cntr(confs), bytes);
     325             :                 }
     326             :         }
     327             : 
     328             : end:
     329             :         ret=0;
     330             : error:
     331             : #ifdef HAVE_WIN32
     332             :         // If using Windows do not close bfd - it needs
     333             :         // to stay open to read VSS/file data/VSS.
     334             :         // It will get closed either when given a
     335             :         // different file path, or when this function
     336             :         // exits.
     337             : #else
     338           8 :         bfd->close(bfd, asfd);
     339             : #endif
     340           8 :         sbuf_free_content(sb);
     341           8 :         free_w(&extrameta);
     342           8 :         return ret;
     343             : }
     344             : 
     345          19 : static int parse_rbuf(struct asfd *asfd, struct sbuf *sb,
     346             :         BFILE *bfd, struct conf **confs)
     347             : {
     348             :         static struct iobuf *rbuf;
     349          19 :         rbuf=asfd->rbuf;
     350             :         //printf("now %d: %c:%s\n", rbuf->len, rbuf->cmd, rbuf->buf);
     351          19 :         if(rbuf->cmd==CMD_DATAPTH)
     352             :         {
     353           2 :                 iobuf_move(&(sb->protocol1->datapth), rbuf);
     354             :         }
     355          17 :         else if(rbuf->cmd==CMD_ATTRIBS)
     356             :         {
     357             :                 // Ignore the stat data - we will fill it
     358             :                 // in again. Some time may have passed by now,
     359             :                 // and it is best to make it as fresh as
     360             :                 // possible.
     361             :         }
     362          18 :         else if(iobuf_is_filedata(rbuf)
     363           9 :           || iobuf_is_vssdata(rbuf))
     364             :         {
     365           8 :                 if(deal_with_data(asfd, sb, bfd, confs))
     366             :                         return -1;
     367             :         }
     368           1 :         else if(rbuf->cmd==CMD_MESSAGE
     369           1 :           || rbuf->cmd==CMD_WARNING)
     370             :         {
     371           1 :                 struct cntr *cntr=NULL;
     372           1 :                 if(confs) cntr=get_cntr(confs);
     373           1 :                 log_recvd(rbuf, cntr, 0);
     374             :         }
     375             :         else
     376             :         {
     377           0 :                 iobuf_log_unexpected(rbuf, __func__);
     378           0 :                 return -1;
     379             :         }
     380             :         return 0;
     381             : }
     382             : 
     383           6 : static int do_backup_phase2_client(struct asfd *asfd,
     384             :         struct conf **confs, int resume)
     385             : {
     386           6 :         int ret=-1;
     387             :         // For efficiency, open Windows files for the VSS data, and do not
     388             :         // close them until another time around the loop, when the actual
     389             :         // data is read.
     390           6 :         BFILE *bfd=NULL;
     391           6 :         struct sbuf *sb=NULL;
     392           6 :         struct iobuf *rbuf=NULL;
     393           6 :         struct cntr *cntr=NULL;
     394           6 :         if(confs) cntr=get_cntr(confs);
     395             : 
     396           6 :         if(!asfd)
     397             :         {
     398           1 :                 logp("%s() called without asfd!\n", __func__);
     399           1 :                 goto end;
     400             :         }
     401           5 :         rbuf=asfd->rbuf;
     402             : 
     403          10 :         if(!(bfd=bfile_alloc())
     404           5 :           || !(sb=sbuf_alloc(PROTO_1)))
     405             :                 goto end;
     406           5 :         bfile_init(bfd, 0, cntr);
     407             : 
     408           5 :         if(!resume)
     409             :         {
     410             :                 // Only do this bit if the server did not tell us to resume.
     411          10 :                 if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
     412           5 :                   || asfd_read_expect(asfd, CMD_GEN, "ok"))
     413             :                         goto end;
     414             :         }
     415           0 :         else if(get_int(confs[OPT_SEND_CLIENT_CNTR]))
     416             :         {
     417             :                 // On resume, the server might update the client with cntr.
     418           0 :                 if(cntr_recv(asfd, confs)) goto end;
     419             :         }
     420             : 
     421             :         while(1)
     422             :         {
     423          24 :                 iobuf_free_content(rbuf);
     424          24 :                 if(asfd->read(asfd)) goto end;
     425          23 :                 else if(!rbuf->buf) continue;
     426             : 
     427          23 :                 if(rbuf->cmd==CMD_GEN && !strcmp(rbuf->buf, "backupphase2end"))
     428             :                 {
     429           4 :                         if(asfd->write_str(asfd, CMD_GEN, "okbackupphase2end"))
     430             :                                 goto end;
     431           4 :                         ret=0;
     432           4 :                         break;
     433             :                 }
     434             : 
     435          19 :                 if(parse_rbuf(asfd, sb, bfd, confs))
     436             :                         goto end;
     437             :         }
     438             : 
     439             : end:
     440             :         // It is possible for a bfd to still be open.
     441           6 :         if(bfd) bfd->close(bfd, asfd);
     442           6 :         bfile_free(&bfd);
     443           6 :         iobuf_free_content(rbuf);
     444           6 :         sbuf_free(&sb);
     445           6 :         return ret;
     446             : }
     447             : 
     448           6 : int backup_phase2_client_protocol1(struct asfd *asfd,
     449             :         struct conf **confs, int resume)
     450             : {
     451           6 :         int ret=0;
     452           6 :         struct cntr *cntr=NULL;
     453           6 :         if(confs) cntr=get_cntr(confs);
     454             : 
     455           6 :         logp("Phase 2 begin (send backup data)\n");
     456           6 :         logf("\n");
     457             : 
     458           6 :         ret=do_backup_phase2_client(asfd, confs, resume);
     459             : 
     460           6 :         cntr_print_end(cntr);
     461           6 :         cntr_print(cntr, ACTION_BACKUP);
     462             : 
     463           6 :         if(ret) logp("Error in phase 2\n");
     464           6 :         logp("Phase 2 end (send file data)\n");
     465             : 
     466           6 :         return ret;
     467             : }

Generated by: LCOV version 1.10