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

Generated by: LCOV version 1.10