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

Generated by: LCOV version 1.10