LCOV - code coverage report
Current view: top level - src/server - timer.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 123 127 96.9 %
Date: 2018-12-30 04:45:13 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           0 :                 free_w(&lower_day_now);
      85           0 :                 free_w(&lower_hour_now);
      86           0 :                 return -1;
      87             :         }
      88          20 :         strtolower(lower_day_now);
      89          20 :         strtolower(lower_hour_now);
      90             : 
      91          53 :         for(t=timebands; t; t=t->next)
      92             :         {
      93          33 :                 free_w(&lower_tb);
      94          33 :                 if(!(lower_tb=strdup_w(t->path, __func__)))
      95             :                         return -1;
      96          33 :                 strtolower(lower_tb);
      97             : 
      98          33 :                 if(!strcmp(lower_tb, "always")
      99          33 :                   || (strstr(lower_tb, lower_day_now)
     100          17 :                     && strstr(lower_tb, lower_hour_now)))
     101             :                 {
     102          16 :                         logp("In timeband: %s\n", t->path);
     103          16 :                         in_timeband=1;
     104             :                 }
     105             :                 else
     106          17 :                         logp("Out of timeband: %s\n", t->path);
     107             :         }
     108          20 :         free_w(&lower_tb);
     109             : 
     110          20 :         return in_timeband;
     111             : }
     112             : 
     113          15 : static long get_interval_in_seconds(const char *str, const char *cname)
     114             : {
     115             :         int s;
     116             :         long seconds;
     117             :         char unit;
     118          15 :         if(sscanf(str, "%d%c", &s, &unit)!=2)
     119             :                 goto error;
     120          15 :         seconds=(long)s;
     121          15 :         switch(unit)
     122             :         {
     123             :                 case 's':
     124             :                         return seconds;
     125             :                 case 'm':
     126           2 :                         return seconds*60;
     127             :                 case 'h':
     128           4 :                         return seconds*60*60;
     129             :                 case 'd':
     130           2 :                         return seconds*60*60*24;
     131             :                 case 'w':
     132           2 :                         return seconds*60*60*24*7;
     133             :                 case 'n':
     134           2 :                         return seconds*60*60*24*30;
     135             :         }
     136             : error:
     137           1 :         logp("interval %s not understood for %s\n", str, cname);
     138           1 :         return -1;
     139             : }
     140             : 
     141          15 : static int check_interval(
     142             :         struct strlist *interval,
     143             :         const char *cname,
     144             :         const char *ctimestamp,
     145             :         time_t time_now)
     146             : {
     147             :         char *cp;
     148             :         long min_time;
     149          15 :         long seconds=0;
     150          15 :         char tstmp[64]="";
     151          15 :         char min_time_buf[64]="";
     152             : 
     153          15 :         if((seconds=get_interval_in_seconds(interval->path, cname))<0)
     154             :                 return -1;
     155          14 :         if(timestamp_read(ctimestamp, tstmp, sizeof(tstmp)))
     156             :         {
     157           0 :                 logp("Could not read timestamp %s\n", ctimestamp);
     158             :                 return 0; // Backup now.
     159             :         }
     160             : 
     161          14 :         min_time=timestamp_to_long(tstmp)+seconds;
     162          14 :         strftime(min_time_buf, sizeof(min_time_buf),
     163          14 :                 DEFAULT_TIMESTAMP_FORMAT, localtime(&min_time));
     164          14 :         cp=strchr(tstmp, ' ');
     165          14 :         if(cp)
     166          14 :                 cp++;
     167             :         else
     168             :                 cp=tstmp;
     169             : 
     170          14 :         logp("Last backup: %s\n", cp);
     171          14 :         logp("Next after : %s (interval %s)\n", min_time_buf, interval->path);
     172             : 
     173          14 :         if(min_time < time_now)
     174             :                 return 0;
     175             :         return 1;
     176             : }
     177             : 
     178             : #ifndef UTEST
     179             : static
     180             : #endif
     181          21 : int run_timer_internal(
     182             :         const char *cname,
     183             :         struct sdirs *sdirs,
     184             :         struct strlist *timer_args,
     185             :         char *day_now,
     186             :         char *hour_now,
     187             :         time_t time_now
     188             : )
     189             : {
     190          21 :         int ret=-1;
     191          21 :         struct strlist *interval=NULL;
     192          21 :         struct strlist *timebands=NULL;
     193          21 :         char *ctimestamp=NULL;
     194             : 
     195          21 :         logp("Running timer for %s\n", cname);
     196             : 
     197          21 :         interval=timer_args;
     198          21 :         if(timer_args)
     199          20 :                 timebands=timer_args->next;
     200             : 
     201          21 :         switch((ret=check_manual_file(sdirs, cname)))
     202             :         {
     203             :                 case -1:
     204             :                         goto end;
     205             :                 case 0:
     206             :                         goto end;
     207             :         }
     208             : 
     209          20 :         switch(check_timebands(day_now, hour_now, timebands))
     210             :         {
     211             :                 case 0:
     212           4 :                         ret=1;
     213           4 :                         goto end;
     214             :                 case -1: // Error;
     215             :                         goto end;
     216             :         }
     217             : 
     218          32 :         if(is_dir_stat(sdirs->current)<=0)
     219             :         {
     220           1 :                 logp("No prior backup of %s\n", cname);
     221           1 :                 ret=0;
     222           1 :                 goto end;
     223             :         }
     224          15 :         if(!(ctimestamp=prepend_s(sdirs->current, "timestamp")))
     225             :         {
     226             :                 ret=-1;
     227             :                 goto end;
     228             :         }
     229             : 
     230          15 :         ret=check_interval(interval, cname, ctimestamp, time_now);
     231             : 
     232             : end:
     233          21 :         free_w(&ctimestamp);
     234          21 :         switch(ret)
     235             :         {
     236             :                 case 0:
     237           9 :                         logp("Do a backup of %s now\n", cname);
     238           9 :                         break;
     239             :                 case 1:
     240          11 :                         logp("Not yet time for a backup of %s\n", cname);
     241          11 :                         break;
     242             :         }
     243          21 :         return ret;
     244             : }
     245             : 
     246           1 : static int run_timer_internal_w(
     247             :         const char *cname,
     248             :         struct sdirs *sdirs,
     249             :         struct strlist *timer_args
     250             : )
     251             : {
     252           1 :         char *day_now=NULL;
     253           1 :         char *hour_now=NULL;
     254           1 :         time_t time_now=0;
     255           1 :         get_current_day_and_hour_and_unixtime(&day_now, &hour_now, &time_now);
     256           1 :         return run_timer_internal(cname, sdirs, timer_args,
     257             :                 day_now, hour_now, time_now);
     258             : }
     259             : 
     260             : 
     261             : static int run_timer_script(
     262             :         struct asfd *asfd,
     263             :         const char *timer_script,
     264             :         const char *cname,
     265             :         struct sdirs *sdirs,
     266             :         struct strlist *timer_args,
     267             :         struct conf **cconfs)
     268             : {
     269           1 :         int a=0;
     270             :         const char *args[12];
     271           1 :         args[a++]=timer_script;
     272           1 :         args[a++]=cname;
     273           1 :         args[a++]=sdirs->current;
     274           1 :         args[a++]=sdirs->clients;
     275           1 :         args[a++]="reserved1";
     276           1 :         args[a++]="reserved2";
     277           1 :         args[a++]=NULL;
     278           1 :         return run_script(asfd, args,
     279             :                 timer_args,
     280             :                 cconfs,
     281             :                 1 /* wait */,
     282             :                 1 /* use logp */,
     283             :                 0 /* no log_remote */);
     284             : }
     285             : 
     286             : // Return -1 for error, 0 to backup, 1 to not backup.
     287           2 : int run_timer(
     288             :         struct asfd *asfd,
     289             :         struct sdirs *sdirs,
     290             :         struct conf **cconfs)
     291             : {
     292           2 :         const char *cname=get_string(cconfs[OPT_CNAME]);
     293           2 :         const char *timer_script=NULL;
     294           2 :         struct strlist *timer_args=get_strlist(cconfs[OPT_TIMER_ARG]);
     295             : 
     296           2 :         if((timer_script=get_string(cconfs[OPT_TIMER_SCRIPT])))
     297           2 :                 return run_timer_script(asfd, timer_script,
     298             :                         cname, sdirs, timer_args, cconfs);
     299             : 
     300           1 :         return run_timer_internal_w(cname, sdirs, timer_args);
     301             : }

Generated by: LCOV version 1.13