int async_rw_ensure_write(char *rcmd, char **rdst, size_t *rlen, char wcmd, const char *wsrc, size_t wlen) { size_t w=wlen; if(doing_estimate) return 0; while(w) if(async_rw(rcmd, rdst, rlen, wcmd, wsrc, &w)) return -1; return 0; }
int async_read_quick(char *rcmd, char **rdst, size_t *rlen) { int r; size_t w=0; int savesec=setsec; int saveusec=setusec; setsec=0; setusec=0; r=async_rw(rcmd, rdst, rlen, '\0', NULL, &w); setsec=savesec; setusec=saveusec; return r; }
static int load_signature_and_send_delta(BFILE *bfd, FILE *in, unsigned long long *bytes, unsigned long long *sentbytes, struct cntr *cntr, size_t datalen) { rs_job_t *job; rs_result r; rs_signature_t *sumset=NULL; unsigned char checksum[MD5_DIGEST_LENGTH+1]; rs_filebuf_t *infb=NULL; rs_filebuf_t *outfb=NULL; rs_buffers_t rsbuf; memset(&rsbuf, 0, sizeof(rsbuf)); if(load_signature(&sumset, cntr)) return -1; //logp("start delta\n"); if(!(job=rs_delta_begin(sumset))) { logp("could not start delta job.\n"); rs_free_sumset(sumset); return RS_IO_ERROR; } if(!(infb=rs_filebuf_new(bfd, in, NULL, -1, ASYNC_BUF_LEN, datalen, cntr)) || !(outfb=rs_filebuf_new(NULL, NULL, NULL, async_get_fd(), ASYNC_BUF_LEN, -1, cntr))) { logp("could not rs_filebuf_new for delta\n"); if(infb) rs_filebuf_free(infb); return -1; } //logp("start delta loop\n"); while(1) { size_t wlen=0; rs_result delresult; delresult=rs_async(job, &rsbuf, infb, outfb); if(delresult==RS_DONE) { r=delresult; // logp("delresult done\n"); break; } else if(delresult==RS_BLOCKED || delresult==RS_RUNNING) { // logp("delresult running/blocked: %d\n", delresult); // Keep going } else { logp("error in rs_async for delta: %d\n", delresult); r=delresult; break; } // FIX ME: get it to read stuff (errors, for example) here too. if(async_rw(NULL, NULL, '\0', '\0', NULL, &wlen)) return -1; } if(r!=RS_DONE) logp("delta loop returned: %d\n", r); //logp("after delta loop: %d\n", r); //logp("\n"); if(r==RS_DONE) { *bytes=infb->bytes; *sentbytes=outfb->bytes; if(!MD5_Final(checksum, &(infb->md5))) { logp("MD5_Final() failed\n"); r=RS_IO_ERROR; } } rs_filebuf_free(infb); rs_filebuf_free(outfb); rs_job_free(job); rs_free_sumset(sumset); if(r==RS_DONE && write_endfile(*bytes, checksum)) // finish delta file return -1; //logp("end of load_sig_send_delta\n"); return r; }
// returns 1 for finished ok. static int do_stuff_to_receive(struct sbuf *rb, FILE *p2fp, const char *datadirtmp, struct dpth *dpth, const char *working, char **last_requested, const char *deltmppath, struct cntr *cntr, struct config *cconf) { int ret=0; char rcmd; size_t rlen=0; size_t wlen=0; char *rbuf=NULL; // This also attempts to write anything in the write buffer. if(async_rw(&rcmd, &rbuf, &rlen, '\0', NULL, &wlen)) { logp("error in async_rw\n"); return -1; } if(rbuf) { if(rcmd==CMD_WARNING) { logp("WARNING: %s\n", rbuf); do_filecounter(cntr, rcmd, 0); } else if(rb->fp || rb->zp) { // Currently writing a file (or meta data) if(rcmd==CMD_APPEND) { int app; //logp("rlen: %d\n", rlen); if((rb->zp && (app=gzwrite(rb->zp, rbuf, rlen))<=0) || (rb->fp && (app=fwrite(rbuf, 1, rlen, rb->fp))<=0)) { logp("error when appending: %d\n", app); async_write_str(CMD_ERROR, "write failed"); ret=-1; } do_filecounter_recvbytes(cntr, rlen); } else if(rcmd==CMD_END_FILE) { // Finished the file. // Write it to the phase2 file, and free the // buffers. if(close_fp(&(rb->fp))) { logp("error closing delta for %s in receive\n", rb->path); ret=-1; } if(gzclose_fp(&(rb->zp))) { logp("error gzclosing delta for %s in receive\n", rb->path); ret=-1; } rb->endfile=rbuf; rb->elen=rlen; rbuf=NULL; if(!ret && rb->receivedelta && finish_delta(rb, working, deltmppath)) ret=-1; else if(!ret) { if(sbuf_to_manifest(rb, p2fp, NULL)) ret=-1; else { char cmd=rb->cmd; if(rb->receivedelta) do_filecounter_changed(cntr, cmd); else do_filecounter(cntr, cmd, 0); if(*last_requested && !strcmp(rb->path, *last_requested)) { free(*last_requested); *last_requested=NULL; } } } if(!ret) { char *cp=NULL; cp=strchr(rb->endfile, ':'); if(rb->endfile) do_filecounter_bytes(cntr, strtoull(rb->endfile, NULL, 10)); if(cp) { // checksum stuff goes here } } free_sbuf(rb); } else { logp("unexpected cmd from client while writing file: %c %s\n", rcmd, rbuf); ret=-1; } } // Otherwise, expecting to be told of a file to save. else if(rcmd==CMD_DATAPTH) { rb->datapth=rbuf; rbuf=NULL; } else if(rcmd==CMD_STAT) { rb->statbuf=rbuf; rb->slen=rlen; rbuf=NULL; } else if(filedata(rcmd)) { rb->cmd=rcmd; rb->plen=rlen; rb->path=rbuf; rbuf=NULL; if(rb->datapth) { // Receiving a delta. if(start_to_receive_delta(rb, working, deltmppath, cconf)) { logp("error in start_to_receive_delta\n"); ret=-1; } } else { // Receiving a whole new file. if(start_to_receive_new_file(rb, datadirtmp, dpth, cntr, cconf)) { logp("error in start_to_receive_new_file\n"); ret=-1; } } } else if(rcmd==CMD_GEN && !strcmp(rbuf, "okbackupphase2end")) { ret=1; //logp("got okbackupphase2end\n"); } else if(rcmd==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, *last_requested)) { free(*last_requested); *last_requested=NULL; } } else { logp("unexpected cmd from client while expecting a file: %c %s\n", rcmd, rbuf); ret=-1; } if(rbuf) { free(rbuf); rbuf=NULL; } } //logp("returning: %d\n", ret); return ret; }