int get_new_timestamp(struct config *cconf, const char *basedir, char *buf, size_t s) { int a=0; time_t t=0; const struct tm *ctm=NULL; unsigned long index=0; char tmpbuf[32]=""; struct bu *arr=NULL; // Want to prefix the timestamp with an index that increases by // one each time. This makes it far more obvious which backup depends // on which - even if the system clock moved around. Take that, // bacula! // get_current_backups orders the array with the highest index number // last if(get_current_backups(basedir, &arr, &a, 1)) return -1; if(a) index=arr[a-1].index; free_current_backups(&arr, a); time(&t); ctm=localtime(&t); // Windows does not like the %T strftime format option - you get // complaints under gdb. strftime(tmpbuf, sizeof(tmpbuf), cconf->timestamp_format, ctm); snprintf(buf, s, "%07lu %s", ++index, tmpbuf); return 0; }
int do_remove_old_backups(const char *basedir, struct config *cconf, const char *client) { int a=0; int b=0; int x=0; int ret=0; int deleted=0; unsigned long m=1; struct bu *arr=NULL; struct strlist **kplist=NULL; kplist=cconf->keep; if(get_current_backups(basedir, &arr, &a, 1)) return -1; // For each of the 'keep' values, generate ranges in which to keep // one backup. for(x=0; x<cconf->kpcount; x++) { unsigned long n=0; n=m * kplist[x]->flag; //printf("keep[%d]: %d - m:%lu n:%lu\n", // x, cconf->keep[x]->flag, m, n); if(x+1 < cconf->kpcount) { unsigned long r=0; unsigned long s=0; unsigned long upto=0; upto=n*cconf->keep[x+1]->flag; //printf("upto: %lu\n", upto); // This is going over each range. for(r=upto; r>n; r-=n) { int count=0; s=r-n; //printf(" try: %lu - %lu\n", s, r); // Count the backups in the range. for(b=0; b<a; b++) { if(s<arr[b].trindex && arr[b].trindex<=r) { //printf(" check backup %lu (%lu) %d\n", arr[b].index, arr[b].trindex, arr[b].deletable); count++; } } // Want to leave one entry in each range. if(count>1) { // Try to delete from the most recent in each // so that hardlinked backups get taken out // last. for(b=a-1; b>=0; b--) { if(s<arr[b].trindex && arr[b].trindex<=r && arr[b].deletable) { //printf("deleting backup %lu (%lu)\n", arr[b].index, arr[b].trindex); if(delete_backup(basedir, arr, a, b, client)) { ret=-1; break; } deleted++; if(--count<=1) break; } } } if(ret) break; } } m=n; if(ret) break; } if(!ret) { // Remove the very oldest backups. //printf("back from: %lu\n", m); for(b=0; b<a; b++) { //printf(" %d: %lu (%lu)\n", b, arr[b].index, arr[b].trindex); if(arr[b].trindex>m) break; } for(; b>=0 && b<a; b--) { if(delete_backup(basedir, arr, a, b, client)) { ret=-1; break; } deleted++; } } free_current_backups(&arr, a); if(ret) return ret; return deleted; }
int do_list_server(const char *basedir, const char *backup, const char *listregex, const char *browsedir, const char *client, struct cntr *p1cntr, struct cntr *cntr) { int a=0; int i=0; int ret=0; int found=0; struct bu *arr=NULL; unsigned long index=0; regex_t *regex=NULL; logp("in do_list\n"); if(compile_regex(®ex, listregex)) return -1; if(get_current_backups(basedir, &arr, &a, 1)) { if(regex) { regfree(regex); free(regex); } return -1; } write_status(client, STATUS_LISTING, NULL, p1cntr, cntr); if(backup && *backup) index=strtoul(backup, NULL, 10); for(i=0; i<a; i++) { // Search all backups for things matching the regex. if(listregex && backup && *backup=='a') { found=TRUE; async_write(CMD_TIMESTAMP, arr[i].timestamp, strlen(arr[i].timestamp)); ret+=list_manifest(arr[i].path, regex, browsedir, client, p1cntr, cntr); } // Search or list a particular backup. else if(backup && *backup) { if(!found && (!strcmp(arr[i].timestamp, backup) || arr[i].index==index)) { found=TRUE; async_write(CMD_TIMESTAMP, arr[i].timestamp, strlen(arr[i].timestamp)); ret=list_manifest(arr[i].path, regex, browsedir, client, p1cntr, cntr); } } // List the backups. else { found=TRUE; async_write(CMD_TIMESTAMP, arr[i].timestamp, strlen(arr[i].timestamp)); } } free_current_backups(&arr, a); if(backup && *backup && !found) { async_write_str(CMD_ERROR, "backup not found"); ret=-1; } if(regex) { regfree(regex); free(regex); } return ret; }
int do_restore_server(const char *basedir, enum action act, const char *client, int srestore, char **dir_for_notify, struct cntr *p1cntr, struct cntr *cntr, struct config *cconf) { int a=0; int i=0; int ret=0; int found=0; struct bu *arr=NULL; unsigned long index=0; char *tmppath1=NULL; char *tmppath2=NULL; regex_t *regex=NULL; logp("in do_restore\n"); if(compile_regex(®ex, cconf->regex)) return -1; if(!(tmppath1=prepend_s(basedir, "tmp1", strlen("tmp1"))) || !(tmppath2=prepend_s(basedir, "tmp2", strlen("tmp2")))) { if(tmppath1) free(tmppath1); if(regex) { regfree(regex); free(regex); } return -1; } if(get_current_backups(basedir, &arr, &a, 1)) { if(tmppath1) free(tmppath1); if(tmppath2) free(tmppath2); if(regex) { regfree(regex); free(regex); } return -1; } if(!(index=strtoul(cconf->backup, NULL, 10)) && a>0) { // No backup specified, do the most recent. ret=restore_manifest(arr, a, a-1, tmppath1, tmppath2, regex, srestore, act, client, dir_for_notify, p1cntr, cntr, cconf); found=TRUE; } if(!found) for(i=0; i<a; i++) { if(!strcmp(arr[i].timestamp, cconf->backup) || arr[i].index==index) { found=TRUE; //logp("got: %s\n", arr[i].path); ret|=restore_manifest(arr, a, i, tmppath1, tmppath2, regex, srestore, act, client, dir_for_notify, p1cntr, cntr, cconf); break; } } free_current_backups(&arr, a); if(!found) { logp("backup not found\n"); async_write_str(CMD_ERROR, "backup not found"); ret=-1; } if(tmppath1) { unlink(tmppath1); free(tmppath1); } if(tmppath2) { unlink(tmppath2); free(tmppath2); } if(regex) { regfree(regex); free(regex); } return ret; }
int do_restore_server(const char *basedir, const char *backup, const char *restoreregex, enum action act, const char *client, struct cntr *p1cntr, struct cntr *cntr, struct config *cconf) { int a=0; int i=0; int ret=0; int found=0; struct bu *arr=NULL; unsigned long index=0; char *tmppath1=NULL; char *tmppath2=NULL; regex_t *regex=NULL; bool all=FALSE; logp("in do_restore\n"); if(compile_regex(®ex, restoreregex)) return -1; if(!(tmppath1=prepend_s(basedir, "tmp1", strlen("tmp1"))) || !(tmppath2=prepend_s(basedir, "tmp2", strlen("tmp2")))) { if(tmppath1) free(tmppath1); if(regex) { regfree(regex); free(regex); } return -1; } if(get_current_backups(basedir, &arr, &a, 1)) { if(tmppath1) free(tmppath1); if(tmppath2) free(tmppath2); if(regex) { regfree(regex); free(regex); } return -1; } if(backup && *backup=='a') { all=TRUE; } else if(!(index=strtoul(backup, NULL, 10)) && a>0) { // No backup specified, do the most recent. ret=restore_manifest(arr, a, a-1, tmppath1, tmppath2, regex, act, client, p1cntr, cntr, cconf, all); found=TRUE; } if(!found) for(i=0; i<a; i++) { if(all || !strcmp(arr[i].timestamp, backup) || arr[i].index==index) { found=TRUE; //logp("got: %s\n", arr[i].path); ret|=restore_manifest(arr, a, i, tmppath1, tmppath2, regex, act, client, p1cntr, cntr, cconf, all); if(!all) break; } } // If doing all backups, send restore end. if(!ret && all && found) ret=do_restore_end(act, cntr); free_current_backups(&arr, a); if(!found) { logp("backup not found\n"); async_write_str(CMD_ERROR, "backup not found"); ret=-1; } if(tmppath1) { unlink(tmppath1); free(tmppath1); } if(tmppath2) { unlink(tmppath2); free(tmppath2); } if(regex) { regfree(regex); free(regex); } return ret; }