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