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