static int do_backup_server(struct async *as, struct sdirs *sdirs, struct conf **cconfs, const char *incexc, int resume) { int ret=0; int do_phase2=1; struct asfd *asfd=as->asfd; enum protocol protocol=get_protocol(cconfs); struct cntr *cntr=get_cntr(cconfs); logp("in do_backup_server\n"); log_rshash(cconfs); if(resume) { if(sdirs_get_real_working_from_symlink(sdirs) || sdirs_get_real_manifest(sdirs, protocol) || open_log(asfd, sdirs, cconfs)) goto error; } else { // Not resuming - need to set everything up fresh. if(sdirs_create_real_working(sdirs, get_string(cconfs[OPT_TIMESTAMP_FORMAT])) || sdirs_get_real_manifest(sdirs, protocol) || open_log(asfd, sdirs, cconfs)) goto error; if(write_incexc(sdirs->rworking, incexc)) { logp("unable to write incexc\n"); goto error; } if(backup_phase1_server(as, sdirs, cconfs)) { logp("error in phase 1\n"); goto error; } } if(resume) { struct stat statp; if(lstat(sdirs->phase1data, &statp) && !lstat(sdirs->changed, &statp) && !lstat(sdirs->unchanged, &statp)) { // In this condition, it looks like there was an // interruption during phase3. Skip phase2. do_phase2=0; } } if(do_phase2) { if(backup_phase2_server(as, sdirs, incexc, resume, cconfs)) { logp("error in backup phase 2\n"); goto error; } asfd->write_str(asfd, CMD_GEN, "okbackupend"); } // Close the connection with the client, the rest of the job we can do // by ourselves. logp("Backup ending - disconnect from client.\n"); if(asfd_flush_asio(asfd)) goto end; as->asfd_remove(as, asfd); asfd_close(asfd); if(backup_phase3_server(sdirs, cconfs)) { logp("error in backup phase 3\n"); goto error; } if(do_rename(sdirs->working, sdirs->finishing)) goto error; if(backup_phase4_server(sdirs, cconfs)) { logp("error in backup phase 4\n"); goto error; } cntr_print(cntr, ACTION_BACKUP, asfd); cntr_stats_to_file(cntr, sdirs->rworking, ACTION_BACKUP); if(protocol==PROTO_2) { // Regenerate dindex before the symlink is renamed, so that the // champ chooser cleanup does not try to remove data files // whilst the dindex regeneration is happening. if(regenerate_client_dindex(sdirs)) goto error; } // Move the symlink to indicate that we are now in the end phase. The // rename() race condition is automatically recoverable here. if(do_rename(sdirs->finishing, sdirs->current)) goto error; logp("Backup completed.\n"); log_fzp_set(NULL, cconfs); compress_filename(sdirs->rworking, "log", "log.gz", get_int(cconfs[OPT_COMPRESSION])); goto end; error: ret=-1; end: log_fzp_set(NULL, cconfs); return ret; }
int do_backup_server_burp1(struct async *as, struct sdirs *sdirs, struct conf *cconf, const char *incexc, int resume) { int ret=0; char msg[256]=""; gzFile mzp=NULL; // Real path to the working directory char *realworking=NULL; char tstmp[64]=""; struct asfd *asfd=as->asfd; struct dpthl dpthl; gzFile cmanfp=NULL; struct stat statp; logp("in do_backup_server\n"); if(init_dpthl(&dpthl, asfd, sdirs, cconf)) { log_and_send(asfd, "could not init_dpthl\n"); goto error; } if(resume) { ssize_t len=0; char real[256]=""; if((len=readlink(sdirs->working, real, sizeof(real)-1))<0) len=0; real[len]='\0'; if(!(realworking=prepend_s(sdirs->client, real))) { log_and_send_oom(asfd, __func__); goto error; } if(open_log(asfd, realworking, cconf)) goto error; } else { // Not resuming - need to set everything up fresh. if(get_new_timestamp(asfd, sdirs, cconf, tstmp, sizeof(tstmp))) goto error; if(!(realworking=prepend_s(sdirs->client, tstmp))) { log_and_send_oom(asfd, __func__); goto error; } // Add the working symlink before creating the directory. // This is because bedup checks the working symlink before // going into a directory. If the directory got created first, // bedup might go into it in the moment before the symlink // gets added. if(symlink(tstmp, sdirs->working)) // relative link to the real work dir { snprintf(msg, sizeof(msg), "could not point working symlink to: %s", realworking); log_and_send(asfd, msg); goto error; } else if(mkdir(realworking, 0777)) { snprintf(msg, sizeof(msg), "could not mkdir for next backup: %s", sdirs->working); log_and_send(asfd, msg); unlink(sdirs->working); goto error; } else if(open_log(asfd, realworking, cconf)) { goto error; } else if(mkdir(sdirs->datadirtmp, 0777)) { snprintf(msg, sizeof(msg), "could not mkdir for datadir: %s", sdirs->datadirtmp); log_and_send(asfd, msg); goto error; } else if(write_timestamp(sdirs->timestamp, tstmp)) { snprintf(msg, sizeof(msg), "unable to write timestamp %s", sdirs->timestamp); log_and_send(asfd, msg); goto error; } else if(incexc && *incexc && write_incexc(realworking, incexc)) { snprintf(msg, sizeof(msg), "unable to write incexc"); log_and_send(asfd, msg); goto error; } if(backup_phase1_server(asfd, sdirs, cconf)) { logp("error in phase 1\n"); goto error; } } // Open the previous (current) manifest. // If the split_vss setting changed between the previous backup // and the new backup, do not open the previous manifest. // This will have the effect of making the client back up everything // fresh. Need to do this, otherwise toggling split_vss on and off // will result in backups that do not work. if(!lstat(sdirs->cmanifest, &statp) && !vss_opts_changed(sdirs, cconf, incexc)) { if(!(cmanfp=gzopen_file(sdirs->cmanifest, "rb"))) { if(!lstat(sdirs->cmanifest, &statp)) { logp("could not open old manifest %s\n", sdirs->cmanifest); goto error; } } } //if(cmanfp) logp("Current manifest: %s\n", sdirs->cmanifest); if(backup_phase2_server(asfd, sdirs, cconf, &cmanfp, &dpthl, resume)) { logp("error in backup phase 2\n"); goto error; } if(backup_phase3_server(sdirs, cconf, 0 /* not recovery mode */, 1 /* compress */)) { logp("error in backup phase 3\n"); goto error; } // will not write anything more to // the new manifest // finish_backup will open it again // for reading if(gzclose_fp(&mzp)) { logp("Error closing manifest after phase3\n"); goto error; } asfd->write_str(asfd, CMD_GEN, "okbackupend"); logp("Backup ending - disconnect from client.\n"); // Close the connection with the client, the rest of the job // we can do by ourselves. asfd_free(&as->asfd); // Move the symlink to indicate that we are now in the end // phase. if(do_rename(sdirs->working, sdirs->finishing)) goto error; set_logfp(NULL, cconf); // does an fclose on logfp. // finish_backup will open logfp again ret=backup_phase4_server(sdirs, cconf); if(!ret && cconf->keep>0) ret=remove_old_backups(asfd, sdirs, cconf); goto end; error: ret=-1; end: gzclose_fp(&cmanfp); gzclose_fp(&mzp); set_logfp(NULL, cconf); // does an fclose on logfp. return ret; }