static int do_backup_phase2_client(struct asfd *asfd, struct conf *conf, int resume) { int ret=-1; // For efficiency, open Windows files for the VSS data, and do not // close them until another time around the loop, when the actual // data is read. BFILE bfd; // Windows VSS headers tell us how much file // data to expect. size_t datalen=0; #ifdef HAVE_WIN32 binit(&bfd, 0, conf); #endif struct sbuf *sb=NULL; struct iobuf *rbuf=asfd->rbuf; if(!(sb=sbuf_alloc(conf))) goto end; if(!resume) { // Only do this bit if the server did not tell us to resume. if(asfd->write_str(asfd, CMD_GEN, "backupphase2") || asfd->read_expect(asfd, CMD_GEN, "ok")) goto end; } else if(conf->send_client_cntr) { // On resume, the server might update the client with cntr. if(cntr_recv(asfd, conf)) goto end; } while(1) { iobuf_free_content(rbuf); if(asfd->read(asfd)) goto end; else if(!rbuf->buf) continue; if(rbuf->cmd==CMD_GEN && !strcmp(rbuf->buf, "backupphase2end")) { if(asfd->write_str(asfd, CMD_GEN, "okbackupphase2end")) goto end; ret=0; break; } if(parse_rbuf(asfd, sb, &bfd, &datalen, conf)) goto end; } end: #ifdef HAVE_WIN32 // It is possible for a bfd to still be open. close_file_for_sendl(&bfd, NULL, asfd); #endif iobuf_free_content(rbuf); sbuf_free(sb); return ret; }
int backup_phase2_client_protocol2(struct asfd *asfd, struct conf **confs, int resume) { int ret=-1; uint8_t end_flags=0; struct slist *slist=NULL; struct iobuf *rbuf=NULL; struct iobuf *wbuf=NULL; struct cntr *cntr=NULL; if(confs) cntr=get_cntr(confs); if(!asfd || !asfd->as) { logp("%s() called without async structs!\n", __func__); goto end; } logp("Phase 2 begin (send backup data)\n"); logfmt("\n"); if(!(slist=slist_alloc()) || !(wbuf=iobuf_alloc()) || blks_generate_init()) goto end; rbuf=asfd->rbuf; if(!resume) { // Only do this bit if the server did not tell us to resume. if(asfd->write_str(asfd, CMD_GEN, "backupphase2") || asfd_read_expect(asfd, CMD_GEN, "ok")) goto end; } else { // On resume, the server might update the client with cntr. if(cntr_recv(asfd, confs)) goto end; } while(!(end_flags&END_BACKUP)) { if(!wbuf->len) { get_wbuf_from_data(confs, wbuf, slist, end_flags); if(!wbuf->len) { if(get_wbuf_from_blks(wbuf, slist, &end_flags)) goto end; } } if(wbuf->len) { if(asfd->append_all_to_write_buffer(asfd, wbuf) ==APPEND_ERROR) goto end; } if(asfd->as->read_write(asfd->as)) { logp("error in %s\n", __func__); goto end; } if(rbuf->buf && deal_with_read(rbuf, slist, cntr, &end_flags)) goto end; if(slist->head // Need to limit how many blocks are allocated at once. && (!slist->blist->head || slist->blist->tail->index - slist->blist->head->index<BLKS_MAX_IN_MEM) ) { if(add_to_blks_list(asfd, confs, slist)) goto end; } if(end_flags&END_BLK_REQUESTS) { // If got to the end of the file request list // and the last block of the last file, and // the write buffer is empty, we got to the end. if(slist->head==slist->tail) { if(!slist->tail || slist->blist->last_sent== slist->tail->protocol2->bend) { if(!wbuf->len) break; } } } } if(asfd->write_str(asfd, CMD_GEN, "backup_end")) goto end; ret=0; end: slist_free(&slist); blks_generate_free(); if(wbuf) { // Write buffer did not allocate 'buf'. wbuf->buf=NULL; iobuf_free(&wbuf); } cntr_print_end(cntr); cntr_print(cntr, ACTION_BACKUP, asfd); if(ret) logp("Error in backup\n"); logp("End backup\n"); 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; }
int backup_phase2_client_burp2(struct asfd *asfd, struct conf *conf, int resume) { int ret=-1; int sigs_end=0; int backup_end=0; int requests_end=0; int blk_requests_end=0; struct win *win=NULL; // Rabin sliding window. struct slist *slist=NULL; struct blist *blist=NULL; struct iobuf *rbuf=NULL; struct iobuf *wbuf=NULL; logp("Phase 2 begin (send backup data)\n"); if(!(slist=slist_alloc()) || !(blist=blist_alloc()) || !(wbuf=iobuf_alloc()) || blks_generate_init(conf) || !(win=win_alloc(&conf->rconf))) goto end; rbuf=asfd->rbuf; if(!resume) { // Only do this bit if the server did not tell us to resume. if(asfd->write_str(asfd, CMD_GEN, "backupphase2") || asfd->read_expect(asfd, CMD_GEN, "ok")) goto end; } else if(conf->send_client_cntr) { // On resume, the server might update the client with the // counters. if(cntr_recv(asfd, conf)) goto end; } while(!backup_end) { if(!wbuf->len) { get_wbuf_from_data(conf, wbuf, slist, blist, blk_requests_end); if(!wbuf->len) { get_wbuf_from_blks(wbuf, slist, requests_end, &sigs_end); } } if(wbuf->len) asfd->append_all_to_write_buffer(asfd, wbuf); if(asfd->as->read_write(asfd->as)) { logp("error in %s\n", __func__); goto end; } if(rbuf->buf && deal_with_read(rbuf, slist, blist, conf, &backup_end, &requests_end, &blk_requests_end)) goto end; if(slist->head // Need to limit how many blocks are allocated at once. && (!blist->head || blist->tail->index - blist->head->index<BLKS_MAX_IN_MEM) ) { if(add_to_blks_list(asfd, conf, slist, blist, win)) goto end; } if(blk_requests_end) { // If got to the end of the file request list // and the last block of the last file, and // the write buffer is empty, we got to the end. if(slist->head==slist->tail) { if(!slist->tail || blist->last_sent==slist->tail->burp2->bend) { if(!wbuf->len) break; } } } } if(asfd->write_str(asfd, CMD_GEN, "backup_end")) goto end; ret=0; end: blk_print_alloc_stats(); //sbuf_print_alloc_stats(); win_free(win); slist_free(&slist); blist_free(&blist); // Write buffer did not allocate 'buf'. wbuf->buf=NULL; iobuf_free(&wbuf); cntr_print_end(conf->cntr); cntr_print(conf->cntr, ACTION_BACKUP); if(ret) logp("Error in backup\n"); logp("End backup\n"); return ret; }