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