LCOV - code coverage report
Current view: top level - src/server - backup.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 69 162 42.6 %
Date: 2019-03-30 01:11:57 Functions: 7 10 70.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../action.h"
       3             : #include "../alloc.h"
       4             : #include "../asfd.h"
       5             : #include "../async.h"
       6             : #include "../conf.h"
       7             : #include "../cmd.h"
       8             : #include "../cntr.h"
       9             : #include "../fsops.h"
      10             : #include "../handy.h"
      11             : #include "../iobuf.h"
      12             : #include "../log.h"
      13             : #include "../run_script.h"
      14             : #include "auth.h"
      15             : #include "backup_phase1.h"
      16             : #include "backup_phase3.h"
      17             : #include "compress.h"
      18             : #include "delete.h"
      19             : #include "sdirs.h"
      20             : #include "protocol1/backup_phase2.h"
      21             : #include "protocol1/backup_phase4.h"
      22             : #include "protocol2/backup_phase2.h"
      23             : #include "protocol2/backup_phase4.h"
      24             : #include "backup.h"
      25             : #include "rubble.h"
      26             : #include "timer.h"
      27             : 
      28           1 : static void log_rshash(struct conf **confs)
      29             : {
      30           1 :         if(get_protocol(confs)!=PROTO_1) return;
      31           0 :         logp("Using librsync hash %s\n",
      32             :                 rshash_to_str(get_e_rshash(confs[OPT_RSHASH])));
      33             : }
      34             : 
      35           1 : static int open_log(struct asfd *asfd,
      36             :         struct sdirs *sdirs, struct conf **cconfs, int resume)
      37             : {
      38           1 :         int ret=-1;
      39           1 :         char *logpath=NULL;
      40           1 :         const char *peer_version=get_string(cconfs[OPT_PEER_VERSION]);
      41             : 
      42           1 :         logp("Backup %s: %s\n", resume?"resumed":"started", sdirs->rworking);
      43             : 
      44           1 :         if(!(logpath=prepend_s(sdirs->rworking, "log"))) goto end;
      45           1 :         if(log_fzp_set(logpath, cconfs))
      46             :         {
      47           0 :                 logp("could not open log file: %s\n", logpath);
      48             :                 goto end;
      49             :         }
      50             : 
      51           1 :         logp("Backup %s\n", resume?"resumed":"started");
      52           1 :         logp("Client version: %s\n", peer_version?:"");
      53           1 :         logp("Protocol: %d\n", (int)get_protocol(cconfs));
      54           1 :         log_rshash(cconfs);
      55           1 :         if(get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
      56           0 :                 logp("Client is Windows\n");
      57             : 
      58             :         // Make sure a warning appears in the backup log.
      59             :         // The client will already have been sent a message with logw.
      60             :         // This time, prevent it sending a logw to the client by specifying
      61             :         // NULL for asfd and cntr.
      62           1 :         if(get_int(cconfs[OPT_VERSION_WARN]))
      63           1 :                 version_warn(NULL, NULL, cconfs);
      64             : 
      65             :         ret=0;
      66             : end:
      67           1 :         free_w(&logpath);
      68           1 :         return ret;
      69             : }
      70             : 
      71           1 : static int write_incexc(const char *realworking, const char *incexc)
      72             : {
      73           1 :         int ret=-1;
      74           1 :         char *tmp=NULL;
      75           1 :         char *path=NULL;
      76           1 :         struct fzp *fzp=NULL;
      77             : 
      78           1 :         if(!incexc || !*incexc) return 0;
      79             : 
      80           0 :         if(!(path=prepend_s(realworking, "incexc"))
      81           0 :           || !(tmp=prepend(path, ".tmp"))
      82           0 :           || !(fzp=fzp_open(tmp, "wb")))
      83             :                 goto end;
      84             : 
      85           0 :         fzp_printf(fzp, "%s", incexc);
      86           0 :         if(fzp_close(&fzp))
      87             :         {
      88           0 :                 logp("error writing to %s in %s\n", tmp, __func__);
      89           0 :                 goto end;
      90             :         }
      91           0 :         if(do_rename(tmp, path))
      92             :                 goto end;
      93           0 :         ret=0;
      94             : end:
      95           0 :         free_w(&path);
      96           0 :         free_w(&tmp);
      97           0 :         return ret;
      98             : }
      99             : 
     100           1 : static int backup_phase1_server(struct async *as,
     101             :         struct sdirs *sdirs, struct conf **cconfs)
     102             : {
     103           1 :         int breaking=get_int(cconfs[OPT_BREAKPOINT]);
     104           1 :         if(breaking==1)
     105           0 :                 return breakpoint(breaking, __func__);
     106           1 :         return backup_phase1_server_all(as, sdirs, cconfs);
     107             : }
     108             : 
     109           0 : static int backup_phase2_server(struct async *as, struct sdirs *sdirs,
     110             :         const char *incexc, int resume, struct conf **cconfs)
     111             : {
     112           0 :         int breaking=get_int(cconfs[OPT_BREAKPOINT]);
     113           0 :         if(breaking==2)
     114           0 :                 return breakpoint(breaking, __func__);
     115             : 
     116           0 :         switch(get_protocol(cconfs))
     117             :         {
     118             :                 case PROTO_1:
     119           0 :                         return backup_phase2_server_protocol1(as, sdirs,
     120             :                                 incexc, resume, cconfs);
     121             :                 default:
     122           0 :                         return backup_phase2_server_protocol2(as, sdirs,
     123             :                                 resume, cconfs);
     124             :         }
     125             : }
     126             : 
     127           0 : static int backup_phase3_server(struct sdirs *sdirs, struct conf **cconfs)
     128             : {
     129           0 :         int breaking=get_int(cconfs[OPT_BREAKPOINT]);
     130           0 :         if(breaking==3)
     131           0 :                 return breakpoint(breaking, __func__);
     132             : 
     133           0 :         return backup_phase3_server_all(sdirs, cconfs);
     134             : }
     135             : 
     136           0 : static int backup_phase4_server(struct sdirs *sdirs, struct conf **cconfs)
     137             : {
     138           0 :         int breaking=get_int(cconfs[OPT_BREAKPOINT]);
     139           0 :         if(breaking==4)
     140           0 :                 return breakpoint(breaking, __func__);
     141             : 
     142           0 :         log_fzp_set(NULL, cconfs);
     143             :         // Phase4 will open logfp again (in case it is resuming).
     144           0 :         switch(get_protocol(cconfs))
     145             :         {
     146             :                 case PROTO_1:
     147           0 :                         return backup_phase4_server_protocol1(sdirs, cconfs);
     148             :                 default:
     149           0 :                         return backup_phase4_server_protocol2(sdirs, cconfs);
     150             :         }
     151             : }
     152             : 
     153             : static char *get_bno_from_sdirs(struct sdirs *sdirs)
     154             : {
     155           1 :         char *cp=NULL;
     156             :         // Should be easier than this.
     157           1 :         if(!(cp=strrchr(sdirs->rworking, '/')))
     158             :                 return NULL;
     159           1 :         return cp+1;
     160             : }
     161             : 
     162           1 : static void set_cntr_bno(struct cntr *cntr, struct sdirs *sdirs)
     163             : {
     164           2 :         char *bno=get_bno_from_sdirs(sdirs);
     165           1 :         if(!bno)
     166             :                 return;
     167           1 :         cntr->bno=atoi(bno);
     168             : }
     169             : 
     170           1 : static int do_backup_server(struct async *as, struct sdirs *sdirs,
     171             :         struct conf **cconfs, const char *incexc, int resume)
     172             : {
     173           1 :         int ret=0;
     174           1 :         int do_phase2=1;
     175           1 :         struct asfd *asfd=as->asfd;
     176           1 :         enum protocol protocol=get_protocol(cconfs);
     177           1 :         struct cntr *cntr=get_cntr(cconfs);
     178             : 
     179           1 :         if(resume)
     180             :         {
     181           0 :                 if(sdirs_get_real_working_from_symlink(sdirs)
     182           0 :                   || sdirs_get_real_manifest(sdirs, protocol))
     183             :                         goto error;
     184             : 
     185           0 :                 if(open_log(asfd, sdirs, cconfs, resume))
     186             :                         goto error;
     187             : 
     188           0 :                 set_cntr_bno(cntr, sdirs);
     189             :         }
     190             :         else
     191             :         {
     192             :                 // Not resuming - need to set everything up fresh.
     193           1 :                 if(sdirs_create_real_working(sdirs,
     194           1 :                         get_string(cconfs[OPT_TIMESTAMP_FORMAT]))
     195           1 :                   || sdirs_get_real_manifest(sdirs, protocol))
     196             :                         goto error;
     197             : 
     198           1 :                 if(open_log(asfd, sdirs, cconfs, resume))
     199             :                         goto error;
     200             : 
     201           1 :                 set_cntr_bno(cntr, sdirs);
     202             : 
     203           1 :                 if(write_incexc(sdirs->rworking, incexc))
     204             :                 {
     205           0 :                         logp("unable to write incexc\n");
     206           0 :                         goto error;
     207             :                 }
     208             : 
     209           1 :                 if(backup_phase1_server(as, sdirs, cconfs))
     210             :                 {
     211           1 :                         logp("error in phase 1\n");
     212           1 :                         goto error;
     213             :                 }
     214             :         }
     215             : 
     216           0 :         if(resume)
     217             :         {
     218             :                 struct stat statp;
     219           0 :                 if(lstat(sdirs->phase1data, &statp)
     220           0 :                   && !lstat(sdirs->changed, &statp)
     221           0 :                   && !lstat(sdirs->unchanged, &statp))
     222             :                 {
     223             :                         // In this condition, it looks like there was an
     224             :                         // interruption during phase3. Skip phase2.
     225           0 :                         do_phase2=0;
     226             :                 }
     227             :         }
     228             : 
     229           0 :         if(do_phase2)
     230             :         {
     231           0 :                 if(backup_phase2_server(as, sdirs, incexc, resume, cconfs))
     232             :                 {
     233           0 :                         logp("error in backup phase 2\n");
     234           0 :                         goto error;
     235             :                 }
     236             : 
     237           0 :                 asfd->write_str(asfd, CMD_GEN, "okbackupend");
     238             :         }
     239             : 
     240             :         // Close the connection with the client, the rest of the job we can do
     241             :         // by ourselves.
     242           0 :         logp("Backup ending - disconnect from client.\n");
     243           0 :         if(asfd_flush_asio(asfd))
     244             :                 goto error;
     245           0 :         as->asfd_remove(as, asfd);
     246           0 :         asfd_close(asfd);
     247             : 
     248           0 :         if(backup_phase3_server(sdirs, cconfs))
     249             :         {
     250           0 :                 logp("error in backup phase 3\n");
     251           0 :                 goto error;
     252             :         }
     253             : 
     254             :         // Write backup_stats before flipping the symlink, so that is there
     255             :         // even if phase4 is interrupted.
     256           0 :         if(cntr_stats_to_file(cntr, sdirs->working, ACTION_BACKUP))
     257             :                 goto error;
     258             : 
     259           0 :         if(do_rename(sdirs->working, sdirs->finishing))
     260             :                 goto error;
     261             : 
     262           0 :         if(backup_phase4_server(sdirs, cconfs))
     263             :         {
     264           0 :                 logp("error in backup phase 4\n");
     265           0 :                 goto error;
     266             :         }
     267             : 
     268           0 :         cntr_print(cntr, ACTION_BACKUP, asfd);
     269             : 
     270           0 :         if(protocol==PROTO_2)
     271             :         {
     272             :                 // Regenerate dindex before the symlink is renamed, so that the
     273             :                 // champ chooser cleanup does not try to remove data files
     274             :                 // whilst the dindex regeneration is happening.
     275           0 :                 if(regenerate_client_dindex(sdirs))
     276             :                         goto error;
     277             :         }
     278             : 
     279             :         // Move the symlink to indicate that we are now in the end phase. The
     280             :         // rename() race condition is automatically recoverable here.
     281           0 :         if(do_rename(sdirs->finishing, sdirs->current))
     282             :                 goto error;
     283             : 
     284           0 :         logp("Backup completed.\n");
     285           0 :         log_fzp_set(NULL, cconfs);
     286           0 :         logp("Backup completed: %s\n", sdirs->rworking);
     287           0 :         compress_filename(sdirs->rworking,
     288             :                 "log", "log.gz", get_int(cconfs[OPT_COMPRESSION]));
     289             : 
     290           0 :         goto end;
     291             : error:
     292             :         ret=-1;
     293             : end:
     294             : 
     295           1 :         if(ret)
     296           1 :                 logp("Backup failed\n");
     297           1 :         log_fzp_set(NULL, cconfs);
     298           1 :         if(ret)
     299             :         {
     300             :                 // Make an entry in the main output, for failed backups.
     301           1 :                 logp("Backup failed: %s\n", sdirs->rworking);
     302             :         }
     303           1 :         return ret;
     304             : }
     305             : 
     306           1 : int run_backup(struct async *as, struct sdirs *sdirs, struct conf **cconfs,
     307             :         const char *incexc, int *timer_ret, int resume)
     308             : {
     309             :         int ret;
     310           1 :         char okstr[32]="";
     311           1 :         struct asfd *asfd=as->asfd;
     312           1 :         struct iobuf *rbuf=asfd->rbuf;
     313           1 :         const char *cname=get_string(cconfs[OPT_CNAME]);
     314             : 
     315           1 :         if(get_string(cconfs[OPT_SUPER_CLIENT]))
     316             :         {
     317             :                 // This client is not the original client, so a backup might
     318             :                 // cause all sorts of trouble.
     319           0 :                 logp("Not allowing backup of %s\n", cname);
     320           0 :                 return asfd->write_str(asfd, CMD_GEN, "Backup is not allowed");
     321             :         }
     322             : 
     323             :         // Set quality of service bits on backups.
     324           1 :         asfd->set_bulk_packets(asfd);
     325             : 
     326           1 :         if(!strncmp_w(rbuf->buf, "backupphase1timed"))
     327             :         {
     328           0 :                 int checkonly=!strncmp_w(rbuf->buf, "backupphase1timedcheck");
     329           0 :                 if(checkonly) logp("Client asked for a timer check only.\n");
     330             : 
     331           0 :                 if((*timer_ret=run_timer(asfd, sdirs, cconfs))<0)
     332             :                 {
     333           0 :                         logp("Error running timer for %s\n", cname);
     334           0 :                         return -1;
     335             :                 }
     336           0 :                 else if(*timer_ret)
     337             :                 {
     338           0 :                         if(!checkonly)
     339           0 :                                 logp("Not running backup of %s\n", cname);
     340           0 :                         return asfd->write_str(asfd,
     341             :                                 CMD_GEN, "timer conditions not met");
     342             :                 }
     343           0 :                 if(checkonly)
     344             :                 {
     345           0 :                         logp("Client asked for a timer check only,\n");
     346           0 :                         logp("so a backup is not happening right now.\n");
     347           0 :                         return asfd->write_str(asfd,
     348             :                                 CMD_GEN, "timer conditions met");
     349             :                 }
     350           0 :                 logp("Running backup of %s\n", cname);
     351             :         }
     352           1 :         else if(!get_int(cconfs[OPT_CLIENT_CAN_FORCE_BACKUP]))
     353             :         {
     354           0 :                 logp("Not allowing forced backup of %s\n", cname);
     355           0 :                 return asfd->write_str(asfd,
     356             :                         CMD_GEN, "Forced backup is not allowed");
     357             :         }
     358             : 
     359           1 :         snprintf(okstr, sizeof(okstr), "%s:%d",
     360             :                 resume?"resume":"ok", get_int(cconfs[OPT_COMPRESSION]));
     361           1 :         if(asfd->write_str(asfd, CMD_GEN, okstr)) return -1;
     362             : 
     363           1 :         if((ret=do_backup_server(as, sdirs, cconfs, incexc, resume)))
     364             :                 goto end;
     365             : 
     366           0 :         if((ret=delete_backups(sdirs, cname,
     367             :                 get_strlist(cconfs[OPT_KEEP]),
     368           0 :                 get_string(cconfs[OPT_MANUAL_DELETE]))))
     369             :                         goto end;
     370             : end:
     371             :         return ret;
     372             : }

Generated by: LCOV version 1.13