static void setup_reads_from_slist_blks(struct asfd *asfd, int *ar, struct slist *slist, int number_of_blks, uint64_t interrupt) { struct sbuf *s; struct blk blk; struct iobuf iobuf; uint64_t file_no=1; if(!slist) return; for(s=slist->head; s; s=s->next) { if(sbuf_is_filedata(s) && !sbuf_is_encrypted(s)) // Not working for proto2 yet. { int b; if(interrupt==file_no++) continue; blk_to_iobuf_sig(&blk, &iobuf); for(b=0; b<number_of_blks; b++) { iobuf_from_str(&iobuf, CMD_DATA, (char *)"some data"); asfd_mock_read_iobuf(asfd, ar, 0, &iobuf); } } } }
static void setup_chfd_reads_from_slist_blks_not_got(struct asfd *chfd, int *cr, struct slist *slist, int number_of_blks, uint64_t interrupt) { int blk_index=1; uint64_t file_no=1; struct blk blk; struct iobuf iobuf; struct sbuf *s; if(!slist) return; for(s=slist->head; s; s=s->next) { if(sbuf_is_filedata(s) && !sbuf_is_encrypted(s)) // Not working for proto2 yet. { int b; if(interrupt==file_no++) continue; for(b=0; b<number_of_blks; b++) { blk.index=blk_index++; blk_to_iobuf_wrap_up(&blk, &iobuf); asfd_mock_read_iobuf(chfd, cr, 0, &iobuf); } } } }
static void setup_writes_from_slist_blk_requests(struct asfd *asfd, int *aw, struct slist *slist, int number_of_blks, uint64_t interrupt) { struct sbuf *s; struct iobuf iobuf; char req[32]=""; int blk_index=1; uint64_t file_no=1; if(!slist) return; for(s=slist->head; s; s=s->next) { if(sbuf_is_filedata(s) && !sbuf_is_encrypted(s)) // Not working for proto2 yet. { int b; if(interrupt==file_no++) continue; for(b=0; b<number_of_blks; b++) { base64_from_uint64(blk_index++, req); iobuf_from_str(&iobuf, CMD_DATA_REQ, req); asfd_assert_write_iobuf(asfd, aw, 0, &iobuf); } } } }
static void setup_asfds_proto1_stuff(struct asfd *asfd, struct slist *slist) { int r=0; int w=0; struct sbuf *s; for(s=slist->head; s; s=s->next) { if(sbuf_is_link(s)) { asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); asfd_assert_write_iobuf(asfd, &w, 0, &s->link); } else if(sbuf_is_filedata(s)) { struct iobuf wbuf; // The string "data" gzipped. unsigned char gzipped_data1[10] = { 0x1f, 0x8b, 0x08, 0, 0, 0, 0, 0, 0x02, 0x03 }; unsigned char gzipped_data2[14] = { 0x4b, 0x49, 0x2c, 0x49, 0x04, 0x00, 0x63, 0xf3, 0xf3, 0xad, 0x04, 0x00, 0x00, 0x00 }; asfd_assert_write_iobuf(asfd, &w, 0, &s->protocol1->datapth); asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); if(sbuf_is_encrypted(s)) { // Encrypted files get sent as is. asfd_assert_write(asfd, &w, 0, CMD_APPEND, "data"); asfd_assert_write(asfd, &w, 0, CMD_END_FILE, "4:8d777f385d3dfec8815d20f7496026dc"); continue; } // Protocol1 always sends it gzipped. iobuf_set(&wbuf, CMD_APPEND, (char *)gzipped_data1, sizeof(gzipped_data1)); asfd_assert_write_iobuf(asfd, &w, 0, &wbuf); iobuf_set(&wbuf, CMD_APPEND, (char *)gzipped_data2, sizeof(gzipped_data2)); asfd_assert_write_iobuf(asfd, &w, 0, &wbuf); asfd_assert_write(asfd, &w, 0, CMD_END_FILE, "4:8d777f385d3dfec8815d20f7496026dc"); } else { asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); } } asfd_assert_write(asfd, &w, 0, CMD_GEN, "restoreend"); asfd_mock_read_no_op(asfd, &r, 100); asfd_mock_read(asfd, &r, 0, CMD_GEN, "restoreend_ok"); }
static int send_file(struct asfd *asfd, struct sbuf *sb, int patches, const char *best, uint64_t *bytes, struct cntr *cntr) { int ret=0; static BFILE *bfd=NULL; if(!bfd && !(bfd=bfile_alloc())) return -1; bfile_init(bfd, 0, cntr); if(bfd->open_for_send(bfd, asfd, best, sb->winattr, 1 /* no O_NOATIME */, cntr, PROTO_1)) return -1; //logp("sending: %s\n", best); if(asfd->write(asfd, &sb->path)) ret=-1; else if(patches) { // If we did some patches, the resulting file // is not gzipped. Gzip it during the send. ret=send_whole_file_gzl(asfd, best, sb->protocol1->datapth.buf, 1, bytes, NULL, cntr, 9, bfd, NULL, 0); } else { // If it was encrypted, it may or may not have been compressed // before encryption. Send it as it as, and let the client // sort it out. if(sbuf_is_encrypted(sb)) { ret=send_whole_filel(asfd, sb->path.cmd, best, sb->protocol1->datapth.buf, 1, bytes, cntr, bfd, NULL, 0); } // It might have been stored uncompressed. Gzip it during // the send. If the client knew what kind of file it would be // receiving, this step could disappear. else if(!dpth_protocol1_is_compressed(sb->compression, sb->protocol1->datapth.buf)) { ret=send_whole_file_gzl(asfd, best, sb->protocol1->datapth.buf, 1, bytes, NULL, cntr, 9, bfd, NULL, 0); } else { // If we did not do some patches, the resulting // file might already be gzipped. Send it as it is. ret=send_whole_filel(asfd, sb->path.cmd, best, sb->protocol1->datapth.buf, 1, bytes, cntr, bfd, NULL, 0); } } bfd->close(bfd, asfd); return ret; }
static void setup_writes_from_slist(struct asfd *asfd, int *aw, struct slist *slist) { struct sbuf *s; if(!slist) return; for(s=slist->head; s; s=s->next) { if(sbuf_is_filedata(s) && !sbuf_is_encrypted(s)) // Not working for proto2 yet. { asfd_assert_write(asfd, aw, 0, s->path.cmd, s->path.buf); } } }
static void setup_reads_from_slist(struct asfd *asfd, int *ar, struct slist *slist, int number_of_blks, uint64_t interrupt) { int file_no=1; struct sbuf *s; struct blk blk; struct iobuf iobuf; if(!slist) return; for(s=slist->head; s; s=s->next) { if(sbuf_is_filedata(s) && !sbuf_is_encrypted(s)) // Not working for proto2 yet. { int b; s->protocol2->index=file_no++; if(interrupt==s->protocol2->index) { char buf[32]=""; asfd_mock_read(asfd, ar, 0, CMD_WARNING, "path vanished\n"); base64_from_uint64(interrupt, buf); asfd_mock_read(asfd, ar, 0, CMD_INTERRUPT, buf); continue; } iobuf_free_content(&s->attr); attribs_encode(s); asfd_mock_read(asfd, ar, 0, CMD_ATTRIBS_SIGS, s->attr.buf); blk.fingerprint=file_no; memset(&blk.md5sum, file_no, MD5_DIGEST_LENGTH); blk_to_iobuf_sig(&blk, &iobuf); for(b=0; b<number_of_blks; b++) asfd_mock_read_iobuf(asfd, ar, 0, &iobuf); } } }
static void setup_chfd_writes_from_slist(struct asfd *chfd, int *cw, struct slist *slist, int number_of_blks, uint64_t interrupt) { struct sbuf *s; struct blk blk; struct iobuf iobuf; uint64_t file_no=1; if(!slist) return; for(s=slist->head; s; s=s->next) { if(sbuf_is_filedata(s) && !sbuf_is_encrypted(s)) // Not working for proto2 yet. { int b; if(interrupt==file_no++) continue; blk.fingerprint=file_no; memset(&blk.md5sum, file_no, MD5_DIGEST_LENGTH); blk_to_iobuf_sig(&blk, &iobuf); for(b=0; b<number_of_blks; b++) asfd_assert_write_iobuf(chfd, cw, 0, &iobuf); } } }
static int do_restore_file_or_get_meta(struct asfd *asfd, BFILE *bfd, struct sbuf *sb, const char *fname, char **metadata, size_t *metalen, struct cntr *cntr, const char *rpath, const char *encryption_password) { int ret=-1; int enccompressed=0; uint64_t rcvdbytes=0; uint64_t sentbytes=0; const char *encpassword=NULL; if(sbuf_is_encrypted(sb)) encpassword=encryption_password; enccompressed=dpth_protocol1_is_compressed(sb->compression, sb->protocol1->datapth.buf); /* printf("%s \n", fname); if(encpassword && !enccompressed) printf("encrypted and not compressed\n"); else if(!encpassword && enccompressed) printf("not encrypted and compressed\n"); else if(!encpassword && !enccompressed) printf("not encrypted and not compressed\n"); else if(encpassword && enccompressed) printf("encrypted and compressed\n"); */ if(metadata) { ret=transfer_gzfile_inl(asfd, sb, fname, NULL, &rcvdbytes, &sentbytes, encpassword, enccompressed, cntr, metadata); *metalen=sentbytes; // skip setting cntr, as we do not actually // restore until a bit later goto end; } else { ret=transfer_gzfile_inl(asfd, sb, fname, bfd, &rcvdbytes, &sentbytes, encpassword, enccompressed, cntr, NULL); #ifndef HAVE_WIN32 if(bfd && bfd->close(bfd, asfd)) { logp("error closing %s in %s\n", fname, __func__); goto end; } #endif if(!ret) attribs_set(asfd, rpath, &sb->statp, sb->winattr, cntr); } ret=0; end: if(ret) { char msg[256]=""; snprintf(msg, sizeof(msg), "Could not transfer file in: %s", rpath); if(restore_interrupt(asfd, sb, msg, cntr, PROTO_1)) ret=-1; } return ret; }
static int maybe_do_delta_stuff(struct asfd *asfd, struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b, struct manio *ucmanio, struct conf **cconfs) { int oldcompressed=0; int compression=p1b->compression; // If the file type changed, I think it is time to back it up again // (for example, EFS changing to normal file, or back again). if(cb->path.cmd!=p1b->path.cmd) return process_new_file(sdirs, cconfs, cb, p1b, ucmanio); // mtime is the actual file data. // ctime is the attributes or meta data. if(cb->statp.st_mtime==p1b->statp.st_mtime && cb->statp.st_ctime==p1b->statp.st_ctime) { // got an unchanged file //logp("got unchanged file: %s %c %c\n", // cb->path.buf, cb->path.cmd, p1b->path.cmd); return process_unchanged_file(p1b, cb, ucmanio, cconfs); } if(cb->statp.st_mtime==p1b->statp.st_mtime && cb->statp.st_ctime!=p1b->statp.st_ctime) { // File data stayed the same, but attributes or meta data // changed. We already have the attributes, but may need to get // extra meta data. // FIX THIS horrible mess. if(cb->path.cmd==CMD_ENC_METADATA || p1b->path.cmd==CMD_ENC_METADATA || cb->path.cmd==CMD_EFS_FILE || p1b->path.cmd==CMD_EFS_FILE // FIX THIS: make unencrypted metadata use the librsync || cb->path.cmd==CMD_METADATA || p1b->path.cmd==CMD_METADATA || sbuf_is_vssdata(cb) || sbuf_is_vssdata(p1b)) return process_new_file(sdirs, cconfs, cb, p1b, ucmanio); // On Windows, we have to back up the whole file if ctime // changed, otherwise things like permission changes do not get // noticed. So, in that case, fall through to the changed stuff // below. // Non-Windows clients finish here. else if(!get_int(cconfs[OPT_CLIENT_IS_WINDOWS])) return process_unchanged_file(p1b, cb, ucmanio, cconfs); } // Got a changed file. //logp("got changed file: %s\n", p1b->path.buf); // If either old or new is encrypted, or librsync is off, we need to // get a new file. // FIX THIS horrible mess. if(!get_int(cconfs[OPT_LIBRSYNC]) // FIX THIS: make unencrypted metadata use the librsync || cb->path.cmd==CMD_METADATA || p1b->path.cmd==CMD_METADATA || sbuf_is_encrypted(cb) || sbuf_is_encrypted(p1b) || sbuf_is_vssdata(cb) || sbuf_is_vssdata(p1b)) return process_new_file(sdirs, cconfs, cb, p1b, ucmanio); // Get new files if they have switched between compression on or off. if(cb->protocol1->datapth.buf && dpth_protocol1_is_compressed(cb->compression, cb->protocol1->datapth.buf)) oldcompressed=1; if( ( oldcompressed && !compression) || (!oldcompressed && compression)) return process_new_file(sdirs, cconfs, cb, p1b, ucmanio); // Otherwise, do the delta stuff (if possible). if(sbuf_is_filedata(p1b) || sbuf_is_vssdata(p1b)) { if(process_changed_file(asfd, sdirs, cconfs, cb, p1b, sdirs->currentdata)) return -1; } else { if(changed_non_file(p1b, ucmanio, p1b->path.cmd, cconfs)) return -1; } sbuf_free_content(cb); return 1; }
static int do_send_file(struct asfd *asfd, struct sbuf *sb, int patches, const char *best, struct cntr *cntr) { enum send_e ret=SEND_FATAL; struct BFILE bfd; uint64_t bytes=0; // Unused. bfile_init(&bfd, 0, cntr); if(bfd.open_for_send(&bfd, asfd, best, sb->winattr, 1 /* no O_NOATIME */, cntr, PROTO_1)) return SEND_FATAL; if(asfd->write(asfd, &sb->path)) ret=SEND_FATAL; else if(patches) { // If we did some patches, the resulting file // is not gzipped. Gzip it during the send. ret=send_whole_file_gzl( asfd, sb->protocol1->datapth.buf, /*quick_read*/1, &bytes, /*encpassword*/NULL, cntr, /*compression*/9, &bfd, /*extrameta*/NULL, /*elen*/0, /*key_deriv*/ENCRYPTION_UNSET, /*salt*/0 ); } else { // If it was encrypted, it may or may not have been compressed // before encryption. Send it as it as, and let the client // sort it out. if(sbuf_is_encrypted(sb)) { ret=send_whole_filel(asfd, #ifdef HAVE_WIN32 sb->path.cmd #endif sb->protocol1->datapth.buf, 1, &bytes, cntr, &bfd, NULL, 0); } // It might have been stored uncompressed. Gzip it during // the send. If the client knew what kind of file it would be // receiving, this step could disappear. else if(!dpth_protocol1_is_compressed(sb->compression, sb->protocol1->datapth.buf)) { ret=send_whole_file_gzl( asfd, sb->protocol1->datapth.buf, /*quick_read*/1, &bytes, /*encpassword*/NULL, cntr, /*compression*/9, &bfd, /*extrameta*/NULL, /*elen*/0, /*key_deriv*/ENCRYPTION_UNSET, /*salt*/0 ); } else { // If we did not do some patches, the resulting // file might already be gzipped. Send it as it is. ret=send_whole_filel(asfd, #ifdef HAVE_WIN32 sb->path.cmd #endif sb->protocol1->datapth.buf, 1, &bytes, cntr, &bfd, NULL, 0); } } bfd.close(&bfd, asfd); switch(ret) { case SEND_OK: case SEND_ERROR: // Carry on. return 0; case SEND_FATAL: default: return -1; } }