LCOV - code coverage report
Current view: top level - src/server - resume.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 74 196 37.8 %
Date: 2018-06-21 07:06:30 Functions: 3 7 42.9 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../cmd.h"
       3             : #include "../cntr.h"
       4             : #include "../iobuf.h"
       5             : #include "../log.h"
       6             : #include "../pathcmp.h"
       7             : #include "../sbuf.h"
       8             : #include "dpth.h"
       9             : #include "resume.h"
      10             : #include "backup_phase1.h"
      11             : #include "protocol1/dpth.h"
      12             : 
      13             : // Used on resume, this just reads the phase1 file and sets up cntr.
      14           0 : static int read_phase1(struct manio *p1manio, struct conf **cconfs)
      15             : {
      16           0 :         int ret=-1;
      17             :         struct sbuf *p1b;
      18           0 :         enum protocol protocol=get_protocol(cconfs);
      19           0 :         struct cntr *cntr=get_cntr(cconfs);
      20           0 :         if(!(p1b=sbuf_alloc(protocol))) return -1;
      21             :         while(1)
      22             :         {
      23           0 :                 sbuf_free_content(p1b);
      24           0 :                 switch(manio_read(p1manio, p1b))
      25             :                 {
      26             :                         case 0: break;
      27           0 :                         case 1: ret=0;
      28             :                         default: goto end;
      29             :                 }
      30           0 :                 cntr_add_phase1(cntr, p1b->path.cmd, 0);
      31             : 
      32           0 :                 if(sbuf_is_estimatable(p1b))
      33           0 :                         cntr_add_val(cntr, CMD_BYTES_ESTIMATED,
      34           0 :                                 (uint64_t)p1b->statp.st_size);
      35             :         }
      36             : end:
      37           0 :         sbuf_free(&p1b);
      38           0 :         return ret;
      39             : }
      40             : 
      41           0 : static int set_higher_datapth(struct sbuf *sb, struct dpth *dpth)
      42             : {
      43             :         // Make sure we end up with the highest datapth we can possibly
      44             :         // find - dpth_protocol1_set_from_string() will only set it if
      45             :         // it is higher.
      46           0 :         if(sb->protocol1 && sb->protocol1->datapth.buf
      47           0 :           && dpth_protocol1_set_from_string(dpth,
      48             :                 sb->protocol1->datapth.buf))
      49             :         {
      50           0 :                 logp("unable to set datapath: %s\n",
      51           0 :                         iobuf_to_printable(&sb->protocol1->datapth));
      52             :                 return -1;
      53             :         }
      54             :         return 0;
      55             : }
      56             : 
      57             : #ifndef UTEST
      58             : static
      59             : #endif
      60          48 : int forward_past_entry(struct manio *manio, struct iobuf *target,
      61             :         enum protocol protocol, man_off_t **pos)
      62             : {
      63          48 :         struct sbuf *sb=NULL;
      64             : 
      65          48 :         if(!(sb=sbuf_alloc(protocol)))
      66             :                 goto error;
      67             : 
      68          48 :         man_off_t_free(pos);
      69          48 :         if(!(*pos=manio_tell(manio)))
      70             :         {
      71           0 :                 logp("Could not manio_tell first pos in %s(): %s\n",
      72           0 :                         __func__, strerror(errno));
      73           0 :                 goto error;
      74             :         }
      75             : 
      76             :         while(1)
      77             :         {
      78        1744 :                 sbuf_free_content(sb);
      79        1744 :                 switch(manio_read(manio, sb))
      80             :                 {
      81             :                         case 0: break;
      82           0 :                         case 1: logp("End of file in %s()\n", __func__);
      83           0 :                                 goto error;
      84             :                         default:
      85           0 :                                 logp("Error in %s()\n", __func__);
      86             :                                 // Treat error in unchanged manio as not OK.
      87           0 :                                 goto error;
      88             :                 }
      89             : 
      90        1744 :                 if(target->cmd==sb->path.cmd
      91        1664 :                   && !pathcmp(target->buf, sb->path.buf))
      92             :                 {
      93          48 :                         man_off_t_free(pos);
      94          48 :                         if(!(*pos=manio_tell(manio)))
      95             :                         {
      96           0 :                                 logp("Could not get pos in %s(): %s\n",
      97           0 :                                         __func__, strerror(errno));
      98           0 :                                 goto error;
      99             :                         }
     100          48 :                         sbuf_free(&sb);
     101          48 :                         return 0;
     102             :                 }
     103             :         }
     104             : 
     105             : error:
     106           0 :         sbuf_free(&sb);
     107           0 :         man_off_t_free(pos);
     108           0 :         return -1;
     109             : }
     110             : 
     111             : #ifndef UTEST
     112             : static
     113             : #endif
     114          88 : int forward_before_entry(struct manio *manio, struct iobuf *target,
     115             :         struct cntr *cntr, struct dpth *dpth, enum protocol protocol,
     116             :         man_off_t **pos)
     117             : {
     118          88 :         int ars=0;
     119          88 :         struct sbuf *sb=NULL;
     120             : 
     121          88 :         if(!(sb=sbuf_alloc(protocol)))
     122             :                 goto error;
     123             : 
     124          88 :         man_off_t_free(pos);
     125          88 :         if(!(*pos=manio_tell(manio)))
     126             :         {
     127           0 :                 logp("Could not manio_tell first pos in %s(): %s\n",
     128           0 :                         __func__, strerror(errno));
     129           0 :                 goto error;
     130             :         }
     131             : 
     132             :         while(1)
     133             :         {
     134        6380 :                 if(sb->endfile.buf
     135        2208 :                   || (sb->path.buf && !sbuf_is_filedata(sb)))
     136             :                 {
     137        4240 :                         man_off_t_free(pos);
     138        4240 :                         if(!(*pos=manio_tell(manio)))
     139             :                         {
     140           0 :                                 logp("Could not manio_tell pos in %s(): "
     141           0 :                                         "%s\n", __func__, strerror(errno));
     142           0 :                                 goto error;
     143             :                         }
     144             :                 }
     145             : 
     146        6380 :                 sbuf_free_content(sb);
     147        6380 :                 ars=manio_read(manio, sb);
     148        6380 :                 if(dpth && set_higher_datapth(sb, dpth)) goto error;
     149             : 
     150        6380 :                 switch(ars)
     151             :                 {
     152             :                         case 0: break;
     153             :                         case 1:
     154           6 :                                 sbuf_free(&sb);
     155           6 :                                 return 0;
     156             :                         default:
     157          10 :                                 logp("Error in %s(), but continuing\n",
     158             :                                         __func__);
     159             :                                 // Treat error in unchanged manio as
     160             :                                 // OK - could have been a short write.
     161          10 :                                 sbuf_free(&sb);
     162          10 :                                 return 0;
     163             :                 }
     164             : 
     165        6364 :                 if(iobuf_pathcmp(target, &sb->path)<=0)
     166             :                 {
     167          72 :                         sbuf_free(&sb);
     168          72 :                         return 0;
     169             :                 }
     170             : 
     171        6292 :                 if(cntr)
     172             :                 {
     173           0 :                         cntr_add_same(cntr, sb->path.cmd);
     174           0 :                         if(sb->endfile.buf)
     175             :                         {
     176           0 :                                 uint64_t e=strtoull(sb->endfile.buf, NULL, 10);
     177           0 :                                 cntr_add_bytes(cntr, e);
     178             :                         }
     179             :                 }
     180             :         }
     181             : 
     182             : error:
     183           0 :         sbuf_free(&sb);
     184           0 :         man_off_t_free(pos);
     185           0 :         return -1;
     186             : }
     187             : 
     188             : #ifndef UTEST
     189             : static
     190             : #endif
     191         208 : int get_last_good_entry(struct manio *manio, struct iobuf *result,
     192             :         struct cntr *cntr, struct dpth *dpth, enum protocol protocol,
     193             :         man_off_t **pos)
     194             : {
     195         208 :         int ars=0;
     196         208 :         int got_vss_start=0;
     197         208 :         struct sbuf *sb=NULL;
     198             :         struct iobuf lastpath;
     199             : 
     200         208 :         if(!(sb=sbuf_alloc(protocol)))
     201             :                 goto error;
     202             : 
     203         208 :         iobuf_init(&lastpath);
     204             : 
     205         208 :         man_off_t_free(pos);
     206         208 :         if(!(*pos=manio_tell(manio)))
     207             :         {
     208           0 :                 logp("Could not manio_tell first pos in %s(): %s\n",
     209           0 :                         __func__, strerror(errno));
     210           0 :                 goto error;
     211             :         }
     212             : 
     213             :         while(1)
     214             :         {
     215       12690 :                 if(sb->path.buf && !got_vss_start)
     216             :                 {
     217        8270 :                         iobuf_free_content(&lastpath);
     218        8270 :                         iobuf_move(&lastpath, &sb->path);
     219        8270 :                         if(!sbuf_is_filedata(sb)
     220         114 :                           && !sbuf_is_vssdata(sb))
     221             :                         {
     222         104 :                                 iobuf_free_content(result);
     223         104 :                                 iobuf_move(result, &lastpath);
     224             : 
     225         104 :                                 man_off_t_free(pos);
     226         104 :                                 if(!(*pos=manio_tell(manio)))
     227             :                                 {
     228           0 :                                         logp("Could not manio_tell pos in %s(): %s\n",
     229           0 :                                                 __func__, strerror(errno));
     230           0 :                                         goto error;
     231             :                                 }
     232             :                         }
     233             :                 }
     234       12690 :                 if(sb->endfile.buf && !got_vss_start)
     235             :                 {
     236        8152 :                         iobuf_free_content(result);
     237        8152 :                         iobuf_move(result, &lastpath);
     238             : 
     239        8152 :                         man_off_t_free(pos);
     240        8152 :                         if(!(*pos=manio_tell(manio)))
     241             :                         {
     242           0 :                                 logp("Could not manio_tell pos in %s(): %s\n",
     243           0 :                                         __func__, strerror(errno));
     244           0 :                                 goto error;
     245             :                         }
     246             :                 }
     247             : 
     248       12690 :                 sbuf_free_content(sb);
     249       12690 :                 ars=manio_read(manio, sb);
     250       12690 :                 if(dpth && set_higher_datapth(sb, dpth)) goto error;
     251             : 
     252       12690 :                 switch(ars)
     253             :                 {
     254             :                         case 0: break;
     255         169 :                         case 1: iobuf_free_content(&lastpath);
     256         169 :                                 sbuf_free(&sb);
     257         169 :                                 return 0;
     258             :                         default:
     259          39 :                                 if(result->buf)
     260          32 :                                         logp("Error after %s in %s()\n",
     261             :                                                 iobuf_to_printable(result),
     262             :                                                 __func__);
     263             :                                 // Treat error in changed manio as
     264             :                                 // OK - could have been a short write.
     265          39 :                                 iobuf_free_content(&lastpath);
     266          39 :                                 sbuf_free(&sb);
     267          39 :                                 return 0;
     268             :                 }
     269             : 
     270             :                 // Some hacks for split_vss.
     271       12482 :                 switch(sb->path.cmd)
     272             :                 {
     273             :                         case CMD_VSS:
     274             :                         case CMD_ENC_VSS:
     275             :                                 got_vss_start=1;
     276             :                                 break;
     277             :                         case CMD_VSS_T:
     278             :                         case CMD_ENC_VSS_T:
     279             :                                 got_vss_start=0;
     280             :                                 break;
     281             :                         case CMD_FILE:
     282             :                         case CMD_ENC_FILE:
     283        8154 :                                 if(S_ISDIR(sb->statp.st_mode))
     284          48 :                                         got_vss_start=0;
     285             :                                 break;
     286             :                         default:
     287             :                                 break;
     288             :                 }
     289             : 
     290       12482 :                 if(cntr)
     291             :                 {
     292             :                         // FIX THIS: cannot distinguish between new and
     293             :                         // changed files.
     294           0 :                         cntr_add_changed(cntr, sb->path.cmd);
     295           0 :                         if(sb->endfile.buf)
     296             :                         {
     297           0 :                                 uint64_t e=strtoull(sb->endfile.buf, NULL, 10);
     298           0 :                                 cntr_add_bytes(cntr, e);
     299             :                         }
     300             :                 }
     301             :         }
     302             : 
     303             : error:
     304           0 :         iobuf_free_content(&lastpath);
     305           0 :         sbuf_free(&sb);
     306           0 :         man_off_t_free(pos);
     307           0 :         return -1;
     308             : }
     309             : 
     310             : // Return p1manio position.
     311           0 : static man_off_t *do_resume_work(struct sdirs *sdirs,
     312             :         struct dpth *dpth, struct conf **cconfs)
     313             : {
     314           0 :         man_off_t *pos=NULL;
     315           0 :         man_off_t *p1pos=NULL;
     316           0 :         struct iobuf *chb=NULL;
     317           0 :         struct manio *cmanio=NULL;
     318           0 :         struct manio *umanio=NULL;
     319           0 :         struct manio *p1manio=NULL;
     320           0 :         enum protocol protocol=get_protocol(cconfs);
     321           0 :         struct cntr *cntr=get_cntr(cconfs);
     322           0 :         int compression=get_int(cconfs[OPT_COMPRESSION]);
     323             : 
     324           0 :         if(!(p1manio=manio_open_phase1(sdirs->phase1data,
     325             :                 MANIO_MODE_READ, protocol))
     326           0 :           || !(cmanio=manio_open_phase2(sdirs->changed,
     327             :                 MANIO_MODE_READ, protocol))
     328           0 :           || !(umanio=manio_open_phase2(sdirs->unchanged,
     329             :                 MANIO_MODE_READ, protocol)))
     330             :                         goto end;
     331             : 
     332           0 :         if(!(chb=iobuf_alloc()))
     333             :                 return NULL;
     334             : 
     335           0 :         logp("Setting up resume positions...\n");
     336             : 
     337           0 :         if(get_last_good_entry(cmanio, chb, cntr, dpth, protocol, &pos))
     338             :                 goto error;
     339           0 :         if(manio_close_and_truncate(&cmanio, pos, compression)) goto error;
     340           0 :         man_off_t_free(&pos);
     341           0 :         if(chb->buf)
     342             :         {
     343           0 :                 logp("  last good entry:    %s\n",
     344             :                         iobuf_to_printable(chb));
     345             :                 // Now need to go to the appropriate places in p1manio and
     346             :                 // unchanged.
     347           0 :                 if(forward_past_entry(p1manio, chb, protocol, &p1pos))
     348             :                         goto error;
     349             : 
     350             :                 // The unchanged file needs to be positioned just before the
     351             :                 // found entry, otherwise it ends up having a duplicated entry.
     352           0 :                 if(forward_before_entry(umanio,
     353             :                         chb, cntr, dpth, protocol, &pos))
     354             :                                 goto error;
     355           0 :                 if(manio_close_and_truncate(&umanio, pos, compression))
     356             :                         goto error;
     357           0 :                 man_off_t_free(&pos);
     358             :         }
     359             :         else
     360             :         {
     361           0 :                 logp("  nothing previously transferred\n");
     362           0 :                 if(!(p1pos=manio_tell(p1manio)))
     363             :                 {
     364           0 :                         logp("Could not get p1pos in %s\n", __func__);
     365           0 :                         goto error;
     366             :                 }
     367           0 :                 if(!(pos=manio_tell(umanio)))
     368             :                 {
     369           0 :                         logp("Could not get pos in %s\n", __func__);
     370           0 :                         goto error;
     371             :                 }
     372           0 :                 if(manio_close_and_truncate(&umanio, pos, compression))
     373             :                         goto error;
     374             :         }
     375             : 
     376             :         // Now should have all file pointers in the right places to resume.
     377             : 
     378             :         goto end;
     379             : error:
     380           0 :         man_off_t_free(&p1pos);
     381             : end:
     382           0 :         iobuf_free(&chb);
     383           0 :         man_off_t_free(&pos);
     384           0 :         manio_close(&p1manio);
     385           0 :         manio_close(&cmanio);
     386           0 :         manio_close(&umanio);
     387           0 :         return p1pos;
     388             : }
     389             : 
     390           0 : man_off_t *do_resume(struct sdirs *sdirs,
     391             :         struct dpth *dpth, struct conf **cconfs)
     392             : {
     393           0 :         man_off_t *p1pos=NULL;
     394           0 :         struct manio *cmanio=NULL;
     395           0 :         struct manio *umanio=NULL;
     396           0 :         struct manio *p1manio=NULL;
     397           0 :         enum protocol protocol=get_protocol(cconfs);
     398             : 
     399           0 :         logp("Begin phase1 (read previous file system scan)\n");
     400           0 :         if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", protocol))
     401           0 :           || read_phase1(p1manio, cconfs))
     402             :                 goto end;
     403           0 :         manio_close(&p1manio);
     404             : 
     405             :         // First, open them in append mode, so that they will be created if
     406             :         // they do not exist.
     407           0 :         if(!(cmanio=manio_open_phase2(sdirs->changed, "ab", protocol))
     408           0 :           || !(umanio=manio_open_phase2(sdirs->unchanged, "ab", protocol)))
     409             :                 goto end;
     410           0 :         manio_close(&cmanio);
     411           0 :         manio_close(&umanio);
     412             : 
     413           0 :         if(!(p1pos=do_resume_work(sdirs, dpth, cconfs))) goto end;
     414             : 
     415           0 :         if(dpth_incr(dpth)) goto end;
     416             : 
     417           0 :         logp("End phase1 (read previous file system scan)\n");
     418             : end:
     419           0 :         manio_close(&p1manio);
     420           0 :         manio_close(&cmanio);
     421           0 :         manio_close(&umanio);
     422           0 :         return p1pos;
     423             : }

Generated by: LCOV version 1.13