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