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