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