#!/usr/bin/perl -w

########################################################################
#
# Script to test how GNU tar will deal with exclusion in Amanda.
#                     (on@cs.ait.ac.th) Olivier Nicole - AIT - July 2006
#
# Configuration : you must edit the variable $gtar bellow and set it
# to the full pathname of the GNU tar program used by your
# configuration of Amanda. That should be a valid GNU tar program,
# other version of tar could give unexpected results.
#
# Usage: testgtar <exclude_file> <directory>
#
# Test the exclude patterns contained in the file <exclude_file> on the
# directory <directory>.
#
# The script will try to guess the version of tar in use. GNU tar will
# be detected as broken if a pattern of the form ./foo excludes a file
# that is not at the top of the hierachy being tared.
#
# Performance: this scripts makes several call to GNU tar:
#  - one call to guess if GNU tar is broken
#  - two calls for each exclude pattern (with and without exclude)
# so it is quite GNU tar intensive. On a dual Xeon 3.0 it runs in 30
# seconds for 2 patterns on a 27 GB directory.
#
########################################################################

# $gtar is the full pathname of the GNU tar program used by Amanda.
# 
# Example:
# $gtar="/usr/local/bin/tar";
#
# Because in a typical Unix installation, many different tar programs
# can coexist, it is not possible to automatically decide what GNU tar
# program is being used by Amanda.
# You can find a clue in the debug files created at run time by
# Amanda, the files should be in /tmp/amanda. Search for the pathname
# of the GNU tar program being used, that should be found in the files
# runtar.xxx.debug

$gtar="/usr/local/bin/gtar";

######################################
# Nothing to change bellow this line #
######################################

if (! defined $gtar || $gtar eq "") {
    print "You must edit this script and set the variable \$gtar 
at the begining of the script\n";
    exit;
}

if ($#ARGV!=1) {
    print "usage: $0 exclude_file directory\n";
    exit;
}

$exclude=$ARGV[0];
$directory=$ARGV[1];

if (! -d $directory) {
    print "The directory $directory does not exist\n";
    exit;
}

if (!((-f $exclude) || (-l $exclude))) {
    print "The exclude_file $exclude does not exist\n";
    exit;
}

if (!((-f $gtar) && (-x $gtar))) {
    print "The GNUTAR $gtar does not exist or is not executable\n";
    exit;
}

if (! open TAR, "$gtar --version 2>&1 |") {
    print "Cannot execute the GNUTAR command $gtar\n";
    exit;
}
$gnu=0;
$tar=0;
$version="";
while (<TAR>) {
    $gnu=1 if /gnu/i;
    $tar=1 if /tar/i;
    $version=$& if /\d+\.\d+(\.\d+)*/;
}
close TAR;

if (! $tar) {
    print "The GNUTAR $gtar does not seem to be a tar program.\n";
    exit;
}

if ($version) {
    print "Running tar version $version.\n";
}

if (! $gnu) {
    print "It seems that GNUTAR $gtar is not GNU but continuing anyway.\n";
}

# test if exclude-from is broken

if (! opendir DIR, $directory) {
    print "Cannot read the directory $directory.\n";
    exit;
}
$done=0;
while ($file=readdir DIR) {
    next if $file=~/^\.(\.)?$/;
    next unless -d "$directory/$file";
    next unless opendir DIR2, "$directory/$file";
    while ($file2=readdir DIR2) {
	next if $file2=~/^\.(\.)?$/;
	
	if (-f "$directory/$file/$file2") {
	    if (! open TMP, ">/tmp/testgtar$$") {
		print "Cannot open a temporary file in /tmp.\n";
		exit;
	    }
	    print TMP "./*$file2";
	    close TMP;
	    $checkname="./$file/$file2";
	    $done=1;
	    last;
	}
    }
    close DIR2;
    last if $done;
}
close DIR;

open TAR, "$gtar --create --file /dev/null --directory $directory --verbose --exclude-from /tmp/testgtar$$ --one-file-system --ignore-failed-read . 2>&1 |";

$broken=1;
while (<TAR>) {
    if (/^$checkname$/) {
	$broken=0;
	last;
    }
}
close TAR;
unlink "/tmp/testgtar$$";

if ($broken) {
    print "It seems that GNUTAR $gtar is broken, but continuing anyway.\n";
}

# Try to rewrite the exclude expressions
#
if (!open EXPR, "$exclude") {
    print "The exclude file $exclude is not readable.\n";
    exit;
}
while (<EXPR>) {
    next if /^\s*$/;
    open TMP, ">/tmp/testgtar$$";
    print TMP $_;
    close TMP;

    chop;
    print "\nFiles matching $_:\n";

    open FULL, "$gtar --create --file /dev/null --directory $directory --verbose --one-file-system --ignore-failed-read . 2>&1 |";
    
    open EXCL, "$gtar --create --file /dev/null --directory $directory --verbose --exclude-from /tmp/testgtar$$ --one-file-system --ignore-failed-read . 2>&1 |";
    while (<EXCL>) {
	$excl=$_;
	while (<FULL>) {
	    if ($_ ne $excl) {
		print $_;
	    }
	    else {
		last;
	    }
	}
    }
    close EXCL;
    close FULL;
   unlink "/tmp/testgtar$$";
}
close EXPR;
