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: 304 399 76.2 %
Date: 2016-09-04 Functions: 20 22 90.9 %

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

Generated by: LCOV version 1.10