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 run_backup(struct async *as, struct sdirs *sdirs, struct conf **cconfs, const char *incexc, int *timer_ret, int resume) { int ret; char okstr[32]=""; struct asfd *asfd=as->asfd; struct iobuf *rbuf=asfd->rbuf; const char *cname=get_string(cconfs[OPT_CNAME]); if(get_string(cconfs[OPT_RESTORE_CLIENT])) { // This client is not the original client, so a backup might // cause all sorts of trouble. logp("Not allowing backup of %s\n", cname); return asfd->write_str(asfd, CMD_GEN, "Backup is not allowed"); } // Set quality of service bits on backups. asfd->set_bulk_packets(asfd); if(!strncmp_w(rbuf->buf, "backupphase1timed")) { int a=0; const char *args[12]; int checkonly=!strncmp_w(rbuf->buf, "backupphase1timedcheck"); if(checkonly) logp("Client asked for a timer check only.\n"); args[a++]=get_string(cconfs[OPT_TIMER_SCRIPT]); args[a++]=cname; args[a++]=sdirs->current; args[a++]=sdirs->clients; args[a++]="reserved1"; args[a++]="reserved2"; args[a++]=NULL; if((*timer_ret=run_script(asfd, args, get_strlist(cconfs[OPT_TIMER_ARG]), cconfs, 1 /* wait */, 1 /* use logp */, 0 /* no log_remote */ ))<0) { logp("Error running timer script for %s\n", cname); return *timer_ret; } if(*timer_ret) { if(!checkonly) logp("Not running backup of %s\n", cname); return asfd->write_str(asfd, CMD_GEN, "timer conditions not met"); } if(checkonly) { logp("Client asked for a timer check only,\n"); logp("so a backup is not happening right now.\n"); return asfd->write_str(asfd, CMD_GEN, "timer conditions met"); } logp("Running backup of %s\n", cname); } else if(!get_int(cconfs[OPT_CLIENT_CAN_FORCE_BACKUP])) { logp("Not allowing forced backup of %s\n", cname); return asfd->write_str(asfd, CMD_GEN, "Forced backup is not allowed"); } snprintf(okstr, sizeof(okstr), "%s:%d", resume?"resume":"ok", get_int(cconfs[OPT_COMPRESSION])); if(asfd->write_str(asfd, CMD_GEN, okstr)) return -1; if((ret=do_backup_server(as, sdirs, cconfs, incexc, resume))) goto end; if((ret=delete_backups(sdirs, cname, get_strlist(cconfs[OPT_KEEP]), get_string(cconfs[OPT_MANUAL_DELETE])))) goto end; if(get_protocol(cconfs)==PROTO_2) ret=regenerate_client_dindex(sdirs); end: return ret; }