LCOV - code coverage report
Current view: top level - src - sbuf.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 148 173 85.5 %
Date: 2016-01-31 Functions: 16 17 94.1 %

          Line data    Source code
       1             : #include "burp.h"
       2             : #include "sbuf.h"
       3             : #include "alloc.h"
       4             : #include "asfd.h"
       5             : #include "attribs.h"
       6             : #include "cmd.h"
       7             : #include "conf.h"
       8             : #include "handy.h"
       9             : #include "log.h"
      10             : #include "msg.h"
      11             : #include "protocol2/blk.h"
      12             : #include "server/protocol2/rblk.h"
      13             : 
      14      132384 : struct sbuf *sbuf_alloc(enum protocol protocol)
      15             : {
      16             :         struct sbuf *sb;
      17      132384 :         if(!(sb=(struct sbuf *)calloc_w(1, sizeof(struct sbuf), __func__)))
      18             :                 return NULL;
      19      132384 :         iobuf_init(&sb->path);
      20      132384 :         iobuf_init(&sb->attr);
      21      132384 :         sb->attr.cmd=CMD_ATTRIBS;
      22      132384 :         iobuf_init(&sb->link);
      23      132384 :         iobuf_init(&sb->endfile);
      24      132384 :         sb->compression=-1;
      25      132384 :         if(protocol==PROTO_1)
      26             :         {
      27       31950 :                 if(!(sb->protocol1=sbuf_protocol1_alloc())) return NULL;
      28             :         }
      29             :         else
      30             :         {
      31      100434 :                 if(!(sb->protocol2=sbuf_protocol2_alloc())) return NULL;
      32             :         }
      33      132384 :         return sb;
      34             : }
      35             : 
      36      228160 : void sbuf_free_content(struct sbuf *sb)
      37             : {
      38      228160 :         iobuf_free_content(&sb->path);
      39      228160 :         iobuf_free_content(&sb->attr);
      40      228160 :         iobuf_free_content(&sb->link);
      41      228160 :         iobuf_free_content(&sb->endfile);
      42      228160 :         memset(&(sb->statp), 0, sizeof(sb->statp));
      43      228160 :         sb->compression=-1;
      44      228160 :         sb->winattr=0;
      45      228160 :         sb->flags=0;
      46      228160 :         sbuf_protocol1_free_content(sb->protocol1);
      47      228160 :         sbuf_protocol2_free_content(sb->protocol2);
      48      228160 : }
      49             : 
      50      387101 : void sbuf_free(struct sbuf **sb)
      51             : {
      52      774202 :         if(!sb || !*sb) return;
      53      132384 :         sbuf_free_content(*sb);
      54      132384 :         free_v((void **)&((*sb)->protocol1));
      55      132384 :         free_v((void **)&((*sb)->protocol2));
      56      132384 :         free_v((void **)sb);
      57             : }
      58             : 
      59         108 : int sbuf_is_link(struct sbuf *sb)
      60             : {
      61         108 :         return iobuf_is_link(&sb->path);
      62             : }
      63             : 
      64      218385 : int sbuf_is_filedata(struct sbuf *sb)
      65             : {
      66      226555 :         return iobuf_is_filedata(&sb->path);
      67             : }
      68             : 
      69       10453 : int sbuf_is_vssdata(struct sbuf *sb)
      70             : {
      71       10551 :         return iobuf_is_vssdata(&sb->path);
      72             : }
      73             : 
      74       85249 : int sbuf_is_encrypted(struct sbuf *sb)
      75             : {
      76       85249 :         return iobuf_is_encrypted(&sb->path);
      77             : }
      78             : 
      79           0 : int sbuf_is_metadata(struct sbuf *sb)
      80             : {
      81           0 :         return iobuf_is_metadata(&sb->path);
      82             : }
      83             : 
      84       91632 : int sbuf_to_manifest(struct sbuf *sb, struct fzp *fzp)
      85             : {
      86       91632 :         if(!sb->path.buf) return 0;
      87             : 
      88       91632 :         if(sb->protocol1)
      89             :         {
      90       11704 :                 if(sb->protocol1->datapth.buf
      91       11704 :                   && iobuf_send_msg_fzp(&(sb->protocol1->datapth), fzp))
      92             :                         return -1;
      93             : 
      94       11704 :                 if(iobuf_send_msg_fzp(&sb->attr, fzp))
      95             :                         return -1;
      96             :         }
      97             :         else
      98             :         {
      99             :                 // Hackity hack: Strip the file index from the beginning of
     100             :                 // the attribs so that manifests where nothing changed are
     101             :                 // identical to each other. Better would be to preserve the
     102             :                 // index.
     103             :                 char *cp;
     104      159856 :                 if(!(cp=strchr(sb->attr.buf, ' ')))
     105             :                 {
     106           0 :                         logp("Strange attributes: %s\n", sb->attr.buf);
     107           0 :                         return -1;
     108             :                 }
     109       79928 :                 if(send_msg_fzp(fzp, CMD_ATTRIBS,
     110       79928 :                         cp, sb->attr.len-(cp-sb->attr.buf)))
     111             :                                 return -1;
     112             :         }
     113       91632 :         if(iobuf_send_msg_fzp(&sb->path, fzp))
     114             :                 return -1;
     115       91632 :         if(sb->link.buf
     116       91632 :           && iobuf_send_msg_fzp(&sb->link, fzp))
     117             :                 return -1;
     118       91632 :         if(sb->endfile.buf
     119       91632 :           && iobuf_send_msg_fzp(&sb->endfile, fzp))
     120             :                 return -1;
     121             : 
     122       91632 :         return 0;
     123             : }
     124             : 
     125             : // Like pathcmp, but sort entries that have the same paths so that metadata
     126             : // comes later, and vss comes earlier, and trailing vss comes later.
     127          10 : int sbuf_pathcmp(struct sbuf *a, struct sbuf *b)
     128             : {
     129          10 :         return iobuf_pathcmp(&a->path, &b->path);
     130             : }
     131             : 
     132             : // Return -1 for error, 0 for could not open file, 1 for success.
     133          22 : int sbuf_open_file(struct sbuf *sb, struct asfd *asfd, struct cntr *cntr,
     134             :         struct conf **confs)
     135             : {
     136          22 :         BFILE *bfd=&sb->protocol2->bfd;
     137             : #ifdef HAVE_WIN32
     138             :         if(win32_lstat(sb->path.buf, &sb->statp, &sb->winattr))
     139             : #else
     140          44 :         if(lstat(sb->path.buf, &sb->statp))
     141             : #endif
     142             :         {
     143             :                 // This file is no longer available.
     144           3 :                 logw(asfd, cntr, "%s has vanished\n", sb->path.buf);
     145           3 :                 return 0;
     146             :         }
     147          19 :         sb->compression=get_int(confs[OPT_COMPRESSION]);
     148             :         // Encryption not yet implemented in protocol2.
     149             :         //sb->protocol2->encryption=conf->protocol2->encryption_password?1:0;
     150          19 :         if(attribs_encode(sb)) return -1;
     151             : 
     152          19 :         if(bfd->open_for_send(bfd, asfd,
     153             :                 sb->path.buf, sb->winattr,
     154          19 :                 get_int(confs[OPT_ATIME]), cntr, PROTO_2))
     155             :         {
     156             :                 logw(asfd, get_cntr(confs),
     157           0 :                         "Could not open %s\n", sb->path.buf);
     158           0 :                 return 0;
     159             :         }
     160             :         return 1;
     161             : }
     162             : 
     163          19 : void sbuf_close_file(struct sbuf *sb, struct asfd *asfd)
     164             : {
     165          19 :         BFILE *bfd=&sb->protocol2->bfd;
     166          19 :         bfd->close(bfd, asfd);
     167          19 : }
     168             : 
     169          38 : ssize_t sbuf_read(struct sbuf *sb, char *buf, size_t bufsize)
     170             : {
     171          38 :         BFILE *bfd=&sb->protocol2->bfd;
     172          38 :         return (ssize_t)bfd->read(bfd, buf, bufsize);
     173             : }
     174             : 
     175             : enum parse_ret
     176             : {
     177             :         PARSE_RET_ERROR=-1,
     178             :         PARSE_RET_NEED_MORE=0,
     179             :         PARSE_RET_COMPLETE=1,
     180             :         PARSE_RET_FINISHED=2,
     181             : };
     182             : 
     183      353136 : static parse_ret parse_cmd(struct sbuf *sb, struct asfd *asfd,
     184             :         struct iobuf *rbuf, struct blk *blk,
     185             :         const char *datpath, struct cntr *cntr)
     186             : {
     187      353136 :         switch(rbuf->cmd)
     188             :         {
     189             :                 case CMD_ATTRIBS:
     190       60512 :                         if(sb->protocol2)
     191       47063 :                                 sbuf_free_content(sb);
     192             :                         else
     193             :                         {
     194       13449 :                                 if(sb->protocol1->datapth.buf)
     195             :                                         // protocol 1 phase 2+ file data
     196             :                                         // starts with datapth.
     197        8204 :                                         iobuf_free_content(&sb->attr);
     198             :                                 else
     199             :                                         // protocol 1 phase 1 or non file data
     200             :                                         // starts with attribs
     201        5245 :                                         sbuf_free_content(sb);
     202             :                         }
     203       60512 :                         iobuf_move(&sb->attr, rbuf);
     204       60512 :                         attribs_decode(sb);
     205       60512 :                         return PARSE_RET_NEED_MORE;
     206             : 
     207             :                 case CMD_FILE:
     208             :                 case CMD_DIRECTORY:
     209             :                 case CMD_SOFT_LINK:
     210             :                 case CMD_HARD_LINK:
     211             :                 case CMD_SPECIAL:
     212             :                 // Stuff not currently supported in burp-2, but OK
     213             :                 // to find in burp-1.
     214             :                 case CMD_ENC_FILE:
     215             :                 case CMD_METADATA:
     216             :                 case CMD_ENC_METADATA:
     217             :                 case CMD_EFS_FILE:
     218             :                 case CMD_VSS:
     219             :                 case CMD_ENC_VSS:
     220             :                 case CMD_VSS_T:
     221             :                 case CMD_ENC_VSS_T:
     222       69576 :                         if(!sb->attr.buf)
     223             :                         {
     224           1 :                                 log_and_send(asfd, "read cmd with no attribs");
     225           1 :                                 return PARSE_RET_ERROR;
     226             :                         }
     227       69575 :                         if(sb->flags & SBUF_NEED_LINK)
     228             :                         {
     229        9083 :                                 if(cmd_is_link(rbuf->cmd))
     230             :                                 {
     231        9083 :                                         iobuf_free_content(&sb->link);
     232        9083 :                                         iobuf_move(&sb->link, rbuf);
     233        9083 :                                         sb->flags &= ~SBUF_NEED_LINK;
     234        9083 :                                         return PARSE_RET_COMPLETE;
     235             :                                 }
     236             :                                 else
     237             :                                 {
     238           0 :                                         log_and_send(asfd, "got non-link after link in manifest");
     239           0 :                                         return PARSE_RET_NEED_MORE;
     240             :                                 }
     241             :                         }
     242             :                         else
     243             :                         {
     244       60492 :                                 iobuf_free_content(&sb->path);
     245       60492 :                                 iobuf_move(&sb->path, rbuf);
     246       60492 :                                 if(cmd_is_link(rbuf->cmd))
     247             :                                 {
     248        9083 :                                         sb->flags |= SBUF_NEED_LINK;
     249        9083 :                                         return PARSE_RET_NEED_MORE;
     250             :                                 }
     251       51409 :                                 else if(sb->protocol1
     252       12085 :                                   && sb->protocol1->datapth.buf)
     253             :                                 {
     254             :                                         // Protocol1 client restore reads
     255             :                                         // CMD_APPEND and CMD_END_FILE in the
     256             :                                         // calling function, so pretend it is
     257             :                                         // complete if we have the hack flag.
     258        8204 :                                         if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
     259             :                                                 return PARSE_RET_COMPLETE;
     260        8200 :                                         return PARSE_RET_NEED_MORE;
     261             :                                 }
     262             :                                 return PARSE_RET_COMPLETE;
     263             :                         }
     264             : #ifndef HAVE_WIN32
     265             :                 case CMD_SIG:
     266             :                         // Fill in the sig/block, if the caller provided
     267             :                         // a pointer for one. Server only.
     268      198406 :                         if(!blk) return PARSE_RET_NEED_MORE;
     269             : 
     270             :                         // Just fill in the sig details.
     271       46452 :                         if(blk_set_from_iobuf_sig_and_savepath(blk, rbuf))
     272             :                                 return PARSE_RET_ERROR;
     273       46452 :                         blk->got_save_path=1;
     274       46452 :                         iobuf_free_content(rbuf);
     275       46452 :                         if(datpath && rblk_retrieve_data(datpath, blk))
     276             :                         {
     277           0 :                                 logp("Could not retrieve blk data.\n");
     278           0 :                                 return PARSE_RET_ERROR;
     279             :                         }
     280             :                         return PARSE_RET_COMPLETE;
     281             : #endif
     282             :                 case CMD_DATA:
     283             :                         // Need to write the block to disk.
     284             :                         // Client only.
     285          14 :                         if(!blk) return PARSE_RET_NEED_MORE;
     286          14 :                         blk->data=rbuf->buf;
     287          14 :                         blk->length=rbuf->len;
     288          14 :                         rbuf->buf=NULL;
     289          14 :                         return PARSE_RET_COMPLETE;
     290             :                 case CMD_MESSAGE:
     291             :                 case CMD_WARNING:
     292           0 :                         log_recvd(rbuf, cntr, 1);
     293           0 :                         return PARSE_RET_NEED_MORE;
     294             :                 case CMD_GEN:
     295          42 :                         if(!strcmp(rbuf->buf, "restoreend")
     296          38 :                           || !strcmp(rbuf->buf, "phase1end")
     297           0 :                           || !strcmp(rbuf->buf, "backupphase2")
     298             :                         // Think these are protocol1 things.
     299           0 :                           || !strcmp(rbuf->buf, "backupend")
     300           0 :                           || !strcmp(rbuf->buf, "estimateend"))
     301             :                                 return PARSE_RET_FINISHED;
     302           0 :                         iobuf_log_unexpected(rbuf, __func__);
     303           0 :                         return PARSE_RET_ERROR;
     304             :                 case CMD_FINGERPRINT:
     305          36 :                         if(blk && blk_set_from_iobuf_fingerprint(blk, rbuf))
     306             :                                 return PARSE_RET_ERROR;
     307             :                         // Fall through.
     308             :                 case CMD_MANIFEST:
     309          52 :                         iobuf_free_content(&sb->path);
     310          52 :                         iobuf_move(&sb->path, rbuf);
     311          52 :                         return PARSE_RET_COMPLETE;
     312             :                 case CMD_ERROR:
     313           0 :                         logp("got error: %s\n", rbuf->buf);
     314           0 :                         return PARSE_RET_ERROR;
     315             :                 case CMD_DATAPTH:
     316        8205 :                         if(!sb->protocol1)
     317             :                         {
     318           0 :                                 iobuf_log_unexpected(rbuf, __func__);
     319           0 :                                 return PARSE_RET_ERROR;
     320             :                         }
     321        8205 :                         if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
     322             :                         {
     323           5 :                                 sbuf_free_content(sb);
     324           5 :                                 sb->flags |= SBUF_CLIENT_RESTORE_HACK;
     325             :                         }
     326             :                         else
     327        8200 :                                 sbuf_free_content(sb);
     328             :                         
     329        8205 :                         iobuf_move(&sb->protocol1->datapth, rbuf);
     330        8205 :                         return PARSE_RET_NEED_MORE;
     331             :                 case CMD_END_FILE:
     332       16329 :                         iobuf_free_content(&sb->endfile);
     333       16329 :                         iobuf_move(&sb->endfile, rbuf);
     334       16329 :                         if(sb->protocol1)
     335             :                         {
     336       16340 :                                 if(!sb->attr.buf
     337        8170 :                                   || !sb->protocol1->datapth.buf
     338       16340 :                                   || (!sbuf_is_filedata(sb)
     339          98 :                                         && !sbuf_is_vssdata(sb)))
     340             :                                 {
     341           0 :                                         logp("got unexpected cmd_endfile");
     342           0 :                                         return PARSE_RET_ERROR;
     343             :                                 }
     344             :                         }
     345             :                         return PARSE_RET_COMPLETE;
     346             :                 default:
     347           0 :                         iobuf_log_unexpected(rbuf, __func__);
     348           0 :                         return PARSE_RET_ERROR;
     349             :         }
     350             :         logp("Fell out of switch unexpectedly in %s()\n", __func__);
     351             :         return PARSE_RET_ERROR;
     352             : }
     353             : 
     354      115527 : static int sbuf_fill(struct sbuf *sb, struct asfd *asfd, struct fzp *fzp,
     355             :         struct blk *blk, const char *datpath, struct cntr *cntr)
     356             : {
     357             :         static struct iobuf *rbuf;
     358             :         static struct iobuf localrbuf;
     359      115527 :         int ret=-1;
     360             : 
     361      115527 :         if(asfd) rbuf=asfd->rbuf;
     362             :         else
     363             :         {
     364             :                 // If not given asfd, use our own iobuf.
     365             :                 memset(&localrbuf, 0, sizeof(struct iobuf));
     366      115475 :                 rbuf=&localrbuf;
     367             :         }
     368             :         while(1)
     369             :         {
     370      353481 :                 iobuf_free_content(rbuf);
     371      353481 :                 if(fzp)
     372             :                 {
     373      353386 :                         if((ret=iobuf_fill_from_fzp(rbuf, fzp)))
     374             :                                 goto end;
     375             :                 }
     376             :                 else
     377             :                 {
     378          95 :                         if(asfd->read(asfd))
     379             :                         {
     380           1 :                                 logp("error in async_read\n");
     381           1 :                                 break;
     382             :                         }
     383             :                 }
     384      353136 :                 switch(parse_cmd(sb, asfd, rbuf, blk, datpath, cntr))
     385             :                 {
     386             :                         case PARSE_RET_NEED_MORE:
     387             :                                 continue;
     388             :                         case PARSE_RET_COMPLETE:
     389             :                                 return 0;
     390             :                         case PARSE_RET_FINISHED:
     391             :                                 ret=1;
     392             :                                 goto end;
     393             :                         case PARSE_RET_ERROR:
     394             :                         default:
     395           1 :                                 ret=-1;
     396           1 :                                 goto end;
     397             :                 }
     398             :         }
     399             : end:
     400         388 :         iobuf_free_content(rbuf);
     401         388 :         return ret;
     402             : }
     403             : 
     404          52 : int sbuf_fill_from_net(struct sbuf *sb, struct asfd *asfd,
     405             :         struct blk *blk, const char *datpath, struct cntr *cntr)
     406             : {
     407          52 :         return sbuf_fill(sb, asfd, NULL, blk, datpath, cntr);
     408             : }
     409             : 
     410      115475 : int sbuf_fill_from_file(struct sbuf *sb, struct fzp *fzp,
     411             :         struct blk *blk, const char *datpath)
     412             : {
     413      115475 :         return sbuf_fill(sb, NULL, fzp, blk, datpath, NULL);
     414             : }

Generated by: LCOV version 1.10