summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@xinu.at>2016-08-12 13:16:39 +0200
committerFlorian Pritz <bluewind@xinu.at>2016-08-12 13:16:39 +0200
commitdfecf88f8181dc5078d0bc8fd8dd48301795d8cf (patch)
treee54df09272850014d6dd91ffbef6d684e6e3261b
parent7953b15584a18b199381a0d07712c1e916006715 (diff)
downloadbin-dfecf88f8181dc5078d0bc8fd8dd48301795d8cf.tar.gz
bin-dfecf88f8181dc5078d0bc8fd8dd48301795d8cf.tar.xz
borg-restore.pl: WIP
Signed-off-by: Florian Pritz <bluewind@xinu.at>
-rwxr-xr-xborg-restore.pl73
1 files changed, 49 insertions, 24 deletions
diff --git a/borg-restore.pl b/borg-restore.pl
index fd0de1d..f88fa1a 100755
--- a/borg-restore.pl
+++ b/borg-restore.pl
@@ -31,6 +31,7 @@ use v5.10;
package main;
use autodie;
+use Carp::Assert;
use Cwd qw(abs_path);
use Data::Dumper;
use DateTime;
@@ -40,6 +41,7 @@ use File::Basename;
use File::Copy;
use File::Path qw(mkpath);
use File::Slurp;
+use File::Temp;
use Getopt::Long;
use IO::Compress::Gzip qw($GzipError);
use IPC::Run qw(run start);
@@ -78,9 +80,6 @@ sub borg_list {
}
}
- splice @archives, 40;
- #splice @archives, 1, 1;
-
return \@archives;
}
@@ -96,8 +95,8 @@ sub find_archives {
my %seen_modtime;
my @ret;
- debug(sprintf("Found %d archive(s) with the following times for %s", @$modtimes+0, $path));
- debug(Dumper(@$modtimes));
+ #debug(sprintf("Found %d archive(s) with the following times for %s", @$modtimes+0, $path));
+ debug(Dumper($modtimes));
debug("Building archive list");
@@ -177,8 +176,11 @@ sub get_cache_path {
sub get_temp_path {
my $item = shift;
- # FIXME securely create temp dir here!!!
- return '/tmp/borg-restore-tmp'.$item;
+ state $tempdir_obj = File::Temp->newdir();
+
+ my $tempdir = $tempdir_obj->dirname;
+
+ return $tempdir."/".$item;
}
sub add_path_to_hash {
@@ -236,7 +238,6 @@ sub handle_removed_archives {
my $archives = shift;
my $previous_archives = shift;
my $borg_archives = shift;
- my $db_path = shift;
my $start = Time::HiRes::gettimeofday();
@@ -250,17 +251,29 @@ sub handle_removed_archives {
my $archive_index = get_archive_index($archive, $archives);
debug(sprintf("Removing archive %s at index %d", $archive, $archive_index));
+ splice @$archives, $archive_index, 1;
while (my ($path, $data) = each %db) {
# TODO remove archive indexes all at once
- splice @$data, $archive_index, 1;
- $db{$path} = sanitize_db_data($data);
+ if (@$data > 0) {
+ #print Dumper($path, 0+@$data, $data, $archives);
+ # TODO should probably store 0 instead of undef for unset values
+ assert($archive_index >= 0) if DEBUG;
+ assert($archive_index < @$data) if DEBUG;
+ splice @$data, $archive_index, 1;
+ if (@$data == 0) {
+ delete $db{$path};
+ } else {
+ $db{$path} = sanitize_db_data($data);
+ assert(@$data == @$archives) if DEBUG;
+ }
+ }
}
- splice @$archives, $archive_index, 1;
+ save_database($archives);
}
- clean_db();
-
+ clean_db($archives);
save_database($archives);
+
my $end = Time::HiRes::gettimeofday();
debug(sprintf("Removing archives finished after: %.5fs", $end - $start));
}
@@ -285,7 +298,6 @@ sub sanitize_db_data {
sub handle_added_archives {
my $archives = shift;
my $borg_archives = shift;
- my $db_path = shift;
my $add_archives = get_missing_items($archives, $borg_archives);
@@ -310,7 +322,7 @@ sub handle_added_archives {
}
$proc->finish() or die "borg list returned $?";
- save_node($archive_index, undef, $lookuptable);
+ save_node($archives, $archive_index, undef, $lookuptable);
save_database($archives);
@@ -326,7 +338,7 @@ sub save_database {
my $db_path_tmp = get_temp_path('archives.db.tmp');
my $db_path_new = get_cache_path('archives.db.new');
my $archive_cache = get_cache_path('archive_list');
- my $archive_cache_tmp = get_cache_path('archive_list.tmp');
+ my $archive_cache_tmp = get_temp_path('archive_list.tmp');
my $archive_cache_new = get_cache_path('archive_list.new');
debug("Saving temporary database to permanent location");
@@ -354,7 +366,6 @@ sub build_archive_cache {
my $db_path = get_cache_path('archives.db');
my $db_path_tmp = get_temp_path('archives.db.tmp');
my $archive_cache = get_cache_path('archive_list');
- my $archive_cache_tmp = get_cache_path('archive_list.tmp');
my $previous_archives = [];
my $archives = [];
@@ -378,14 +389,15 @@ sub build_archive_cache {
open_db_rw($db_path_tmp);
- handle_removed_archives($archives, $previous_archives, $borg_archives, $db_path_tmp);
- handle_added_archives($archives, $borg_archives, $db_path_tmp);
+ handle_removed_archives($archives, $previous_archives, $borg_archives);
+ handle_added_archives($archives, $borg_archives);
- print Dumper(0+keys %db, $db{"home/flo/TODO"});
- untie %db;
+ if ($opts{debug}) {
+ debug(sprintf("DB contains information for %d archives", scalar(@$archives)));
+ run([qw(echo count)], '|', ['gdbmtool', $db_path]);
+ }
- unlink($db_path_tmp);
- unlink($archive_cache_tmp);
+ untie %db;
}
sub open_db_rw {
@@ -399,6 +411,7 @@ sub cp {
}
sub save_node {
+ my $archives = shift;
my $archive_index = shift;
my $prefix = shift;
my $node = shift;
@@ -415,9 +428,10 @@ sub save_node {
}
$$data[$archive_index] = $$node[0]->{$child}[1];
+ assert(@$data == @$archives) if DEBUG;
$db{$path} = sanitize_db_data($data);
- save_node($archive_index, $path, $$node[0]->{$child});
+ save_node($archives, $archive_index, $path, $$node[0]->{$child});
}
}
@@ -438,12 +452,15 @@ sub get_mtime_from_lookuptable {
}
sub clean_db {
+ my $archives = shift;
+
while (my ($path, $data) = each %db) {
# check if data is empty or all fields in data are undef
if (!@$data || all { !defined($_) } @$data) {
debug("Deleting path because it's not part of any archive: ", $path);
delete $db{$path};
}
+ assert(@$data == @$archives) if DEBUG;
}
}
@@ -476,6 +493,14 @@ sub main {
my @paths = @ARGV;
+ # TODO only accept one source path
+ # <source path> [time spec] <destination path>
+ # handle destination path similar to rsync
+ # / at the end -> replace directory
+ # no / -> restore into directory
+ #
+ # time spec: take most recent backup that is at least $timespec old
+
#if (@paths > 1) {
#say STDERR "ERROR: more than one path is currently not supported";
#exit 1;