/* Need to make all the stuff that this does atomic so that existing backups never get broken, even if somebody turns the power off on the server. */ static int atomic_data_jiggle(struct sdirs *sdirs, struct fdirs *fdirs, int hardlinked_current, struct conf **cconfs) { int ret=-1; char *datapth=NULL; char *tmpman=NULL; struct stat statp; char *deltabdir=NULL; char *deltafdir=NULL; char *sigpath=NULL; struct fzp *zp=NULL; struct sbuf *sb=NULL; struct fzp *delfp=NULL; logp("Doing the atomic data jiggle...\n"); if(!(tmpman=get_tmp_filename(fdirs->manifest))) goto error; if(lstat(fdirs->manifest, &statp)) { // Manifest does not exist - maybe the server was killed before // it could be renamed. logp("%s did not exist - trying %s\n", fdirs->manifest, tmpman); // Rename race condition is of no consequence, because manifest // already does not exist. do_rename(tmpman, fdirs->manifest); } if(!(zp=fzp_gzopen(fdirs->manifest, "rb"))) goto error; if(!(deltabdir=prepend_s(fdirs->currentdup, "deltas.reverse")) || !(deltafdir=prepend_s(sdirs->finishing, "deltas.forward")) || !(sigpath=prepend_s(fdirs->currentdup, "sig.tmp")) || !(sb=sbuf_alloc(PROTO_1))) { log_out_of_memory(__func__); goto error; } mkdir(fdirs->datadir, 0777); while(1) { switch(sbuf_fill_from_file(sb, zp, NULL, NULL)) { case 0: break; case 1: goto end; default: goto error; } if(sb->protocol1->datapth.buf) { if(write_status(CNTR_STATUS_SHUFFLING, sb->protocol1->datapth.buf, get_cntr(cconfs)) || jiggle(sdirs, fdirs, sb, hardlinked_current, deltabdir, deltafdir, sigpath, &delfp, cconfs)) goto error; } sbuf_free_content(sb); } end: if(fzp_close(&delfp)) { logp("error closing %s in atomic_data_jiggle\n", fdirs->deletionsfile); goto error; } if(maybe_delete_files_from_manifest(tmpman, fdirs, cconfs)) goto error; // Remove the temporary data directory, we have probably removed // useful files from it. recursive_delete_dirs_only(deltafdir); ret=0; error: fzp_close(&zp); fzp_close(&delfp); sbuf_free(&sb); free_w(&deltabdir); free_w(&deltafdir); free_w(&sigpath); free_w(&datapth); free_w(&tmpman); return ret; }
/* Need to make all the stuff that this does atomic so that existing backups never get broken, even if somebody turns the power off on the server. */ static int atomic_data_jiggle(struct sdirs *sdirs, struct fdirs *fdirs, int hardlinked_current, struct conf *cconf, unsigned long bno) { int ars=0; int ret=-1; char *datapth=NULL; char *tmpman=NULL; struct stat statp; char *deltabdir=NULL; char *deltafdir=NULL; char *sigpath=NULL; gzFile zp=NULL; struct sbuf *sb=NULL; FILE *delfp=NULL; logp("Doing the atomic data jiggle...\n"); if(!(tmpman=get_tmp_filename(fdirs->manifest))) goto end; if(lstat(fdirs->manifest, &statp)) { // Manifest does not exist - maybe the server was killed before // it could be renamed. logp("%s did not exist - trying %s\n", fdirs->manifest, tmpman); // Rename race condition is of no consequence, because manifest // already does not exist. do_rename(tmpman, fdirs->manifest); } if(!(zp=gzopen_file(fdirs->manifest, "rb"))) goto end; if(!(deltabdir=prepend_s(fdirs->currentdup, "deltas.reverse")) || !(deltafdir=prepend_s(sdirs->finishing, "deltas.forward")) || !(sigpath=prepend_s(fdirs->currentdup, "sig.tmp")) || !(sb=sbuf_alloc(cconf))) { log_out_of_memory(__func__); goto end; } mkdir(fdirs->datadir, 0777); while(!(ars=sbufl_fill(sb, NULL, NULL, zp, cconf->cntr))) { if(sb->burp1->datapth.buf) { if(write_status(STATUS_SHUFFLING, sb->burp1->datapth.buf, cconf)) goto end; if((ret=jiggle(sdirs, fdirs, sb, hardlinked_current, deltabdir, deltafdir, sigpath, &delfp, cconf))) goto end; } sbuf_free_content(sb); } if(ars<0) goto end; if(close_fp(&delfp)) { logp("error closing %s in atomic_data_jiggle\n", fdirs->deletionsfile); goto end; } if(maybe_delete_files_from_manifest(tmpman, fdirs, cconf)) goto end; // Remove the temporary data directory, we have probably removed // useful files from it. sync(); // try to help CIFS recursive_delete(deltafdir, NULL, 0 /* do not del files */); end: gzclose_fp(&zp); close_fp(&delfp); sbuf_free(&sb); free_w(&deltabdir); free_w(&deltafdir); free_w(&sigpath); free_w(&datapth); free_w(&tmpman); return ret; }
/* Need to make all the stuff that this does atomic so that existing backups never get broken, even if somebody turns the power off on the server. */ static int atomic_data_jiggle(const char *finishing, const char *working, const char *manifest, const char *current, const char *currentdata, const char *datadir, const char *datadirtmp, const char *deletionsfile, struct config *cconf, const char *client, int hardlinked, unsigned long bno, struct cntr *p1cntr, struct cntr *cntr) { int ret=0; int ars=0; char *datapth=NULL; char *tmpman=NULL; struct stat statp; char *deltabdir=NULL; char *deltafdir=NULL; char *sigpath=NULL; gzFile zp=NULL; struct sbuf sb; FILE *delfp=NULL; logp("Doing the atomic data jiggle...\n"); if(!(tmpman=get_tmp_filename(manifest))) return -1; if(lstat(manifest, &statp)) { // Manifest does not exist - maybe the server was killed before // it could be renamed. logp("%s did not exist - trying %s\n", manifest, tmpman); do_rename(tmpman, manifest); } free(tmpman); if(!(zp=gzopen_file(manifest, "rb"))) return -1; if(!(deltabdir=prepend_s(current, "deltas.reverse", strlen("deltas.reverse"))) || !(deltafdir=prepend_s(finishing, "deltas.forward", strlen("deltas.forward"))) || !(sigpath=prepend_s(current, "sig.tmp", strlen("sig.tmp")))) { log_out_of_memory(__FUNCTION__); gzclose_fp(&zp); return -1; } mkdir(datadir, 0777); init_sbuf(&sb); while(!(ars=sbuf_fill(NULL, zp, &sb, cntr))) { if(sb.datapth) { write_status(client, STATUS_SHUFFLING, sb.datapth, p1cntr, cntr); if((ret=jiggle(sb.datapth, currentdata, datadirtmp, datadir, deltabdir, deltafdir, sigpath, sb.endfile, deletionsfile, &delfp, &sb, hardlinked, sb.compression, cntr, cconf))) break; } free_sbuf(&sb); } if(!ret) { if(ars>0) ret=0; else ret=-1; } if(close_fp(&delfp)) { logp("error closing %s in atomic_data_jiggle\n", deletionsfile); ret=-1; } gzclose_fp(&zp); if(maybe_delete_files_from_manifest(manifest, deletionsfile, cconf, cntr)) ret=-1; // Remove the temporary data directory, we have probably removed // useful files from it. sync(); // try to help CIFS recursive_delete(deltafdir, NULL, FALSE /* do not del files */); if(deltabdir) free(deltabdir); if(deltafdir) free(deltafdir); if(sigpath) free(sigpath); if(datapth) free(datapth); return ret; }