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: 54 228 23.7 %
Date: 2015-11-30 Functions: 3 10 30.0 %

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

Generated by: LCOV version 1.10