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 : }
|