// return -1 for error, 0 for OK, 1 if the client wants to interrupt the // transfer. int do_quick_read(struct asfd *asfd, const char *datapth, struct conf **confs) { int r=0; struct iobuf *rbuf; if(asfd->as->read_quick(asfd->as)) return -1; rbuf=asfd->rbuf; if(rbuf->buf) { if(rbuf->cmd==CMD_MESSAGE || rbuf->cmd==CMD_WARNING) { log_recvd(rbuf, confs, 0); } else if(rbuf->cmd==CMD_INTERRUPT) { // Client wants to interrupt - double check that // it is still talking about the file that we are // sending. if(datapth && !strcmp(rbuf->buf, datapth)) r=1; } else { iobuf_log_unexpected(rbuf, __func__); r=-1; } iobuf_free_content(rbuf); } return r; }
static int get_meta( struct asfd *asfd, struct cntr *cntr, char **metadata, size_t *metalen) { int ret=-1; struct iobuf *rbuf=asfd->rbuf; while(1) { iobuf_free_content(rbuf); if(asfd->read(asfd)) goto end; switch(rbuf->cmd) { case CMD_DATA: if(!(*metadata=(char *)realloc_w(*metadata, (*metalen)+rbuf->len, __func__))) goto end; memcpy((*metadata)+(*metalen), rbuf->buf, rbuf->len); *metalen+=rbuf->len; break; case CMD_END_FILE: ret=0; goto end; case CMD_MESSAGE: case CMD_WARNING: log_recvd(rbuf, cntr, 0); break; default: iobuf_log_unexpected(rbuf, __func__); goto end; } } end: iobuf_free_content(rbuf); return ret; }
static int deal_with_read(struct iobuf *rbuf, struct slist *slist, struct cntr *cntr, uint8_t *end_flags, struct dpth *dpth) { int ret=0; switch(rbuf->cmd) { /* Incoming block data. */ case CMD_DATA: if(add_data_to_store(cntr, slist, rbuf, dpth)) goto error; goto end; /* Incoming block signatures. */ case CMD_ATTRIBS_SIGS: static struct iobuf attr; static uint64_t index; iobuf_init(&attr); iobuf_move(&attr, rbuf); index=decode_file_no(&attr); // Need to go through slist to find the matching // entry. if(set_up_for_sig_info(slist, &attr, index)) goto error; return 0; case CMD_SIG: if(add_to_sig_list(slist, rbuf)) goto error; goto end; /* Incoming control/message stuff. */ case CMD_MESSAGE: case CMD_WARNING: { struct cntr *cntr=NULL; log_recvd(rbuf, cntr, 0); goto end; } case CMD_GEN: if(!strcmp(rbuf->buf, "sigs_end")) { (*end_flags)|=END_SIGS; goto end; } else if(!strcmp(rbuf->buf, "backup_end")) { (*end_flags)|=END_BACKUP; goto end; } break; case CMD_INTERRUPT: { uint64_t file_no; file_no=base64_to_uint64(rbuf->buf); if(slist_del_sbuf_by_index(slist, file_no)) goto error; goto end; } default: break; } iobuf_log_unexpected(rbuf, __func__); error: ret=-1; end: iobuf_free_content(rbuf); return ret; }
static int deal_with_read(struct iobuf *rbuf, struct slist *slist, struct cntr *cntr, uint8_t *end_flags) { int ret=0; switch(rbuf->cmd) { /* Incoming file request. */ case CMD_FILE: case CMD_METADATA: if(add_to_file_requests(slist, rbuf)) goto error; return 0; /* Incoming data block request. */ case CMD_DATA_REQ: if(add_to_data_requests(slist->blist, rbuf)) goto error; goto end; /* Incoming control/message stuff. */ case CMD_WRAP_UP: { int64_t wrap_up; struct blk *blk; struct blist *blist=slist->blist; from_base64(&wrap_up, rbuf->buf); for(blk=blist->head; blk; blk=blk->next) { if(blk->index==(uint64_t)wrap_up) { blist->last_requested=blk; blist->last_sent=blk; break; } } if(!blk) { logp("Could not find wrap up index: %016" PRIX64 "\n", wrap_up); // goto error; } goto end; } case CMD_MESSAGE: case CMD_WARNING: { log_recvd(rbuf, cntr, 0); goto end; } case CMD_GEN: if(!strcmp(rbuf->buf, "requests_end")) { (*end_flags)|=END_REQUESTS; goto end; } else if(!strcmp(rbuf->buf, "blk_requests_end")) { (*end_flags)|=END_BLK_REQUESTS; goto end; } else if(!strcmp(rbuf->buf, "backup_end")) { (*end_flags)|=END_BACKUP; goto end; } break; default: break; } iobuf_log_unexpected(rbuf, __func__); error: ret=-1; end: iobuf_free_content(rbuf); 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; }
// returns 1 for finished ok. static int do_stuff_to_receive(struct asfd *asfd, struct sdirs *sdirs, struct conf **cconfs, struct sbuf *rb, struct fzp *chfp, struct dpth *dpth, char **last_requested) { struct iobuf *rbuf=asfd->rbuf; iobuf_free_content(rbuf); // This also attempts to write anything in the write buffer. if(asfd->as->read_write(asfd->as)) { logp("error in %s\n", __func__); return -1; } if(!rbuf->buf) return 0; if(rbuf->cmd==CMD_MESSAGE || rbuf->cmd==CMD_WARNING) { log_recvd(rbuf, cconfs, 0); return 0; } if(rb->protocol1->fzp) { // Currently writing a file (or meta data) switch(rbuf->cmd) { case CMD_APPEND: if(deal_with_receive_append(asfd, rb, cconfs)) goto error; return 0; case CMD_END_FILE: if(deal_with_receive_end_file(asfd, sdirs, rb, chfp, cconfs, last_requested)) goto error; return 0; default: iobuf_log_unexpected(rbuf, __func__); goto error; } } // Otherwise, expecting to be told of a file to save. switch(rbuf->cmd) { case CMD_DATAPTH: iobuf_move(&rb->protocol1->datapth, rbuf); return 0; case CMD_ATTRIBS: iobuf_move(&rb->attr, rbuf); return 0; case CMD_GEN: if(!strcmp(rbuf->buf, "okbackupphase2end")) goto end_phase2; iobuf_log_unexpected(rbuf, __func__); goto error; case CMD_INTERRUPT: // Interrupt - forget about the last requested // file if it matches. Otherwise, we can get // stuck on the select in the async stuff, // waiting for something that will never arrive. if(*last_requested && !strcmp(rbuf->buf, *last_requested)) free_w(last_requested); return 0; default: break; } if(cmd_is_filedata(rbuf->cmd)) { if(deal_with_filedata(asfd, sdirs, rb, rbuf, dpth, cconfs)) goto error; return 0; } iobuf_log_unexpected(rbuf, __func__); error: return -1; end_phase2: return 1; }
int transfer_gzfile_inl(struct asfd *asfd, struct sbuf *sb, const char *path, BFILE *bfd, uint64_t *rcvd, uint64_t *sent, const char *encpassword, int enccompressed, struct cntr *cntr, char **metadata) { int quit=0; int ret=-1; uint8_t out[ZCHUNK]; int doutlen=0; //uint8_t doutbuf[1000+EVP_MAX_BLOCK_LENGTH]; uint8_t doutbuf[ZCHUNK-EVP_MAX_BLOCK_LENGTH]; struct iobuf *rbuf=asfd->rbuf; z_stream zstrm; EVP_CIPHER_CTX *enc_ctx=NULL; // Checksum stuff //MD5_CTX md5; //uint8_t checksum[MD5_DIGEST_LENGTH]; #ifdef HAVE_WIN32 if(sb && sb->path.cmd==CMD_EFS_FILE) return transfer_efs_in(asfd, bfd, rcvd, sent, cntr); #endif //if(!MD5_Init(&md5)) //{ // logp("MD5_Init() failed"); // return -1; //} zstrm.zalloc=Z_NULL; zstrm.zfree=Z_NULL; zstrm.opaque=Z_NULL; zstrm.avail_in=0; zstrm.next_in=Z_NULL; if(inflateInit2(&zstrm, (15+16))) { logp("unable to init inflate\n"); return -1; } if(encpassword && !(enc_ctx=enc_setup(0, encpassword))) { inflateEnd(&zstrm); return -1; } while(!quit) { iobuf_free_content(rbuf); if(asfd->read(asfd)) { if(enc_ctx) { EVP_CIPHER_CTX_cleanup(enc_ctx); free(enc_ctx); } inflateEnd(&zstrm); return -1; } (*rcvd)+=rbuf->len; //logp("transfer in: %c:%s\n", rbuf->cmd, rbuf->buf); switch(rbuf->cmd) { case CMD_APPEND: // append if(!bfd && !metadata) { logp("given append, but no file or metadata to write to\n"); asfd->write_str(asfd, CMD_ERROR, "append with no file or metadata"); quit++; ret=-1; } else { size_t lentouse; uint8_t *buftouse=NULL; /* if(!MD5_Update(&md5, rbuf->buf, rbuf->len)) { logp("MD5 update enc error\n"); quit++; ret=-1; break; } */ // If doing decryption, it needs // to be done before uncompressing. if(enc_ctx) { // updating our checksum needs to // be done first /* if(!MD5_Update(&md5, rbuf->buf, rbuf->len)) { logp("MD5 update enc error\n"); quit++; ret=-1; break; } else */ if(!EVP_CipherUpdate(enc_ctx, doutbuf, &doutlen, (uint8_t *)rbuf->buf, rbuf->len)) { logp("Decryption error\n"); quit++; ret=-1; break; } if(!doutlen) break; lentouse=(size_t)doutlen; buftouse=doutbuf; } else { lentouse=rbuf->len; buftouse=(uint8_t *)rbuf->buf; } //logp("want to write: %d\n", zstrm.avail_in); if(do_inflate(asfd, &zstrm, bfd, out, buftouse, lentouse, metadata, encpassword, enccompressed, sent)) { ret=-1; quit++; break; } } break; case CMD_END_FILE: // finish up if(enc_ctx) { if(!EVP_CipherFinal_ex(enc_ctx, doutbuf, &doutlen)) { logp("Decryption failure at the end.\n"); ret=-1; quit++; break; } if(doutlen && do_inflate(asfd, &zstrm, bfd, out, doutbuf, (size_t)doutlen, metadata, encpassword, enccompressed, sent)) { ret=-1; quit++; break; } } /* if(MD5_Final(checksum, &md5)) { char *oldsum=NULL; const char *newsum=NULL; if((oldsum=strchr(buf, ':'))) { oldsum++; newsum=bytes_to_md5str(checksum); // log if the checksum differed if(strcmp(newsum, oldsum)) logw(asfd, cntr, "md5sum for '%s' did not match! (%s!=%s)\n", path, newsum, oldsum); } } else { logp("MD5_Final() failed\n"); } */ quit++; ret=0; break; case CMD_MESSAGE: case CMD_WARNING: log_recvd(rbuf, cntr, 0); break; default: iobuf_log_unexpected(rbuf, __func__); quit++; ret=-1; break; } } inflateEnd(&zstrm); if(enc_ctx) { EVP_CIPHER_CTX_cleanup(enc_ctx); free(enc_ctx); } iobuf_free_content(rbuf); if(ret) logp("transfer file returning: %d\n", ret); return ret; }
static int deal_with_read(struct iobuf *rbuf, struct slist *slist, struct cntr *cntr, uint8_t *end_flags, struct dpth *dpth) { int ret=0; static struct sbuf *inew=NULL; if(!inew && !(inew=sbuf_alloc(PROTO_2))) goto error; switch(rbuf->cmd) { /* Incoming block data. */ case CMD_DATA: if(add_data_to_store(cntr, slist, rbuf, dpth)) goto error; goto end; /* Incoming block signatures. */ case CMD_ATTRIBS_SIGS: // New set of stuff incoming. Clean up. iobuf_free_content(&inew->attr); iobuf_move(&inew->attr, rbuf); inew->protocol2->index=decode_file_no(&inew->attr); // Need to go through slist to find the matching // entry. if(set_up_for_sig_info(slist, inew)) goto error; return 0; case CMD_SIG: if(add_to_sig_list(slist, rbuf)) goto error; goto end; /* Incoming control/message stuff. */ case CMD_MESSAGE: case CMD_WARNING: { struct cntr *cntr=NULL; log_recvd(rbuf, cntr, 0); goto end; } case CMD_GEN: if(!strcmp(rbuf->buf, "sigs_end")) { (*end_flags)|=END_SIGS; goto end; } else if(!strcmp(rbuf->buf, "backup_end")) { (*end_flags)|=END_BACKUP; goto end; } break; default: break; } iobuf_log_unexpected(rbuf, __func__); error: ret=-1; sbuf_free(&inew); end: iobuf_free_content(rbuf); return ret; }
static enum parse_ret parse_cmd(struct sbuf *sb, struct asfd *asfd, struct iobuf *rbuf, struct blk *blk, struct cntr *cntr) { switch(rbuf->cmd) { case CMD_ATTRIBS: if(sb->protocol2) sbuf_free_content(sb); else { if(sb->protocol1->datapth.buf) // protocol 1 phase 2+ file data // starts with datapth. iobuf_free_content(&sb->attr); else // protocol 1 phase 1 or non file data // starts with attribs sbuf_free_content(sb); } iobuf_move(&sb->attr, rbuf); attribs_decode(sb); return PARSE_RET_NEED_MORE; case CMD_FILE: case CMD_DIRECTORY: case CMD_SOFT_LINK: case CMD_HARD_LINK: case CMD_SPECIAL: // Stuff not currently supported in burp-2, but OK // to find in burp-1. case CMD_ENC_FILE: case CMD_METADATA: case CMD_ENC_METADATA: case CMD_EFS_FILE: case CMD_VSS: case CMD_ENC_VSS: case CMD_VSS_T: case CMD_ENC_VSS_T: if(!sb->attr.buf) { log_and_send(asfd, "read cmd with no attribs"); return PARSE_RET_ERROR; } if(sb->flags & SBUF_NEED_LINK) { if(cmd_is_link(rbuf->cmd)) { iobuf_free_content(&sb->link); iobuf_move(&sb->link, rbuf); sb->flags &= ~SBUF_NEED_LINK; return PARSE_RET_COMPLETE; } else { log_and_send(asfd, "got non-link after link in manifest"); return PARSE_RET_NEED_MORE; } } else { iobuf_free_content(&sb->path); iobuf_move(&sb->path, rbuf); if(cmd_is_link(rbuf->cmd)) { sb->flags |= SBUF_NEED_LINK; return PARSE_RET_NEED_MORE; } else if(sb->protocol1 && sb->protocol1->datapth.buf) { // Protocol1 client restore reads // CMD_APPEND and CMD_END_FILE in the // calling function, so pretend it is // complete if we have the hack flag. if(sb->flags & SBUF_CLIENT_RESTORE_HACK) return PARSE_RET_COMPLETE; return PARSE_RET_NEED_MORE; } return PARSE_RET_COMPLETE; } #ifndef HAVE_WIN32 case CMD_SIG: // Fill in the sig/block, if the caller provided // a pointer for one. Server only. if(!blk) return PARSE_RET_NEED_MORE; // Just fill in the sig details. if(blk_set_from_iobuf_sig_and_savepath(blk, rbuf)) return PARSE_RET_ERROR; blk->got_save_path=1; iobuf_free_content(rbuf); return PARSE_RET_COMPLETE; #endif case CMD_DATA: // Need to write the block to disk. // Client only. if(!blk) return PARSE_RET_NEED_MORE; blk->data=rbuf->buf; blk->length=rbuf->len; rbuf->buf=NULL; return PARSE_RET_COMPLETE; case CMD_MESSAGE: case CMD_WARNING: log_recvd(rbuf, cntr, 1); return PARSE_RET_NEED_MORE; case CMD_GEN: if(!strcmp(rbuf->buf, "restoreend") || !strcmp(rbuf->buf, "phase1end") || !strcmp(rbuf->buf, "backupphase2") // Think these are protocol1 things. || !strcmp(rbuf->buf, "backupend") || !strcmp(rbuf->buf, "estimateend")) return PARSE_RET_FINISHED; iobuf_log_unexpected(rbuf, __func__); return PARSE_RET_ERROR; case CMD_FINGERPRINT: if(blk && blk_set_from_iobuf_fingerprint(blk, rbuf)) return PARSE_RET_ERROR; // Fall through. case CMD_MANIFEST: iobuf_free_content(&sb->path); iobuf_move(&sb->path, rbuf); return PARSE_RET_COMPLETE; case CMD_ERROR: logp("got error: %s\n", rbuf->buf); return PARSE_RET_ERROR; case CMD_DATAPTH: if(!sb->protocol1) { iobuf_log_unexpected(rbuf, __func__); return PARSE_RET_ERROR; } if(sb->flags & SBUF_CLIENT_RESTORE_HACK) { sbuf_free_content(sb); sb->flags |= SBUF_CLIENT_RESTORE_HACK; } else sbuf_free_content(sb); iobuf_move(&sb->protocol1->datapth, rbuf); return PARSE_RET_NEED_MORE; case CMD_END_FILE: iobuf_free_content(&sb->endfile); iobuf_move(&sb->endfile, rbuf); if(sb->protocol1) { if(!sb->attr.buf || !sb->protocol1->datapth.buf || (!sbuf_is_filedata(sb) && !sbuf_is_vssdata(sb))) { logp("got unexpected cmd_endfile"); return PARSE_RET_ERROR; } } return PARSE_RET_COMPLETE; default: iobuf_log_unexpected(rbuf, __func__); return PARSE_RET_ERROR; } logp("Fell out of switch unexpectedly in %s()\n", __func__); return PARSE_RET_ERROR; }
static int restore_stream(struct asfd *asfd, struct sdirs *sdirs, struct slist *slist, struct bu *bu, const char *manifest, regex_t *regex, int srestore, struct conf **cconfs, enum action act, enum cntr_status cntr_status) { int ret=-1; int last_ent_was_dir=0; struct sbuf *sb=NULL; struct iobuf *rbuf=asfd->rbuf; struct manio *manio=NULL; struct blk *blk=NULL; struct sbuf *need_data=NULL; enum protocol protocol=get_protocol(cconfs); struct cntr *cntr=get_cntr(cconfs); if(protocol==PROTO_2) { if(asfd->write_str(asfd, CMD_GEN, "restore_stream") || asfd->read_expect(asfd, CMD_GEN, "restore_stream_ok") || !(blk=blk_alloc())) goto end; } if(!(manio=manio_open(manifest, "rb", protocol)) || !(need_data=sbuf_alloc(protocol)) || !(sb=sbuf_alloc(protocol))) goto end; while(1) { iobuf_free_content(rbuf); if(asfd->as->read_quick(asfd->as)) { logp("read quick error\n"); goto end; } if(rbuf->buf) switch(rbuf->cmd) { case CMD_MESSAGE: case CMD_WARNING: { log_recvd(rbuf, cntr, 0); continue; } case CMD_INTERRUPT: // Client wanted to interrupt the // sending of a file. But if we are // here, we have already moved on. // Ignore. continue; default: iobuf_log_unexpected(rbuf, __func__); goto end; } switch(manio_read_with_blk(manio, sb, need_data->path.buf?blk:NULL, sdirs)) { case 0: break; // Keep going. case 1: ret=0; goto end; // Finished OK. default: goto end; // Error; } if(protocol==PROTO_2) { if(sb->endfile.buf) { sbuf_free_content(sb); continue; } if(blk->data) { if(protocol2_extra_restore_stream_bits(asfd, blk, slist, act, need_data, last_ent_was_dir, cntr)) goto end; continue; } sbuf_free_content(need_data); } if(want_to_restore(srestore, sb, regex, cconfs)) { if(restore_ent(asfd, &sb, slist, bu, act, sdirs, cntr_status, cconfs, need_data, &last_ent_was_dir, manifest)) goto end; } else if(sbuf_is_filedata(sb) || sbuf_is_vssdata(sb)) { // Add it to the list of filedata that was not // restored. struct f_link **bucket=NULL; if(!linkhash_search(&sb->statp, &bucket) && linkhash_add(sb->path.buf, &sb->statp, bucket)) goto end; } sbuf_free_content(sb); } end: blk_free(&blk); sbuf_free(&sb); sbuf_free(&need_data); iobuf_free_content(rbuf); manio_close(&manio); return ret; }
int transfer_gzfile_in(struct asfd *asfd, const char *path, BFILE *bfd, uint64_t *rcvd, uint64_t *sent, struct cntr *cntr) { int quit=0; int ret=-1; uint8_t out[ZCHUNK]; struct iobuf *rbuf=asfd->rbuf; z_stream zstrm; zstrm.zalloc=Z_NULL; zstrm.zfree=Z_NULL; zstrm.opaque=Z_NULL; zstrm.avail_in=0; zstrm.next_in=Z_NULL; if(inflateInit2(&zstrm, (15+16))) { logp("unable to init inflate\n"); goto end; } while(!quit) { iobuf_free_content(rbuf); if(asfd->read(asfd)) goto end_inflate; (*rcvd)+=rbuf->len; //logp("transfer in: %c:%s\n", rbuf->cmd, rbuf->buf); switch(rbuf->cmd) { case CMD_APPEND: // append if(!bfd) { logp("given append, but no file to write to\n"); asfd->write_str(asfd, CMD_ERROR, "append with no file"); goto end_inflate; } else { if(do_inflate(asfd, &zstrm, bfd, out, sent)) goto end_inflate; } break; case CMD_END_FILE: // finish up goto end_ok; case CMD_MESSAGE: case CMD_WARNING: { struct cntr *cntr=NULL; log_recvd(rbuf, cntr, 0); break; } default: iobuf_log_unexpected(rbuf, __func__); goto end_inflate; } } end_ok: ret=0; end_inflate: inflateEnd(&zstrm); end: if(ret) logp("transfer file returning: %d\n", ret); iobuf_free_content(rbuf); return ret; }