int datapoint_read(datapoint_t* p, int fd) { if ((timestamp_read(&p->t, fd) != 0) || (value_read(&p->v, fd) != 0)) return -1; return 0; }
static int check_interval( struct strlist *interval, const char *cname, const char *ctimestamp, time_t time_now) { char *cp; long min_time; long seconds=0; char tstmp[64]=""; char min_time_buf[64]=""; if((seconds=get_interval_in_seconds(interval->path, cname))<0) return -1; if(timestamp_read(ctimestamp, tstmp, sizeof(tstmp))) { logp("Could not read timestamp %s\n", ctimestamp); return 0; // Backup now. } min_time=timestamp_to_long(tstmp)+seconds; strftime(min_time_buf, sizeof(min_time_buf), DEFAULT_TIMESTAMP_FORMAT, localtime(&min_time)); cp=strchr(tstmp, ' '); if(cp) cp++; else cp=tstmp; logp("Last backup: %s\n", cp); logp("Next after : %s (interval %s)\n", min_time_buf, interval->path); if(min_time < time_now) return 0; return 1; }
int backup_phase4_server_burp1(struct sdirs *sdirs, struct conf *cconf) { int ret=-1; struct stat statp; ssize_t len=0; char realcurrent[256]=""; unsigned long bno=0; int hardlinked_current=0; char tstmp[64]=""; int previous_backup=0; struct fdirs *fdirs=NULL; if((len=readlink(sdirs->current, realcurrent, sizeof(realcurrent)-1))<0) len=0; realcurrent[len]='\0'; if(!(fdirs=fdirs_alloc()) || fdirs_init(fdirs, sdirs, realcurrent)) goto end; if(set_logfp(fdirs->logpath, cconf)) goto end; logp("Begin phase4 (shuffle files)\n"); if(write_status(STATUS_SHUFFLING, NULL, cconf)) goto end; if(!lstat(sdirs->current, &statp)) // Had a previous backup. { previous_backup++; if(lstat(fdirs->hlinkedcurrent, &statp)) { hardlinked_current=0; logp("Previous backup is not a hardlinked_archive\n"); logp(" will generate reverse deltas\n"); } else { hardlinked_current=1; logp("Previous backup is a hardlinked_archive\n"); logp(" will not generate reverse deltas\n"); } // If current was not a hardlinked_archive, need to duplicate // it. if(!hardlinked_current && lstat(fdirs->currentdup, &statp)) { // Have not duplicated the current backup yet. if(!lstat(fdirs->currentduptmp, &statp)) { logp("Removing previous directory: %s\n", fdirs->currentduptmp); if(recursive_delete(fdirs->currentduptmp, NULL, 1 /* del files */)) { logp("Could not delete %s\n", fdirs->currentduptmp); goto end; } } logp("Duplicating current backup.\n"); if(recursive_hardlink(sdirs->current, fdirs->currentduptmp, cconf) // The rename race condition is of no consequence here // because currentdup does not exist. || do_rename(fdirs->currentduptmp, fdirs->currentdup)) goto end; } } if(timestamp_read(fdirs->timestamp, tstmp, sizeof(tstmp))) { logp("could not read timestamp file: %s\n", fdirs->timestamp); goto end; } // Get the backup number. bno=strtoul(tstmp, NULL, 10); // Determine whether the new backup should be a hardlinked // archive or not, from the conf and the backup number... if(need_hardlinked_archive(cconf, bno)) { // Create a file to indicate that the previous backup // does not have others depending on it. FILE *hfp=NULL; if(!(hfp=open_file(fdirs->hlinked, "wb"))) goto end; // Stick the next backup timestamp in it. It might // be useful one day when wondering when the next // backup, now deleted, was made. fprintf(hfp, "%s\n", tstmp); if(close_fp(&hfp)) { logp("error closing hardlinked indication\n"); goto end; } } else unlink(fdirs->hlinked); if(atomic_data_jiggle(sdirs, fdirs, hardlinked_current, cconf, bno)) { logp("could not finish up backup.\n"); goto end; } if(write_status(STATUS_SHUFFLING, "deleting temporary files", cconf)) goto end; // Remove the temporary data directory, we have now removed // everything useful from it. recursive_delete(fdirs->datadirtmp, NULL, 1 /* del files */); // Clean up the currentdata directory - this is now the 'old' // currentdata directory. Any files that were deleted from // the client will be left in there, so call recursive_delete // with the option that makes it not delete files. // This will have the effect of getting rid of unnecessary // directories. sync(); // try to help CIFS recursive_delete(fdirs->currentdupdata, NULL, 0 /* do not del files */); // Rename the old current to something that we know to delete. if(previous_backup && !hardlinked_current) { if(deleteme_move(sdirs->client, fdirs->fullrealcurrent, realcurrent, cconf) // I have tested that potential race conditions on the // rename() are automatically recoverable here. || do_rename(fdirs->currentdup, fdirs->fullrealcurrent)) goto end; } if(deleteme_maybe_delete(cconf, sdirs->client)) goto end; cntr_stats_to_file(cconf->cntr, sdirs->finishing, ACTION_BACKUP); logp("End phase4 (shuffle files)\n"); ret=0; end: fdirs_free(fdirs); return ret; }