Line data Source code
1 : #include "../../burp.h"
2 : #include "../../alloc.h"
3 : #include "../../asfd.h"
4 : #include "../../async.h"
5 : #include "../../bu.h"
6 : #include "../../cmd.h"
7 : #include "../../cntr.h"
8 : #include "../../handy.h"
9 : #include "../../hexmap.h"
10 : #include "../../log.h"
11 : #include "../../prepend.h"
12 : #include "../../protocol1/handy.h"
13 : #include "../../server/protocol1/backup_phase4.h"
14 : #include "../../server/protocol1/link.h"
15 : #include "../../server/protocol1/zlibio.h"
16 : #include "../../sbuf.h"
17 : #include "../../slist.h"
18 : #include "../sdirs.h"
19 : #include "dpth.h"
20 : #include "restore.h"
21 :
22 : #include <librsync.h>
23 :
24 0 : static int create_zero_length_file(const char *path)
25 : {
26 0 : int ret=0;
27 : struct fzp *dest;
28 0 : if(!(dest=fzp_open(path, "wb")))
29 0 : ret=-1;
30 0 : ret|=fzp_close(&dest);
31 0 : return ret;
32 : }
33 :
34 0 : static int inflate_or_link_oldfile(struct asfd *asfd, const char *oldpath,
35 : const char *infpath, struct conf **cconfs, int compression)
36 : {
37 0 : int ret=0;
38 : struct stat statp;
39 :
40 0 : if(lstat(oldpath, &statp))
41 : {
42 0 : logp("could not lstat %s\n", oldpath);
43 0 : return -1;
44 : }
45 :
46 0 : if(dpth_protocol1_is_compressed(compression, oldpath))
47 : {
48 : //logp("inflating...\n");
49 :
50 0 : if(!statp.st_size)
51 : {
52 : // Empty file - cannot inflate.
53 0 : logp("asked to inflate zero length file: %s\n",
54 : oldpath);
55 0 : return create_zero_length_file(infpath);
56 : }
57 :
58 0 : if((ret=zlib_inflate(asfd, oldpath, infpath, get_cntr(cconfs))))
59 0 : logp("zlib_inflate returned: %d\n", ret);
60 : }
61 : else
62 : {
63 : // Not compressed - just hard link it.
64 0 : if(do_link(oldpath, infpath, &statp, cconfs,
65 : 1 /* allow overwrite of infpath */))
66 : return -1;
67 : }
68 : return ret;
69 : }
70 :
71 4 : static int do_send_file(struct asfd *asfd, struct sbuf *sb,
72 : int patches, const char *best, struct cntr *cntr)
73 : {
74 4 : enum send_e ret=SEND_FATAL;
75 : struct BFILE bfd;
76 4 : uint64_t bytes=0; // Unused.
77 :
78 4 : bfile_init(&bfd, 0, cntr);
79 4 : if(bfd.open_for_send(&bfd, asfd, best, sb->winattr,
80 : 1 /* no O_NOATIME */, cntr))
81 : return SEND_FATAL;
82 4 : if(asfd->write(asfd, &sb->path))
83 : ret=SEND_FATAL;
84 4 : else if(patches)
85 : {
86 : // If we did some patches, the resulting file
87 : // is not gzipped. Gzip it during the send.
88 0 : ret=send_whole_file_gzl(
89 : asfd,
90 0 : sb->protocol1->datapth.buf,
91 : /*quick_read*/1,
92 : &bytes,
93 : /*encpassword*/NULL,
94 : cntr,
95 : /*compression*/9,
96 : &bfd,
97 : /*extrameta*/NULL,
98 : /*elen*/0,
99 : /*key_deriv*/ENCRYPTION_UNSET,
100 : /*salt*/0
101 : );
102 : }
103 : else
104 : {
105 : // If it was encrypted, it may or may not have been compressed
106 : // before encryption. Send it as it as, and let the client
107 : // sort it out.
108 4 : if(sbuf_is_encrypted(sb))
109 : {
110 2 : ret=send_whole_filel(asfd,
111 : #ifdef HAVE_WIN32
112 : sb->path.cmd
113 : #endif
114 2 : sb->protocol1->datapth.buf,
115 : 1, &bytes, cntr, &bfd, NULL, 0);
116 : }
117 : // It might have been stored uncompressed. Gzip it during
118 : // the send. If the client knew what kind of file it would be
119 : // receiving, this step could disappear.
120 2 : else if(!dpth_protocol1_is_compressed(sb->compression,
121 2 : sb->protocol1->datapth.buf))
122 : {
123 2 : ret=send_whole_file_gzl(
124 : asfd,
125 2 : sb->protocol1->datapth.buf,
126 : /*quick_read*/1,
127 : &bytes,
128 : /*encpassword*/NULL,
129 : cntr,
130 : /*compression*/9,
131 : &bfd,
132 : /*extrameta*/NULL,
133 : /*elen*/0,
134 : /*key_deriv*/ENCRYPTION_UNSET,
135 : /*salt*/0
136 : );
137 : }
138 : else
139 : {
140 : // If we did not do some patches, the resulting
141 : // file might already be gzipped. Send it as it is.
142 0 : ret=send_whole_filel(asfd,
143 : #ifdef HAVE_WIN32
144 : sb->path.cmd
145 : #endif
146 0 : sb->protocol1->datapth.buf,
147 : 1, &bytes, cntr, &bfd, NULL, 0);
148 : }
149 : }
150 4 : bfd.close(&bfd, asfd);
151 :
152 4 : switch(ret)
153 : {
154 : case SEND_OK:
155 : case SEND_ERROR: // Carry on.
156 : return 0;
157 : case SEND_FATAL:
158 : default:
159 0 : return -1;
160 : }
161 : }
162 :
163 : #ifndef UTEST
164 : static
165 : #endif
166 5 : int verify_file(struct asfd *asfd, struct sbuf *sb,
167 : int patches, const char *best, struct cntr *cntr)
168 : {
169 : MD5_CTX md5;
170 5 : int b=0;
171 5 : const char *cp=NULL;
172 5 : const char *newsum=NULL;
173 : uint8_t in[ZCHUNK];
174 : uint8_t checksum[MD5_DIGEST_LENGTH];
175 5 : uint64_t cbytes=0;
176 5 : struct fzp *fzp=NULL;
177 :
178 5 : if(!sb->endfile.buf
179 5 : || !(cp=strrchr(sb->endfile.buf, ':')))
180 : {
181 1 : logw(asfd, cntr,
182 : "%s has no md5sum!\n",
183 1 : iobuf_to_printable(&sb->protocol1->datapth));
184 1 : return 0;
185 : }
186 4 : cp++;
187 4 : if(!MD5_Init(&md5))
188 : {
189 0 : logp("MD5_Init() failed\n");
190 0 : return -1;
191 : }
192 4 : if(patches
193 4 : || sb->path.cmd==CMD_ENC_FILE
194 4 : || sb->path.cmd==CMD_ENC_METADATA
195 4 : || sb->path.cmd==CMD_EFS_FILE
196 4 : || sb->path.cmd==CMD_ENC_VSS
197 4 : || sb->path.cmd==CMD_ENC_VSS_T
198 4 : || (!patches && !dpth_protocol1_is_compressed(sb->compression, best)))
199 2 : fzp=fzp_open(best, "rb");
200 : else
201 2 : fzp=fzp_gzopen(best, "rb");
202 :
203 4 : if(!fzp)
204 : {
205 1 : logw(asfd, cntr, "could not open %s\n", best);
206 1 : return 0;
207 : }
208 5 : while((b=fzp_read(fzp, in, ZCHUNK))>0)
209 : {
210 2 : cbytes+=b;
211 2 : if(!MD5_Update(&md5, in, b))
212 : {
213 0 : logp("MD5_Update() failed\n");
214 0 : fzp_close(&fzp);
215 0 : return -1;
216 : }
217 : }
218 3 : if(!fzp_eof(fzp))
219 : {
220 1 : logw(asfd, cntr, "error while reading %s\n", best);
221 1 : fzp_close(&fzp);
222 1 : return 0;
223 : }
224 2 : fzp_close(&fzp);
225 2 : if(!MD5_Final(checksum, &md5))
226 : {
227 0 : logp("MD5_Final() failed\n");
228 0 : return -1;
229 : }
230 2 : newsum=bytes_to_md5str(checksum);
231 :
232 2 : if(strcmp(newsum, cp))
233 : {
234 1 : logp("%s %s\n", newsum, cp);
235 1 : logw(asfd, cntr, "md5sum for '%s (%s)' did not match!\n",
236 : iobuf_to_printable(&sb->path),
237 1 : iobuf_to_printable(&sb->protocol1->datapth));
238 1 : logp("md5sum for '%s (%s)' did not match!\n",
239 : iobuf_to_printable(&sb->path),
240 1 : iobuf_to_printable(&sb->protocol1->datapth));
241 1 : return 0;
242 : }
243 :
244 : // Just send the file name to the client, so that it can show cntr.
245 1 : if(asfd->write(asfd, &sb->path)) return -1;
246 1 : return 0;
247 : }
248 :
249 4 : static int process_data_dir_file(struct asfd *asfd,
250 : struct bu *bu, struct bu *b, const char *path,
251 : struct sbuf *sb, enum action act, struct sdirs *sdirs,
252 : struct conf **cconfs)
253 : {
254 4 : int ret=-1;
255 4 : int patches=0;
256 4 : char *dpath=NULL;
257 : struct stat dstatp;
258 4 : const char *tmp=NULL;
259 4 : const char *best=NULL;
260 : static char *tmppath1=NULL;
261 : static char *tmppath2=NULL;
262 4 : struct cntr *cntr=NULL;
263 4 : if(cconfs) cntr=get_cntr(cconfs);
264 :
265 4 : if((!tmppath1 && !(tmppath1=prepend_s(bu->path, "tmp1")))
266 4 : || (!tmppath2 && !(tmppath2=prepend_s(bu->path, "tmp2"))))
267 : goto end;
268 :
269 4 : best=path;
270 4 : tmp=tmppath1;
271 : // Now go down the list, applying any deltas.
272 4 : for(b=b->prev; b && b->next!=bu; b=b->prev)
273 : {
274 0 : free_w(&dpath);
275 0 : if(!(dpath=prepend_s(b->delta, sb->protocol1->datapth.buf)))
276 : goto end;
277 :
278 0 : if(lstat(dpath, &dstatp) || !S_ISREG(dstatp.st_mode))
279 0 : continue;
280 :
281 0 : if(!patches)
282 : {
283 : // Need to gunzip the first one.
284 0 : if(inflate_or_link_oldfile(asfd, best, tmp,
285 : cconfs, sb->compression))
286 : {
287 0 : logw(asfd, cntr,
288 : "problem when inflating %s\n", best);
289 0 : ret=0;
290 : goto end;
291 : }
292 0 : best=tmp;
293 0 : if(tmp==tmppath1) tmp=tmppath2;
294 : else tmp=tmppath1;
295 : }
296 :
297 0 : if(do_patch(best, dpath, tmp,
298 : 0 /* do not gzip the result */,
299 : sb->compression /* from the manifest */))
300 : {
301 0 : logw(asfd, cntr, "problem when patching %s with %s\n", path, b->timestamp);
302 0 : ret=0;
303 : goto end;
304 : }
305 :
306 0 : best=tmp;
307 0 : if(tmp==tmppath1) tmp=tmppath2;
308 : else tmp=tmppath1;
309 0 : unlink(tmp);
310 0 : patches++;
311 : }
312 :
313 4 : switch(act)
314 : {
315 : case ACTION_RESTORE:
316 4 : if(do_send_file(asfd, sb, patches, best, cntr))
317 : goto end;
318 : break;
319 : case ACTION_VERIFY:
320 0 : if(verify_file(asfd, sb, patches, best, cntr))
321 : goto end;
322 : break;
323 : default:
324 0 : logp("Unknown action: %d\n", act);
325 : goto end;
326 : }
327 4 : cntr_add(cntr, sb->path.cmd, 0);
328 4 : cntr_add_bytes(cntr, strtoull(sb->endfile.buf, NULL, 10));
329 :
330 4 : ret=0;
331 : end:
332 4 : free_w(&dpath);
333 4 : if(tmppath1) unlink(tmppath1);
334 4 : if(tmppath2) unlink(tmppath2);
335 4 : free_w(&tmppath1);
336 4 : free_w(&tmppath2);
337 4 : return ret;
338 : }
339 :
340 : // a = length of struct bu array
341 : // i = position to restore from
342 : #ifndef UTEST
343 : static
344 : #endif
345 5 : int restore_file(struct asfd *asfd, struct bu *bu,
346 : struct sbuf *sb, enum action act,
347 : struct sdirs *sdirs, struct conf **cconfs)
348 : {
349 5 : int ret=-1;
350 5 : char *path=NULL;
351 : struct bu *b;
352 5 : struct bu *hlwarn=NULL;
353 : struct stat statp;
354 5 : struct cntr *cntr=NULL;
355 5 : if(cconfs) cntr=get_cntr(cconfs);
356 :
357 : // Go up the array until we find the file in the data directory.
358 10 : for(b=bu; b; b=b->next)
359 : {
360 4 : free_w(&path);
361 4 : if(!(path=prepend_s(b->data, sb->protocol1->datapth.buf)))
362 : goto end;
363 :
364 8 : if(lstat(path, &statp) || !S_ISREG(statp.st_mode))
365 0 : continue;
366 :
367 4 : if(b!=bu && (bu->flags & BU_HARDLINKED)) hlwarn=b;
368 :
369 4 : if(process_data_dir_file(asfd, bu, b,
370 : path, sb, act, sdirs, cconfs))
371 : goto end;
372 :
373 : // This warning must be done after everything else,
374 : // Because the client does not expect another cmd after
375 : // the warning.
376 4 : if(hlwarn) logw(asfd, cntr, "restore found %s in %s\n",
377 : iobuf_to_printable(&sb->path),
378 : hlwarn->basename);
379 : ret=0; // All OK.
380 : break;
381 : }
382 :
383 5 : if(!b)
384 : {
385 1 : logw(asfd, cntr, "restore could not find %s (%s)\n",
386 : iobuf_to_printable(&sb->path),
387 1 : iobuf_to_printable(&sb->protocol1->datapth));
388 1 : ret=0; // Carry on to subsequent files.
389 : }
390 : end:
391 5 : free_w(&path);
392 5 : return ret;
393 : }
394 :
395 10 : int restore_sbuf_protocol1(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
396 : enum action act, struct sdirs *sdirs, struct conf **cconfs)
397 : {
398 10 : if((sb->protocol1->datapth.buf
399 4 : && asfd->write(asfd, &(sb->protocol1->datapth)))
400 10 : || asfd->write(asfd, &sb->attr))
401 : return -1;
402 10 : else if(sbuf_is_filedata(sb)
403 6 : || sbuf_is_vssdata(sb))
404 : {
405 4 : if(!sb->protocol1->datapth.buf)
406 : {
407 0 : logw(asfd, get_cntr(cconfs),
408 : "Got filedata entry with no datapth: %s\n",
409 : iobuf_to_printable(&sb->path));
410 0 : return 0;
411 : }
412 4 : return restore_file(asfd, bu, sb, act, sdirs, cconfs);
413 : }
414 : else
415 : {
416 6 : if(asfd->write(asfd, &sb->path))
417 : return -1;
418 : // If it is a link, send what
419 : // it points to.
420 6 : else if(sbuf_is_link(sb)
421 4 : && asfd->write(asfd, &sb->link)) return -1;
422 6 : cntr_add(get_cntr(cconfs), sb->path.cmd, 0);
423 : }
424 6 : return 0;
425 : }
|