LCOV - code coverage report
Current view: top level - src - sbuf.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 130 194 67.0 %
Date: 2015-11-30 Functions: 11 17 64.7 %

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

Generated by: LCOV version 1.10