LCOV - code coverage report
Current view: top level - src/server - timer.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 125 126 99.2 %
Date: 2020-05-31 21:14:12 Functions: 9 9 100.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../asfd.h"
       4             : #include "../fsops.h"
       5             : #include "../log.h"
       6             : #include "../prepend.h"
       7             : #include "../run_script.h"
       8             : #include "../strlist.h"
       9             : #include "../times.h"
      10             : #include "sdirs.h"
      11             : #include "timestamp.h"
      12             : 
      13             : static int is_dir_stat(const char *path)
      14             : {
      15             :         struct stat buf;
      16          16 :         if(stat(path, &buf))
      17             :                 return -1;
      18          15 :         return S_ISDIR(buf.st_mode);
      19             : }
      20             : 
      21          21 : static int check_manual_file(struct sdirs *sdirs, const char *cname)
      22             : {
      23          21 :         int ret=-1;
      24          21 :         char *manual=NULL;
      25             : 
      26             :         // A 'backup' file placed in the storage directory tells this script
      27             :         // that a backup needs to be done right now.
      28             :         // This gives the 'server initiates a manual backup' feature.
      29             :         // The path should probably be part of sdirs so we do not have to build
      30             :         // it here.
      31          21 :         if(astrcat(&manual, sdirs->clients, __func__)
      32          21 :           || astrcat(&manual, "/", __func__)
      33          21 :           || astrcat(&manual, cname, __func__)
      34          21 :           || astrcat(&manual, "/backup", __func__))
      35             :                 goto end;
      36          21 :         if(is_reg_lstat(manual)>0)
      37             :         {
      38           1 :                 logp("Found %s\n", manual);
      39           1 :                 unlink(manual);
      40           1 :                 ret=0;
      41             :                 goto end;
      42             :         }
      43             :         ret=1;
      44             : end:
      45          21 :         free_w(&manual);
      46          21 :         return ret;
      47             : }
      48             : 
      49           1 : static void get_current_day_and_hour_and_unixtime(
      50             :         char **d,
      51             :         char **h,
      52             :         time_t *t)
      53             : {
      54             :         static char day[4]="";
      55             :         static char hour[3]="";
      56           1 :         const struct tm *ctm=NULL;
      57           1 :         *t=time(NULL);
      58           1 :         ctm=localtime(t);
      59           1 :         strftime(day, sizeof(day), "%a", ctm);
      60           1 :         strftime(hour, sizeof(hour), "%H", ctm);
      61           1 :         *d=day;
      62           1 :         *h=hour;
      63           1 : }
      64             : 
      65          73 : static void strtolower(char *str)
      66             : {
      67             :         char *cp;
      68        1099 :         for(cp=str; *cp; cp++)
      69        1026 :                 *cp=tolower(*cp);
      70          73 : }
      71             : 
      72          20 : static int check_timebands(const char *day_now, const char *hour_now,
      73             :         struct strlist *timebands)
      74             : {
      75          20 :         char *lower_tb=NULL;
      76          20 :         int in_timeband=0;
      77             :         struct strlist *t;
      78          20 :         char *lower_day_now=NULL;
      79          20 :         char *lower_hour_now=NULL;
      80             : 
      81          20 :         if(!(lower_day_now=strdup_w(day_now, __func__))
      82          20 :           || !(lower_hour_now=strdup_w(hour_now, __func__)))
      83             :         {
      84             :                 in_timeband=-1;
      85             :                 goto end;
      86             :         }
      87          20 :         strtolower(lower_day_now);
      88          20 :         strtolower(lower_hour_now);
      89             : 
      90          53 :         for(t=timebands; t; t=t->next)
      91             :         {
      92          33 :                 free_w(&lower_tb);
      93          33 :                 if(!(lower_tb=strdup_w(t->path, __func__)))
      94             :                 {
      95             :                         in_timeband=-1;
      96             :                         goto end;
      97             :                 }
      98          33 :                 strtolower(lower_tb);
      99             : 
     100          33 :                 if(!strcmp(lower_tb, "always")
     101          33 :                   || (strstr(lower_tb, lower_day_now)
     102          17 :                     && strstr(lower_tb, lower_hour_now)))
     103             :                 {
     104          16 :                         logp("In timeband: %s\n", t->path);
     105          16 :                         in_timeband=1;
     106             :                 }
     107             :                 else
     108          17 :                         logp("Out of timeband: %s\n", t->path);
     109             :         }
     110             : 
     111             : end:
     112          20 :         free_w(&lower_day_now);
     113          20 :         free_w(&lower_hour_now);
     114          20 :         free_w(&lower_tb);
     115             : 
     116          20 :         return in_timeband;
     117             : }
     118             : 
     119          15 : static long get_interval_in_seconds(const char *str, const char *cname)
     120             : {
     121             :         int s;
     122             :         long seconds;
     123             :         char unit;
     124          15 :         if(sscanf(str, "%d%c", &s, &unit)!=2)
     125             :                 goto error;
     126          15 :         seconds=(long)s;
     127          15 :         switch(unit)
     128             :         {
     129             :                 case 's':
     130             :                         return seconds;
     131             :                 case 'm':
     132           2 :                         return seconds*60;
     133             :                 case 'h':
     134           4 :                         return seconds*60*60;
     135             :                 case 'd':
     136           2 :                         return seconds*60*60*24;
     137             :                 case 'w':
     138           2 :                         return seconds*60*60*24*7;
     139             :                 case 'n':
     140           2 :                         return seconds*60*60*24*30;
     141             :         }
     142             : error:
     143           1 :         logp("interval %s not understood for %s\n", str, cname);
     144           1 :         return -1;
     145             : }
     146             : 
     147          15 : static int check_interval(
     148             :         struct strlist *interval,
     149             :         const char *cname,
     150             :         const char *ctimestamp,
     151             :         time_t time_now)
     152             : {
     153             :         char *cp;
     154             :         long min_time;
     155          15 :         long seconds=0;
     156          15 :         char tstmp[64]="";
     157          15 :         char min_time_buf[64]="";
     158             : 
     159          15 :         if((seconds=get_interval_in_seconds(interval->path, cname))<0)
     160             :                 return -1;
     161          14 :         if(timestamp_read(ctimestamp, tstmp, sizeof(tstmp)))
     162             :         {
     163           0 :                 logp("Could not read timestamp %s\n", ctimestamp);
     164             :                 return 0; // Backup now.
     165             :         }
     166             : 
     167          14 :         min_time=timestamp_to_long(tstmp)+seconds;
     168          14 :         strftime(min_time_buf, sizeof(min_time_buf),
     169          14 :                 DEFAULT_TIMESTAMP_FORMAT, localtime(&min_time));
     170          14 :         cp=strchr(tstmp, ' ');
     171          14 :         if(cp)
     172          14 :                 cp++;
     173             :         else
     174             :                 cp=tstmp;
     175             : 
     176          14 :         logp("Last backup: %s\n", cp);
     177          14 :         logp("Next after : %s (interval %s)\n", min_time_buf, interval->path);
     178             : 
     179          14 :         if(min_time < time_now)
     180             :                 return 0;
     181             :         return 1;
     182             : }
     183             : 
     184             : #ifndef UTEST
     185             : static
     186             : #endif
     187          21 : int run_timer_internal(
     188             :         const char *cname,
     189             :         struct sdirs *sdirs,
     190             :         struct strlist *timer_args,
     191             :         char *day_now,
     192             :         char *hour_now,
     193             :         time_t time_now
     194             : )
     195             : {
     196          21 :         int ret=-1;
     197          21 :         struct strlist *interval=NULL;
     198          21 :         struct strlist *timebands=NULL;
     199          21 :         char *ctimestamp=NULL;
     200             : 
     201          21 :         logp("Running timer for %s\n", cname);
     202             : 
     203          21 :         interval=timer_args;
     204          21 :         if(timer_args)
     205          20 :                 timebands=timer_args->next;
     206             : 
     207          21 :         switch((ret=check_manual_file(sdirs, cname)))
     208             :         {
     209             :                 case -1:
     210             :                         goto end;
     211             :                 case 0:
     212             :                         goto end;
     213             :         }
     214             : 
     215          20 :         switch(check_timebands(day_now, hour_now, timebands))
     216             :         {
     217             :                 case 0:
     218           4 :                         ret=1;
     219           4 :                         goto end;
     220             :                 case -1: // Error;
     221             :                         goto end;
     222             :         }
     223             : 
     224          32 :         if(is_dir_stat(sdirs->current)<=0)
     225             :         {
     226           1 :                 logp("No prior backup of %s\n", cname);
     227           1 :                 ret=0;
     228           1 :                 goto end;
     229             :         }
     230          15 :         if(!(ctimestamp=prepend_s(sdirs->current, "timestamp")))
     231             :         {
     232             :                 ret=-1;
     233             :                 goto end;
     234             :         }
     235             : 
     236          15 :         ret=check_interval(interval, cname, ctimestamp, time_now);
     237             : 
     238             : end:
     239          21 :         free_w(&ctimestamp);
     240          21 :         switch(ret)
     241             :         {
     242             :                 case 0:
     243           9 :                         logp("Do a backup of %s now\n", cname);
     244           9 :                         break;
     245             :                 case 1:
     246          11 :                         logp("Not yet time for a backup of %s\n", cname);
     247          11 :                         break;
     248             :         }
     249          21 :         return ret;
     250             : }
     251             : 
     252           1 : static int run_timer_internal_w(
     253             :         const char *cname,
     254             :         struct sdirs *sdirs,
     255             :         struct strlist *timer_args
     256             : )
     257             : {
     258           1 :         char *day_now=NULL;
     259           1 :         char *hour_now=NULL;
     260           1 :         time_t time_now=0;
     261           1 :         get_current_day_and_hour_and_unixtime(&day_now, &hour_now, &time_now);
     262           1 :         return run_timer_internal(cname, sdirs, timer_args,
     263             :                 day_now, hour_now, time_now);
     264             : }
     265             : 
     266             : 
     267             : static int run_timer_script(
     268             :         struct asfd *asfd,
     269             :         const char *timer_script,
     270             :         const char *cname,
     271             :         struct sdirs *sdirs,
     272             :         struct strlist *timer_args,
     273             :         struct conf **cconfs)
     274             : {
     275           1 :         int a=0;
     276             :         const char *args[12];
     277           1 :         args[a++]=timer_script;
     278           1 :         args[a++]=cname;
     279           1 :         args[a++]=sdirs->current;
     280           1 :         args[a++]=sdirs->clients;
     281           1 :         args[a++]="reserved1";
     282           1 :         args[a++]="reserved2";
     283           1 :         args[a++]=NULL;
     284           1 :         return run_script(asfd, args,
     285             :                 timer_args,
     286             :                 cconfs,
     287             :                 1 /* wait */,
     288             :                 1 /* use logp */,
     289             :                 0 /* no log_remote */);
     290             : }
     291             : 
     292             : // Return -1 for error, 0 to backup, 1 to not backup.
     293           2 : int run_timer(
     294             :         struct asfd *asfd,
     295             :         struct sdirs *sdirs,
     296             :         struct conf **cconfs)
     297             : {
     298           2 :         const char *cname=get_string(cconfs[OPT_CNAME]);
     299           2 :         const char *timer_script=NULL;
     300           2 :         struct strlist *timer_args=get_strlist(cconfs[OPT_TIMER_ARG]);
     301             : 
     302           2 :         if((timer_script=get_string(cconfs[OPT_TIMER_SCRIPT])))
     303           2 :                 return run_timer_script(asfd, timer_script,
     304             :                         cname, sdirs, timer_args, cconfs);
     305             : 
     306           1 :         return run_timer_internal_w(cname, sdirs, timer_args);
     307             : }

Generated by: LCOV version 1.13