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