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