Line data Source code
1 : #include "../../burp.h"
2 : #include "../../alloc.h"
3 : #include "../../asfd.h"
4 : #include "../../async.h"
5 : #include "../../attribs.h"
6 : #include "../../cmd.h"
7 : #include "../../cntr.h"
8 : #include "../../conf.h"
9 : #include "../../conffile.h"
10 : #include "../../fsops.h"
11 : #include "../../handy.h"
12 : #include "../../iobuf.h"
13 : #include "../../log.h"
14 : #include "../../sbuf.h"
15 : #include "../child.h"
16 : #include "../compress.h"
17 : #include "../resume.h"
18 : #include "blocklen.h"
19 : #include "dpth.h"
20 : #include "backup_phase2.h"
21 : #include "link.h"
22 :
23 : static size_t treepathlen=0;
24 :
25 0 : static int path_length_warn(struct iobuf *path, struct conf **cconfs)
26 : {
27 0 : if(get_int(cconfs[OPT_PATH_LENGTH_WARN]))
28 0 : logw(NULL, get_cntr(cconfs), "Path too long for tree - will save in data structure instead: %s\n", path->buf);
29 0 : return 1;
30 : }
31 :
32 4 : static int path_too_long(struct iobuf *path, struct conf **cconfs)
33 : {
34 : static const char *cp;
35 4 : if(treepathlen+path->len+1>fs_full_path_max)
36 : {
37 : // FIX THIS:
38 : // Cannot warn down the asfd to the client, because it can
39 : // arrive after the client has disconnected, which causes
40 : // an error on the server side.
41 : // Would need to change the way that "backupphase2end" works
42 : // to be able to fix it.
43 0 : return path_length_warn(path, cconfs);
44 : }
45 4 : if((cp=strrchr(path->buf, '/'))) cp++;
46 0 : else cp=path->buf;
47 4 : if(strlen(cp)>fs_name_max) return path_length_warn(path, cconfs);
48 : return 0;
49 : }
50 :
51 4 : static int treedata(struct sbuf *sb, struct conf **cconfs)
52 : {
53 : // Windows is sending directory data as if it is file data - this
54 : // cannot be saved in a tree structure.
55 4 : if(S_ISDIR(sb->statp.st_mode)) return 0;
56 :
57 8 : if(sb->path.cmd!=CMD_FILE
58 4 : && sb->path.cmd!=CMD_ENC_FILE
59 0 : && sb->path.cmd!=CMD_EFS_FILE)
60 : return 0;
61 :
62 4 : return !path_too_long(&sb->path, cconfs);
63 : }
64 :
65 4 : static char *set_new_datapth(struct asfd *asfd,
66 : struct sdirs *sdirs, struct conf **cconfs,
67 : struct sbuf *sb, struct dpth *dpth, int *istreedata)
68 : {
69 4 : char *tmp=NULL;
70 4 : char *rpath=NULL;
71 4 : if(get_int(cconfs[OPT_DIRECTORY_TREE]))
72 4 : *istreedata=treedata(sb, cconfs);
73 :
74 4 : if(*istreedata)
75 : {
76 : // We want to place this file in a directory structure like
77 : // the directory structure on the original client.
78 4 : if(!(tmp=prepend_s(TREE_DIR, sb->path.buf)))
79 : {
80 0 : log_and_send_oom(asfd);
81 : return NULL;
82 : }
83 : }
84 : else
85 : {
86 0 : if(!(tmp=strdup_w(dpth_protocol1_mk(dpth, sb->compression,
87 : sb->path.cmd), __func__))) return NULL;
88 : }
89 4 : iobuf_from_str(&sb->protocol1->datapth, CMD_DATAPTH, tmp);
90 4 : if(build_path(sdirs->datadirtmp,
91 4 : sb->protocol1->datapth.buf, &rpath, sdirs->datadirtmp))
92 : {
93 0 : log_and_send(asfd, "build path failed");
94 : return NULL;
95 : }
96 4 : return rpath;
97 : }
98 :
99 4 : static int start_to_receive_new_file(struct asfd *asfd,
100 : struct sdirs *sdirs, struct conf **cconfs,
101 : struct sbuf *sb, struct dpth *dpth)
102 : {
103 4 : int ret=-1;
104 4 : char *rpath=NULL;
105 4 : int istreedata=0;
106 :
107 : //logp("start to receive: %s\n", sb->path.buf);
108 :
109 4 : if(!(rpath=set_new_datapth(asfd,
110 : sdirs, cconfs, sb, dpth, &istreedata)))
111 : goto end;
112 :
113 4 : if(!(sb->protocol1->fzp=fzp_open(rpath, "wb")))
114 : {
115 0 : log_and_send(asfd, "make file failed");
116 0 : goto end;
117 : }
118 4 : if(!istreedata) dpth_incr(dpth);
119 : ret=0;
120 : end:
121 4 : free_w(&rpath);
122 4 : return ret;
123 : }
124 :
125 : enum processed_e
126 : {
127 : P_ERROR=-1,
128 : P_DONE_NEW=0,
129 : P_DONE_CHANGED=1,
130 : P_DONE_UNCHANGED=2,
131 : P_DONE_DELETED=3,
132 : P_NEW=4,
133 : P_CHANGED=5
134 : };
135 :
136 : #include <librsync.h>
137 :
138 2 : static enum processed_e process_changed_file(struct asfd *asfd,
139 : struct conf **cconfs,
140 : struct sbuf *cb, struct sbuf *p1b,
141 : const char *adir)
142 : {
143 2 : int ret=P_ERROR;
144 2 : size_t blocklen=0;
145 2 : char *curpath=NULL;
146 : //logp("need to process changed file: %s (%s)\n",
147 : // cb->path, cb->datapth);
148 :
149 : // Move datapth onto p1b.
150 2 : iobuf_move(&p1b->protocol1->datapth, &cb->protocol1->datapth);
151 :
152 2 : if(!(curpath=prepend_s(adir, p1b->protocol1->datapth.buf)))
153 : {
154 0 : log_out_of_memory(__func__);
155 : goto end;
156 : }
157 2 : if(dpth_protocol1_is_compressed(cb->compression, curpath))
158 0 : p1b->protocol1->sigfzp=fzp_gzopen(curpath, "rb");
159 : else
160 2 : p1b->protocol1->sigfzp=fzp_open(curpath, "rb");
161 2 : if(!p1b->protocol1->sigfzp)
162 : {
163 0 : logp("could not open %s: %s\n", curpath, strerror(errno));
164 : goto end;
165 : }
166 :
167 2 : blocklen=get_librsync_block_len(cb->endfile.buf);
168 4 : if(!(p1b->protocol1->sigjob=
169 : #ifdef RS_DEFAULT_STRONG_LEN
170 2 : rs_sig_begin(blocklen, RS_DEFAULT_STRONG_LEN)
171 : #else
172 : // This is for librsync-1.0.0. RS_DEFAULT_STRONG_LEN was 8 in
173 : // librsync-0.9.7.
174 : rs_sig_begin(blocklen, 8,
175 : rshash_to_magic_number(get_e_rshash(cconfs[OPT_RSHASH])))
176 : #endif
177 : ))
178 : {
179 0 : logp("could not start signature job.\n");
180 : goto end;
181 : }
182 : //logp("sig begin: %s\n", p1b->protocol1->datapth.buf);
183 2 : if(!(p1b->protocol1->infb=rs_filebuf_new(NULL,
184 2 : p1b->protocol1->sigfzp,
185 : NULL, blocklen, -1)))
186 : {
187 0 : logp("could not rs_filebuf_new for infb.\n");
188 : goto end;
189 : }
190 2 : if(!(p1b->protocol1->outfb=rs_filebuf_new(NULL, NULL,
191 : asfd, ASYNC_BUF_LEN, -1)))
192 : {
193 0 : logp("could not rs_filebuf_new for in_outfb.\n");
194 : goto end;
195 : }
196 :
197 : // Flag the things that need to be sent (to the client)
198 2 : p1b->flags |= SBUF_SEND_DATAPTH;
199 2 : p1b->flags |= SBUF_SEND_STAT;
200 2 : p1b->flags |= SBUF_SEND_PATH;
201 :
202 : //logp("sending sig for %s\n", p1b->path);
203 : //logp("(%s)\n", p1b->datapth);
204 :
205 2 : ret=P_CHANGED;
206 : end:
207 2 : free_w(&curpath);
208 2 : return ret;
209 : }
210 :
211 68 : static enum processed_e new_non_file(struct sbuf *p1b,
212 : struct manio *ucmanio, struct conf **cconfs)
213 : {
214 : // Is something that does not need more data backed up.
215 : // Like a directory or a link or something like that.
216 : // Goes into the unchanged file, so that it does not end up out of
217 : // order with normal files, which has to wait around for their data
218 : // to turn up.
219 68 : if(manio_write_sbuf(ucmanio, p1b))
220 : return P_ERROR;
221 68 : cntr_add(get_cntr(cconfs), p1b->path.cmd, 0);
222 68 : return P_DONE_NEW;
223 : }
224 :
225 0 : static enum processed_e changed_non_file(struct sbuf *p1b,
226 : struct manio *ucmanio, enum cmd cmd, struct conf **cconfs)
227 : {
228 : // As new_non_file.
229 0 : if(manio_write_sbuf(ucmanio, p1b))
230 : return P_ERROR;
231 0 : cntr_add_changed(get_cntr(cconfs), cmd);
232 0 : return P_DONE_CHANGED;
233 : }
234 :
235 122 : static enum processed_e process_new(struct conf **cconfs,
236 : struct sbuf *p1b, struct manio *ucmanio)
237 : {
238 122 : if(sbuf_is_filedata(p1b)
239 68 : || sbuf_is_vssdata(p1b))
240 : {
241 : //logp("need to process new file: %s\n", p1b->path);
242 : // Flag the things that need to be sent (to the client)
243 54 : p1b->flags |= SBUF_SEND_STAT;
244 54 : p1b->flags |= SBUF_SEND_PATH;
245 54 : return P_NEW;
246 : }
247 68 : return new_non_file(p1b, ucmanio, cconfs);
248 : }
249 :
250 6 : static enum processed_e process_unchanged_file(struct sbuf *p1b, struct sbuf *cb,
251 : struct manio *ucmanio, struct conf **cconfs)
252 : {
253 : // Need to re-encode the p1b attribs to include compression and
254 : // other bits and pieces that are recorded on cb.
255 6 : iobuf_move(&p1b->protocol1->datapth, &cb->protocol1->datapth);
256 6 : iobuf_move(&p1b->endfile, &cb->endfile);
257 6 : p1b->compression=cb->compression;
258 : // Why is winattr not getting sent in phase1?
259 6 : p1b->winattr=cb->winattr;
260 : // Need to free attr so that it is reallocated, because it may get
261 : // longer than what the client told us in phase1.
262 6 : iobuf_free_content(&p1b->attr);
263 6 : if(attribs_encode(p1b))
264 : return P_ERROR;
265 6 : if(manio_write_sbuf(ucmanio, p1b))
266 : return P_ERROR;
267 6 : cntr_add_same(get_cntr(cconfs), p1b->path.cmd);
268 6 : if(p1b->endfile.buf) cntr_add_bytes(get_cntr(cconfs),
269 0 : strtoull(p1b->endfile.buf, NULL, 10));
270 : return P_DONE_UNCHANGED;
271 : }
272 :
273 10 : static int open_previous_manifest(struct manio **manio, struct sdirs *sdirs)
274 : {
275 : struct stat statp;
276 20 : if(!lstat(sdirs->cmanifest, &statp)
277 2 : && !(*manio=manio_open(sdirs->cmanifest, "rb", PROTO_1)))
278 : {
279 0 : logp("could not open old manifest %s\n", sdirs->cmanifest);
280 : return -1;
281 : }
282 : return 0;
283 : }
284 :
285 0 : static int get_hardlink_master_from_hmanio(
286 : struct manio **hmanio,
287 : struct sdirs *sdirs,
288 : struct sbuf *cb,
289 : struct sbuf *hb
290 : ) {
291 : int passes=0;
292 : while(1)
293 : {
294 0 : sbuf_free_content(hb);
295 0 : switch(manio_read(*hmanio, hb))
296 : {
297 : case 0: // Keep going.
298 : break;
299 : case 1: // Finished OK.
300 0 : manio_close(hmanio);
301 : // Might have already been part way down the
302 : // manifest when we started. If we get to the
303 : // end, go back to the beginning once.
304 0 : if(!passes)
305 : {
306 0 : if(open_previous_manifest(hmanio,
307 : sdirs)) return -1;
308 0 : passes++;
309 0 : continue;
310 : }
311 : return 0;
312 : default: // Error;
313 : return -1;
314 : }
315 0 : if(hb->path.cmd!=CMD_FILE
316 0 : && hb->path.cmd!=CMD_ENC_FILE)
317 0 : continue;
318 0 : if(!strcmp(hb->path.buf, cb->link.buf))
319 : return 1; // Found it.
320 : }
321 : return -1;
322 : }
323 :
324 0 : static int relink_deleted_hardlink_master(
325 : struct manio **hmanio,
326 : struct sdirs *sdirs,
327 : struct sbuf *p1b,
328 : struct sbuf *cb,
329 : struct conf **cconfs
330 : ) {
331 0 : int ret=-1;
332 0 : char *oldpath=NULL;
333 0 : char *newpath=NULL;
334 : struct stat statp;
335 0 : struct sbuf *hb=NULL;
336 :
337 0 : if(!(hb=sbuf_alloc(PROTO_1)))
338 : goto end;
339 :
340 0 : switch(get_hardlink_master_from_hmanio(hmanio, sdirs, cb, hb))
341 : {
342 : case 0: // Did not find it.
343 : return 0;
344 : case 1: // Found it.
345 : break;
346 : default: // Error.
347 : goto end;
348 : }
349 :
350 : // Protect against the old file being encrypted, and the new file not
351 : // being encrypted - and vice versa.
352 0 : if(p1b->path.cmd!=hb->path.cmd)
353 : return 0;
354 :
355 0 : if(!(oldpath=prepend_s(sdirs->ctreepath, cb->link.buf))
356 0 : || !(newpath=prepend_s(sdirs->relink, p1b->path.buf)))
357 : goto end;
358 0 : if(lstat(oldpath, &statp) || !S_ISREG(statp.st_mode))
359 : {
360 : ret=0;
361 : goto end;
362 : }
363 0 : if(build_path_w(newpath))
364 : goto end;
365 0 : if(do_link(oldpath, newpath, &statp, cconfs, /*overwrite*/0))
366 : goto end;
367 :
368 0 : iobuf_free_content(&cb->protocol1->datapth);
369 :
370 0 : free_w(&newpath);
371 0 : if(!(newpath=strdup_w(p1b->path.buf, __func__)))
372 : goto end;
373 0 : iobuf_from_str(&hb->protocol1->datapth, CMD_DATAPTH, newpath);
374 0 : newpath=NULL;
375 0 : if(!(newpath=strdup_w(p1b->path.buf, __func__)))
376 : goto end;
377 0 : iobuf_from_str(&cb->protocol1->datapth, CMD_DATAPTH, newpath);
378 0 : newpath=NULL;
379 0 : iobuf_move(&cb->endfile, &hb->endfile);
380 :
381 0 : ret=1;
382 : end:
383 0 : free_w(&oldpath);
384 0 : free_w(&newpath);
385 0 : sbuf_free(&hb);
386 : return ret;
387 : }
388 :
389 10 : static enum processed_e maybe_do_delta_stuff(struct asfd *asfd,
390 : struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
391 : struct manio *ucmanio, struct manio **hmanio, struct conf **cconfs)
392 : {
393 10 : int oldcompressed=0;
394 10 : int compression=p1b->compression;
395 :
396 : // If the file type changed, I think it is time to back it up again
397 : // (for example, EFS changing to normal file, or back again).
398 10 : if(cb->path.cmd!=p1b->path.cmd)
399 : {
400 0 : if(hmanio && *hmanio
401 0 : && cb->path.cmd==CMD_HARD_LINK
402 0 : && (p1b->path.cmd==CMD_FILE
403 0 : || p1b->path.cmd==CMD_ENC_FILE))
404 : {
405 0 : struct stat *p1statp=&p1b->statp;
406 0 : struct stat *cstatp=&cb->statp;
407 : // A hardlink changed into a file. It is possible that
408 : // The file that the hardlink was pointing to got
409 : // deleted. Maybe we can reuse the previous file.
410 0 : if(p1statp->st_dev==cstatp->st_dev
411 0 : && p1statp->st_ino==cstatp->st_ino
412 0 : && p1statp->st_mtime==cstatp->st_mtime)
413 : {
414 0 : switch(relink_deleted_hardlink_master(
415 : hmanio, sdirs,
416 : p1b, cb, cconfs))
417 : {
418 : case 0:
419 : break;
420 : case 1:
421 0 : return process_unchanged_file(
422 : p1b, cb,
423 : ucmanio, cconfs);
424 : default:
425 : return P_ERROR;
426 : }
427 : }
428 : }
429 0 : return process_new(cconfs, p1b, ucmanio);
430 : }
431 :
432 : // mtime is the actual file data.
433 : // ctime is the attributes or meta data.
434 10 : if(cb->statp.st_mtime==p1b->statp.st_mtime
435 6 : && cb->statp.st_ctime==p1b->statp.st_ctime)
436 : {
437 : // got an unchanged file
438 : //logp("got unchanged file: %s %c %c\n",
439 : // cb->path.buf, cb->path.cmd, p1b->path.cmd);
440 6 : return process_unchanged_file(p1b, cb, ucmanio, cconfs);
441 : }
442 :
443 4 : if(cb->statp.st_mtime==p1b->statp.st_mtime
444 0 : && cb->statp.st_ctime!=p1b->statp.st_ctime)
445 : {
446 : // File data stayed the same, but attributes or meta data
447 : // changed. We already have the attributes, but may need to get
448 : // extra meta data.
449 : // FIX THIS horrible mess.
450 0 : if(cb->path.cmd==CMD_ENC_METADATA
451 0 : || p1b->path.cmd==CMD_ENC_METADATA
452 0 : || cb->path.cmd==CMD_EFS_FILE
453 0 : || p1b->path.cmd==CMD_EFS_FILE
454 : // FIX THIS: make unencrypted metadata use the librsync
455 0 : || cb->path.cmd==CMD_METADATA
456 0 : || p1b->path.cmd==CMD_METADATA
457 0 : || sbuf_is_vssdata(cb)
458 0 : || sbuf_is_vssdata(p1b))
459 0 : return process_new(cconfs, p1b, ucmanio);
460 : // On Windows, we have to back up the whole file if ctime
461 : // changed, otherwise things like permission changes do not get
462 : // noticed. So, in that case, fall through to the changed stuff
463 : // below.
464 : // Non-Windows clients finish here.
465 0 : else if(!get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
466 0 : return process_unchanged_file(p1b,
467 : cb, ucmanio, cconfs);
468 : }
469 :
470 : // Got a changed file.
471 : //logp("got changed file: %s\n", p1b->path.buf);
472 :
473 : // If either old or new is encrypted, or librsync is off, we need to
474 : // get a new file.
475 : // FIX THIS horrible mess.
476 4 : if(!get_int(cconfs[OPT_LIBRSYNC])
477 : // FIX THIS: make unencrypted metadata use the librsync
478 4 : || cb->path.cmd==CMD_METADATA
479 4 : || p1b->path.cmd==CMD_METADATA
480 4 : || sbuf_is_encrypted(cb)
481 2 : || sbuf_is_encrypted(p1b)
482 2 : || sbuf_is_vssdata(cb)
483 2 : || sbuf_is_vssdata(p1b))
484 2 : return process_new(cconfs, p1b, ucmanio);
485 :
486 : // Get new files if they have switched between compression on or off.
487 2 : if(cb->protocol1->datapth.buf
488 2 : && dpth_protocol1_is_compressed(cb->compression,
489 : cb->protocol1->datapth.buf))
490 0 : oldcompressed=1;
491 2 : if( ( oldcompressed && !compression)
492 2 : || (!oldcompressed && compression))
493 0 : return process_new(cconfs, p1b, ucmanio);
494 :
495 : // Otherwise, do the delta stuff (if possible).
496 2 : if(sbuf_is_filedata(p1b)
497 0 : || sbuf_is_vssdata(p1b))
498 2 : return process_changed_file(asfd, cconfs, cb, p1b,
499 2 : sdirs->currentdata);
500 0 : return changed_non_file(p1b, ucmanio, p1b->path.cmd, cconfs);
501 : }
502 :
503 : static enum processed_e process_deleted_file(struct sbuf *cb,
504 : struct conf **cconfs)
505 : {
506 2 : cntr_add_deleted(get_cntr(cconfs), cb->path.cmd);
507 : return P_DONE_DELETED;
508 : }
509 :
510 : // return 1 to say that a file was processed
511 12 : static enum processed_e maybe_process_file(struct asfd *asfd,
512 2 : struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
513 : struct manio *ucmanio, struct manio **hmanio, struct conf **cconfs)
514 : {
515 : int pcmp;
516 12 : if(p1b)
517 : {
518 11 : if(!(pcmp=sbuf_pathcmp(cb, p1b)))
519 10 : return maybe_do_delta_stuff(asfd, sdirs, cb, p1b,
520 : ucmanio, hmanio, cconfs);
521 1 : else if(pcmp>0)
522 : {
523 : //logp("ahead: %s\n", p1b->path.buf);
524 : // ahead - need to get the whole file
525 0 : return process_new(cconfs, p1b, ucmanio);
526 : }
527 : }
528 : //logp("behind: %s\n", p1b->path.buf);
529 : // Behind - need to read more from the old manifest.
530 : // Count a deleted file - it was in the old manifest
531 : // but not the new.
532 4 : return process_deleted_file(cb, cconfs);
533 : }
534 :
535 : enum sts_e
536 : {
537 : STS_ERROR=-1,
538 : STS_OK=0,
539 : STS_BLOCKED=1
540 : };
541 :
542 : // Return 1 if there is still stuff needing to be sent.
543 : // FIX THIS: lots of repeated code.
544 63 : static enum sts_e do_stuff_to_send(struct asfd *asfd,
545 : struct sbuf *p1b, char **last_requested)
546 : {
547 : static struct iobuf wbuf;
548 63 : if(p1b->flags & SBUF_SEND_DATAPTH)
549 : {
550 2 : iobuf_copy(&wbuf, &p1b->protocol1->datapth);
551 2 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
552 : {
553 : case APPEND_OK: break;
554 : case APPEND_BLOCKED: return STS_BLOCKED;
555 0 : default: return STS_ERROR;
556 : }
557 2 : p1b->flags &= ~SBUF_SEND_DATAPTH;
558 : }
559 63 : if(p1b->flags & SBUF_SEND_STAT)
560 : {
561 56 : iobuf_copy(&wbuf, &p1b->attr);
562 56 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
563 : {
564 : case APPEND_OK: break;
565 : case APPEND_BLOCKED: return STS_BLOCKED;
566 0 : default: return STS_ERROR;
567 : }
568 56 : p1b->flags &= ~SBUF_SEND_STAT;
569 : }
570 63 : if(p1b->flags & SBUF_SEND_PATH)
571 : {
572 56 : iobuf_copy(&wbuf, &p1b->path);
573 56 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
574 : {
575 : case APPEND_OK: break;
576 : case APPEND_BLOCKED: return STS_BLOCKED;
577 0 : default: return STS_ERROR;
578 : }
579 56 : p1b->flags &= ~SBUF_SEND_PATH;
580 56 : free_w(last_requested);
581 56 : if(!(*last_requested=strdup_w(p1b->path.buf, __func__)))
582 : return STS_ERROR;
583 : }
584 63 : if(p1b->protocol1->sigjob && !(p1b->flags & SBUF_SEND_ENDOFSIG))
585 : {
586 : rs_result sigresult;
587 :
588 4 : switch((sigresult=rs_async(p1b->protocol1->sigjob,
589 : &(p1b->protocol1->rsbuf),
590 : p1b->protocol1->infb, p1b->protocol1->outfb)))
591 : {
592 : case RS_DONE:
593 2 : p1b->flags |= SBUF_SEND_ENDOFSIG;
594 2 : break;
595 : case RS_BLOCKED:
596 : case RS_RUNNING:
597 : // keep going round the loop.
598 : return STS_BLOCKED;
599 : default:
600 0 : logp("error in rs_async: %d\n", sigresult);
601 0 : return STS_ERROR;
602 : }
603 : }
604 61 : if(p1b->flags & SBUF_SEND_ENDOFSIG)
605 : {
606 2 : iobuf_from_str(&wbuf, CMD_END_FILE, (char *)"endfile");
607 2 : switch(asfd->append_all_to_write_buffer(asfd, &wbuf))
608 : {
609 : case APPEND_OK: break;
610 : case APPEND_BLOCKED: return STS_BLOCKED;
611 0 : default: return STS_ERROR;
612 : }
613 2 : p1b->flags &= ~SBUF_SEND_ENDOFSIG;
614 : }
615 : return STS_OK;
616 : }
617 :
618 4 : static int start_to_receive_delta(struct sdirs *sdirs, struct sbuf *rb)
619 : {
620 4 : if(rb->compression)
621 : {
622 0 : if(!(rb->protocol1->fzp=fzp_gzopen(sdirs->deltmppath,
623 0 : comp_level(rb->compression))))
624 : return -1;
625 : }
626 : else
627 : {
628 4 : if(!(rb->protocol1->fzp=fzp_open(sdirs->deltmppath, "wb")))
629 : return -1;
630 : }
631 4 : rb->flags |= SBUF_RECV_DELTA;
632 :
633 : return 0;
634 : }
635 :
636 4 : static int finish_delta(struct sdirs *sdirs, struct sbuf *rb)
637 : {
638 4 : int ret=0;
639 4 : char *deltmp=NULL;
640 4 : char *delpath=NULL;
641 4 : if(!(deltmp=prepend_s("deltas.forward", rb->protocol1->datapth.buf))
642 4 : || !(delpath=prepend_s(sdirs->working, deltmp))
643 4 : || mkpath(&delpath, sdirs->working)
644 : // Rename race condition is of no consequence here, as delpath will
645 : // just get recreated.
646 4 : || do_rename(sdirs->deltmppath, delpath))
647 : ret=-1;
648 4 : free_w(&delpath);
649 4 : free_w(&deltmp);
650 4 : return ret;
651 : }
652 :
653 8 : static int deal_with_receive_end_file(struct asfd *asfd, struct sdirs *sdirs,
654 4 : struct sbuf *rb, struct manio *chmanio, struct conf **cconfs,
655 : char **last_requested)
656 : {
657 8 : int ret=-1;
658 : static char *cp=NULL;
659 : static struct iobuf *rbuf;
660 8 : struct cntr *cntr=get_cntr(cconfs);
661 8 : rbuf=asfd->rbuf;
662 : // Finished the file.
663 : // Write it to the phase2 file, and free the buffers.
664 :
665 8 : if(fzp_close(&(rb->protocol1->fzp)))
666 : {
667 0 : logp("error closing delta for %s in receive\n", rb->path.buf);
668 : goto end;
669 : }
670 8 : iobuf_move(&rb->endfile, rbuf);
671 12 : if(rb->flags & SBUF_RECV_DELTA && finish_delta(sdirs, rb))
672 : goto end;
673 :
674 8 : if(manio_write_sbuf(chmanio, rb))
675 : goto end;
676 :
677 8 : if(rb->flags & SBUF_RECV_DELTA)
678 4 : cntr_add_changed(cntr, rb->path.cmd);
679 : else
680 4 : cntr_add(cntr, rb->path.cmd, 0);
681 :
682 8 : if(*last_requested && !strcmp(rb->path.buf, *last_requested))
683 2 : free_w(last_requested);
684 :
685 8 : cp=strchr(rb->endfile.buf, ':');
686 8 : if(rb->endfile.buf)
687 8 : cntr_add_bytes(cntr, strtoull(rb->endfile.buf, NULL, 10));
688 : if(cp)
689 : {
690 : // checksum stuff goes here
691 : }
692 :
693 : ret=0;
694 : end:
695 8 : sbuf_free_content(rb);
696 8 : return ret;
697 : }
698 :
699 8 : static int deal_with_receive_append(struct asfd *asfd, struct sbuf *rb)
700 : {
701 8 : int app=0;
702 : static struct iobuf *rbuf;
703 8 : rbuf=asfd->rbuf;
704 : //logp("rbuf->len: %d\n", rbuf->len);
705 :
706 8 : if(rb->protocol1->fzp)
707 8 : app=fzp_write(rb->protocol1->fzp, rbuf->buf, rbuf->len);
708 :
709 8 : if(app>0) return 0;
710 0 : logp("error when appending: %d\n", app);
711 0 : asfd->write_str(asfd, CMD_ERROR, "write failed");
712 : return -1;
713 : }
714 :
715 8 : static int deal_with_filedata(struct asfd *asfd,
716 : struct sdirs *sdirs, struct sbuf *rb,
717 : struct iobuf *rbuf, struct dpth *dpth, struct conf **cconfs)
718 : {
719 8 : iobuf_move(&rb->path, rbuf);
720 :
721 8 : if(rb->protocol1->datapth.buf)
722 : {
723 : // Receiving a delta.
724 4 : if(start_to_receive_delta(sdirs, rb))
725 : {
726 0 : logp("error in start_to_receive_delta\n");
727 0 : return -1;
728 : }
729 : return 0;
730 : }
731 :
732 : // Receiving a whole new file.
733 4 : if(start_to_receive_new_file(asfd, sdirs, cconfs, rb, dpth))
734 : {
735 0 : logp("error in start_to_receive_new_file\n");
736 0 : return -1;
737 : }
738 : return 0;
739 : }
740 :
741 : enum str_e
742 : {
743 : STR_ERROR=-1,
744 : STR_OK=0,
745 : STR_FINISHED=1
746 : };
747 :
748 : // returns 1 for finished ok.
749 85 : static enum str_e do_stuff_to_receive(struct asfd *asfd,
750 : struct sdirs *sdirs, struct conf **cconfs,
751 : struct sbuf *rb, struct manio *chmanio,
752 : struct dpth *dpth, char **last_requested)
753 : {
754 85 : struct iobuf *rbuf=asfd->rbuf;
755 :
756 170 : if(rbuf->cmd==CMD_MESSAGE
757 85 : || rbuf->cmd==CMD_WARNING)
758 : {
759 0 : struct cntr *cntr=NULL;
760 0 : if(cconfs) cntr=get_cntr(cconfs);
761 0 : log_recvd(rbuf, cntr, 0);
762 0 : return STR_OK;
763 : }
764 :
765 85 : if(rb->protocol1->fzp)
766 : {
767 : // Currently writing a file (or meta data)
768 16 : switch(rbuf->cmd)
769 : {
770 : case CMD_APPEND:
771 8 : if(deal_with_receive_append(asfd, rb))
772 : goto error;
773 : return STR_OK;
774 : case CMD_END_FILE:
775 8 : if(deal_with_receive_end_file(asfd, sdirs, rb,
776 : chmanio, cconfs, last_requested))
777 : goto error;
778 : return STR_OK;
779 : default:
780 0 : iobuf_log_unexpected(rbuf, __func__);
781 0 : goto error;
782 : }
783 : }
784 :
785 : // Otherwise, expecting to be told of a file to save.
786 69 : switch(rbuf->cmd)
787 : {
788 : case CMD_DATAPTH:
789 4 : iobuf_move(&rb->protocol1->datapth, rbuf);
790 4 : return STR_OK;
791 : case CMD_ATTRIBS:
792 8 : iobuf_move(&rb->attr, rbuf);
793 8 : attribs_decode(rb);
794 8 : return STR_OK;
795 : case CMD_GEN:
796 5 : if(!strcmp(rbuf->buf, "okbackupphase2end"))
797 : goto end_phase2;
798 0 : iobuf_log_unexpected(rbuf, __func__);
799 0 : goto error;
800 : case CMD_INTERRUPT:
801 : // Interrupt - forget about the last requested
802 : // file if it matches. Otherwise, we can get
803 : // stuck on the select in the async stuff,
804 : // waiting for something that will never arrive.
805 44 : if(*last_requested
806 44 : && !strcmp(rbuf->buf, *last_requested))
807 1 : free_w(last_requested);
808 : return STR_OK;
809 : default:
810 : break;
811 : }
812 8 : if(iobuf_is_filedata(rbuf)
813 0 : || iobuf_is_vssdata(rbuf))
814 : {
815 8 : if(deal_with_filedata(asfd, sdirs, rb, rbuf, dpth, cconfs))
816 : goto error;
817 : return STR_OK;
818 : }
819 0 : iobuf_log_unexpected(rbuf, __func__);
820 :
821 : error:
822 : return STR_ERROR;
823 : end_phase2:
824 : return STR_FINISHED;
825 : }
826 :
827 5 : static int vss_opts_changed(struct sdirs *sdirs, struct conf **cconfs,
828 : const char *incexc)
829 : {
830 5 : int ret=-1;
831 : struct conf **oldconfs;
832 : struct conf **newconfs;
833 5 : if(!(oldconfs=confs_alloc())
834 5 : || !(newconfs=confs_alloc()))
835 : goto end;
836 5 : confs_init(oldconfs);
837 5 : confs_init(newconfs);
838 :
839 : // Figure out the old config, which is in the incexc file left
840 : // in the current backup directory on the server.
841 5 : if(conf_parse_incexcs_path(oldconfs, sdirs->cincexc))
842 : {
843 : // Assume that the file did not exist, and therefore
844 : // the old split_vss setting is 0.
845 4 : set_int(oldconfs[OPT_SPLIT_VSS], 0);
846 4 : set_int(oldconfs[OPT_STRIP_VSS], 0);
847 : }
848 :
849 : // Figure out the new config, which is either in the incexc file from
850 : // the client, or in the cconf on the server.
851 5 : if(incexc)
852 : {
853 0 : if(conf_parse_incexcs_buf(newconfs, incexc))
854 : {
855 : // Should probably not got here.
856 0 : set_int(newconfs[OPT_SPLIT_VSS], 0);
857 0 : set_int(newconfs[OPT_STRIP_VSS], 0);
858 : }
859 : }
860 : else
861 : {
862 5 : set_int(newconfs[OPT_SPLIT_VSS],
863 5 : get_int(cconfs[OPT_SPLIT_VSS]));
864 5 : set_int(newconfs[OPT_STRIP_VSS],
865 5 : get_int(cconfs[OPT_STRIP_VSS]));
866 : }
867 :
868 5 : if(get_int(newconfs[OPT_SPLIT_VSS])!=get_int(oldconfs[OPT_SPLIT_VSS]))
869 : {
870 0 : logp("split_vss=%d (changed since last backup)\n",
871 0 : get_int(newconfs[OPT_SPLIT_VSS]));
872 0 : ret=1; goto end;
873 : }
874 5 : if(get_int(newconfs[OPT_STRIP_VSS])!=get_int(oldconfs[OPT_STRIP_VSS]))
875 : {
876 0 : logp("strip_vss=%d (changed since last backup)\n",
877 0 : get_int(newconfs[OPT_STRIP_VSS]));
878 0 : ret=1; goto end;
879 : }
880 : ret=0;
881 : end:
882 5 : if(ret==1) logp("All files will be treated as new\n");
883 5 : confs_free(&oldconfs);
884 5 : confs_free(&newconfs);
885 5 : return ret;
886 : }
887 :
888 : // Maybe open the previous (current) manifest.
889 : // If the split_vss setting changed between the previous backup and the new
890 : // backup, do not open the previous manifest. This will have the effect of
891 : // making the client back up everything fresh. Need to do this, otherwise
892 : // toggling split_vss on and off will result in backups that do not work.
893 5 : static int maybe_open_previous_manifest(struct manio **manio,
894 : struct sdirs *sdirs, const char *incexc, struct conf **cconfs)
895 : {
896 5 : if(vss_opts_changed(sdirs, cconfs, incexc))
897 : return 0;
898 5 : return open_previous_manifest(manio, sdirs);
899 : }
900 :
901 135 : static int process_next_file_from_manios(struct asfd *asfd,
902 : struct sdirs *sdirs,
903 : struct manio **p1manio,
904 : struct manio **cmanio,
905 : struct manio *ucmanio,
906 : struct manio **hmanio,
907 : struct sbuf **p1b,
908 : struct sbuf *cb,
909 : struct conf **cconfs)
910 : {
911 135 : if(!(*p1b=sbuf_alloc(PROTO_1)))
912 : goto error;
913 135 : switch(manio_read(*p1manio, *p1b))
914 : {
915 : case 0:
916 : break;
917 : case 1:
918 5 : manio_close(p1manio);
919 5 : if(asfd->write_str(asfd, CMD_GEN, "backupphase2end"))
920 : goto error;
921 5 : sbuf_free(p1b);
922 5 : break;
923 : case -1:
924 : goto error;
925 : }
926 :
927 135 : if(!*cmanio)
928 : {
929 124 : if(!*p1b) return 0;
930 : // No old manifest, need to ask for a new file.
931 120 : switch(process_new(cconfs, *p1b, ucmanio))
932 : {
933 : case P_NEW:
934 : return 0;
935 : case P_DONE_NEW:
936 : goto p1b_done;
937 : default:
938 : goto error;
939 : }
940 : }
941 :
942 : // Have an old manifest, look for it there.
943 :
944 : // Might already have it, or be ahead in the old
945 : // manifest.
946 11 : if(cb->path.buf)
947 : {
948 2 : switch(maybe_process_file(asfd,
949 : sdirs, cb, *p1b, ucmanio, hmanio, cconfs))
950 : {
951 : case P_NEW:
952 : return 0;
953 : case P_CHANGED:
954 : // Free cb content for things like encrypted
955 : // files, which we only pretend are new.
956 0 : sbuf_free_content(cb);
957 0 : return 0;
958 : case P_DONE_NEW:
959 : goto p1b_done;
960 : case P_DONE_CHANGED:
961 : case P_DONE_UNCHANGED:
962 0 : sbuf_free_content(cb);
963 0 : goto p1b_done;
964 : case P_DONE_DELETED:
965 2 : sbuf_free_content(cb);
966 2 : break;
967 : case P_ERROR:
968 : goto error;
969 : }
970 : }
971 :
972 : while(1)
973 : {
974 11 : sbuf_free_content(cb);
975 11 : switch(manio_read(*cmanio, cb))
976 : {
977 : case 0: break;
978 1 : case 1: manio_close(cmanio);
979 1 : if(*p1b) switch(process_new(cconfs,
980 : *p1b, ucmanio))
981 : {
982 : case P_NEW:
983 : return 0;
984 : case P_DONE_NEW:
985 : goto p1b_done;
986 : default:
987 : goto error;
988 : }
989 : return 0;
990 : case -1: goto error;
991 : }
992 10 : switch(maybe_process_file(asfd, sdirs,
993 : cb, *p1b, ucmanio, hmanio, cconfs))
994 : {
995 : case P_NEW:
996 : return 0;
997 : case P_CHANGED:
998 : // Free cb content for things like encrypted
999 : // files, which we only pretend are new.
1000 2 : sbuf_free_content(cb);
1001 2 : return 0;
1002 : case P_DONE_NEW:
1003 : goto p1b_done;
1004 : case P_DONE_CHANGED:
1005 : case P_DONE_UNCHANGED:
1006 6 : sbuf_free_content(cb);
1007 6 : goto p1b_done;
1008 : case P_DONE_DELETED:
1009 0 : sbuf_free_content(cb);
1010 0 : continue;
1011 : case P_ERROR:
1012 : goto error;
1013 : }
1014 : }
1015 : error:
1016 : return -1;
1017 : p1b_done:
1018 74 : sbuf_free(p1b);
1019 74 : return 0;
1020 : }
1021 :
1022 10 : int backup_phase2_server_protocol1(struct async *as, struct sdirs *sdirs,
1023 : const char *incexc, int resume, struct conf **cconfs)
1024 : {
1025 10 : int ret=0;
1026 10 : man_off_t *p1pos=NULL;
1027 10 : struct manio *p1manio=NULL;
1028 10 : struct dpth *dpth=NULL;
1029 10 : char *deltmppath=NULL;
1030 10 : char *last_requested=NULL;
1031 10 : struct manio *chmanio=NULL; // changed data
1032 10 : struct manio *ucmanio=NULL; // unchanged data
1033 10 : struct manio *cmanio=NULL; // previous (current) manifest
1034 10 : struct manio *hmanio=NULL; // to look up deleted hardlinks
1035 10 : struct sbuf *cb=NULL; // file list in current manifest
1036 10 : struct sbuf *p1b=NULL; // file list from client
1037 10 : struct sbuf *rb=NULL; // receiving file from client
1038 10 : struct asfd *asfd=NULL;
1039 10 : int breaking=0;
1040 10 : int breakcount=0;
1041 10 : struct cntr *cntr=NULL;
1042 :
1043 10 : if(!as)
1044 : {
1045 1 : logp("async not provided to %s()\n", __func__);
1046 1 : goto error;
1047 : }
1048 9 : if(!sdirs)
1049 : {
1050 2 : logp("sdirs not provided to %s()\n", __func__);
1051 2 : goto error;
1052 : }
1053 7 : if(!cconfs)
1054 : {
1055 1 : logp("cconfs not provided to %s()\n", __func__);
1056 1 : goto error;
1057 : }
1058 6 : asfd=as->asfd;
1059 6 : if(!asfd)
1060 : {
1061 1 : logp("asfd not provided to %s()\n", __func__);
1062 1 : goto error;
1063 : }
1064 5 : cntr=get_cntr(cconfs);
1065 :
1066 5 : if(get_int(cconfs[OPT_BREAKPOINT])>=2000
1067 0 : && get_int(cconfs[OPT_BREAKPOINT])<3000)
1068 : {
1069 0 : breaking=get_int(cconfs[OPT_BREAKPOINT]);
1070 0 : breakcount=breaking-2000;
1071 : }
1072 :
1073 5 : logp("Begin phase2 (receive file data)\n");
1074 :
1075 5 : if(!(dpth=dpth_alloc())
1076 5 : || dpth_protocol1_init(dpth, sdirs->currentdata,
1077 : get_int(cconfs[OPT_MAX_STORAGE_SUBDIRS])))
1078 : goto error;
1079 :
1080 5 : if(maybe_open_previous_manifest(&cmanio, sdirs, incexc, cconfs))
1081 : goto error;
1082 : // If the first file that others hardlink to has been deleted, we will
1083 : // need to look through the previous manifest to find the information
1084 : // for that original file, in order to not have to copy all the data
1085 : // across again.
1086 5 : if(open_previous_manifest(&hmanio, sdirs))
1087 : goto error;
1088 :
1089 5 : if(get_int(cconfs[OPT_DIRECTORY_TREE]))
1090 : {
1091 : // Need to make sure we do not try to create a path that is
1092 : // too long.
1093 5 : if(build_path_w(sdirs->treepath)) goto error;
1094 5 : mkdir(sdirs->treepath, 0777);
1095 5 : treepathlen=strlen(sdirs->treepath);
1096 5 : if(init_fs_max(sdirs->treepath))
1097 : goto error;
1098 : }
1099 :
1100 5 : if(resume)
1101 : {
1102 0 : if(!(p1pos=do_resume(sdirs, dpth, cconfs)))
1103 : goto error;
1104 0 : if(cntr_send_sdirs(asfd, sdirs, cconfs))
1105 : goto error;
1106 : }
1107 :
1108 5 : if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", PROTO_1))
1109 5 : || (resume && manio_seek(p1manio, p1pos)))
1110 : goto error;
1111 5 : if(!(cb=sbuf_alloc(PROTO_1))
1112 5 : || !(p1b=sbuf_alloc(PROTO_1))
1113 5 : || !(rb=sbuf_alloc(PROTO_1)))
1114 : goto error;
1115 :
1116 : // Unchanged and changed should now be truncated correctly, we just
1117 : // have to open them for appending.
1118 : // Data is not getting written to a compressed file.
1119 : // This is important for recovery if the power goes.
1120 5 : if(!(ucmanio=manio_open_phase2(sdirs->unchanged, "ab", PROTO_1))
1121 5 : || !(chmanio=manio_open_phase2(sdirs->changed, "ab", PROTO_1)))
1122 : goto error;
1123 :
1124 : while(1)
1125 : {
1126 921 : if(breaking && breakcount--==0)
1127 0 : return breakpoint(breaking, __func__);
1128 :
1129 921 : if(write_status(CNTR_STATUS_BACKUP,
1130 921 : rb->path.buf?rb->path.buf:"", cntr))
1131 : goto error;
1132 1842 : if(last_requested
1133 921 : || !p1manio
1134 16 : || asfd->writebuflen)
1135 : {
1136 905 : iobuf_free_content(asfd->rbuf);
1137 905 : if(asfd->as->read_write(asfd->as))
1138 : {
1139 0 : logp("error in %s\n", __func__);
1140 0 : goto error;
1141 : }
1142 :
1143 905 : if(asfd->rbuf->buf)
1144 85 : switch(do_stuff_to_receive(asfd, sdirs,
1145 : cconfs, rb, chmanio, dpth, &last_requested))
1146 : {
1147 : case STR_OK:
1148 : break;
1149 : case STR_FINISHED:
1150 : goto end;
1151 : case STR_ERROR:
1152 : goto error;
1153 : }
1154 : }
1155 :
1156 916 : if(p1b) switch(do_stuff_to_send(asfd, p1b, &last_requested))
1157 : {
1158 : case STS_OK:
1159 61 : sbuf_free(&p1b);
1160 61 : break;
1161 : case STS_BLOCKED:
1162 2 : continue;
1163 : case STS_ERROR:
1164 : goto error;
1165 : }
1166 :
1167 914 : if(p1manio
1168 135 : && process_next_file_from_manios(asfd, sdirs,
1169 : &p1manio, &cmanio, ucmanio, &hmanio, &p1b, cb, cconfs))
1170 : goto error;
1171 : }
1172 :
1173 : error:
1174 : ret=-1;
1175 : end:
1176 10 : if(manio_close(&chmanio))
1177 : {
1178 0 : logp("error closing %s in %s\n", sdirs->changed, __func__);
1179 0 : ret=-1;
1180 : }
1181 10 : if(manio_close(&ucmanio))
1182 : {
1183 0 : logp("error closing %s in %s\n", sdirs->unchanged, __func__);
1184 0 : ret=-1;
1185 : }
1186 10 : free_w(&deltmppath);
1187 10 : free_w(&last_requested);
1188 10 : sbuf_free(&cb);
1189 10 : sbuf_free(&p1b);
1190 10 : sbuf_free(&rb);
1191 10 : manio_close(&p1manio);
1192 10 : manio_close(&cmanio);
1193 10 : manio_close(&hmanio);
1194 10 : dpth_free(&dpth);
1195 10 : man_off_t_free(&p1pos);
1196 10 : if(!ret && sdirs)
1197 5 : unlink(sdirs->phase1data);
1198 :
1199 10 : logp("End phase2 (receive file data)\n");
1200 :
1201 10 : return ret;
1202 : }
|