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_estimatable(p1b))
33 0 : cntr_add_val(cntr, CMD_BYTES_ESTIMATED,
34 0 : (uint64_t)p1b->statp.st_size);
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 : sb->protocol1->datapth.buf))
49 : {
50 0 : logp("unable to set datapath: %s\n",
51 0 : iobuf_to_printable(&sb->protocol1->datapth));
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 0 : 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 1744 : if(target->cmd==sb->path.cmd
91 1664 : && !pathcmp(target->buf, sb->path.buf))
92 : {
93 48 : man_off_t_free(pos);
94 48 : if(!(*pos=manio_tell(manio)))
95 : {
96 0 : 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 0 : 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 2208 : || (sb->path.buf && !sbuf_is_filedata(sb)))
136 : {
137 4240 : man_off_t_free(pos);
138 4240 : if(!(*pos=manio_tell(manio)))
139 : {
140 0 : 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 10 : logp("Error in %s(), but continuing\n",
158 : __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 : }
179 : }
180 : }
181 :
182 : error:
183 0 : sbuf_free(&sb);
184 0 : man_off_t_free(pos);
185 0 : return -1;
186 : }
187 :
188 : #ifndef UTEST
189 : static
190 : #endif
191 208 : int get_last_good_entry(struct manio *manio, struct iobuf *result,
192 : struct cntr *cntr, struct dpth *dpth, enum protocol protocol,
193 : man_off_t **pos)
194 : {
195 208 : int ars=0;
196 208 : int got_vss_start=0;
197 208 : struct sbuf *sb=NULL;
198 : struct iobuf lastpath;
199 :
200 208 : if(!(sb=sbuf_alloc(protocol)))
201 : goto error;
202 :
203 208 : iobuf_init(&lastpath);
204 :
205 208 : man_off_t_free(pos);
206 208 : if(!(*pos=manio_tell(manio)))
207 : {
208 0 : logp("Could not manio_tell first pos in %s(): %s\n",
209 0 : __func__, strerror(errno));
210 0 : goto error;
211 : }
212 :
213 : while(1)
214 : {
215 12690 : if(sb->path.buf && !got_vss_start)
216 : {
217 8270 : iobuf_free_content(&lastpath);
218 8270 : iobuf_move(&lastpath, &sb->path);
219 8270 : if(!sbuf_is_filedata(sb)
220 114 : && !sbuf_is_vssdata(sb))
221 : {
222 104 : iobuf_free_content(result);
223 104 : iobuf_move(result, &lastpath);
224 :
225 104 : man_off_t_free(pos);
226 104 : if(!(*pos=manio_tell(manio)))
227 : {
228 0 : logp("Could not manio_tell pos in %s(): %s\n",
229 0 : __func__, strerror(errno));
230 0 : goto error;
231 : }
232 : }
233 : }
234 12690 : if(sb->endfile.buf && !got_vss_start)
235 : {
236 8152 : iobuf_free_content(result);
237 8152 : iobuf_move(result, &lastpath);
238 :
239 8152 : man_off_t_free(pos);
240 8152 : if(!(*pos=manio_tell(manio)))
241 : {
242 0 : logp("Could not manio_tell pos in %s(): %s\n",
243 0 : __func__, strerror(errno));
244 0 : goto error;
245 : }
246 : }
247 :
248 12690 : sbuf_free_content(sb);
249 12690 : ars=manio_read(manio, sb);
250 12690 : if(dpth && set_higher_datapth(sb, dpth)) goto error;
251 :
252 12690 : switch(ars)
253 : {
254 : case 0: break;
255 169 : case 1: iobuf_free_content(&lastpath);
256 169 : sbuf_free(&sb);
257 169 : return 0;
258 : default:
259 39 : if(result->buf)
260 32 : logp("Error after %s in %s()\n",
261 : iobuf_to_printable(result),
262 : __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 : // FIX THIS: cannot distinguish between new and
293 : // changed files.
294 0 : cntr_add_changed(cntr, sb->path.cmd);
295 0 : if(sb->endfile.buf)
296 : {
297 0 : uint64_t e=strtoull(sb->endfile.buf, NULL, 10);
298 0 : cntr_add_bytes(cntr, e);
299 : }
300 : }
301 : }
302 :
303 : error:
304 0 : iobuf_free_content(&lastpath);
305 0 : sbuf_free(&sb);
306 0 : man_off_t_free(pos);
307 0 : return -1;
308 : }
309 :
310 : // Return p1manio position.
311 0 : static man_off_t *do_resume_work(struct sdirs *sdirs,
312 : struct dpth *dpth, struct conf **cconfs)
313 : {
314 0 : man_off_t *pos=NULL;
315 0 : man_off_t *p1pos=NULL;
316 0 : struct iobuf *chb=NULL;
317 0 : struct manio *cmanio=NULL;
318 0 : struct manio *umanio=NULL;
319 0 : struct manio *p1manio=NULL;
320 0 : enum protocol protocol=get_protocol(cconfs);
321 0 : struct cntr *cntr=get_cntr(cconfs);
322 0 : int compression=get_int(cconfs[OPT_COMPRESSION]);
323 :
324 0 : if(!(p1manio=manio_open_phase1(sdirs->phase1data,
325 : MANIO_MODE_READ, protocol))
326 0 : || !(cmanio=manio_open_phase2(sdirs->changed,
327 : MANIO_MODE_READ, protocol))
328 0 : || !(umanio=manio_open_phase2(sdirs->unchanged,
329 : MANIO_MODE_READ, protocol)))
330 : goto end;
331 :
332 0 : if(!(chb=iobuf_alloc()))
333 : return NULL;
334 :
335 0 : logp("Setting up resume positions...\n");
336 :
337 0 : if(get_last_good_entry(cmanio, chb, cntr, dpth, protocol, &pos))
338 : goto error;
339 0 : if(manio_close_and_truncate(&cmanio, pos, compression)) goto error;
340 0 : man_off_t_free(&pos);
341 0 : if(chb->buf)
342 : {
343 0 : logp(" last good entry: %s\n",
344 : iobuf_to_printable(chb));
345 : // Now need to go to the appropriate places in p1manio and
346 : // unchanged.
347 0 : if(forward_past_entry(p1manio, chb, protocol, &p1pos))
348 : goto error;
349 :
350 : // The unchanged file needs to be positioned just before the
351 : // found entry, otherwise it ends up having a duplicated entry.
352 0 : if(forward_before_entry(umanio,
353 : chb, cntr, dpth, protocol, &pos))
354 : goto error;
355 0 : if(manio_close_and_truncate(&umanio, pos, compression))
356 : goto error;
357 0 : man_off_t_free(&pos);
358 : }
359 : else
360 : {
361 0 : logp(" nothing previously transferred\n");
362 0 : if(!(p1pos=manio_tell(p1manio)))
363 : {
364 0 : logp("Could not get p1pos in %s\n", __func__);
365 0 : goto error;
366 : }
367 0 : if(!(pos=manio_tell(umanio)))
368 : {
369 0 : logp("Could not get pos in %s\n", __func__);
370 0 : goto error;
371 : }
372 0 : if(manio_close_and_truncate(&umanio, pos, compression))
373 : goto error;
374 : }
375 :
376 : // Now should have all file pointers in the right places to resume.
377 :
378 : goto end;
379 : error:
380 0 : man_off_t_free(&p1pos);
381 : end:
382 0 : iobuf_free(&chb);
383 0 : man_off_t_free(&pos);
384 0 : manio_close(&p1manio);
385 0 : manio_close(&cmanio);
386 0 : manio_close(&umanio);
387 0 : return p1pos;
388 : }
389 :
390 0 : man_off_t *do_resume(struct sdirs *sdirs,
391 : struct dpth *dpth, struct conf **cconfs)
392 : {
393 0 : man_off_t *p1pos=NULL;
394 0 : struct manio *cmanio=NULL;
395 0 : struct manio *umanio=NULL;
396 0 : struct manio *p1manio=NULL;
397 0 : enum protocol protocol=get_protocol(cconfs);
398 :
399 0 : logp("Begin phase1 (read previous file system scan)\n");
400 0 : if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", protocol))
401 0 : || read_phase1(p1manio, cconfs))
402 : goto end;
403 0 : manio_close(&p1manio);
404 :
405 : // First, open them in append mode, so that they will be created if
406 : // they do not exist.
407 0 : if(!(cmanio=manio_open_phase2(sdirs->changed, "ab", protocol))
408 0 : || !(umanio=manio_open_phase2(sdirs->unchanged, "ab", protocol)))
409 : goto end;
410 0 : manio_close(&cmanio);
411 0 : manio_close(&umanio);
412 :
413 0 : if(!(p1pos=do_resume_work(sdirs, dpth, cconfs))) goto end;
414 :
415 0 : if(dpth_incr(dpth)) goto end;
416 :
417 0 : logp("End phase1 (read previous file system scan)\n");
418 : end:
419 0 : manio_close(&p1manio);
420 0 : manio_close(&cmanio);
421 0 : manio_close(&umanio);
422 0 : return p1pos;
423 : }
|