Line data Source code
1 : #include "../burp.h"
2 : #include "../cmd.h"
3 : #include "../cntr.h"
4 : #include "../iobuf.h"
5 : #include "../log.h"
6 : #include "../pathcmp.h"
7 : #include "../sbuf.h"
8 : #include "dpth.h"
9 : #include "resume.h"
10 : #include "backup_phase1.h"
11 : #include "protocol1/dpth.h"
12 :
13 : // Used on resume, this just reads the phase1 file and sets up cntr.
14 0 : static int read_phase1(struct manio *p1manio, struct conf **cconfs)
15 : {
16 0 : int ret=-1;
17 : struct sbuf *p1b;
18 0 : enum protocol protocol=get_protocol(cconfs);
19 0 : struct cntr *cntr=get_cntr(cconfs);
20 0 : if(!(p1b=sbuf_alloc(protocol))) return -1;
21 : while(1)
22 : {
23 0 : sbuf_free_content(p1b);
24 0 : switch(manio_read(p1manio, p1b))
25 : {
26 : case 0: break;
27 0 : case 1: ret=0;
28 : default: goto end;
29 : }
30 0 : cntr_add_phase1(cntr, p1b->path.cmd, 0);
31 :
32 0 : if(sbuf_is_filedata(p1b))
33 : cntr_add_val(cntr, CMD_BYTES_ESTIMATED,
34 0 : (uint64_t)p1b->statp.st_size, 0);
35 : }
36 : end:
37 0 : sbuf_free(&p1b);
38 0 : return ret;
39 : }
40 :
41 0 : static int set_higher_datapth(struct sbuf *sb, struct dpth *dpth)
42 : {
43 : // Make sure we end up with the highest datapth we can possibly
44 : // find - dpth_protocol1_set_from_string() will only set it if
45 : // it is higher.
46 0 : if(sb->protocol1 && sb->protocol1->datapth.buf
47 0 : && dpth_protocol1_set_from_string(dpth,
48 0 : sb->protocol1->datapth.buf))
49 : {
50 : logp("unable to set datapath: %s\n",
51 0 : sb->protocol1->datapth.buf);
52 : return -1;
53 : }
54 : return 0;
55 : }
56 :
57 : #ifndef UTEST
58 : static
59 : #endif
60 48 : int forward_past_entry(struct manio *manio, struct iobuf *target,
61 : enum protocol protocol, man_off_t **pos)
62 : {
63 48 : struct sbuf *sb=NULL;
64 :
65 48 : if(!(sb=sbuf_alloc(protocol)))
66 : goto error;
67 :
68 48 : man_off_t_free(pos);
69 48 : if(!(*pos=manio_tell(manio)))
70 : {
71 : logp("Could not manio_tell first pos in %s(): %s\n",
72 0 : __func__, strerror(errno));
73 0 : goto error;
74 : }
75 :
76 : while(1)
77 : {
78 1744 : sbuf_free_content(sb);
79 1744 : switch(manio_read(manio, sb))
80 : {
81 : case 0: break;
82 0 : case 1: logp("End of file in %s()\n", __func__);
83 0 : goto error;
84 : default:
85 0 : logp("Error in %s()\n", __func__);
86 : // Treat error in unchanged manio as not OK.
87 0 : goto error;
88 : }
89 :
90 3488 : if(target->cmd==sb->path.cmd
91 1744 : && !pathcmp(target->buf, sb->path.buf))
92 : {
93 48 : man_off_t_free(pos);
94 48 : if(!(*pos=manio_tell(manio)))
95 : {
96 : logp("Could not get pos in %s(): %s\n",
97 0 : __func__, strerror(errno));
98 0 : goto error;
99 : }
100 48 : sbuf_free(&sb);
101 48 : return 0;
102 : }
103 : }
104 :
105 : error:
106 0 : sbuf_free(&sb);
107 0 : man_off_t_free(pos);
108 0 : return -1;
109 : }
110 :
111 : #ifndef UTEST
112 : static
113 : #endif
114 88 : int forward_before_entry(struct manio *manio, struct iobuf *target,
115 : struct cntr *cntr, struct dpth *dpth, enum protocol protocol,
116 : man_off_t **pos)
117 : {
118 88 : int ars=0;
119 88 : struct sbuf *sb=NULL;
120 :
121 88 : if(!(sb=sbuf_alloc(protocol)))
122 : goto error;
123 :
124 88 : man_off_t_free(pos);
125 88 : if(!(*pos=manio_tell(manio)))
126 : {
127 : logp("Could not manio_tell first pos in %s(): %s\n",
128 0 : __func__, strerror(errno));
129 0 : goto error;
130 : }
131 :
132 : while(1)
133 : {
134 6380 : if(sb->endfile.buf
135 6380 : || (sb->path.buf && !sbuf_is_filedata(sb)))
136 : {
137 4240 : man_off_t_free(pos);
138 4240 : if(!(*pos=manio_tell(manio)))
139 : {
140 : logp("Could not manio_tell pos in %s(): "
141 0 : "%s\n", __func__, strerror(errno));
142 0 : goto error;
143 : }
144 : }
145 :
146 6380 : sbuf_free_content(sb);
147 6380 : ars=manio_read(manio, sb);
148 6380 : if(dpth && set_higher_datapth(sb, dpth)) goto error;
149 :
150 6380 : switch(ars)
151 : {
152 : case 0: break;
153 : case 1:
154 6 : sbuf_free(&sb);
155 6 : return 0;
156 : default:
157 : logp("Error in %s(), but continuing\n",
158 10 : __func__);
159 : // Treat error in unchanged manio as
160 : // OK - could have been a short write.
161 10 : sbuf_free(&sb);
162 10 : return 0;
163 : }
164 :
165 6364 : if(iobuf_pathcmp(target, &sb->path)<=0)
166 : {
167 72 : sbuf_free(&sb);
168 72 : return 0;
169 : }
170 :
171 6292 : if(cntr)
172 : {
173 0 : cntr_add_same(cntr, sb->path.cmd);
174 0 : if(sb->endfile.buf)
175 : {
176 0 : uint64_t e=strtoull(sb->endfile.buf, NULL, 10);
177 0 : cntr_add_bytes(cntr, e);
178 0 : cntr_add_recvbytes(cntr, e);
179 : }
180 : }
181 : }
182 :
183 : error:
184 0 : sbuf_free(&sb);
185 0 : man_off_t_free(pos);
186 0 : return -1;
187 : }
188 :
189 : #ifndef UTEST
190 : static
191 : #endif
192 208 : int get_last_good_entry(struct manio *manio, struct iobuf *result,
193 : struct cntr *cntr, struct dpth *dpth, enum protocol protocol,
194 : man_off_t **pos)
195 : {
196 208 : int ars=0;
197 208 : int got_vss_start=0;
198 208 : struct sbuf *sb=NULL;
199 : struct iobuf lastpath;
200 :
201 208 : if(!(sb=sbuf_alloc(protocol)))
202 : goto error;
203 :
204 208 : iobuf_init(&lastpath);
205 :
206 208 : man_off_t_free(pos);
207 208 : if(!(*pos=manio_tell(manio)))
208 : {
209 : logp("Could not manio_tell first pos in %s(): %s\n",
210 0 : __func__, strerror(errno));
211 0 : goto error;
212 : }
213 :
214 : while(1)
215 : {
216 12690 : if(sb->path.buf && !got_vss_start)
217 : {
218 8270 : iobuf_free_content(&lastpath);
219 8270 : iobuf_move(&lastpath, &sb->path);
220 16540 : if(!sbuf_is_filedata(sb)
221 8270 : && !sbuf_is_vssdata(sb))
222 : {
223 104 : iobuf_free_content(result);
224 104 : iobuf_move(result, &lastpath);
225 :
226 104 : man_off_t_free(pos);
227 104 : if(!(*pos=manio_tell(manio)))
228 : {
229 : logp("Could not manio_tell pos in %s(): %s\n",
230 0 : __func__, strerror(errno));
231 0 : goto error;
232 : }
233 : }
234 : }
235 12690 : if(sb->endfile.buf && !got_vss_start)
236 : {
237 8152 : iobuf_free_content(result);
238 8152 : iobuf_move(result, &lastpath);
239 :
240 8152 : man_off_t_free(pos);
241 8152 : if(!(*pos=manio_tell(manio)))
242 : {
243 : logp("Could not manio_tell pos in %s(): %s\n",
244 0 : __func__, strerror(errno));
245 0 : goto error;
246 : }
247 : }
248 :
249 12690 : sbuf_free_content(sb);
250 12690 : ars=manio_read(manio, sb);
251 12690 : if(dpth && set_higher_datapth(sb, dpth)) goto error;
252 :
253 12690 : switch(ars)
254 : {
255 : case 0: break;
256 169 : case 1: iobuf_free_content(&lastpath);
257 169 : sbuf_free(&sb);
258 169 : return 0;
259 : default:
260 39 : if(result->buf)
261 : logp("Error after %s in %s()\n",
262 32 : result->buf, __func__);
263 : // Treat error in changed manio as
264 : // OK - could have been a short write.
265 39 : iobuf_free_content(&lastpath);
266 39 : sbuf_free(&sb);
267 39 : return 0;
268 : }
269 :
270 : // Some hacks for split_vss.
271 12482 : switch(sb->path.cmd)
272 : {
273 : case CMD_VSS:
274 : case CMD_ENC_VSS:
275 : got_vss_start=1;
276 : break;
277 : case CMD_VSS_T:
278 : case CMD_ENC_VSS_T:
279 : got_vss_start=0;
280 : break;
281 : case CMD_FILE:
282 : case CMD_ENC_FILE:
283 8154 : if(S_ISDIR(sb->statp.st_mode))
284 48 : got_vss_start=0;
285 : break;
286 : default:
287 : break;
288 : }
289 :
290 12482 : if(cntr)
291 : {
292 0 : cntr_add_changed(cntr, sb->path.cmd);
293 0 : if(sb->endfile.buf)
294 : {
295 0 : uint64_t e=strtoull(sb->endfile.buf, NULL, 10);
296 0 : cntr_add_bytes(cntr, e);
297 0 : cntr_add_recvbytes(cntr, e);
298 : }
299 : }
300 : }
301 :
302 : error:
303 0 : iobuf_free_content(&lastpath);
304 0 : sbuf_free(&sb);
305 0 : man_off_t_free(pos);
306 0 : return -1;
307 : }
308 :
309 : // Return p1manio position.
310 0 : static man_off_t *do_resume_work(struct sdirs *sdirs,
311 : struct dpth *dpth, struct conf **cconfs)
312 : {
313 0 : man_off_t *pos=NULL;
314 0 : man_off_t *p1pos=NULL;
315 0 : struct iobuf *chb=NULL;
316 0 : struct manio *cmanio=NULL;
317 0 : struct manio *umanio=NULL;
318 0 : struct manio *p1manio=NULL;
319 0 : enum protocol protocol=get_protocol(cconfs);
320 0 : struct cntr *cntr=get_cntr(cconfs);
321 0 : int compression=get_int(cconfs[OPT_COMPRESSION]);
322 :
323 0 : if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", protocol))
324 0 : || !(cmanio=manio_open_phase2(sdirs->changed, "rb", protocol))
325 0 : || !(umanio=manio_open_phase2(sdirs->unchanged, "rb", protocol)))
326 : goto end;
327 :
328 0 : if(!(chb=iobuf_alloc()))
329 : return NULL;
330 :
331 0 : logp("Setting up resume positions...\n");
332 :
333 0 : if(get_last_good_entry(cmanio, chb, cntr, dpth, protocol, &pos))
334 : goto error;
335 0 : if(manio_close_and_truncate(&cmanio, pos, compression)) goto error;
336 0 : man_off_t_free(&pos);
337 0 : if(chb->buf)
338 : {
339 0 : logp(" last good entry: %s\n", chb->buf);
340 : // Now need to go to the appropriate places in p1manio and
341 : // unchanged.
342 0 : if(forward_past_entry(p1manio, chb, protocol, &p1pos))
343 : goto error;
344 :
345 : // The unchanged file needs to be positioned just before the
346 : // found entry, otherwise it ends up having a duplicated entry.
347 0 : if(forward_before_entry(umanio,
348 0 : chb, cntr, dpth, protocol, &pos))
349 : goto error;
350 0 : if(manio_close_and_truncate(&umanio, pos, compression))
351 : goto error;
352 0 : man_off_t_free(&pos);
353 : }
354 : else
355 : {
356 0 : logp(" nothing previously transferred\n");
357 0 : if(!(p1pos=manio_tell(p1manio)))
358 : goto error;
359 0 : if(!(pos=manio_tell(umanio)))
360 : goto error;
361 0 : if(manio_close_and_truncate(&umanio, pos, compression))
362 : goto error;
363 : }
364 :
365 : // Now should have all file pointers in the right places to resume.
366 :
367 0 : if(get_int(cconfs[OPT_SEND_CLIENT_CNTR])
368 0 : && cntr_send(cntr)) goto error;
369 :
370 : goto end;
371 : error:
372 0 : man_off_t_free(&p1pos);
373 : end:
374 0 : iobuf_free(&chb);
375 0 : man_off_t_free(&pos);
376 0 : manio_close(&p1manio);
377 0 : manio_close(&cmanio);
378 0 : manio_close(&umanio);
379 0 : return p1pos;
380 : }
381 :
382 0 : man_off_t *do_resume(struct sdirs *sdirs,
383 : struct dpth *dpth, struct conf **cconfs)
384 : {
385 0 : man_off_t *p1pos=NULL;
386 0 : struct manio *cmanio=NULL;
387 0 : struct manio *umanio=NULL;
388 0 : struct manio *p1manio=NULL;
389 0 : enum protocol protocol=get_protocol(cconfs);
390 :
391 0 : logp("Begin phase1 (read previous file system scan)\n");
392 0 : if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", protocol))
393 0 : || read_phase1(p1manio, cconfs))
394 : goto end;
395 0 : manio_close(&p1manio);
396 :
397 : // First, open them in append mode, so that they will be created if
398 : // they do not exist.
399 0 : if(!(cmanio=manio_open_phase2(sdirs->changed, "ab", protocol))
400 0 : || !(umanio=manio_open_phase2(sdirs->unchanged, "ab", protocol)))
401 : goto end;
402 0 : manio_close(&cmanio);
403 0 : manio_close(&umanio);
404 :
405 0 : if(!(p1pos=do_resume_work(sdirs, dpth, cconfs))) goto end;
406 :
407 0 : if(dpth_incr(dpth)) goto end;
408 :
409 0 : logp("End phase1 (read previous file system scan)\n");
410 : end:
411 0 : manio_close(&p1manio);
412 0 : manio_close(&cmanio);
413 0 : manio_close(&umanio);
414 0 : return p1pos;
415 : }
|