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; }
/* These receive_a_file() and send_file() functions are for use by extra_comms and the CA stuff, rather than backups/restores. */ int receive_a_file(struct asfd *asfd, const char *path, struct conf **confs) { int ret=-1; BFILE *bfd=NULL; unsigned long long rcvdbytes=0; unsigned long long sentbytes=0; if(!(bfd=bfile_alloc())) goto end; bfile_init(bfd, 0, confs); #ifdef HAVE_WIN32 bfd->set_win32_api(bfd, 0); #endif if(bfd->open(bfd, asfd, path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR)) { berrno be; berrno_init(&be); logp("Could not open for writing %s: %s\n", path, berrno_bstrerror(&be, errno)); goto end; } ret=transfer_gzfile_in(asfd, path, bfd, &rcvdbytes, &sentbytes, confs); if(bfd->close(bfd, asfd)) { logp("error closing %s in receive_a_file\n", path); goto end; } logp("Received: %s\n", path); ret=0; end: bfd->close(bfd, asfd); bfile_free(&bfd); return ret; }
int do_restore_client(struct asfd *asfd, struct conf **confs, enum action act, int vss_restore) { int ret=-1; char msg[512]=""; struct sbuf *sb=NULL; struct blk *blk=NULL; BFILE *bfd=NULL; char *fullpath=NULL; char *style=NULL; char *datpath=NULL; struct cntr *cntr=get_cntr(confs); enum protocol protocol=get_protocol(confs); int strip=get_int(confs[OPT_STRIP]); int overwrite=get_int(confs[OPT_OVERWRITE]); const char *backup=get_string(confs[OPT_BACKUP]); const char *regex=get_string(confs[OPT_REGEX]); const char *restore_prefix=get_string(confs[OPT_RESTOREPREFIX]); const char *encryption_password=get_string(confs[OPT_ENCRYPTION_PASSWORD]); if(!(bfd=bfile_alloc())) goto end; bfile_init(bfd, 0, cntr); snprintf(msg, sizeof(msg), "%s %s:%s", act_str(act), backup?backup:"", regex?regex:""); logp("doing %s\n", msg); if(asfd->write_str(asfd, CMD_GEN, msg) || asfd_read_expect(asfd, CMD_GEN, "ok")) goto error; logp("doing %s confirmed\n", act_str(act)); #if defined(HAVE_WIN32) if(act==ACTION_RESTORE) win32_enable_backup_privileges(); #endif if(!(style=get_restore_style(asfd, confs))) goto error; if(!strcmp(style, RESTORE_SPOOL)) { if(restore_spool(asfd, confs, &datpath)) goto error; } else logp("Streaming restore direct\n"); logf("\n"); if(get_int(confs[OPT_SEND_CLIENT_CNTR]) && cntr_recv(asfd, confs)) goto error; if(!(sb=sbuf_alloc(protocol)) || (protocol==PROTO_2 && !(blk=blk_alloc()))) { log_and_send_oom(asfd, __func__); goto error; } while(1) { sbuf_free_content(sb); if(protocol==PROTO_1) sb->flags |= SBUF_CLIENT_RESTORE_HACK; switch(sbuf_fill_from_net(sb, asfd, blk, datpath, cntr)) { case 0: break; case 1: if(asfd->write_str(asfd, CMD_GEN, "restoreend ok")) goto error; goto end; // It was OK. default: case -1: goto error; } if(protocol==PROTO_2) { if(blk->data) { int wret=0; if(act==ACTION_VERIFY) cntr_add(cntr, CMD_DATA, 1); else wret=write_data(asfd, bfd, blk); if(!datpath) blk_free_content(blk); blk->data=NULL; if(wret) goto error; continue; } else if(sb->endfile.buf) { continue; } } switch(sb->path.cmd) { case CMD_DIRECTORY: case CMD_FILE: case CMD_ENC_FILE: case CMD_SOFT_LINK: case CMD_HARD_LINK: case CMD_SPECIAL: case CMD_METADATA: case CMD_ENC_METADATA: case CMD_VSS: case CMD_ENC_VSS: case CMD_VSS_T: case CMD_ENC_VSS_T: case CMD_EFS_FILE: if(strip) { int s; s=strip_path_components(asfd, sb, strip, cntr, protocol); if(s<0) goto error; if(s==0) { // Too many components stripped // - carry on. continue; } // It is OK, sb.path is now stripped. } free_w(&fullpath); if(!(fullpath=prepend_s(restore_prefix, sb->path.buf))) { log_and_send_oom(asfd, __func__); goto error; } if(act==ACTION_RESTORE) { strip_invalid_characters(&fullpath); if(!overwrite_ok(sb, overwrite, #ifdef HAVE_WIN32 bfd, #endif fullpath)) { char msg[512]=""; // Something exists at that path. snprintf(msg, sizeof(msg), "Path exists: %s\n", fullpath); if(restore_interrupt(asfd, sb, msg, cntr, protocol)) goto error; continue; } } break; case CMD_MESSAGE: case CMD_WARNING: log_recvd(&sb->path, cntr, 1); logf("\n"); continue; default: break; } switch(sb->path.cmd) { // These are the same in both protocol1 and protocol2. case CMD_DIRECTORY: if(restore_dir(asfd, sb, fullpath, act, cntr, protocol)) goto error; continue; case CMD_SOFT_LINK: case CMD_HARD_LINK: if(restore_link(asfd, sb, fullpath, act, cntr, protocol, restore_prefix)) goto error; continue; case CMD_SPECIAL: if(restore_special(asfd, sb, fullpath, act, cntr, protocol)) goto error; continue; default: break; } if(protocol==PROTO_2) { if(restore_switch_protocol2(asfd, sb, fullpath, act, bfd, vss_restore, cntr)) goto error; } else { if(restore_switch_protocol1(asfd, sb, fullpath, act, bfd, vss_restore, cntr, encryption_password)) goto error; } } end: ret=0; error: // It is possible for a fd to still be open. bfd->close(bfd, asfd); bfile_free(&bfd); cntr_print_end(cntr); cntr_print(cntr, act); if(!ret) logp("%s finished\n", act_str(act)); else logp("ret: %d\n", ret); sbuf_free(&sb); free_w(&style); if(datpath) { recursive_delete(datpath); free_w(&datpath); } free_w(&fullpath); blk_free(&blk); return ret; }