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