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, "rb", protocol))
325 0 : || !(cmanio=manio_open_phase2(sdirs->changed, "rb", protocol))
326 0 : || !(umanio=manio_open_phase2(sdirs->unchanged, "rb", protocol)))
327 : goto end;
328 :
329 0 : if(!(chb=iobuf_alloc()))
330 : return NULL;
331 :
332 0 : logp("Setting up resume positions...\n");
333 :
334 0 : if(get_last_good_entry(cmanio, chb, cntr, dpth, protocol, &pos))
335 : goto error;
336 0 : if(manio_close_and_truncate(&cmanio, pos, compression)) goto error;
337 0 : man_off_t_free(&pos);
338 0 : if(chb->buf)
339 : {
340 0 : logp(" last good entry: %s\n",
341 : iobuf_to_printable(chb));
342 : // Now need to go to the appropriate places in p1manio and
343 : // unchanged.
344 0 : if(forward_past_entry(p1manio, chb, protocol, &p1pos))
345 : goto error;
346 :
347 : // The unchanged file needs to be positioned just before the
348 : // found entry, otherwise it ends up having a duplicated entry.
349 0 : if(forward_before_entry(umanio,
350 : chb, cntr, dpth, protocol, &pos))
351 : goto error;
352 0 : if(manio_close_and_truncate(&umanio, pos, compression))
353 : goto error;
354 0 : man_off_t_free(&pos);
355 : }
356 : else
357 : {
358 0 : logp(" nothing previously transferred\n");
359 0 : if(!(p1pos=manio_tell(p1manio)))
360 : goto error;
361 0 : if(!(pos=manio_tell(umanio)))
362 : goto error;
363 0 : if(manio_close_and_truncate(&umanio, pos, compression))
364 : goto error;
365 : }
366 :
367 : // Now should have all file pointers in the right places to resume.
368 :
369 : goto end;
370 : error:
371 0 : man_off_t_free(&p1pos);
372 : end:
373 0 : iobuf_free(&chb);
374 0 : man_off_t_free(&pos);
375 0 : manio_close(&p1manio);
376 0 : manio_close(&cmanio);
377 0 : manio_close(&umanio);
378 0 : return p1pos;
379 : }
380 :
381 0 : man_off_t *do_resume(struct sdirs *sdirs,
382 : struct dpth *dpth, struct conf **cconfs)
383 : {
384 0 : man_off_t *p1pos=NULL;
385 0 : struct manio *cmanio=NULL;
386 0 : struct manio *umanio=NULL;
387 0 : struct manio *p1manio=NULL;
388 0 : enum protocol protocol=get_protocol(cconfs);
389 :
390 0 : logp("Begin phase1 (read previous file system scan)\n");
391 0 : if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", protocol))
392 0 : || read_phase1(p1manio, cconfs))
393 : goto end;
394 0 : manio_close(&p1manio);
395 :
396 : // First, open them in append mode, so that they will be created if
397 : // they do not exist.
398 0 : if(!(cmanio=manio_open_phase2(sdirs->changed, "ab", protocol))
399 0 : || !(umanio=manio_open_phase2(sdirs->unchanged, "ab", protocol)))
400 : goto end;
401 0 : manio_close(&cmanio);
402 0 : manio_close(&umanio);
403 :
404 0 : if(!(p1pos=do_resume_work(sdirs, dpth, cconfs))) goto end;
405 :
406 0 : if(dpth_incr(dpth)) goto end;
407 :
408 0 : logp("End phase1 (read previous file system scan)\n");
409 : end:
410 0 : manio_close(&p1manio);
411 0 : manio_close(&cmanio);
412 0 : manio_close(&umanio);
413 0 : return p1pos;
414 : }
|