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: 351 531 66.1 %
Date: 2019-07-31 11:35:18 Functions: 24 28 85.7 %

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

Generated by: LCOV version 1.13