// return 1 to say that a file was processed static int maybe_process_file(struct asfd *asfd, struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b, struct fzp *ucfp, struct conf **cconfs) { switch(sbuf_pathcmp(cb, p1b)) { case 0: return maybe_do_delta_stuff(asfd, sdirs, cb, p1b, ucfp, cconfs); case 1: //logp("ahead: %s\n", p1b->path); // ahead - need to get the whole file if(process_new(sdirs, cconfs, p1b, ucfp)) return -1; // Do not free. return 1; case -1: default: //logp("behind: %s\n", p1b->path); // Behind - need to read more from the old manifest. // Count a deleted file - it was in the old manifest // but not the new. cntr_add_deleted(get_cntr(cconfs[OPT_CNTR]), cb->path.cmd); return 0; } }
// Return -1 for error, 0 for entry not changed, 1 for entry changed (or new). static int entry_changed(struct sbuf *sb, struct manios *manios, struct asfd *chfd, struct sbuf **csb) { static int finished=0; static struct blk *blk=NULL; if(finished) return 1; if((*csb)->path.buf) { // Already have an entry. } else { // Need to read another. if(!blk && !(blk=blk_alloc())) return -1; switch(manio_read_with_blk(manios->current, *csb, blk, NULL)) { case 1: // Reached the end. sbuf_free(csb); blk_free(&blk); finished=1; return 1; case -1: return -1; } if(!(*csb)->path.buf) { logp("Should have a path at this point, but do not, in %s\n", __func__); return -1; } // Got an entry. } while(1) { switch(sbuf_pathcmp(*csb, sb)) { case 0: return found_in_current_manifest(*csb, sb, manios, &blk, chfd); case 1: return 1; case -1: // Behind - need to read more data from the old // manifest. switch(manio_read_with_blk(manios->current, *csb, blk, NULL)) { case 1: // Reached the end. sbuf_free(csb); blk_free(&blk); return 1; case -1: return -1; } // Got something, go back around the loop. } } return 0; }
// Combine the phase1 and phase2 files into a new manifest. int backup_phase3_server_all(struct sdirs *sdirs, struct conf **confs) { int ret=-1; int pcmp=0; struct blk *blk=NULL; struct sbuf *usb=NULL; struct sbuf *csb=NULL; char *manifesttmp=NULL; struct manio *newmanio=NULL; struct manio *chmanio=NULL; struct manio *unmanio=NULL; enum protocol protocol=get_protocol(confs); struct cntr *cntr=get_cntr(confs); const char *rmanifest_relative=NULL; logp("Begin phase3 (merge manifests)\n"); if(protocol==PROTO_2) rmanifest_relative=get_rmanifest_relative(sdirs, confs); if(!(manifesttmp=get_tmp_filename(sdirs->manifest)) || !(newmanio=manio_open_phase3(manifesttmp, comp_level(get_int(confs[OPT_COMPRESSION])), protocol, rmanifest_relative)) || !(chmanio=manio_open_phase2(sdirs->changed, "rb", protocol)) || !(unmanio=manio_open_phase2(sdirs->unchanged, "rb", protocol)) || !(usb=sbuf_alloc(protocol)) || !(csb=sbuf_alloc(protocol))) goto end; while(chmanio || unmanio) { if(!blk && !(blk=blk_alloc())) goto end; if(unmanio && !usb->path.buf) { switch(manio_read(unmanio, usb)) { case -1: goto end; case 1: manio_close(&unmanio); } } if(chmanio && !csb->path.buf) { switch(manio_read(chmanio, csb)) { case -1: goto end; case 1: manio_close(&chmanio); } } if(usb->path.buf && !csb->path.buf) { if(write_status(CNTR_STATUS_MERGING, usb->path.buf, cntr)) goto end; switch(manio_copy_entry( usb, usb, &blk, unmanio, newmanio)) { case -1: goto end; case 1: manio_close(&unmanio); } } else if(!usb->path.buf && csb->path.buf) { if(write_status(CNTR_STATUS_MERGING, csb->path.buf, cntr)) goto end; switch(manio_copy_entry( csb, csb, &blk, chmanio, newmanio)) { case -1: goto end; case 1: manio_close(&chmanio); } } else if(!usb->path.buf && !csb->path.buf) { continue; } else if(!(pcmp=sbuf_pathcmp(usb, csb))) { // They were the same - write one. if(write_status(CNTR_STATUS_MERGING, csb->path.buf, cntr)) goto end; switch(manio_copy_entry( csb, csb, &blk, chmanio, newmanio)) { case -1: goto end; case 1: manio_close(&chmanio); } } else if(pcmp<0) { if(write_status(CNTR_STATUS_MERGING, usb->path.buf, cntr)) goto end; switch(manio_copy_entry( usb, usb, &blk, unmanio, newmanio)) { case -1: goto end; case 1: manio_close(&unmanio); } } else { if(write_status(CNTR_STATUS_MERGING, csb->path.buf, cntr)) goto end; switch(manio_copy_entry( csb, csb, &blk, chmanio, newmanio)) { case -1: goto end; case 1: manio_close(&chmanio); } } } // Flush to disk. if(manio_close(&newmanio)) { logp("error gzclosing %s in backup_phase3_server\n", manifesttmp); goto end; } // Rename race condition should be of no consequence here, as the // manifest should just get recreated automatically. if(do_rename(manifesttmp, sdirs->manifest)) goto end; else { recursive_delete(sdirs->changed); recursive_delete(sdirs->unchanged); } logp("End phase3 (merge manifests)\n"); ret=0; end: manio_close(&newmanio); manio_close(&chmanio); manio_close(&unmanio); sbuf_free(&csb); sbuf_free(&usb); blk_free(&blk); free_w(&manifesttmp); return ret; }
// This is basically backup_phase3_server() from protocol1. It used to merge the // unchanged and changed data into a single file. Now it splits the manifests // into several files. int backup_phase3_server_protocol2(struct sdirs *sdirs, struct conf **confs) { int ret=1; int pcmp=0; char *hooksdir=NULL; char *dindexdir=NULL; char *manifesttmp=NULL; struct sbuf *usb=NULL; struct sbuf *csb=NULL; struct blk *blk=NULL; int finished_ch=0; int finished_un=0; struct manio *newmanio=NULL; struct manio *chmanio=NULL; struct manio *unmanio=NULL; uint64_t fcount=0; logp("Start phase3\n"); if(!(manifesttmp=get_tmp_filename(sdirs->rmanifest)) || !(newmanio=manio_alloc()) || !(chmanio=manio_alloc()) || !(unmanio=manio_alloc()) || !(hooksdir=prepend_s(manifesttmp, "hooks")) || !(dindexdir=prepend_s(manifesttmp, "dindex")) || manio_init_write(newmanio, manifesttmp) || manio_init_write_hooks(newmanio, get_string(confs[OPT_DIRECTORY]), hooksdir, sdirs->rmanifest) || manio_init_write_dindex(newmanio, dindexdir) || manio_init_read(chmanio, sdirs->changed) || manio_init_read(unmanio, sdirs->unchanged) || !(usb=sbuf_alloc(confs)) || !(csb=sbuf_alloc(confs))) goto end; while(!finished_ch || !finished_un) { if(!blk && !(blk=blk_alloc())) goto end; if(!finished_un && usb && !usb->path.buf) { switch(manio_sbuf_fill(unmanio, NULL /* no async */, usb, NULL, NULL, confs)) { case -1: goto end; case 1: finished_un++; } } if(!finished_ch && csb && !csb->path.buf) { switch(manio_sbuf_fill(chmanio, NULL /* no async */, csb, NULL, NULL, confs)) { case -1: goto end; case 1: finished_ch++; } } if((usb && usb->path.buf) && (!csb || !csb->path.buf)) { switch(manio_copy_entry(NULL /* no async */, &usb, usb, &blk, unmanio, newmanio, confs)) { case -1: goto end; case 1: finished_un++; } } else if((!usb || !usb->path.buf) && (csb && csb->path.buf)) { switch(manio_copy_entry(NULL /* no async */, &csb, csb, &blk, chmanio, newmanio, confs)) { case -1: goto end; case 1: finished_ch++; } } else if((!usb || !usb->path.buf) && (!csb || !(csb->path.buf))) { continue; } else if(!(pcmp=sbuf_pathcmp(usb, csb))) { // They were the same - write one. switch(manio_copy_entry(NULL /* no async */, &csb, csb, &blk, chmanio, newmanio, confs)) { case -1: goto end; case 1: finished_ch++; } } else if(pcmp<0) { switch(manio_copy_entry(NULL /* no async */, &usb, usb, &blk, unmanio, newmanio, confs)) { case -1: goto end; case 1: finished_un++; } } else { switch(manio_copy_entry(NULL /* no async */, &csb, csb, &blk, chmanio, newmanio, confs)) { case -1: goto end; case 1: finished_ch++; } } } fcount=newmanio->fcount; // Flush to disk and set up for reading. if(manio_free(&newmanio) || !(newmanio=manio_alloc()) || manio_init_read(newmanio, sdirs->rmanifest)) goto end; // Rename race condition should be of no consequence here, as the // manifest should just get recreated automatically. if(do_rename(manifesttmp, sdirs->rmanifest)) goto end; else { recursive_delete(sdirs->changed, NULL, 1); recursive_delete(sdirs->unchanged, NULL, 1); } if(sparse_generation(newmanio, fcount, sdirs, confs)) goto end; ret=0; logp("End phase3\n"); end: manio_free(&newmanio); manio_free(&chmanio); manio_free(&unmanio); sbuf_free(&csb); sbuf_free(&usb); blk_free(&blk); free_w(&hooksdir); free_w(&dindexdir); free_w(&manifesttmp); return ret; }
// Return -1 for error, 0 for entry not changed, 1 for entry changed (or new). static int entry_changed(struct asfd *asfd, struct sbuf *sb, struct manio *cmanio, struct manio *unmanio, struct conf *conf) { static int finished=0; static struct sbuf *csb=NULL; static struct blk *blk=NULL; if(finished) return 1; if(!csb && !(csb=sbuf_alloc(conf))) return -1; if(csb->path.buf) { // Already have an entry. } else { // Need to read another. if(!blk && !(blk=blk_alloc())) return -1; switch(manio_sbuf_fill(cmanio, asfd, csb, blk, NULL, conf)) { case 1: // Reached the end. sbuf_free(&csb); blk_free(&blk); finished=1; return 1; case -1: return -1; } if(!csb->path.buf) { logp("Should have a path at this point, but do not, in %s\n", __func__); return -1; } // Got an entry. } while(1) { switch(sbuf_pathcmp(csb, sb)) { case 0: return found_in_current_manifest(asfd, csb, sb, cmanio, unmanio, &blk, conf); case 1: return 1; case -1: // Behind - need to read more data from the old // manifest. switch(manio_sbuf_fill(cmanio, asfd, csb, blk, NULL, conf)) { case -1: return -1; case 1: { // Reached the end. sbuf_free(&csb); blk_free(&blk); return 1; } } // Got something, go back around the loop. } } return 0; }
static int maybe_delete_files_from_manifest(const char *manifesttmp, struct fdirs *fdirs, struct conf *cconf) { int ars=0; int ret=-1; int pcmp=0; FILE *dfp=NULL; gzFile nmzp=NULL; gzFile omzp=NULL; struct sbuf *db=NULL; struct sbuf *mb=NULL; struct stat statp; if(lstat(fdirs->deletionsfile, &statp)) // No deletions, no problem. return 0; logp("Performing deletions on manifest\n"); if(!(manifesttmp=get_tmp_filename(fdirs->manifest))) goto end; if(!(dfp=open_file(fdirs->deletionsfile, "rb")) || !(omzp=gzopen_file(fdirs->manifest, "rb")) || !(nmzp=gzopen_file(manifesttmp, comp_level(cconf))) || !(db=sbuf_alloc(cconf)) || !(mb=sbuf_alloc(cconf))) goto end; while(omzp || dfp) { if(dfp && !db->path.buf && (ars=sbufl_fill(db, NULL, dfp, NULL, cconf->cntr))) { if(ars<0) goto end; // ars==1 means it ended ok. close_fp(&dfp); } if(omzp && !mb->path.buf && (ars=sbufl_fill(mb, NULL, NULL, omzp, cconf->cntr))) { if(ars<0) goto end; // ars==1 means it ended ok. gzclose_fp(&omzp); } if(mb->path.buf && !db->path.buf) { if(sbufl_to_manifest(mb, NULL, nmzp)) goto end; sbuf_free_content(mb); } else if(!mb->path.buf && db->path.buf) { sbuf_free_content(db); } else if(!mb->path.buf && !db->path.buf) { continue; } else if(!(pcmp=sbuf_pathcmp(mb, db))) { // They were the same - do not write. sbuf_free_content(mb); sbuf_free_content(db); } else if(pcmp<0) { // Behind in manifest. Write. if(sbufl_to_manifest(mb, NULL, nmzp)) goto end; sbuf_free_content(mb); } else { // Behind in deletions file. Do not write. sbuf_free_content(db); } } ret=0; end: if(gzclose_fp(&nmzp)) { logp("error closing %s in %s\n", manifesttmp, __func__); ret=-1; } close_fp(&dfp); gzclose_fp(&omzp); sbuf_free(&db); sbuf_free(&mb); if(!ret) { unlink(fdirs->deletionsfile); // The rename race condition is not a problem here, as long // as manifesttmp is the same path as that generated in the // atomic data jiggle. if(do_rename(manifesttmp, fdirs->manifest)) return -1; } if(manifesttmp) unlink(manifesttmp); return ret; }
// Combine the phase1 and phase2 files into a new manifest. int backup_phase3_server(const char *phase2data, const char *unchangeddata, const char *manifest, int recovery, int compress, const char *client, struct cntr *p1cntr, struct cntr *cntr, struct config *cconf) { int ars=0; int ret=0; int pcmp=0; FILE *ucfp=NULL; FILE *p2fp=NULL; FILE *mp=NULL; gzFile mzp=NULL; struct sbuf ucb; struct sbuf p2b; char *manifesttmp=NULL; logp("Begin phase3 (merge manifests)\n"); if(!(manifesttmp=get_tmp_filename(manifest))) return -1; if(!(ucfp=open_file(unchangeddata, "rb")) || !(p2fp=open_file(phase2data, "rb")) || (compress && !(mzp=gzopen_file(manifesttmp, comp_level(cconf)))) || (!compress && !(mp=open_file(manifesttmp, "wb")))) { close_fp(&ucfp); gzclose_fp(&mzp); close_fp(&p2fp); close_fp(&mp); free(manifesttmp); return -1; } init_sbuf(&ucb); init_sbuf(&p2b); while(ucfp || p2fp) { if(ucfp && !ucb.path && (ars=sbuf_fill(ucfp, NULL, &ucb, cntr))) { if(ars<0) { ret=-1; break; } // ars==1 means it ended ok. close_fp(&ucfp); } if(p2fp && !p2b.path && (ars=sbuf_fill(p2fp, NULL, &p2b, cntr))) { if(ars<0) { ret=-1; break; } // ars==1 means it ended ok. close_fp(&p2fp); // In recovery mode, only want to read to the last // entry in the phase 2 file. if(recovery) break; } if(ucb.path && !p2b.path) { write_status(client, STATUS_MERGING, ucb.path, p1cntr, cntr); if(sbuf_to_manifest(&ucb, mp, mzp)) { ret=-1; break; } free_sbuf(&ucb); } else if(!ucb.path && p2b.path) { write_status(client, STATUS_MERGING, p2b.path, p1cntr, cntr); if(sbuf_to_manifest(&p2b, mp, mzp)) { ret=-1; break; } free_sbuf(&p2b); } else if(!ucb.path && !p2b.path) { continue; } else if(!(pcmp=sbuf_pathcmp(&ucb, &p2b))) { // They were the same - write one and free both. write_status(client, STATUS_MERGING, p2b.path, p1cntr, cntr); if(sbuf_to_manifest(&p2b, mp, mzp)) { ret=-1; break; } free_sbuf(&p2b); free_sbuf(&ucb); } else if(pcmp<0) { write_status(client, STATUS_MERGING, ucb.path, p1cntr, cntr); if(sbuf_to_manifest(&ucb, mp, mzp)) { ret=-1; break; } free_sbuf(&ucb); } else { write_status(client, STATUS_MERGING, p2b.path, p1cntr, cntr); if(sbuf_to_manifest(&p2b, mp, mzp)) { ret=-1; break; } free_sbuf(&p2b); } } free_sbuf(&ucb); free_sbuf(&p2b); close_fp(&p2fp); close_fp(&ucfp); if(close_fp(&mp)) { logp("error closing %s in backup_phase3_server\n", manifesttmp); ret=-1; } if(gzclose_fp(&mzp)) { logp("error gzclosing %s in backup_phase3_server\n", manifesttmp); ret=-1; } if(!ret) { if(do_rename(manifesttmp, manifest)) ret=-1; else { unlink(phase2data); unlink(unchangeddata); } } free(manifesttmp); logp("End phase3 (merge manifests)\n"); return ret; }
// Return -1 for error, 0 for entry not changed, 1 for entry changed (or new). static int entry_changed(struct sbuf *sb, struct manios *manios, struct asfd *chfd, struct sbuf **csb, struct cntr *cntr) { static int finished=0; int pcmp; if(finished) { cntr_add_new(cntr, sb->path.cmd); return 1; } if(*csb && (*csb)->path.buf) { // Already have an entry. } else { // Need to read another. switch(manio_read(manios->current, *csb)) { case 1: // Reached the end. sbuf_free(csb); finished=1; cntr_add_new(cntr, sb->path.cmd); return 1; case -1: return -1; } if(!(*csb)->path.buf) { logp("Should have a path at this point, but do not, in %s\n", __func__); return -1; } // Got an entry. } while(1) { if(!(pcmp=sbuf_pathcmp(*csb, sb))) return found_in_current_manifest(*csb, sb, manios, chfd, cntr); else if(pcmp>0) { cntr_add_new(cntr, sb->path.cmd); return 1; } // cntr_add_deleted(cntr, (*csb)->path.cmd); // Behind - need to read more data from the old manifest. switch(manio_read(manios->current, *csb)) { case 1: // Reached the end. sbuf_free(csb); cntr_add_new(cntr, sb->path.cmd); return 1; case -1: return -1; } // Got something, go back around the loop. } return 0; }
static int maybe_delete_files_from_manifest(const char *manifest, const char *deletionsfile, struct config *cconf, struct cntr *cntr) { int ars=0; int ret=0; int pcmp=0; FILE *dfp=NULL; struct sbuf db; struct sbuf mb; gzFile nmzp=NULL; gzFile omzp=NULL; char *manifesttmp=NULL; struct stat statp; if(lstat(deletionsfile, &statp)) { // No deletions, no problem. return 0; } logp("Performing deletions on manifest\n"); if(!(manifesttmp=get_tmp_filename(manifest))) { ret=-1; goto end; } if(!(dfp=open_file(deletionsfile, "rb")) || !(omzp=gzopen_file(manifest, "rb")) || !(nmzp=gzopen_file(manifesttmp, comp_level(cconf)))) { ret=-1; goto end; } init_sbuf(&db); init_sbuf(&mb); while(omzp || dfp) { if(dfp && !db.path && (ars=sbuf_fill(dfp, NULL, &db, cntr))) { if(ars<0) { ret=-1; break; } // ars==1 means it ended ok. close_fp(&dfp); } if(omzp && !mb.path && (ars=sbuf_fill(NULL, omzp, &mb, cntr))) { if(ars<0) { ret=-1; break; } // ars==1 means it ended ok. gzclose_fp(&omzp); } if(mb.path && !db.path) { if(sbuf_to_manifest(&mb, NULL, nmzp)) { ret=-1; break; } free_sbuf(&mb); } else if(!mb.path && db.path) { free_sbuf(&db); } else if(!mb.path && !db.path) { continue; } else if(!(pcmp=sbuf_pathcmp(&mb, &db))) { // They were the same - do not write. free_sbuf(&mb); free_sbuf(&db); } else if(pcmp<0) { // Behind in manifest. Write. if(sbuf_to_manifest(&mb, NULL, nmzp)) { ret=-1; break; } free_sbuf(&mb); } else { // Behind in deletions file. Do not write. free_sbuf(&db); } } end: if(gzclose_fp(&nmzp)) { logp("error closing %s in maybe_delete_files_from_manifest\n", manifesttmp); ret=-1; } close_fp(&dfp); gzclose_fp(&omzp); free_sbuf(&db); free_sbuf(&mb); if(!ret) { unlink(deletionsfile); if(do_rename(manifesttmp, manifest)) { free(manifesttmp); return -1; } } if(manifesttmp) { unlink(manifesttmp); free(manifesttmp); } return ret; }
// return 1 to say that a file was processed static int maybe_process_file(struct sbuf *cb, struct sbuf *p1b, FILE *ucfp, const char *currentdata, const char *datadirtmp, const char *deltmppath, struct dpth *dpth, int *resume_partial, struct cntr *cntr, struct config *cconf) { int pcmp; // logp("in maybe_proc %s\n", p1b->path); if(!(pcmp=sbuf_pathcmp(cb, p1b))) { int oldcompressed=0; // If the file type changed, I think it is time to back it // up again (for example, EFS changing to normal file, or // back again). if(cb->cmd!=p1b->cmd) return process_new_file(cb, p1b, ucfp, currentdata, datadirtmp, deltmppath, dpth, resume_partial, cntr, cconf); // mtime is the actual file data. // ctime is the attributes or meta data. if(cb->statp.st_mtime==p1b->statp.st_mtime && cb->statp.st_ctime==p1b->statp.st_ctime) { // got an unchanged file //logp("got unchanged file: %s %c %c\n", cb->path, cb->cmd, p1b->cmd); return process_unchanged_file(cb, ucfp, cntr); } if(cb->statp.st_mtime==p1b->statp.st_mtime && cb->statp.st_ctime!=p1b->statp.st_ctime) { // File data stayed the same, but attributes or meta // data changed. We already have the attributes, but // may need to get extra meta data. if(cb->cmd==CMD_ENC_METADATA || p1b->cmd==CMD_ENC_METADATA // TODO: make unencrypted metadata use the librsync || cb->cmd==CMD_METADATA || p1b->cmd==CMD_METADATA || cb->cmd==CMD_VSS || p1b->cmd==CMD_VSS || cb->cmd==CMD_ENC_VSS || p1b->cmd==CMD_ENC_VSS || cb->cmd==CMD_VSS_T || p1b->cmd==CMD_VSS_T || cb->cmd==CMD_ENC_VSS_T || p1b->cmd==CMD_ENC_VSS_T || cb->cmd==CMD_EFS_FILE || p1b->cmd==CMD_EFS_FILE) return process_new_file(cb, p1b, ucfp, currentdata, datadirtmp, deltmppath, dpth, resume_partial, cntr, cconf); else return process_unchanged_file(cb, ucfp, cntr); } // Got a changed file. //logp("got changed file: %s\n", p1b->path); // If either old or new is encrypted, or librsync is off, // we need to get a new file. if(!cconf->librsync || cb->cmd==CMD_ENC_FILE || p1b->cmd==CMD_ENC_FILE || cb->cmd==CMD_ENC_METADATA || p1b->cmd==CMD_ENC_METADATA || cb->cmd==CMD_EFS_FILE || p1b->cmd==CMD_EFS_FILE // TODO: make unencrypted metadata use the librsync || cb->cmd==CMD_METADATA || p1b->cmd==CMD_METADATA || cb->cmd==CMD_VSS || p1b->cmd==CMD_VSS || cb->cmd==CMD_ENC_VSS || p1b->cmd==CMD_ENC_VSS || cb->cmd==CMD_VSS_T || p1b->cmd==CMD_VSS_T || cb->cmd==CMD_ENC_VSS_T || p1b->cmd==CMD_ENC_VSS_T) return process_new_file(cb, p1b, ucfp, currentdata, datadirtmp, deltmppath, dpth, resume_partial, cntr, cconf); // Get new files if they have switched between compression on // or off. if(cb->datapth && dpth_is_compressed(cb->compression, cb->datapth)) oldcompressed=1; if( ( oldcompressed && !cconf->compression) || (!oldcompressed && cconf->compression)) return process_new_file(cb, p1b, ucfp, currentdata, datadirtmp, deltmppath, dpth, resume_partial, cntr, cconf); // Otherwise, do the delta stuff (if possible). if(filedata(p1b->cmd)) { if(process_changed_file(cb, p1b, currentdata, datadirtmp, deltmppath, resume_partial, cntr, cconf)) return -1; } else { if(changed_non_file(p1b, ucfp, p1b->cmd, cntr)) return -1; } free_sbuf(cb); return 1; } else if(pcmp>0) { //logp("ahead: %s\n", p1b->path); // ahead - need to get the whole file if(process_new(p1b, ucfp, currentdata, datadirtmp, deltmppath, dpth, resume_partial, cntr, cconf)) return -1; // do not free return 1; } else { //logp("behind: %s\n", p1b->path); // behind - need to read more from the old // manifest // Count a deleted file - it was in the old manifest but not // the new. do_filecounter_deleted(cntr, cb->cmd); } return 0; }
// return 1 to say that a file was processed static int maybe_process_file(struct asfd *asfd, struct sdirs *sdirs, struct conf *cconf, struct sbuf *cb, struct sbuf *p1b, FILE *ucfp, struct dpthl *dpthl) { int pcmp; if(!(pcmp=sbuf_pathcmp(cb, p1b))) { int oldcompressed=0; // If the file type changed, I think it is time to back it // up again (for example, EFS changing to normal file, or // back again). if(cb->path.cmd!=p1b->path.cmd) return process_new_file(sdirs, cconf, cb, p1b, ucfp, dpthl); // mtime is the actual file data. // ctime is the attributes or meta data. if(cb->statp.st_mtime==p1b->statp.st_mtime && cb->statp.st_ctime==p1b->statp.st_ctime) { // got an unchanged file //logp("got unchanged file: %s %c %c\n", cb->path, cb->cmd, p1b->cmd); return process_unchanged_file(cb, ucfp, cconf); } if(cb->statp.st_mtime==p1b->statp.st_mtime && cb->statp.st_ctime!=p1b->statp.st_ctime) { // File data stayed the same, but attributes or meta // data changed. We already have the attributes, but // may need to get extra meta data. if(cb->path.cmd==CMD_ENC_METADATA || p1b->path.cmd==CMD_ENC_METADATA // TODO: make unencrypted metadata use the librsync || cb->path.cmd==CMD_METADATA || p1b->path.cmd==CMD_METADATA || cb->path.cmd==CMD_VSS || p1b->path.cmd==CMD_VSS || cb->path.cmd==CMD_ENC_VSS || p1b->path.cmd==CMD_ENC_VSS || cb->path.cmd==CMD_VSS_T || p1b->path.cmd==CMD_VSS_T || cb->path.cmd==CMD_ENC_VSS_T || p1b->path.cmd==CMD_ENC_VSS_T || cb->path.cmd==CMD_EFS_FILE || p1b->path.cmd==CMD_EFS_FILE) return process_new_file(sdirs, cconf, cb, p1b, ucfp, dpthl); // On Windows, we have to back up the whole file if // ctime changed, otherwise things like permission // changes do not get noticed. So, in that case, fall // through to the changed stuff below. // Non-Windows clients finish here. else if(!cconf->client_is_windows) return process_unchanged_file(cb, ucfp, cconf); } // Got a changed file. //logp("got changed file: %s\n", p1b->path); // If either old or new is encrypted, or librsync is off, // we need to get a new file. if(!cconf->librsync || cb->path.cmd==CMD_ENC_FILE || p1b->path.cmd==CMD_ENC_FILE || cb->path.cmd==CMD_ENC_METADATA || p1b->path.cmd==CMD_ENC_METADATA || cb->path.cmd==CMD_EFS_FILE || p1b->path.cmd==CMD_EFS_FILE // TODO: make unencrypted metadata use the librsync || cb->path.cmd==CMD_METADATA || p1b->path.cmd==CMD_METADATA || cb->path.cmd==CMD_VSS || p1b->path.cmd==CMD_VSS || cb->path.cmd==CMD_ENC_VSS || p1b->path.cmd==CMD_ENC_VSS || cb->path.cmd==CMD_VSS_T || p1b->path.cmd==CMD_VSS_T || cb->path.cmd==CMD_ENC_VSS_T || p1b->path.cmd==CMD_ENC_VSS_T) return process_new_file(sdirs, cconf, cb, p1b, ucfp, dpthl); // Get new files if they have switched between compression on // or off. if(cb->burp1->datapth.buf && dpthl_is_compressed(cb->compression, cb->burp1->datapth.buf)) oldcompressed=1; if( ( oldcompressed && !cconf->compression) || (!oldcompressed && cconf->compression)) return process_new_file(sdirs, cconf, cb, p1b, ucfp, dpthl); // Otherwise, do the delta stuff (if possible). if(filedata(p1b->path.cmd)) { if(process_changed_file(asfd, sdirs, cconf, cb, p1b, sdirs->currentdata)) return -1; } else { if(changed_non_file(p1b, ucfp, p1b->path.cmd, cconf)) return -1; } sbuf_free_content(cb); return 1; } else if(pcmp>0) { //logp("ahead: %s\n", p1b->path); // ahead - need to get the whole file if(process_new(sdirs, cconf, p1b, ucfp, dpthl)) return -1; // do not free return 1; } else { //logp("behind: %s\n", p1b->path); // behind - need to read more from the old // manifest // Count a deleted file - it was in the old manifest but not // the new. cntr_add_deleted(cconf->cntr, cb->path.cmd); } return 0; }