#!/usr/bin/perl
use strict;
use warnings;

# CONS
my $APL_VAR = $ENV{APL_VAR};
my $APL_USR = $ENV{APL_USR};
my $APL_HTTPD_GRP = $ENV{APL_HTTPD_GRP};
my $BCKTMP = "$APL_VAR/tmp/backup";
my $SLEEP = 2;
my $BCKDIR = "$APL_VAR/backup/master";
my $BACKUP_PID = "$APL_VAR/backup/master_backup.pid";
my $RESTORE_PID = "$APL_VAR/backup/master_restore.pid";
my $CLEANUP_TMT = 3600; # hourly
my $CLEANUP_MIN_SIZE = 50; # Start cleaning if temp dir grows over this size
my $KEEP_LOGS_DAYS_MIN = 30;

# VARS
my $last_cleanup_time = 0;

# SUB
sub move_uploaded_backups {
    opendir DH, "$BCKTMP" or die "Cannot opendir $BCKTMP: $!";
    my @files = grep { /\.(?:origin|mbck)$/ } readdir DH;
    closedir DH;
    foreach my $file (@files) {
	next unless $file=~/\.origin$/;
	open FH, "$BCKTMP/$file" or next;
	my %orig = map {/^(\w+)=(.*)$/} grep {/^\w+=/} <FH>;
	close FH;
	my $backup = $orig{backup};
	my $protected = $orig{protected};
	next unless $protected; # Skip unencrypted backups
	# Unpack backup to target location
	my ($bckname) = $backup =~ /^(\d{6}_\d{6})\.mbck$/;
	next unless $bckname;
	next unless -f "$BCKTMP/$backup";
	# Remove backup dir with the same name if exists
	system("/bin/rm -rf $BCKDIR/$bckname &>/dev/null") if -d "$BCKDIR/$bckname";
	system("/usr/bin/unzip -P X3ins1de -d $BCKDIR $BCKTMP/$backup &>/dev/null");
	if (open FH, ">$BCKDIR/$bckname/origin") {
	    print FH "$_=$orig{$_}\n" foreach sort grep {!/^backup$/} keys %orig;
	    close FH;
	}
	# Set ownership on backup dir so that apache can browse it
	system("/bin/chown -R $APL_USR:$APL_HTTPD_GRP $BCKDIR/$bckname &>/dev/null");
    }
    
    # Finally, erase all backups and origin files from tmp dir
    system("/bin/rm -f $BCKTMP/*.{origin,mbck} &>/dev/null") if @files;
}

sub cleanup {
    # Wait until master_backup or master_restore exits
    return if -f $BACKUP_PID or -f $RESTORE_PID;
    
    opendir DH, "$BCKTMP" or die "Cannot opendir $BCKTMP: $!";
    my @files = grep { ! /^\./ } readdir DH;
    closedir DH;
    foreach my $file (@files) {
	my $path = "$BCKTMP/$file";
	# Unlink backups that were not processed
	unlink $path if $file =~ /\.(?:mbck|origin|tmp)$/;
    }
    
    # Clean restore logs and other files if dir size exceeds pre-defined limit
    my ($dirsize) = `/usr/bin/du -m --max-depth=0 $BCKTMP 2>/dev/null` =~ /^(\d+)/;
    if ($dirsize >= $CLEANUP_MIN_SIZE) {
	# clean old logs
	system("/usr/bin/find -name '*.log' -mtime +$KEEP_LOGS_DAYS_MIN -delete");
	# clean rest
	system("/usr/bin/find -not -name '.' -not -name '*.log' -delete");
    }
    
    $last_cleanup_time = time;
}

# MAIN
while (1) {
    move_uploaded_backups;
    
    if (time - $last_cleanup_time > $CLEANUP_TMT) {
	cleanup;
    }
    sleep $SLEEP;
}
