// Also used by restore.c. // FIX THIS: This stuff is very similar to make_rev_delta, can maybe share // some code. int do_patch(struct asfd *asfd, const char *dst, const char *del, const char *upd, bool gzupd, int compression) { struct fzp *dstp=NULL; struct fzp *delfzp=NULL; struct fzp *upfzp=NULL; rs_result result=RS_IO_ERROR; if(!(dstp=fzp_open(dst, "rb"))) goto end; if(!(delfzp=fzp_gzopen(del, "rb"))) goto end; if(gzupd) upfzp=fzp_gzopen(upd, comp_level(compression)); else upfzp=fzp_open(upd, "wb"); if(!upfzp) goto end; result=rs_patch_gzfile(dstp, delfzp, upfzp); end: fzp_close(&dstp); fzp_close(&delfzp); if(fzp_close(&upfzp)) { logp("error closing %s in %s\n", upd, __func__); result=RS_IO_ERROR; } return result; }
static int duplicate_file(const char *oldpath, const char *newpath) { int ret=-1; size_t s=0; size_t t=0; struct fzp *op=NULL; struct fzp *np=NULL; char buf[DUP_CHUNK]=""; if(!(op=fzp_open(oldpath, "rb")) || !(np=fzp_open(newpath, "wb"))) goto end; while((s=fzp_read(op, buf, DUP_CHUNK))>0) { t=fzp_write(np, buf, s); if(t!=s) { logp("could not write all bytes: %lu!=%lu\n", (unsigned long)s, (unsigned long)t); goto end; } } ret=0; end: fzp_close(&np); fzp_close(&op); if(ret) logp("could not duplicate %s to %s\n", oldpath, newpath); return ret; }
static int full_match(struct file *o, struct file *n, struct fzp **ofp, struct fzp **nfp) { size_t ogot; size_t ngot; unsigned int i=0; static char obuf[FULL_CHUNK]; static char nbuf[FULL_CHUNK]; if(*ofp) fzp_seek(*ofp, 0, SEEK_SET); else if(!(*ofp=fzp_open(o->path, "rb"))) { // Blank this entry so that it can be ignored from // now on. free_w(&o->path); return 0; } if(*nfp) fzp_seek(*nfp, 0, SEEK_SET); else if(!(*nfp=fzp_open(n->path, "rb"))) return 0; while(1) { ogot=fzp_read(*ofp, obuf, FULL_CHUNK); ngot=fzp_read(*nfp, nbuf, FULL_CHUNK); if(ogot!=ngot) return 0; for(i=0; i<ogot; i++) if(obuf[i]!=nbuf[i]) return 0; if(ogot<FULL_CHUNK) break; } return 1; }
static int make_rev_sig(const char *dst, const char *sig, const char *endfile, int compression, struct conf **confs) { int ret=-1; struct fzp *dstfzp=NULL; struct fzp *sigp=NULL; //logp("make rev sig: %s %s\n", dst, sig); if(dpth_protocol1_is_compressed(compression, dst)) dstfzp=fzp_gzopen(dst, "rb"); else dstfzp=fzp_open(dst, "rb"); if(!dstfzp || !(sigp=fzp_open(sig, "wb")) || rs_sig_gzfile(dstfzp, sigp, get_librsync_block_len(endfile), RS_DEFAULT_STRONG_LEN, confs)!=RS_DONE) goto end; ret=0; end: //logp("end of make rev sig\n"); fzp_close(&dstfzp); if(fzp_close(&sigp)) { logp("error closing %s in %s\n", sig, __func__); return -1; } return ret; }
static int make_rev_delta(const char *src, const char *sig, const char *del, int compression, struct conf **cconfs) { int ret=-1; rs_result result; struct fzp *srcfzp=NULL; struct fzp *delfzp=NULL; struct fzp *sigp=NULL; rs_signature_t *sumset=NULL; //logp("make rev delta: %s %s %s\n", src, sig, del); if(!(sigp=fzp_open(sig, "rb"))) goto end; if((result=rs_loadsig_fzp(sigp, &sumset))!=RS_DONE) { logp("rs_loadsig_fzp returned %d %s\n", result, rs_strerror(result)); goto end; } if((result=rs_build_hash_table(sumset))!=RS_DONE) { logp("rs_build_hash_table returned %d %s\n", result, rs_strerror(result)); goto end; } //logp("make rev deltb: %s %s %s\n", src, sig, del); if(dpth_protocol1_is_compressed(compression, src)) srcfzp=fzp_gzopen(src, "rb"); else srcfzp=fzp_open(src, "rb"); if(!srcfzp) goto end; if(get_int(cconfs[OPT_COMPRESSION])) delfzp=fzp_gzopen(del, comp_level(get_int(cconfs[OPT_COMPRESSION]))); else delfzp=fzp_open(del, "wb"); if(!delfzp) goto end; if((result=rs_delta_gzfile(sumset, srcfzp, delfzp))!=RS_DONE) { logp("rs_delta_gzfile returned %d %s\n", result, rs_strerror(result)); goto end; } ret=0; end: if(sumset) rs_free_sumset(sumset); fzp_close(&srcfzp); fzp_close(&sigp); if(fzp_close(&delfzp)) { logp("error closing delfzp %s in %s\n", del, __func__); ret=-1; } return ret; }
static int start_to_receive_new_file(struct asfd *asfd, struct sdirs *sdirs, struct conf **cconfs, struct sbuf *sb, struct dpth *dpth) { int ret=-1; char *rpath=NULL; int istreedata=0; //logp("start to receive: %s\n", sb->path.buf); if(!(rpath=set_new_datapth(asfd, sdirs, cconfs, sb, dpth, &istreedata))) goto end; if(!(sb->protocol1->fzp=fzp_open(rpath, "wb"))) { log_and_send(asfd, "make file failed"); goto end; } if(!istreedata) dpth_incr(dpth); ret=0; end: free_w(&rpath); return ret; }
int log_fzp_set(const char *path, struct conf **confs) { fzp_close(&logfzp); if(path) { logp("Logging to %s\n", path); if(!(logfzp=fzp_open(path, "ab"))) return -1; } if(logfzp) fzp_setlinebuf(logfzp); do_syslog=get_int(confs[OPT_SYSLOG]); if(force_quiet) { do_stdout=0; do_progress_counter=0; } else { do_stdout=get_int(confs[OPT_STDOUT]); do_progress_counter=get_int(confs[OPT_PROGRESS_COUNTER]); } if(syslog_opened) { closelog(); syslog_opened=0; } if(do_syslog) { openlog(prog, LOG_PID, LOG_USER); syslog_opened++; } return 0; }
struct slist *build_manifest_with_data_files(const char *path, const char *datapath, int entries, int data_files) { struct blk *b=NULL; struct slist *slist=NULL; struct manio *manio=NULL; struct fzp *fzp=NULL; char spath[256]=""; char cpath[256]=""; fail_unless((manio=manio_open_phase3(path, "wb", PROTO_2, RMANIFEST_RELATIVE))!=NULL); slist=do_build_manifest(manio, PROTO_2, entries, data_files); fail_unless(!manio_close(&manio)); for(b=slist->blist->head; b; b=b->next) { snprintf(spath, sizeof(spath), "%s/%s", datapath, uint64_to_savepathstr(b->savepath)); if(strcmp(spath, cpath)) { snprintf(cpath, sizeof(cpath), "%s", spath); fzp_close(&fzp); } if(!fzp) { fail_unless(!build_path_w(cpath)); fail_unless((fzp=fzp_open(cpath, "wb"))!=NULL); } fzp_printf(fzp, "%c%04X%s", CMD_DATA, strlen("data"), "data"); } fzp_close(&fzp); return slist; }
int manio_read_fcount(struct manio *manio) { int ret=-1; size_t s; struct fzp *fzp=NULL; char *path=NULL; char buf[16]=""; if(!(path=get_fcount_path(manio)) || !(fzp=fzp_open(path, "rb"))) goto end; if(!fzp_gets(fzp, buf, sizeof(buf))) { logp("fzp_gets on %s failed\n", path); goto end; } s=strlen(buf); if(s!=9) { logp("data in %s is not the right length (%s!=9)\n", s); goto end; } manio->offset->fcount=strtoul(buf, NULL, 16); ret=0; end: fzp_close(&fzp); free_w(&path); return ret; }
static int incexc_matches(const char *fullrealwork, const char *incexc) { int ret=0; int got=0; struct fzp *fzp=NULL; char buf[4096]=""; const char *inc=NULL; char *old_incexc_path=NULL; if(!(old_incexc_path=prepend_s(fullrealwork, "incexc"))) return -1; if(!(fzp=fzp_open(old_incexc_path, "rb"))) { // Assume that no incexc file could be found because the client // was on an old version. Assume resume is OK and return 1. ret=1; goto end; } inc=incexc; while((got=fzp_read(fzp, buf, sizeof(buf)))>0) { if(strlen(inc)<(size_t)got) break; if(strncmp(buf, inc, got)) break; inc+=got; } if(inc && strlen(inc)) ret=0; else ret=1; end: fzp_close(&fzp); free_w(&old_incexc_path); return ret; }
static int manio_open_next_fpath(struct manio *manio) { static struct stat statp; free_w(&manio->offset->fpath); if(!(manio->offset->fpath=get_next_fpath(manio, manio->offset))) return -1; if(!strcmp(manio->mode, MANIO_MODE_READ) && lstat(manio->offset->fpath, &statp)) return 0; if(build_path_w(manio->offset->fpath)) return -1; switch(manio->phase) { case 2: if(!(manio->fzp=fzp_open(manio->offset->fpath, manio->mode))) return -1; return 0; case 1: case 3: default: if(!(manio->fzp=fzp_gzopen(manio->offset->fpath, manio->mode))) return -1; return 0; } }
static int bcompress(const char *src, const char *dst, int compression) { int res; int got; struct fzp *sfzp=NULL; struct fzp *dfzp=NULL; char buf[ZCHUNK]; if(!(sfzp=fzp_open(src, "rb")) || !(dfzp=fzp_gzopen(dst, comp_level(compression)))) goto error; while((got=fzp_read(sfzp, buf, sizeof(buf)))>0) { res=fzp_write(dfzp, buf, got); if(res!=got) { logp("compressing %s - read %d but wrote %d\n", src, got, res); goto error; } } fzp_close(&sfzp); return fzp_close(&dfzp); error: fzp_close(&sfzp); fzp_close(&dfzp); return -1; }
int status_client_ncurses(struct conf **confs) { int ret=-1; int csin=-1; int csout=-1; pid_t childpid=-1; struct async *as=NULL; const char *monitor_logfile=get_string(confs[OPT_MONITOR_LOGFILE]); struct asfd *so_asfd=NULL; struct sel *sel=NULL; if(!(sel=sel_alloc())) goto end; setup_signals(); // Fork a burp child process that will contact the server over SSL. // We will read and write from and to its stdout and stdin. if((childpid=fork_monitor(&csin, &csout, confs))<0) goto end; //printf("childpid: %d\n", childpid); if(!(as=async_alloc()) || as->init(as, 0) || !setup_asfd_linebuf_write(as, "monitor stdin", &csin) || !setup_asfd_linebuf_read(as, "monitor stdout", &csout)) goto end; //printf("ml: %s\n", monitor_logfile); #ifdef HAVE_NCURSES if(actg==ACTION_STATUS) { if(!setup_asfd_ncurses_stdin(as)) goto end; ncurses_init(); } #endif if(!(so_asfd=setup_asfd_stdout(as))) goto end; if(monitor_logfile && !(lfzp=fzp_open(monitor_logfile, "wb"))) goto end; log_fzp_set_direct(lfzp); ret=status_client_ncurses_main_loop(as, so_asfd, sel, get_string(confs[OPT_ORIG_CLIENT])); end: #ifdef HAVE_NCURSES if(actg==ACTION_STATUS) ncurses_free(); #endif if(ret) logp("%s exiting with error: %d\n", __func__, ret); fzp_close(&lfzp); async_asfd_free_all(&as); close_fd(&csin); close_fd(&csout); sel_free(&sel); return ret; }
static int create_zero_length_file(const char *path) { int ret=0; struct fzp *dest; if(!(dest=fzp_open(path, "wb"))) ret=-1; ret|=fzp_close(&dest); return ret; }
static struct asfd *asfd_setup(const char *outputpath) { struct asfd *asfd; fail_unless((asfd=asfd_alloc())!=NULL); fail_unless((asfd->rbuf=iobuf_alloc())!=NULL); asfd->write=my_asfd_write; fail_unless(!build_path_w(outputpath)); fail_unless((output=fzp_open(outputpath, "wb"))!=NULL); json_set_pretty_print(1); return asfd; }
int zlib_inflate(struct asfd *asfd, const char *source_path, const char *dest_path, struct conf **confs) { int ret=-1; size_t b=0; uint8_t in[ZCHUNK]; struct fzp *src=NULL; struct fzp *dst=NULL; if(!(src=fzp_gzopen(source_path, "rb"))) { logw(asfd, confs, "could not gzopen %s in %s: %s\n", source_path, __func__, strerror(errno)); goto end; } if(!(dst=fzp_open(dest_path, "wb"))) { logw(asfd, confs, "could not open %s in %s: %s\n", dest_path, __func__, strerror(errno)); goto end; } while((b=fzp_read(src, in, ZCHUNK))>0) { if(fzp_write(dst, in, b)!=b) { logw(asfd, confs, "error when writing to %s\n", dest_path); goto end; } } if(!fzp_eof(src)) { logw(asfd, confs, "error while reading %s in %s\n", source_path, __func__); goto end; } if(fzp_close(&dst)) { logw(asfd, confs, "error when closing %s in %s: %s\n", dest_path, __func__, strerror(errno)); goto end; } ret=0; end: fzp_close(&src); fzp_close(&dst); return ret; }
END_TEST #define FULL_CHUNK 4096 static void do_assert_files_equal(const char *opath, const char *npath, int compressed) { size_t ogot; size_t ngot; unsigned int i=0; struct fzp *ofp; struct fzp *nfp; static char obuf[FULL_CHUNK]; static char nbuf[FULL_CHUNK]; if(compressed) { fail_unless((ofp=fzp_gzopen(opath, "rb"))!=NULL); fail_unless((nfp=fzp_gzopen(npath, "rb"))!=NULL); } else { fail_unless((ofp=fzp_open(opath, "rb"))!=NULL); fail_unless((nfp=fzp_open(npath, "rb"))!=NULL); } while(1) { ogot=fzp_read(ofp, obuf, FULL_CHUNK); ngot=fzp_read(nfp, nbuf, FULL_CHUNK); fail_unless(ogot==ngot); for(i=0; i<ogot; i++) fail_unless(obuf[i]==nbuf[i]); if(ogot<FULL_CHUNK) break; } fzp_close(&ofp); fzp_close(&nfp); }
static int start_to_receive_delta(struct sdirs *sdirs, struct conf **cconfs, struct sbuf *rb) { if(get_int(cconfs[OPT_COMPRESSION])) { if(!(rb->protocol1->fzp=fzp_gzopen(sdirs->deltmppath, comp_level(cconfs)))) return -1; } else { if(!(rb->protocol1->fzp=fzp_open(sdirs->deltmppath, "wb"))) return -1; } rb->flags |= SBUFL_RECV_DELTA; return 0; }
static int start_to_receive_delta(struct sdirs *sdirs, struct conf **cconfs, struct sbuf *rb) { if(rb->compression) { if(!(rb->protocol1->fzp=fzp_gzopen(sdirs->deltmppath, comp_level(rb->compression)))) return -1; } else { if(!(rb->protocol1->fzp=fzp_open(sdirs->deltmppath, "wb"))) return -1; } rb->flags |= SBUF_RECV_DELTA; return 0; }
static int load_rblk(struct rblk *rblks, int ind, const char *datpath) { int r; int ret=-1; int done=0; struct fzp *fzp=NULL; struct iobuf rbuf; iobuf_init(&rbuf); free_w(&rblks[ind].datpath); if(!(rblks[ind].datpath=strdup_w(datpath, __func__))) goto end; logp("swap %d to: %s\n", ind, datpath); if(!(fzp=fzp_open(datpath, "rb"))) goto end; for(r=0; r<DATA_FILE_SIG_MAX; r++) { switch(iobuf_fill_from_fzp_data(&rbuf, fzp)) { case 0: if(rbuf.cmd!=CMD_DATA) { logp("unknown cmd in %s: %c\n", __func__, rbuf.cmd); goto end; } iobuf_free_content(&rblks[ind].readbuf[r]); iobuf_move(&rblks[ind].readbuf[r], &rbuf); continue; case 1: done++; break; default: goto end; } if(done) break; } rblks[ind].readbuflen=r; ret=0; end: fzp_close(&fzp); return ret; }
static int get_part_cksum(struct file *f, struct fzp **fzp) { MD5_CTX md5; int got=0; static char buf[PART_CHUNK]; unsigned char checksum[MD5_DIGEST_LENGTH+1]; if(*fzp) fzp_seek(*fzp, 0, SEEK_SET); else if(!(*fzp=fzp_open(f->path, "rb"))) { f->part_cksum=0; return 0; } if(!MD5_Init(&md5)) { logp("MD5_Init() failed\n"); return -1; } got=fzp_read(*fzp, buf, PART_CHUNK); if(!MD5_Update(&md5, buf, got)) { logp("MD5_Update() failed\n"); return -1; } if(!MD5_Final(checksum, &md5)) { logp("MD5_Final() failed\n"); return -1; } memcpy(&(f->part_cksum), checksum, sizeof(unsigned)); // Try for a bit of efficiency - no need to calculate the full checksum // again if we already read the whole file. if(got<PART_CHUNK) f->full_cksum=f->part_cksum; return 0; }
static int write_incexc(const char *realworking, const char *incexc) { int ret=-1; struct fzp *fzp=NULL; char *path=NULL; if(!incexc || !*incexc) return 0; if(!(path=prepend_s(realworking, "incexc")) || !(fzp=fzp_open(path, "wb"))) goto end; fzp_printf(fzp, "%s", incexc); ret=0; end: if(fzp_close(&fzp)) { logp("error writing to %s in write_incexc\n", path); ret=-1; } free_w(&path); return ret; }
static int get_full_cksum(struct file *f, struct fzp **fzp) { size_t s=0; MD5_CTX md5; static char buf[FULL_CHUNK]; unsigned char checksum[MD5_DIGEST_LENGTH+1]; if(*fzp) fzp_seek(*fzp, 0, SEEK_SET); else if(!(*fzp=fzp_open(f->path, "rb"))) { f->full_cksum=0; return 0; } if(!MD5_Init(&md5)) { logp("MD5_Init() failed\n"); return -1; } while((s=fzp_read(*fzp, buf, FULL_CHUNK))>0) { if(!MD5_Update(&md5, buf, s)) { logp("MD5_Update() failed\n"); return -1; } if(s<FULL_CHUNK) break; } if(!MD5_Final(checksum, &md5)) { logp("MD5_Final() failed\n"); return -1; } memcpy(&(f->full_cksum), checksum, sizeof(unsigned)); return 0; }
END_TEST START_TEST(test_protocol1_verify_file_gzip_read_failure) { struct asfd *asfd; struct cntr *cntr; struct sbuf *sb; const char *path="somepath"; const char *datapth="/datapth"; const char *endfile="0:0"; const char *best=BASE "/existent"; const char *plain_text="some plain text"; size_t s; struct fzp *fzp; s=strlen(plain_text); clean(); cntr=setup_cntr(); sb=setup_sbuf(path, datapth, endfile, 1/*compression*/); // Make a corrupt gzipped file. build_path_w(best); fail_unless((fzp=fzp_gzopen(best, "wb"))!=NULL); fail_unless(fzp_write(fzp, plain_text, s)==s); fail_unless(!fzp_close(&fzp)); fail_unless((fzp=fzp_open(best, "r+b"))!=NULL); fail_unless(!fzp_seek(fzp, 10, SEEK_SET)); fail_unless(fzp_write(fzp, "aa", 2)==2); fail_unless(!fzp_close(&fzp)); asfd=asfd_mock_setup(&areads, &awrites); setup_error_while_reading(asfd, best); // Returns 0 so that the parent process continues. fail_unless(!verify_file(asfd, sb, 0 /*patches*/, best, cntr)); fail_unless(cntr->ent[CMD_WARNING]->count==1); tear_down(&sb, &cntr, NULL, &asfd); }
static int get_cname_from_ssl_cert(struct conf **c) { int ret=-1; struct fzp *fzp=NULL; X509 *cert=NULL; X509_NAME *subj=NULL; char *path=get_string(c[OPT_SSL_CERT]); const char *cn=NULL; if(!path || !(fzp=fzp_open(path, "rb"))) return 0; if(!(cert=fzp_PEM_read_X509(fzp))) { logp("unable to parse %s in: %s\n", path, __func__); goto end; } if(!(subj=X509_get_subject_name(cert))) { logp("unable to get subject from %s in: %s\n", path, __func__); goto end; } if(!(cn=extract_cn(subj))) { logp("could not get CN from %s\n", path); goto end; } if(set_string(c[OPT_CNAME], cn)) goto end; logp("cname from cert: %s\n", cn); ret=0; end: if(cert) X509_free(cert); fzp_close(&fzp); return ret; }
static int inflate_oldfile(const char *opath, const char *infpath, struct stat *statp, struct cntr *cntr) { int ret=0; if(!statp->st_size) { struct fzp *dest=NULL; // Empty file - cannot inflate. // just close the destination and we have duplicated a // zero length file. if(!(dest=fzp_open(infpath, "wb"))) goto end; logp("asked to inflate zero length file: %s\n", opath); if(fzp_close(&dest)) logp("error closing %s in %s\n", infpath, __func__); } else if(zlib_inflate(NULL, opath, infpath, cntr)) { logp("zlib_inflate returned error\n"); ret=-1; } end: return ret; }
// Backup phase4 needs to know the fcount, so leave a file behind that // contains it (otherwise phase4 will have to read and sort the directory // contents). static int manio_write_fcount(struct manio *manio) { int ret=-1; struct fzp *fzp=NULL; char *path=NULL; if(!(path=get_fcount_path(manio)) || !(fzp=fzp_open(path, "wb"))) goto end; if(fzp_printf(fzp, "%08"PRIX64"\n", manio->offset->fcount)!=9) { logp("Short write when writing to %s\n", path); goto end; } ret=0; end: if(fzp_close(&fzp)) { logp("Could not close file pointer to %s\n", path); ret=-1; } free_w(&path); return ret; }
static char *get_ca_dir(struct conf **confs) { struct fzp *fzp=NULL; char buf[4096]=""; const char *ca_conf=get_string(confs[OPT_CA_CONF]); if(!(fzp=fzp_open(ca_conf, "r"))) goto end; while(fzp_gets(fzp, buf, sizeof(buf))) { char *field=NULL; char *value=NULL; if(conf_get_pair(buf, &field, &value) || !field || !value) continue; if(!strcasecmp(field, "CA_DIR")) { if(!(gca_dir=strdup_w(value, __func__))) goto end; break; } } end: fzp_close(&fzp); return gca_dir; }
static int verify_file(struct asfd *asfd, struct sbuf *sb, int patches, const char *best, uint64_t *bytes, struct cntr *cntr) { MD5_CTX md5; size_t b=0; const char *cp=NULL; const char *newsum=NULL; uint8_t in[ZCHUNK]; uint8_t checksum[MD5_DIGEST_LENGTH]; uint64_t cbytes=0; struct fzp *fzp=NULL; if(!(cp=strrchr(sb->endfile.buf, ':'))) { logw(asfd, cntr, "%s has no md5sum!\n", sb->protocol1->datapth.buf); return 0; } cp++; if(!MD5_Init(&md5)) { logp("MD5_Init() failed\n"); return -1; } if(patches || sb->path.cmd==CMD_ENC_FILE || sb->path.cmd==CMD_ENC_METADATA || sb->path.cmd==CMD_EFS_FILE || sb->path.cmd==CMD_ENC_VSS || (!patches && !dpth_protocol1_is_compressed(sb->compression, best))) fzp=fzp_open(best, "rb"); else fzp=fzp_gzopen(best, "rb"); if(!fzp) { logw(asfd, cntr, "could not open %s\n", best); return 0; } while((b=fzp_read(fzp, in, ZCHUNK))>0) { cbytes+=b; if(!MD5_Update(&md5, in, b)) { logp("MD5_Update() failed\n"); fzp_close(&fzp); return -1; } } if(!fzp_eof(fzp)) { logw(asfd, cntr, "error while reading %s\n", best); fzp_close(&fzp); return 0; } fzp_close(&fzp); if(!MD5_Final(checksum, &md5)) { logp("MD5_Final() failed\n"); return -1; } newsum=bytes_to_md5str(checksum); if(strcmp(newsum, cp)) { logp("%s %s\n", newsum, cp); logw(asfd, cntr, "md5sum for '%s (%s)' did not match!\n", sb->path.buf, sb->protocol1->datapth.buf); logp("md5sum for '%s (%s)' did not match!\n", sb->path.buf, sb->protocol1->datapth.buf); return 0; } *bytes+=cbytes; // Just send the file name to the client, so that it can show cntr. if(asfd->write(asfd, &sb->path)) return -1; return 0; }
int backup_phase2_server_protocol1(struct async *as, struct sdirs *sdirs, const char *incexc, int resume, struct conf **cconfs) { int ret=0; struct manio *p1manio=NULL; struct dpth *dpth=NULL; char *deltmppath=NULL; char *last_requested=NULL; // Where to write changed data. // Data is not getting written to a compressed file. // This is important for recovery if the power goes. struct fzp *chfp=NULL; struct fzp *ucfp=NULL; // unchanged data struct fzp *cmanfp=NULL; // previous (current) manifest. struct sbuf *cb=NULL; // file list in current manifest struct sbuf *p1b=NULL; // file list from client struct sbuf *rb=NULL; // receiving file from client struct asfd *asfd=as->asfd; int breaking=0; int breakcount=0; if(get_int(cconfs[OPT_BREAKPOINT])>=2000 && get_int(cconfs[OPT_BREAKPOINT])<3000) { breaking=get_int(cconfs[OPT_BREAKPOINT]); breakcount=breaking-2000; } logp("Begin phase2 (receive file data)\n"); if(!(dpth=dpth_alloc()) || dpth_protocol1_init(dpth, sdirs->currentdata, get_int(cconfs[OPT_MAX_STORAGE_SUBDIRS]))) goto error; if(open_previous_manifest(&cmanfp, sdirs, incexc, cconfs)) goto error; if(get_int(cconfs[OPT_DIRECTORY_TREE])) { // Need to make sure we do not try to create a path that is // too long. if(build_path_w(sdirs->treepath)) goto error; treepathlen=strlen(sdirs->treepath); init_fs_max(sdirs->treepath); } if(!(p1manio=manio_alloc()) || manio_init_read(p1manio, sdirs->phase1data) || !(cb=sbuf_alloc(cconfs)) || !(p1b=sbuf_alloc(cconfs)) || !(rb=sbuf_alloc(cconfs))) goto error; manio_set_protocol(p1manio, PROTO_1); if(resume && do_resume(p1manio, sdirs, dpth, cconfs)) goto error; // Unchanged and changed should now be truncated correctly, we just // have to open them for appending. if(!(ucfp=fzp_open(sdirs->unchanged, "a+b")) || !(chfp=fzp_open(sdirs->changed, "a+b"))) goto error; if(manio_closed(p1manio) && manio_open_next_fpath(p1manio)) goto error; while(1) { if(breaking) { if(breakcount--==0) return breakpoint(cconfs, __func__); } //printf("in loop, %s %s %c\n", // cmanfp?"got cmanfp":"no cmanfp", // rb->path.buf?:"no rb->path", // rb->path.buf?'X':rb->path.cmd); if(write_status(CNTR_STATUS_BACKUP, rb->path.buf?rb->path.buf:p1b->path.buf, cconfs)) goto error; if(last_requested || manio_closed(p1manio) || asfd->writebuflen) { switch(do_stuff_to_receive(asfd, sdirs, cconfs, rb, chfp, dpth, &last_requested)) { case 0: break; case 1: goto end; // Finished ok. case -1: goto error; } } switch(do_stuff_to_send(asfd, p1b, &last_requested)) { case 0: break; case 1: continue; case -1: goto error; } if(manio_closed(p1manio)) continue; sbuf_free_content(p1b); switch(manio_sbuf_fill_phase1(p1manio, asfd, p1b, NULL, sdirs, cconfs)) { case 0: break; case 1: manio_close(p1manio); if(asfd->write_str(asfd, CMD_GEN, "backupphase2end")) goto error; break; case -1: goto error; } if(!cmanfp) { // No old manifest, need to ask for a new file. if(process_new(sdirs, cconfs, p1b, ucfp)) goto error; continue; } // Have an old manifest, look for it there. // Might already have it, or be ahead in the old // manifest. if(cb->path.buf) switch(maybe_process_file(asfd, sdirs, cb, p1b, ucfp, cconfs)) { case 0: break; case 1: continue; case -1: goto error; } while(cmanfp) { sbuf_free_content(cb); switch(sbufl_fill(cb, asfd, cmanfp, cconfs)) { case 0: break; case 1: fzp_close(&cmanfp); if(process_new(sdirs, cconfs, p1b, ucfp)) goto error; continue; case -1: goto error; } switch(maybe_process_file(asfd, sdirs, cb, p1b, ucfp, cconfs)) { case 0: continue; case 1: break; case -1: goto error; } break; } } error: ret=-1; end: if(fzp_close(&chfp)) { logp("error closing %s in %s\n", sdirs->changed, __func__); ret=-1; } if(fzp_close(&ucfp)) { logp("error closing %s in %s\n", sdirs->unchanged, __func__); ret=-1; } free_w(&deltmppath); sbuf_free(&cb); sbuf_free(&p1b); sbuf_free(&rb); manio_free(&p1manio); fzp_close(&cmanfp); dpth_free(&dpth); if(!ret) unlink(sdirs->phase1data); logp("End phase2 (receive file data)\n"); return ret; }