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 : #include "timer.h"
27 :
28 1 : static void log_rshash(struct conf **confs)
29 : {
30 1 : if(get_protocol(confs)!=PROTO_1) return;
31 0 : logp("Using librsync hash %s\n",
32 : rshash_to_str(get_e_rshash(confs[OPT_RSHASH])));
33 : }
34 :
35 1 : static int open_log(struct asfd *asfd,
36 : struct sdirs *sdirs, struct conf **cconfs, int resume)
37 : {
38 1 : int ret=-1;
39 1 : char *logpath=NULL;
40 1 : const char *peer_version=get_string(cconfs[OPT_PEER_VERSION]);
41 :
42 1 : logp("Backup %s: %s\n", resume?"resumed":"started", sdirs->rworking);
43 :
44 1 : if(!(logpath=prepend_s(sdirs->rworking, "log"))) goto end;
45 1 : if(log_fzp_set(logpath, cconfs))
46 : {
47 0 : logp("could not open log file: %s\n", logpath);
48 : goto end;
49 : }
50 :
51 1 : logp("Backup %s\n", resume?"resumed":"started");
52 1 : logp("Client version: %s\n", peer_version?:"");
53 1 : logp("Protocol: %d\n", (int)get_protocol(cconfs));
54 1 : log_rshash(cconfs);
55 1 : if(get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
56 0 : logp("Client is Windows\n");
57 :
58 : // Make sure a warning appears in the backup log.
59 : // The client will already have been sent a message with logw.
60 : // This time, prevent it sending a logw to the client by specifying
61 : // NULL for asfd and cntr.
62 1 : if(get_int(cconfs[OPT_VERSION_WARN]))
63 1 : version_warn(NULL, NULL, cconfs);
64 :
65 : ret=0;
66 : end:
67 1 : free_w(&logpath);
68 1 : return ret;
69 : }
70 :
71 1 : static int write_incexc(const char *realworking, const char *incexc)
72 : {
73 1 : int ret=-1;
74 1 : char *tmp=NULL;
75 1 : char *path=NULL;
76 1 : struct fzp *fzp=NULL;
77 :
78 1 : if(!incexc || !*incexc) return 0;
79 :
80 0 : if(!(path=prepend_s(realworking, "incexc"))
81 0 : || !(tmp=prepend(path, ".tmp"))
82 0 : || !(fzp=fzp_open(tmp, "wb")))
83 : goto end;
84 :
85 0 : fzp_printf(fzp, "%s", incexc);
86 0 : if(fzp_close(&fzp))
87 : {
88 0 : logp("error writing to %s in %s\n", tmp, __func__);
89 0 : goto end;
90 : }
91 0 : if(do_rename(tmp, path))
92 : goto end;
93 0 : ret=0;
94 : end:
95 0 : free_w(&path);
96 0 : free_w(&tmp);
97 0 : return ret;
98 : }
99 :
100 1 : static int backup_phase1_server(struct async *as,
101 : struct sdirs *sdirs, struct conf **cconfs)
102 : {
103 1 : int breaking=get_int(cconfs[OPT_BREAKPOINT]);
104 1 : if(breaking==1)
105 0 : return breakpoint(breaking, __func__);
106 1 : return backup_phase1_server_all(as, sdirs, cconfs);
107 : }
108 :
109 0 : static int backup_phase2_server(struct async *as, struct sdirs *sdirs,
110 : const char *incexc, int resume, struct conf **cconfs)
111 : {
112 0 : int breaking=get_int(cconfs[OPT_BREAKPOINT]);
113 0 : if(breaking==2)
114 0 : return breakpoint(breaking, __func__);
115 :
116 0 : switch(get_protocol(cconfs))
117 : {
118 : case PROTO_1:
119 0 : return backup_phase2_server_protocol1(as, sdirs,
120 : incexc, resume, cconfs);
121 : default:
122 0 : return backup_phase2_server_protocol2(as, sdirs,
123 : resume, cconfs);
124 : }
125 : }
126 :
127 0 : static int backup_phase3_server(struct sdirs *sdirs, struct conf **cconfs)
128 : {
129 0 : int breaking=get_int(cconfs[OPT_BREAKPOINT]);
130 0 : if(breaking==3)
131 0 : return breakpoint(breaking, __func__);
132 :
133 0 : return backup_phase3_server_all(sdirs, cconfs);
134 : }
135 :
136 0 : static int backup_phase4_server(struct sdirs *sdirs, struct conf **cconfs)
137 : {
138 0 : int breaking=get_int(cconfs[OPT_BREAKPOINT]);
139 0 : if(breaking==4)
140 0 : return breakpoint(breaking, __func__);
141 :
142 0 : log_fzp_set(NULL, cconfs);
143 : // Phase4 will open logfp again (in case it is resuming).
144 0 : switch(get_protocol(cconfs))
145 : {
146 : case PROTO_1:
147 0 : return backup_phase4_server_protocol1(sdirs, cconfs);
148 : default:
149 0 : return backup_phase4_server_protocol2(sdirs, cconfs);
150 : }
151 : }
152 :
153 : static char *get_bno_from_sdirs(struct sdirs *sdirs)
154 : {
155 1 : char *cp=NULL;
156 : // Should be easier than this.
157 1 : if(!(cp=strrchr(sdirs->rworking, '/')))
158 : return NULL;
159 1 : return cp+1;
160 : }
161 :
162 1 : static void set_cntr_bno(struct cntr *cntr, struct sdirs *sdirs)
163 : {
164 2 : char *bno=get_bno_from_sdirs(sdirs);
165 1 : if(!bno)
166 : return;
167 1 : cntr->bno=atoi(bno);
168 : }
169 :
170 1 : static int do_backup_server(struct async *as, struct sdirs *sdirs,
171 : struct conf **cconfs, const char *incexc, int resume)
172 : {
173 1 : int ret=0;
174 1 : int do_phase2=1;
175 1 : struct asfd *asfd=as->asfd;
176 1 : enum protocol protocol=get_protocol(cconfs);
177 1 : struct cntr *cntr=get_cntr(cconfs);
178 :
179 1 : if(resume)
180 : {
181 0 : if(sdirs_get_real_working_from_symlink(sdirs)
182 0 : || sdirs_get_real_manifest(sdirs, protocol))
183 : goto error;
184 :
185 0 : if(open_log(asfd, sdirs, cconfs, resume))
186 : goto error;
187 :
188 0 : set_cntr_bno(cntr, sdirs);
189 : }
190 : else
191 : {
192 : // Not resuming - need to set everything up fresh.
193 1 : if(sdirs_create_real_working(sdirs,
194 1 : get_string(cconfs[OPT_TIMESTAMP_FORMAT]))
195 1 : || sdirs_get_real_manifest(sdirs, protocol))
196 : goto error;
197 :
198 1 : if(open_log(asfd, sdirs, cconfs, resume))
199 : goto error;
200 :
201 1 : set_cntr_bno(cntr, sdirs);
202 :
203 1 : if(write_incexc(sdirs->rworking, incexc))
204 : {
205 0 : logp("unable to write incexc\n");
206 0 : goto error;
207 : }
208 :
209 1 : if(backup_phase1_server(as, sdirs, cconfs))
210 : {
211 1 : logp("error in phase 1\n");
212 1 : goto error;
213 : }
214 : }
215 :
216 0 : if(resume)
217 : {
218 : struct stat statp;
219 0 : if(lstat(sdirs->phase1data, &statp)
220 0 : && !lstat(sdirs->changed, &statp)
221 0 : && !lstat(sdirs->unchanged, &statp))
222 : {
223 : // In this condition, it looks like there was an
224 : // interruption during phase3. Skip phase2.
225 0 : do_phase2=0;
226 : }
227 : }
228 :
229 0 : if(do_phase2)
230 : {
231 0 : if(backup_phase2_server(as, sdirs, incexc, resume, cconfs))
232 : {
233 0 : logp("error in backup phase 2\n");
234 0 : goto error;
235 : }
236 :
237 0 : asfd->write_str(asfd, CMD_GEN, "okbackupend");
238 : }
239 :
240 : // Close the connection with the client, the rest of the job we can do
241 : // by ourselves.
242 0 : logp("Backup ending - disconnect from client.\n");
243 0 : if(asfd_flush_asio(asfd))
244 : goto error;
245 0 : as->asfd_remove(as, asfd);
246 0 : asfd_close(asfd);
247 :
248 0 : if(backup_phase3_server(sdirs, cconfs))
249 : {
250 0 : logp("error in backup phase 3\n");
251 0 : goto error;
252 : }
253 :
254 0 : if(do_rename(sdirs->working, sdirs->finishing))
255 : goto error;
256 :
257 0 : if(backup_phase4_server(sdirs, cconfs))
258 : {
259 0 : logp("error in backup phase 4\n");
260 0 : goto error;
261 : }
262 :
263 0 : cntr_print(cntr, ACTION_BACKUP, asfd);
264 0 : cntr_stats_to_file(cntr, sdirs->rworking, ACTION_BACKUP);
265 :
266 0 : if(protocol==PROTO_2)
267 : {
268 : // Regenerate dindex before the symlink is renamed, so that the
269 : // champ chooser cleanup does not try to remove data files
270 : // whilst the dindex regeneration is happening.
271 0 : if(regenerate_client_dindex(sdirs))
272 : goto error;
273 : }
274 :
275 : // Move the symlink to indicate that we are now in the end phase. The
276 : // rename() race condition is automatically recoverable here.
277 0 : if(do_rename(sdirs->finishing, sdirs->current))
278 : goto error;
279 :
280 0 : logp("Backup completed.\n");
281 0 : log_fzp_set(NULL, cconfs);
282 0 : logp("Backup completed: %s\n", sdirs->rworking);
283 0 : compress_filename(sdirs->rworking,
284 : "log", "log.gz", get_int(cconfs[OPT_COMPRESSION]));
285 :
286 0 : goto end;
287 : error:
288 : ret=-1;
289 : end:
290 :
291 1 : if(ret)
292 1 : logp("Backup failed\n");
293 1 : log_fzp_set(NULL, cconfs);
294 1 : if(ret)
295 : {
296 : // Make an entry in the main output, for failed backups.
297 1 : logp("Backup failed: %s\n", sdirs->rworking);
298 : }
299 1 : return ret;
300 : }
301 :
302 1 : int run_backup(struct async *as, struct sdirs *sdirs, struct conf **cconfs,
303 : const char *incexc, int *timer_ret, int resume)
304 : {
305 : int ret;
306 1 : char okstr[32]="";
307 1 : struct asfd *asfd=as->asfd;
308 1 : struct iobuf *rbuf=asfd->rbuf;
309 1 : const char *cname=get_string(cconfs[OPT_CNAME]);
310 :
311 1 : if(get_string(cconfs[OPT_RESTORE_CLIENT]))
312 : {
313 : // This client is not the original client, so a backup might
314 : // cause all sorts of trouble.
315 0 : logp("Not allowing backup of %s\n", cname);
316 0 : return asfd->write_str(asfd, CMD_GEN, "Backup is not allowed");
317 : }
318 :
319 : // Set quality of service bits on backups.
320 1 : asfd->set_bulk_packets(asfd);
321 :
322 1 : if(!strncmp_w(rbuf->buf, "backupphase1timed"))
323 : {
324 0 : int checkonly=!strncmp_w(rbuf->buf, "backupphase1timedcheck");
325 0 : if(checkonly) logp("Client asked for a timer check only.\n");
326 :
327 0 : if((*timer_ret=run_timer(asfd, sdirs, cconfs))<0)
328 : {
329 0 : logp("Error running timer for %s\n", cname);
330 0 : return -1;
331 : }
332 0 : else if(*timer_ret)
333 : {
334 0 : if(!checkonly)
335 0 : logp("Not running backup of %s\n", cname);
336 0 : return asfd->write_str(asfd,
337 : CMD_GEN, "timer conditions not met");
338 : }
339 0 : if(checkonly)
340 : {
341 0 : logp("Client asked for a timer check only,\n");
342 0 : logp("so a backup is not happening right now.\n");
343 0 : return asfd->write_str(asfd,
344 : CMD_GEN, "timer conditions met");
345 : }
346 0 : logp("Running backup of %s\n", cname);
347 : }
348 1 : else if(!get_int(cconfs[OPT_CLIENT_CAN_FORCE_BACKUP]))
349 : {
350 0 : logp("Not allowing forced backup of %s\n", cname);
351 0 : return asfd->write_str(asfd,
352 : CMD_GEN, "Forced backup is not allowed");
353 : }
354 :
355 1 : snprintf(okstr, sizeof(okstr), "%s:%d",
356 : resume?"resume":"ok", get_int(cconfs[OPT_COMPRESSION]));
357 1 : if(asfd->write_str(asfd, CMD_GEN, okstr)) return -1;
358 :
359 1 : if((ret=do_backup_server(as, sdirs, cconfs, incexc, resume)))
360 : goto end;
361 :
362 0 : if((ret=delete_backups(sdirs, cname,
363 : get_strlist(cconfs[OPT_KEEP]),
364 0 : get_string(cconfs[OPT_MANUAL_DELETE]))))
365 : goto end;
366 : end:
367 : return ret;
368 : }
|