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: 0 479 0.0 %
Date: 2015-10-31 Functions: 0 23 0.0 %

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

Generated by: LCOV version 1.10