LCOV - code coverage report
Current view: top level - src/server/protocol1 - backup_phase2.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 310 414 74.9 %
Date: 2017-02-01 Functions: 21 23 91.3 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.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 "../../conffile.h"
      10             : #include "../../fsops.h"
      11             : #include "../../handy.h"
      12             : #include "../../iobuf.h"
      13             : #include "../../log.h"
      14             : #include "../../sbuf.h"
      15             : #include "../child.h"
      16             : #include "../compress.h"
      17             : #include "../resume.h"
      18             : #include "blocklen.h"
      19             : #include "dpth.h"
      20             : #include "backup_phase2.h"
      21             : 
      22             : static size_t treepathlen=0;
      23             : 
      24           0 : static int path_length_warn(struct iobuf *path, struct conf **cconfs)
      25             : {
      26           0 :         if(get_int(cconfs[OPT_PATH_LENGTH_WARN]))
      27           0 :                 logw(NULL, get_cntr(cconfs), "Path too long for tree - will save in data structure instead: %s\n", path->buf);
      28           0 :         return 1;
      29             : }
      30             : 
      31           4 : static int path_too_long(struct iobuf *path, struct conf **cconfs)
      32             : {
      33             :         static const char *cp;
      34           4 :         if(treepathlen+path->len+1>fs_full_path_max)
      35             :         {
      36             :                 // FIX THIS:
      37             :                 // Cannot warn down the asfd to the client, because it can
      38             :                 // arrive after the client has disconnected, which causes
      39             :                 // an error on the server side.
      40             :                 // Would need to change the way that "backupphase2end" works
      41             :                 // to be able to fix it.
      42           0 :                 return path_length_warn(path, cconfs);
      43             :         }
      44           4 :         if((cp=strrchr(path->buf, '/'))) cp++;
      45           0 :         else cp=path->buf;
      46           4 :         if(strlen(cp)>fs_name_max) return path_length_warn(path, cconfs);
      47             :         return 0;
      48             : }
      49             : 
      50           4 : static int treedata(struct sbuf *sb, struct conf **cconfs)
      51             : {
      52             :         // Windows is sending directory data as if it is file data - this
      53             :         // cannot be saved in a tree structure.
      54           4 :         if(S_ISDIR(sb->statp.st_mode)) return 0;
      55             : 
      56           8 :         if(sb->path.cmd!=CMD_FILE
      57           4 :           && sb->path.cmd!=CMD_ENC_FILE
      58           0 :           && sb->path.cmd!=CMD_EFS_FILE)
      59             :                 return 0;
      60             : 
      61           4 :         return !path_too_long(&sb->path, cconfs);
      62             : }
      63             : 
      64           4 : static char *set_new_datapth(struct asfd *asfd,
      65             :         struct sdirs *sdirs, struct conf **cconfs,
      66             :         struct sbuf *sb, struct dpth *dpth, int *istreedata)
      67             : {
      68           4 :         char *tmp=NULL;
      69           4 :         char *rpath=NULL;
      70           4 :         if(get_int(cconfs[OPT_DIRECTORY_TREE]))
      71           4 :                 *istreedata=treedata(sb, cconfs);
      72             : 
      73           4 :         if(*istreedata)
      74             :         {
      75             :                 // We want to place this file in a directory structure like
      76             :                 // the directory structure on the original client.
      77           4 :                 if(!(tmp=prepend_s(TREE_DIR, sb->path.buf)))
      78             :                 {
      79           0 :                         log_and_send_oom(asfd);
      80             :                         return NULL;
      81             :                 }
      82             :         }
      83             :         else
      84             :         {
      85           0 :                 if(!(tmp=strdup_w(dpth_protocol1_mk(dpth, sb->compression,
      86             :                         sb->path.cmd), __func__))) return NULL;
      87             :         }
      88           4 :         iobuf_from_str(&sb->protocol1->datapth, CMD_DATAPTH, tmp);
      89           4 :         if(build_path(sdirs->datadirtmp,
      90           4 :                 sb->protocol1->datapth.buf, &rpath, sdirs->datadirtmp))
      91             :         {
      92           0 :                 log_and_send(asfd, "build path failed");
      93             :                 return NULL;
      94             :         }
      95           4 :         return rpath;
      96             : }
      97             : 
      98           4 : static int start_to_receive_new_file(struct asfd *asfd,
      99             :         struct sdirs *sdirs, struct conf **cconfs,
     100             :         struct sbuf *sb, struct dpth *dpth)
     101             : {
     102           4 :         int ret=-1;
     103           4 :         char *rpath=NULL;
     104           4 :         int istreedata=0;
     105             : 
     106             : //logp("start to receive: %s\n", sb->path.buf);
     107             : 
     108           4 :         if(!(rpath=set_new_datapth(asfd,
     109             :                 sdirs, cconfs, sb, dpth, &istreedata)))
     110             :                         goto end;
     111             :         
     112           4 :         if(!(sb->protocol1->fzp=fzp_open(rpath, "wb")))
     113             :         {
     114           0 :                 log_and_send(asfd, "make file failed");
     115           0 :                 goto end;
     116             :         }
     117           4 :         if(!istreedata) dpth_incr(dpth);
     118             :         ret=0;
     119             : end:
     120           4 :         free_w(&rpath);
     121           4 :         return ret;
     122             : }
     123             : 
     124             : enum processed_e
     125             : {
     126             :         P_ERROR=-1,
     127             :         P_DONE_NEW=0,
     128             :         P_DONE_CHANGED=1,
     129             :         P_DONE_UNCHANGED=2,
     130             :         P_DONE_DELETED=3,
     131             :         P_NEW=4,
     132             :         P_CHANGED=5
     133             : };
     134             : 
     135             : #include <librsync.h>
     136             : 
     137           2 : static enum processed_e process_changed_file(struct asfd *asfd,
     138             :         struct conf **cconfs,
     139             :         struct sbuf *cb, struct sbuf *p1b,
     140             :         const char *adir)
     141             : {
     142           2 :         int ret=P_ERROR;
     143           2 :         size_t blocklen=0;
     144           2 :         char *curpath=NULL;
     145             :         //logp("need to process changed file: %s (%s)\n",
     146             :         //      cb->path, cb->datapth);
     147             : 
     148             :         // Move datapth onto p1b.
     149           2 :         iobuf_move(&p1b->protocol1->datapth, &cb->protocol1->datapth);
     150             : 
     151           2 :         if(!(curpath=prepend_s(adir, p1b->protocol1->datapth.buf)))
     152             :         {
     153           0 :                 log_out_of_memory(__func__);
     154             :                 goto end;
     155             :         }
     156           2 :         if(dpth_protocol1_is_compressed(cb->compression, curpath))
     157           0 :                 p1b->protocol1->sigfzp=fzp_gzopen(curpath, "rb");
     158             :         else
     159           2 :                 p1b->protocol1->sigfzp=fzp_open(curpath, "rb");
     160           2 :         if(!p1b->protocol1->sigfzp)
     161             :         {
     162           0 :                 logp("could not open %s: %s\n", curpath, strerror(errno));
     163             :                 goto end;
     164             :         }
     165             : 
     166           2 :         blocklen=get_librsync_block_len(cb->endfile.buf);
     167           4 :         if(!(p1b->protocol1->sigjob=
     168             : #ifdef RS_DEFAULT_STRONG_LEN
     169           2 :                 rs_sig_begin(blocklen, RS_DEFAULT_STRONG_LEN)
     170             : #else
     171             :                 // This is for librsync-1.0.0. RS_DEFAULT_STRONG_LEN was 8 in
     172             :                 // librsync-0.9.7.
     173             :                 rs_sig_begin(blocklen, 8,
     174             :                   rshash_to_magic_number(get_e_rshash(cconfs[OPT_RSHASH])))
     175             : #endif
     176             :         ))
     177             :         {
     178           0 :                 logp("could not start signature job.\n");
     179             :                 goto end;
     180             :         }
     181             :         //logp("sig begin: %s\n", p1b->protocol1->datapth.buf);
     182           2 :         if(!(p1b->protocol1->infb=rs_filebuf_new(NULL,
     183           2 :                 p1b->protocol1->sigfzp,
     184             :                 NULL, blocklen, -1)))
     185             :         {
     186           0 :                 logp("could not rs_filebuf_new for infb.\n");
     187             :                 goto end;
     188             :         }
     189           2 :         if(!(p1b->protocol1->outfb=rs_filebuf_new(NULL, NULL,
     190             :                 asfd, ASYNC_BUF_LEN, -1)))
     191             :         {
     192           0 :                 logp("could not rs_filebuf_new for in_outfb.\n");
     193             :                 goto end;
     194             :         }
     195             : 
     196             :         // Flag the things that need to be sent (to the client)
     197           2 :         p1b->flags |= SBUF_SEND_DATAPTH;
     198           2 :         p1b->flags |= SBUF_SEND_STAT;
     199           2 :         p1b->flags |= SBUF_SEND_PATH;
     200             : 
     201             :         //logp("sending sig for %s\n", p1b->path);
     202             :         //logp("(%s)\n", p1b->datapth);
     203             : 
     204           2 :         ret=P_CHANGED;
     205             : end:
     206           2 :         free_w(&curpath);
     207           2 :         return ret;
     208             : }
     209             : 
     210          68 : static enum processed_e new_non_file(struct sbuf *p1b,
     211             :         struct manio *ucmanio, struct conf **cconfs)
     212             : {
     213             :         // Is something that does not need more data backed up.
     214             :         // Like a directory or a link or something like that.
     215             :         // Goes into the unchanged file, so that it does not end up out of
     216             :         // order with normal files, which has to wait around for their data
     217             :         // to turn up.
     218          68 :         if(manio_write_sbuf(ucmanio, p1b))
     219             :                 return P_ERROR;
     220          68 :         cntr_add(get_cntr(cconfs), p1b->path.cmd, 0);
     221          68 :         return P_DONE_NEW;
     222             : }
     223             : 
     224           0 : static enum processed_e changed_non_file(struct sbuf *p1b,
     225             :         struct manio *ucmanio, enum cmd cmd, struct conf **cconfs)
     226             : {
     227             :         // As new_non_file.
     228           0 :         if(manio_write_sbuf(ucmanio, p1b))
     229             :                 return P_ERROR;
     230           0 :         cntr_add_changed(get_cntr(cconfs), cmd);
     231           0 :         return P_DONE_CHANGED;
     232             : }
     233             : 
     234         122 : static enum processed_e process_new(struct conf **cconfs,
     235             :         struct sbuf *p1b, struct manio *ucmanio)
     236             : {
     237         122 :         if(sbuf_is_filedata(p1b)
     238          68 :           || sbuf_is_vssdata(p1b))
     239             :         {
     240             :                 //logp("need to process new file: %s\n", p1b->path);
     241             :                 // Flag the things that need to be sent (to the client)
     242          54 :                 p1b->flags |= SBUF_SEND_STAT;
     243          54 :                 p1b->flags |= SBUF_SEND_PATH;
     244          54 :                 return P_NEW;
     245             :         }
     246          68 :         return new_non_file(p1b, ucmanio, cconfs);
     247             : }
     248             : 
     249           6 : static enum processed_e process_unchanged_file(struct sbuf *p1b, struct sbuf *cb,
     250             :         struct manio *ucmanio, struct conf **cconfs)
     251             : {
     252             :         // Need to re-encode the p1b attribs to include compression and
     253             :         // other bits and pieces that are recorded on cb.
     254           6 :         iobuf_move(&p1b->protocol1->datapth, &cb->protocol1->datapth);
     255           6 :         iobuf_move(&p1b->endfile, &cb->endfile);
     256           6 :         p1b->compression=cb->compression;
     257             :         // Why is winattr not getting sent in phase1?
     258           6 :         p1b->winattr=cb->winattr;
     259             :         // Need to free attr so that it is reallocated, because it may get
     260             :         // longer than what the client told us in phase1.
     261           6 :         iobuf_free_content(&p1b->attr);
     262           6 :         if(attribs_encode(p1b))
     263             :                 return P_ERROR;
     264           6 :         if(manio_write_sbuf(ucmanio, p1b))
     265             :                 return P_ERROR;
     266           6 :         cntr_add_same(get_cntr(cconfs), p1b->path.cmd);
     267           6 :         if(p1b->endfile.buf) cntr_add_bytes(get_cntr(cconfs),
     268           0 :                 strtoull(p1b->endfile.buf, NULL, 10));
     269             :         return P_DONE_UNCHANGED;
     270             : }
     271             : 
     272          10 : static enum processed_e maybe_do_delta_stuff(struct asfd *asfd,
     273             :         struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
     274             :         struct manio *ucmanio, struct conf **cconfs)
     275             : {
     276          10 :         int oldcompressed=0;
     277          10 :         int compression=p1b->compression;
     278             : 
     279             :         // If the file type changed, I think it is time to back it up again
     280             :         // (for example, EFS changing to normal file, or back again).
     281          10 :         if(cb->path.cmd!=p1b->path.cmd)
     282           0 :                 return process_new(cconfs, p1b, ucmanio);
     283             : 
     284             :         // mtime is the actual file data.
     285             :         // ctime is the attributes or meta data.
     286          10 :         if(cb->statp.st_mtime==p1b->statp.st_mtime
     287           6 :           && cb->statp.st_ctime==p1b->statp.st_ctime)
     288             :         {
     289             :                 // got an unchanged file
     290             :                 //logp("got unchanged file: %s %c %c\n",
     291             :                 //      cb->path.buf, cb->path.cmd, p1b->path.cmd);
     292           6 :                 return process_unchanged_file(p1b, cb, ucmanio, cconfs);
     293             :         }
     294             : 
     295           4 :         if(cb->statp.st_mtime==p1b->statp.st_mtime
     296           0 :           && cb->statp.st_ctime!=p1b->statp.st_ctime)
     297             :         {
     298             :                 // File data stayed the same, but attributes or meta data
     299             :                 // changed. We already have the attributes, but may need to get
     300             :                 // extra meta data.
     301             :                 // FIX THIS horrible mess.
     302           0 :                 if(cb->path.cmd==CMD_ENC_METADATA
     303           0 :                   || p1b->path.cmd==CMD_ENC_METADATA
     304           0 :                   || cb->path.cmd==CMD_EFS_FILE
     305           0 :                   || p1b->path.cmd==CMD_EFS_FILE
     306             :                 // FIX THIS: make unencrypted metadata use the librsync
     307           0 :                   || cb->path.cmd==CMD_METADATA
     308           0 :                   || p1b->path.cmd==CMD_METADATA
     309           0 :                   || sbuf_is_vssdata(cb)
     310           0 :                   || sbuf_is_vssdata(p1b))
     311           0 :                         return process_new(cconfs, p1b, ucmanio);
     312             :                 // On Windows, we have to back up the whole file if ctime
     313             :                 // changed, otherwise things like permission changes do not get
     314             :                 // noticed. So, in that case, fall through to the changed stuff
     315             :                 // below.
     316             :                 // Non-Windows clients finish here.
     317           0 :                 else if(!get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
     318           0 :                         return process_unchanged_file(p1b,
     319             :                                 cb, ucmanio, cconfs);
     320             :         }
     321             : 
     322             :         // Got a changed file.
     323             :         //logp("got changed file: %s\n", p1b->path.buf);
     324             : 
     325             :         // If either old or new is encrypted, or librsync is off, we need to
     326             :         // get a new file.
     327             :         // FIX THIS horrible mess.
     328           4 :         if(!get_int(cconfs[OPT_LIBRSYNC])
     329             :         // FIX THIS: make unencrypted metadata use the librsync
     330           4 :           || cb->path.cmd==CMD_METADATA
     331           4 :           || p1b->path.cmd==CMD_METADATA
     332           4 :           || sbuf_is_encrypted(cb)
     333           2 :           || sbuf_is_encrypted(p1b)
     334           2 :           || sbuf_is_vssdata(cb)
     335           2 :           || sbuf_is_vssdata(p1b))
     336           2 :                 return process_new(cconfs, p1b, ucmanio);
     337             : 
     338             :         // Get new files if they have switched between compression on or off.
     339           2 :         if(cb->protocol1->datapth.buf
     340           2 :           && dpth_protocol1_is_compressed(cb->compression,
     341             :             cb->protocol1->datapth.buf))
     342           0 :                 oldcompressed=1;
     343           2 :         if( ( oldcompressed && !compression)
     344           2 :          || (!oldcompressed &&  compression))
     345           0 :                 return process_new(cconfs, p1b, ucmanio);
     346             : 
     347             :         // Otherwise, do the delta stuff (if possible).
     348           2 :         if(sbuf_is_filedata(p1b)
     349           0 :           || sbuf_is_vssdata(p1b))
     350           2 :                 return process_changed_file(asfd, cconfs, cb, p1b,
     351           2 :                         sdirs->currentdata);
     352           0 :         return changed_non_file(p1b, ucmanio, p1b->path.cmd, cconfs);
     353             : }
     354             : 
     355             : static enum processed_e process_deleted_file(struct sbuf *cb,
     356             :         struct conf **cconfs)
     357             : {
     358           0 :         cntr_add_deleted(get_cntr(cconfs), cb->path.cmd);
     359             :         return P_DONE_DELETED;
     360             : }
     361             : 
     362             : // return 1 to say that a file was processed
     363          10 : static enum processed_e maybe_process_file(struct asfd *asfd,
     364           0 :         struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
     365             :         struct manio *ucmanio, struct conf **cconfs)
     366             : {
     367             :         int pcmp;
     368          10 :         if(p1b)
     369             :         {
     370          10 :                 if(!(pcmp=sbuf_pathcmp(cb, p1b)))
     371          10 :                         return maybe_do_delta_stuff(asfd, sdirs, cb, p1b,
     372             :                                 ucmanio, cconfs);
     373           0 :                 else if(pcmp>0)
     374             :                 {
     375             :                         //logp("ahead: %s\n", p1b->path);
     376             :                         // ahead - need to get the whole file
     377           0 :                         return process_new(cconfs, p1b, ucmanio);
     378             :                 }
     379             :         }
     380             :         //logp("behind: %s\n", p1b->path);
     381             :         // Behind - need to read more from the old manifest.
     382             :         // Count a deleted file - it was in the old manifest
     383             :         // but not the new.
     384           0 :         return process_deleted_file(cb, cconfs);
     385             : }
     386             : 
     387             : enum sts_e
     388             : {
     389             :         STS_ERROR=-1,
     390             :         STS_OK=0,
     391             :         STS_BLOCKED=1
     392             : };
     393             : 
     394             : // Return 1 if there is still stuff needing to be sent.
     395             : // FIX THIS: lots of repeated code.
     396          63 : static enum sts_e do_stuff_to_send(struct asfd *asfd,
     397             :         struct sbuf *p1b, char **last_requested)
     398             : {
     399             :         static struct iobuf wbuf;
     400          63 :         if(p1b->flags & SBUF_SEND_DATAPTH)
     401             :         {
     402           2 :                 iobuf_copy(&wbuf, &p1b->protocol1->datapth);
     403           2 :                 switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
     404             :                 {
     405             :                         case APPEND_OK: break;
     406             :                         case APPEND_BLOCKED: return STS_BLOCKED;
     407           0 :                         default: return STS_ERROR;
     408             :                 }
     409           2 :                 p1b->flags &= ~SBUF_SEND_DATAPTH;
     410             :         }
     411          63 :         if(p1b->flags & SBUF_SEND_STAT)
     412             :         {
     413          56 :                 iobuf_copy(&wbuf, &p1b->attr);
     414          56 :                 switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
     415             :                 {
     416             :                         case APPEND_OK: break;
     417             :                         case APPEND_BLOCKED: return STS_BLOCKED;
     418           0 :                         default: return STS_ERROR;
     419             :                 }
     420          56 :                 p1b->flags &= ~SBUF_SEND_STAT;
     421             :         }
     422          63 :         if(p1b->flags & SBUF_SEND_PATH)
     423             :         {
     424          56 :                 iobuf_copy(&wbuf, &p1b->path);
     425          56 :                 switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
     426             :                 {
     427             :                         case APPEND_OK: break;
     428             :                         case APPEND_BLOCKED: return STS_BLOCKED;
     429           0 :                         default: return STS_ERROR;
     430             :                 }
     431          56 :                 p1b->flags &= ~SBUF_SEND_PATH;
     432          56 :                 free_w(last_requested);
     433          56 :                 if(!(*last_requested=strdup_w(p1b->path.buf, __func__)))
     434             :                         return STS_ERROR;
     435             :         }
     436          63 :         if(p1b->protocol1->sigjob && !(p1b->flags & SBUF_SEND_ENDOFSIG))
     437             :         {
     438             :                 rs_result sigresult;
     439             : 
     440           4 :                 switch((sigresult=rs_async(p1b->protocol1->sigjob,
     441             :                         &(p1b->protocol1->rsbuf),
     442             :                         p1b->protocol1->infb, p1b->protocol1->outfb)))
     443             :                 {
     444             :                         case RS_DONE:
     445           2 :                                 p1b->flags |= SBUF_SEND_ENDOFSIG;
     446           2 :                                 break;
     447             :                         case RS_BLOCKED:
     448             :                         case RS_RUNNING:
     449             :                                 // keep going round the loop.
     450             :                                 return STS_BLOCKED;
     451             :                         default:
     452           0 :                                 logp("error in rs_async: %d\n", sigresult);
     453           0 :                                 return STS_ERROR;
     454             :                 }
     455             :         }
     456          61 :         if(p1b->flags & SBUF_SEND_ENDOFSIG)
     457             :         {
     458           2 :                 iobuf_from_str(&wbuf, CMD_END_FILE, (char *)"endfile");
     459           2 :                 switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
     460             :                 {
     461             :                         case APPEND_OK: break;
     462             :                         case APPEND_BLOCKED: return STS_BLOCKED;
     463           0 :                         default: return STS_ERROR;
     464             :                 }
     465           2 :                 p1b->flags &= ~SBUF_SEND_ENDOFSIG;
     466             :         }
     467             :         return STS_OK;
     468             : }
     469             : 
     470           4 : static int start_to_receive_delta(struct sdirs *sdirs, struct sbuf *rb)
     471             : {
     472           4 :         if(rb->compression)
     473             :         {
     474           0 :                 if(!(rb->protocol1->fzp=fzp_gzopen(sdirs->deltmppath,
     475           0 :                         comp_level(rb->compression))))
     476             :                                 return -1;
     477             :         }
     478             :         else
     479             :         {
     480           4 :                 if(!(rb->protocol1->fzp=fzp_open(sdirs->deltmppath, "wb")))
     481             :                         return -1;
     482             :         }
     483           4 :         rb->flags |= SBUF_RECV_DELTA;
     484             : 
     485             :         return 0;
     486             : }
     487             : 
     488           4 : static int finish_delta(struct sdirs *sdirs, struct sbuf *rb)
     489             : {
     490           4 :         int ret=0;
     491           4 :         char *deltmp=NULL;
     492           4 :         char *delpath=NULL;
     493           4 :         if(!(deltmp=prepend_s("deltas.forward", rb->protocol1->datapth.buf))
     494           4 :           || !(delpath=prepend_s(sdirs->working, deltmp))
     495           4 :           || mkpath(&delpath, sdirs->working)
     496             :         // Rename race condition is of no consequence here, as delpath will
     497             :         // just get recreated.
     498           4 :           || do_rename(sdirs->deltmppath, delpath))
     499             :                 ret=-1;
     500           4 :         free_w(&delpath);
     501           4 :         free_w(&deltmp);
     502           4 :         return ret;
     503             : }
     504             : 
     505           8 : static int deal_with_receive_end_file(struct asfd *asfd, struct sdirs *sdirs,
     506           4 :         struct sbuf *rb, struct manio *chmanio, struct conf **cconfs,
     507             :         char **last_requested)
     508             : {
     509           8 :         int ret=-1;
     510             :         static char *cp=NULL;
     511             :         static struct iobuf *rbuf;
     512           8 :         struct cntr *cntr=get_cntr(cconfs);
     513           8 :         rbuf=asfd->rbuf;
     514             :         // Finished the file.
     515             :         // Write it to the phase2 file, and free the buffers.
     516             : 
     517           8 :         if(fzp_close(&(rb->protocol1->fzp)))
     518             :         {
     519           0 :                 logp("error closing delta for %s in receive\n", rb->path.buf);
     520             :                 goto end;
     521             :         }
     522           8 :         iobuf_move(&rb->endfile, rbuf);
     523          12 :         if(rb->flags & SBUF_RECV_DELTA && finish_delta(sdirs, rb))
     524             :                 goto end;
     525             : 
     526           8 :         if(manio_write_sbuf(chmanio, rb))
     527             :                 goto end;
     528             : 
     529           8 :         if(rb->flags & SBUF_RECV_DELTA)
     530           4 :                 cntr_add_changed(cntr, rb->path.cmd);
     531             :         else
     532           4 :                 cntr_add(cntr, rb->path.cmd, 0);
     533             : 
     534           8 :         if(*last_requested && !strcmp(rb->path.buf, *last_requested))
     535           2 :                 free_w(last_requested);
     536             : 
     537           8 :         cp=strchr(rb->endfile.buf, ':');
     538           8 :         if(rb->endfile.buf)
     539           8 :                 cntr_add_bytes(cntr, strtoull(rb->endfile.buf, NULL, 10));
     540             :         if(cp)
     541             :         {
     542             :                 // checksum stuff goes here
     543             :         }
     544             : 
     545             :         ret=0;
     546             : end:
     547           8 :         sbuf_free_content(rb);
     548           8 :         return ret;
     549             : }
     550             : 
     551           8 : static int deal_with_receive_append(struct asfd *asfd, struct sbuf *rb)
     552             : {
     553           8 :         int app=0;
     554             :         static struct iobuf *rbuf;
     555           8 :         rbuf=asfd->rbuf;
     556             :         //logp("rbuf->len: %d\n", rbuf->len);
     557             : 
     558           8 :         if(rb->protocol1->fzp)
     559           8 :                 app=fzp_write(rb->protocol1->fzp, rbuf->buf, rbuf->len);
     560             : 
     561           8 :         if(app>0) return 0;
     562           0 :         logp("error when appending: %d\n", app);
     563           0 :         asfd->write_str(asfd, CMD_ERROR, "write failed");
     564             :         return -1;
     565             : }
     566             : 
     567           8 : static int deal_with_filedata(struct asfd *asfd,
     568             :         struct sdirs *sdirs, struct sbuf *rb,
     569             :         struct iobuf *rbuf, struct dpth *dpth, struct conf **cconfs)
     570             : {
     571           8 :         iobuf_move(&rb->path, rbuf);
     572             : 
     573           8 :         if(rb->protocol1->datapth.buf)
     574             :         {
     575             :                 // Receiving a delta.
     576           4 :                 if(start_to_receive_delta(sdirs, rb))
     577             :                 {
     578           0 :                         logp("error in start_to_receive_delta\n");
     579           0 :                         return -1;
     580             :                 }
     581             :                 return 0;
     582             :         }
     583             : 
     584             :         // Receiving a whole new file.
     585           4 :         if(start_to_receive_new_file(asfd, sdirs, cconfs, rb, dpth))
     586             :         {
     587           0 :                 logp("error in start_to_receive_new_file\n");
     588           0 :                 return -1;
     589             :         }
     590             :         return 0;
     591             : }
     592             : 
     593             : enum str_e
     594             : {
     595             :         STR_ERROR=-1,
     596             :         STR_OK=0,
     597             :         STR_FINISHED=1
     598             : };
     599             : 
     600             : // returns 1 for finished ok.
     601          85 : static enum str_e do_stuff_to_receive(struct asfd *asfd,
     602             :         struct sdirs *sdirs, struct conf **cconfs,
     603             :         struct sbuf *rb, struct manio *chmanio,
     604             :         struct dpth *dpth, char **last_requested)
     605             : {
     606          85 :         struct iobuf *rbuf=asfd->rbuf;
     607             : 
     608         170 :         if(rbuf->cmd==CMD_MESSAGE
     609          85 :           || rbuf->cmd==CMD_WARNING)
     610             :         {
     611           0 :                 struct cntr *cntr=NULL;
     612           0 :                 if(cconfs) cntr=get_cntr(cconfs);
     613           0 :                 log_recvd(rbuf, cntr, 0);
     614           0 :                 return STR_OK;
     615             :         }
     616             : 
     617          85 :         if(rb->protocol1->fzp)
     618             :         {
     619             :                 // Currently writing a file (or meta data)
     620          16 :                 switch(rbuf->cmd)
     621             :                 {
     622             :                         case CMD_APPEND:
     623           8 :                                 if(deal_with_receive_append(asfd, rb))
     624             :                                         goto error;
     625             :                                 return STR_OK;
     626             :                         case CMD_END_FILE:
     627           8 :                                 if(deal_with_receive_end_file(asfd, sdirs, rb,
     628             :                                         chmanio, cconfs, last_requested))
     629             :                                                 goto error;
     630             :                                 return STR_OK;
     631             :                         default:
     632           0 :                                 iobuf_log_unexpected(rbuf, __func__);
     633           0 :                                 goto error;
     634             :                 }
     635             :         }
     636             : 
     637             :         // Otherwise, expecting to be told of a file to save.
     638          69 :         switch(rbuf->cmd)
     639             :         {
     640             :                 case CMD_DATAPTH:
     641           4 :                         iobuf_move(&rb->protocol1->datapth, rbuf);
     642           4 :                         return STR_OK;
     643             :                 case CMD_ATTRIBS:
     644           8 :                         iobuf_move(&rb->attr, rbuf);
     645           8 :                         attribs_decode(rb);
     646           8 :                         return STR_OK;
     647             :                 case CMD_GEN:
     648           5 :                         if(!strcmp(rbuf->buf, "okbackupphase2end"))
     649             :                                 goto end_phase2;
     650           0 :                         iobuf_log_unexpected(rbuf, __func__);
     651           0 :                         goto error;
     652             :                 case CMD_INTERRUPT:
     653             :                         // Interrupt - forget about the last requested
     654             :                         // file if it matches. Otherwise, we can get
     655             :                         // stuck on the select in the async stuff,
     656             :                         // waiting for something that will never arrive.
     657          44 :                         if(*last_requested
     658          44 :                           && !strcmp(rbuf->buf, *last_requested))
     659           1 :                                 free_w(last_requested);
     660             :                         return STR_OK;
     661             :                 default:
     662             :                         break;
     663             :         }
     664           8 :         if(iobuf_is_filedata(rbuf)
     665           0 :           || iobuf_is_vssdata(rbuf))
     666             :         {
     667           8 :                 if(deal_with_filedata(asfd, sdirs, rb, rbuf, dpth, cconfs))
     668             :                         goto error;
     669             :                 return STR_OK;
     670             :         }
     671           0 :         iobuf_log_unexpected(rbuf, __func__);
     672             : 
     673             : error:
     674             :         return STR_ERROR;
     675             : end_phase2:
     676             :         return STR_FINISHED;
     677             : }
     678             : 
     679           1 : static int vss_opts_changed(struct sdirs *sdirs, struct conf **cconfs,
     680             :         const char *incexc)
     681             : {
     682           1 :         int ret=-1;
     683             :         struct conf **oldconfs;
     684             :         struct conf **newconfs;
     685           1 :         if(!(oldconfs=confs_alloc())
     686           1 :           || !(newconfs=confs_alloc()))
     687             :                 goto end;
     688           1 :         confs_init(oldconfs);
     689           1 :         confs_init(newconfs);
     690             : 
     691             :         // Figure out the old config, which is in the incexc file left
     692             :         // in the current backup directory on the server.
     693           1 :         if(conf_parse_incexcs_path(oldconfs, sdirs->cincexc))
     694             :         {
     695             :                 // Assume that the file did not exist, and therefore
     696             :                 // the old split_vss setting is 0.
     697           0 :                 set_int(oldconfs[OPT_SPLIT_VSS], 0);
     698           0 :                 set_int(oldconfs[OPT_STRIP_VSS], 0);
     699             :         }
     700             : 
     701             :         // Figure out the new config, which is either in the incexc file from
     702             :         // the client, or in the cconf on the server.
     703           1 :         if(incexc)
     704             :         {
     705           0 :                 if(conf_parse_incexcs_buf(newconfs, incexc))
     706             :                 {
     707             :                         // Should probably not got here.
     708           0 :                         set_int(newconfs[OPT_SPLIT_VSS], 0);
     709           0 :                         set_int(newconfs[OPT_STRIP_VSS], 0);
     710             :                 }
     711             :         }
     712             :         else
     713             :         {
     714           1 :                 set_int(newconfs[OPT_SPLIT_VSS],
     715           1 :                         get_int(cconfs[OPT_SPLIT_VSS]));
     716           1 :                 set_int(newconfs[OPT_STRIP_VSS],
     717           1 :                         get_int(cconfs[OPT_STRIP_VSS]));
     718             :         }
     719             : 
     720           1 :         if(get_int(newconfs[OPT_SPLIT_VSS])!=get_int(oldconfs[OPT_SPLIT_VSS]))
     721             :         {
     722           0 :                 logp("split_vss=%d (changed since last backup)\n",
     723           0 :                         get_int(newconfs[OPT_SPLIT_VSS]));
     724           0 :                 ret=1; goto end;
     725             :         }
     726           1 :         if(get_int(newconfs[OPT_STRIP_VSS])!=get_int(oldconfs[OPT_STRIP_VSS]))
     727             :         {
     728           0 :                 logp("strip_vss=%d (changed since last backup)\n",
     729           0 :                         get_int(newconfs[OPT_STRIP_VSS]));
     730           0 :                 ret=1; goto end;
     731             :         }
     732             :         ret=0;
     733             : end:
     734           1 :         if(ret==1) logp("All files will be treated as new\n");
     735           1 :         confs_free(&oldconfs);
     736           1 :         confs_free(&newconfs);
     737           1 :         return ret;
     738             : }
     739             : 
     740             : // Open the previous (current) manifest.
     741             : // If the split_vss setting changed between the previous backup and the new
     742             : // backup, do not open the previous manifest. This will have the effect of
     743             : // making the client back up everything fresh. Need to do this, otherwise
     744             : // toggling split_vss on and off will result in backups that do not work.
     745           5 : static int open_previous_manifest(struct manio **cmanio,
     746             :         struct sdirs *sdirs, const char *incexc, struct conf **cconfs)
     747             : {
     748             :         struct stat statp;
     749          10 :         if(!lstat(sdirs->cmanifest, &statp)
     750           1 :           && !vss_opts_changed(sdirs, cconfs, incexc)
     751           1 :           && !(*cmanio=manio_open(sdirs->cmanifest, "rb", PROTO_1)))
     752             :         {
     753           0 :                 logp("could not open old manifest %s\n", sdirs->cmanifest);
     754           0 :                 return -1;
     755             :         }
     756             :         return 0;
     757             : }
     758             : 
     759         135 : static int process_next_file_from_manios(struct asfd *asfd,
     760             :         struct sdirs *sdirs,
     761             :         struct manio **p1manio,
     762             :         struct manio **cmanio,
     763             :         struct manio *ucmanio,
     764             :         struct sbuf **p1b,
     765             :         struct sbuf *cb,
     766             :         struct conf **cconfs)
     767             : {
     768         135 :         if(!(*p1b=sbuf_alloc(PROTO_1)))
     769             :                 goto error;
     770         135 :         switch(manio_read(*p1manio, *p1b))
     771             :         {
     772             :                 case 0:
     773             :                         break;
     774             :                 case 1:
     775           5 :                         manio_close(p1manio);
     776           5 :                         if(asfd->write_str(asfd, CMD_GEN, "backupphase2end"))
     777             :                                 goto error;
     778           5 :                         sbuf_free(p1b);
     779           5 :                         break;
     780             :                 case -1:
     781             :                         goto error;
     782             :         }
     783             : 
     784         135 :         if(!*cmanio)
     785             :         {
     786         124 :                 if(!*p1b) return 0;
     787             :                 // No old manifest, need to ask for a new file.
     788         120 :                 switch(process_new(cconfs, *p1b, ucmanio))
     789             :                 {
     790             :                         case P_NEW:
     791             :                                 return 0;
     792             :                         case P_DONE_NEW:
     793             :                                 goto p1b_done;
     794             :                         default:
     795             :                                 goto error;
     796             :                 }
     797             :         }
     798             : 
     799             :         // Have an old manifest, look for it there.
     800             : 
     801             :         // Might already have it, or be ahead in the old
     802             :         // manifest.
     803          11 :         if(cb->path.buf)
     804             :         {
     805           0 :                 switch(maybe_process_file(asfd,
     806             :                         sdirs, cb, *p1b, ucmanio, cconfs))
     807             :                 {
     808             :                         case P_NEW:
     809             :                         case P_CHANGED:
     810             :                                 // Free cb content for things like encrypted
     811             :                                 // files, which we only pretend are new.
     812           0 :                                 sbuf_free_content(cb);
     813           0 :                                 return 0;
     814             :                         case P_DONE_NEW:
     815             :                                 goto p1b_done;
     816             :                         case P_DONE_CHANGED:
     817             :                         case P_DONE_UNCHANGED:
     818           0 :                                 sbuf_free_content(cb);
     819           0 :                                 goto p1b_done;
     820             :                         case P_DONE_DELETED:
     821           0 :                                 sbuf_free_content(cb);
     822           0 :                                 break;
     823             :                         case P_ERROR:
     824             :                                 goto error;
     825             :                 }
     826             :         }
     827             : 
     828             :         while(1)
     829             :         {
     830          11 :                 sbuf_free_content(cb);
     831          11 :                 switch(manio_read(*cmanio, cb))
     832             :                 {
     833             :                         case 0: break;
     834           1 :                         case 1: manio_close(cmanio);
     835           1 :                                 if(*p1b) switch(process_new(cconfs,
     836             :                                         *p1b, ucmanio))
     837             :                                 {
     838             :                                         case P_NEW:
     839             :                                                 return 0;
     840             :                                         case P_DONE_NEW:
     841             :                                                 goto p1b_done;
     842             :                                         default:
     843             :                                                 goto error;
     844             :                                 }
     845             :                                 return 0;
     846             :                         case -1: goto error;
     847             :                 }
     848          10 :                 switch(maybe_process_file(asfd, sdirs,
     849             :                         cb, *p1b, ucmanio, cconfs))
     850             :                 {
     851             :                         case P_NEW:
     852             :                         case P_CHANGED:
     853             :                                 // Free cb content for things like encrypted
     854             :                                 // files, which we only pretend are new.
     855           4 :                                 sbuf_free_content(cb);
     856           4 :                                 return 0;
     857             :                         case P_DONE_NEW:
     858             :                                 goto p1b_done;
     859             :                         case P_DONE_CHANGED:
     860             :                         case P_DONE_UNCHANGED:
     861           6 :                                 sbuf_free_content(cb);
     862           6 :                                 goto p1b_done;
     863             :                         case P_DONE_DELETED:
     864           0 :                                 sbuf_free_content(cb);
     865           0 :                                 continue;
     866             :                         case P_ERROR:
     867             :                                 goto error;
     868             :                 }
     869             :         }
     870             : error:
     871             :         return -1;
     872             : p1b_done:
     873          74 :         sbuf_free(p1b);
     874          74 :         return 0;
     875             : }
     876             : 
     877          10 : int backup_phase2_server_protocol1(struct async *as, struct sdirs *sdirs,
     878             :         const char *incexc, int resume, struct conf **cconfs)
     879             : {
     880          10 :         int ret=0;
     881          10 :         man_off_t *p1pos=NULL;
     882          10 :         struct manio *p1manio=NULL;
     883          10 :         struct dpth *dpth=NULL;
     884          10 :         char *deltmppath=NULL;
     885          10 :         char *last_requested=NULL;
     886          10 :         struct manio *chmanio=NULL; // changed data
     887          10 :         struct manio *ucmanio=NULL; // unchanged data
     888          10 :         struct manio *cmanio=NULL; // previous (current) manifest.
     889          10 :         struct sbuf *cb=NULL; // file list in current manifest
     890          10 :         struct sbuf *p1b=NULL; // file list from client
     891          10 :         struct sbuf *rb=NULL; // receiving file from client
     892          10 :         struct asfd *asfd=NULL;
     893          10 :         int breaking=0;
     894          10 :         int breakcount=0;
     895          10 :         struct cntr *cntr=NULL;
     896             : 
     897          10 :         if(!as)
     898             :         {
     899           1 :                 logp("async not provided to %s()\n", __func__);
     900           1 :                 goto error;
     901             :         }
     902           9 :         if(!sdirs)
     903             :         {
     904           2 :                 logp("sdirs not provided to %s()\n", __func__);
     905           2 :                 goto error;
     906             :         }
     907           7 :         if(!cconfs)
     908             :         {
     909           1 :                 logp("cconfs not provided to %s()\n", __func__);
     910           1 :                 goto error;
     911             :         }
     912           6 :         asfd=as->asfd;
     913           6 :         if(!asfd)
     914             :         {
     915           1 :                 logp("asfd not provided to %s()\n", __func__);
     916           1 :                 goto error;
     917             :         }
     918           5 :         cntr=get_cntr(cconfs);
     919             : 
     920           5 :         if(get_int(cconfs[OPT_BREAKPOINT])>=2000
     921           0 :           && get_int(cconfs[OPT_BREAKPOINT])<3000)
     922             :         {
     923           0 :                 breaking=get_int(cconfs[OPT_BREAKPOINT]);
     924           0 :                 breakcount=breaking-2000;
     925             :         }
     926             : 
     927           5 :         logp("Begin phase2 (receive file data)\n");
     928             : 
     929           5 :         if(!(dpth=dpth_alloc())
     930           5 :           || dpth_protocol1_init(dpth, sdirs->currentdata,
     931             :                 get_int(cconfs[OPT_MAX_STORAGE_SUBDIRS])))
     932             :                         goto error;
     933             : 
     934           5 :         if(open_previous_manifest(&cmanio, sdirs, incexc, cconfs))
     935             :                 goto error;
     936             : 
     937           5 :         if(get_int(cconfs[OPT_DIRECTORY_TREE]))
     938             :         {
     939             :                 // Need to make sure we do not try to create a path that is
     940             :                 // too long.
     941           5 :                 if(build_path_w(sdirs->treepath)) goto error;
     942           5 :                 mkdir(sdirs->treepath, 0777);
     943           5 :                 treepathlen=strlen(sdirs->treepath);
     944           5 :                 if(init_fs_max(sdirs->treepath))
     945             :                         goto error;
     946             :         }
     947             : 
     948           5 :         if(resume)
     949             :         {
     950           0 :                 if(!(p1pos=do_resume(sdirs, dpth, cconfs)))
     951             :                         goto error;
     952           0 :                 if(cntr_send_sdirs(asfd, sdirs, cconfs))
     953             :                         goto error;
     954             :         }
     955             : 
     956           5 :         if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", PROTO_1))
     957           5 :           || (resume && manio_seek(p1manio, p1pos)))
     958             :                 goto error;
     959           5 :         if(!(cb=sbuf_alloc(PROTO_1))
     960           5 :           || !(p1b=sbuf_alloc(PROTO_1))
     961           5 :           || !(rb=sbuf_alloc(PROTO_1)))
     962             :                 goto error;
     963             : 
     964             :         // Unchanged and changed should now be truncated correctly, we just
     965             :         // have to open them for appending.
     966             :         // Data is not getting written to a compressed file.
     967             :         // This is important for recovery if the power goes.
     968           5 :         if(!(ucmanio=manio_open_phase2(sdirs->unchanged, "ab", PROTO_1))
     969           5 :           || !(chmanio=manio_open_phase2(sdirs->changed, "ab", PROTO_1)))
     970             :                 goto error;
     971             : 
     972             :         while(1)
     973             :         {
     974         921 :                 if(breaking && breakcount--==0)
     975           0 :                         return breakpoint(breaking, __func__);
     976             : 
     977         921 :                 if(write_status(CNTR_STATUS_BACKUP,
     978         921 :                         rb->path.buf?rb->path.buf:"", cntr))
     979             :                                 goto error;
     980        1842 :                 if(last_requested
     981         921 :                   || !p1manio
     982          16 :                   || asfd->writebuflen)
     983             :                 {
     984         905 :                         iobuf_free_content(asfd->rbuf);
     985         905 :                         if(asfd->as->read_write(asfd->as))
     986             :                         {
     987           0 :                                 logp("error in %s\n", __func__);
     988           0 :                                 goto error;
     989             :                         }
     990             : 
     991         905 :                         if(asfd->rbuf->buf)
     992          85 :                           switch(do_stuff_to_receive(asfd, sdirs,
     993             :                                 cconfs, rb, chmanio, dpth, &last_requested))
     994             :                         {
     995             :                                 case STR_OK:
     996             :                                         break;
     997             :                                 case STR_FINISHED:
     998             :                                         goto end;
     999             :                                 case STR_ERROR:
    1000             :                                         goto error;
    1001             :                         }
    1002             :                 }
    1003             : 
    1004         916 :                 if(p1b) switch(do_stuff_to_send(asfd, p1b, &last_requested))
    1005             :                 {
    1006             :                         case STS_OK:
    1007          61 :                                 sbuf_free(&p1b);
    1008          61 :                                 break;
    1009             :                         case STS_BLOCKED:
    1010           2 :                                 continue;
    1011             :                         case STS_ERROR:
    1012             :                                 goto error;
    1013             :                 }
    1014             : 
    1015         914 :                 if(p1manio
    1016         135 :                  && process_next_file_from_manios(asfd, sdirs,
    1017             :                         &p1manio, &cmanio, ucmanio, &p1b, cb, cconfs))
    1018             :                                         goto error;
    1019             :         }
    1020             : 
    1021             : error:
    1022             :         ret=-1;
    1023             : end:
    1024          10 :         if(manio_close(&chmanio))
    1025             :         {
    1026           0 :                 logp("error closing %s in %s\n", sdirs->changed, __func__);
    1027           0 :                 ret=-1;
    1028             :         }
    1029          10 :         if(manio_close(&ucmanio))
    1030             :         {
    1031           0 :                 logp("error closing %s in %s\n", sdirs->unchanged, __func__);
    1032           0 :                 ret=-1;
    1033             :         }
    1034          10 :         free_w(&deltmppath);
    1035          10 :         free_w(&last_requested);
    1036          10 :         sbuf_free(&cb);
    1037          10 :         sbuf_free(&p1b);
    1038          10 :         sbuf_free(&rb);
    1039          10 :         manio_close(&p1manio);
    1040          10 :         manio_close(&cmanio);
    1041          10 :         dpth_free(&dpth);
    1042          10 :         man_off_t_free(&p1pos);
    1043          10 :         if(!ret && sdirs)
    1044           5 :                 unlink(sdirs->phase1data);
    1045             : 
    1046          10 :         logp("End phase2 (receive file data)\n");
    1047             : 
    1048          10 :         return ret;
    1049             : }

Generated by: LCOV version 1.10