#!/usr/bin/perl
use warnings;
use strict;
use Simba::CA;
use POSIX qw(strftime);
use Getopt::Long;
use Filesys::Statvfs;
use File::stat;

my @filesets;

GetOptions('filesets=i' => \@filesets);
@filesets = split(/,/,join(',',@filesets));

$ENV{PATH} = "/usr/bin";

my $now = strftime('%Y-%m-%dT%H:%M:%S', localtime());
open(my $log, '>>', '/var/log/simba/ca.log.' . $now);
$log->autoflush(1);

my $ca = Simba::CA->new({
			    dbi_file => $ENV{SIMBA_DB_CONN} || "$ENV{HOME}/.dbi/simba",
			    fh_log   => $log,
			    (@filesets ? ( filesets => \@filesets ) : ()),
			});
$ca->log_level(9);

# Try to find all devices suitable for backup and mount them.
# We do this by trying to find a matching device for each subdirectory
# of /backup. Another way might be to check all USB disks.
my $st = stat("/backup/");
my $base_device = $st->dev;
for (glob("/backup/*")) {
    my $st = stat($_);
    my $dir_device = $st->dev;
    $ca->log(0, "checking $_");
    if ($base_device == $dir_device) {
        # not a mount point
        (my $basedir = $_) =~ s{^/backup/}{};
        if (-e "/dev/disk/by-id/$basedir") {
            # matching device exists
	    $ca->log(0, "mounting /dev/disk/by-id/$basedir on $_");
            system("/bin/mount", "-o", "nodev,noexec,nomand,nosuid", "/dev/disk/by-id/$basedir", $_);
        }
    }
}


# find the backup dir with the most free space available.
# other strategies are possible, like round robin, or daily, weekly,
# etc. backups.

my @backup_dirs = map {
			$_ = $1 if m{(.*)/.*}; # basedir and detaint
			my($bsize, $frsize, $blocks, $bfree, $bavail,
			   $files, $ffree, $favail, $flag, $namemax)
			    = statvfs($_);
			my $available_bytes = $bsize * $bavail;
			my $avg_file_size = $bavail * ($blocks - $bfree) / ($files - $ffree);
			my $available_bytes_by_files = $avg_file_size * $favail;
			$available_bytes = $available_bytes_by_files if $available_bytes_by_files < $available_bytes;
			[ $_, $available_bytes ]
                      } glob("/backup/*/active");
my $sum_free = 0;
$sum_free += $_->[1] for (@backup_dirs);
my $rnd = rand() * $sum_free;
my $count_free = 0;
my $backup_dir;
for(@backup_dirs) {
    $count_free += $_->[1];
    $ca->log(3, "considering base $_->[0] (est. $_->[1] bytes)\n");
    if ($count_free >= $rnd) {
	$backup_dir = $_->[0];
	$ca->log(3, "using base $_->[0]\n");
	last;
    }
}
unless ($backup_dir) {
    $ca->log(0, "no backup directory found");
    exit(1);
}
$ca->basedir($backup_dir);

$ca->run();