#! /usr/bin/perl

my $prefix;
my $datarootdir;
my $datadir;
my $openssl="/usr/bin/openssl";

BEGIN {
    if (exists $ENV{GLOBUS_LOCATION}) {
        $prefix = $ENV{GLOBUS_LOCATION};
    } else {
        $prefix = '/usr';
    }
    $datarootdir="${prefix}/share";
    $datadir="/usr/share";
}

use strict;
use Getopt::Long;

my $ca_dir = undef;
my $help = 0;
my @ca_dir_options = (
        "$ENV{HOME}/.globus/certificates",
        "/etc/grid-security/certificates",
        "$datadir/certificates");

if (exists($ENV{X509_CERT_DIR}))
{
    $ca_dir = $ENV{X509_CERT_DIR};
}

my $result = GetOptions("d=s" => \$ca_dir, "help" => \$help);


if (!$result)
{
    exit(1);
}

if ($help)
{
    print "Usage: $0 [-d TRUSTED-CA-DIR] [-help]\n";
    exit(0);
}

if (!defined($ca_dir))
{
    foreach my $dir (@ca_dir_options)
    {
        if (!defined($dir))
        {
            next;
        }
        if (-d "$dir/.")
        {
            $ca_dir = $dir;
            last;
        }
    }
}

if (!defined($ca_dir))
{
    print STDERR "Error determining trusted CA directory\n";
    exit(1);
}

print "Updating CA hashes in $ca_dir\n";
if (!-w $ca_dir)
{
    print "Error writing to $ca_dir\n";
    exit(1);
}

chdir $ca_dir;

my %hashmaps = ();
my @files = ();
my $file;

select STDOUT;
$|=1;
print "Checking files";
foreach $file (<*>)
{
    push(@files, $file);

    if ($file =~ m|^([a-f0-9]+).[0-9]+$| && ! -l $file)
    {
        my $oldhash = $1;
        my $hash = `"$openssl" x509 -in $file -noout -hash`;
        chomp($hash);

        print ".";
        if ($oldhash ne $hash && !exists($hashmaps{$oldhash}))
        {
            $hashmaps{$oldhash} = $hash;
        }
    }
}
print "\n";

if (scalar(keys %hashmaps) == 0)
{
    print "Nothing to do\n";
    exit(0);
}

print "Linking files";
my $errors = "";
foreach $file (@files)
{
    my $new_file = $file;

    for my $hash (keys %hashmaps)
    {
        if ($new_file =~ m/$hash/)
        {
            my $newhash = $hashmaps{$hash};
            $new_file =~ s/$hash/$newhash/;
            if (-l $new_file)
            {
                unlink($new_file);
            }
            if (!symlink($file, $new_file))
            {
                $errors .= "symlink($file, $new_file) failed: $!\n";
            }
            print ".";
        }
    }
}
print STDERR $errors if $errors ne "";
print "\nDone\n";
exit(1) if $errors ne "";
