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

Generated by: LCOV version 1.16