#############################################################################
#
# Copyright Avaya Inc., All Rights Reserved.
#
# THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Avaya Inc.
#
# The copyright notice above does not evidence any actual or intended
# publication of such source code.
#
# Some third-party source code components may have been modified from their
# original versions by Avaya Inc.
#
# The modifications are Copyright Avaya Inc., All Rights Reserved.
#
#############################################################################
package         backup_verification;
require         Exporter;

our @ISA        = qw(Exporter);
our @EXPORT     = qw(   BACKUP_PATH
                        check_dir_list
                        check_file_list
                        check_wild_list
                        handle_extra_os_items
                        handle_extra_security_items
                        open_ds_file
                        print_list
                        process_ds_file
                        process_restore_list
                        verify_restore_files
                        verify_restore_files_list
                        verify_restore_files_migration);
our $VERSION    = 0.01;

use strict;
use warnings;

sub check_dir_list($@);
sub check_file_list($@);
sub check_wild_list($@);
sub handle_extra_os_items($);
sub handle_extra_security_items($);
sub open_ds_file($$);
sub print_list(@);
sub process_ds_file($$$$$);
sub process_restore_list($$$$$);
sub verify_restore_files($$$$);
sub verify_restore_files_list($$@);
sub verify_restore_files_migration($$);

use constant BACKUP_PATH => '/etc/opt/ecs/backup';



#############################################################################
#
# function:     verify_restore_files($$$$)
#
# description:  Verify that the files in the restore tarfile are all allowed
#               to be restored according to the dataset *_ds.conf file.  The
#               dataset argument will specify os, xln, or security datasets.
#               The tarfile_path argument will contain the full path to the
#               tarfile that is being restored.  The next argument
#               is a reference to the array that will store any files that
#               should be ignored during a restore.  Finally, the last 
#               argument is the path where the *_ds.conf file is found.
#       
#               Essentially, the function compares the *_ds.conf list to the
#               list of files in the restore tarball.  If the tarball has
#               extra files, these files will be ignored during the restore.
#
# special considerations:
#               None
#
#############################################################################

sub verify_restore_files($$$$)
{
    # Get the variables to be passed in.  Should be
    # a dataset type, a path to the restore file, and
    # a reference to the array that will contain the
    # eventual list of files to ignore. Also, get the
    # path where the ds file should be found.
    my ($dataset, $tarfile_path, $ignore_list_ref, $ds_path) = @_;

    # Create some lists to store the different types
    # of files that we might find in the *_ds.conf.  We could
    # have directories, files, wildcard files, and some unknown
    # names as well.
    my @ds_dir_list;
    my @ds_file_list;
    my @ds_wild_list;
    my @ds_unknown_list;

    # Set the local path to something safe, in case the caller is using
    # taint mode.
    local $ENV{PATH} = '/bin';

    # Make sure the dataset variable is a type that we expect.
    if ($dataset !~ m/^(os|security|xln|audix-.*)$/)
    {
        print STDERR 'Invalid dataset type. You can use os, security' . 
                     ", xln, or audix sets.\n";
        return 1;
    }

    # The dataset variable is valid, so construct the path to the actual
    # ds.conf file and copy the contents into an array.
    my $ds_file = $ds_path . '/' . $1 . '_ds.conf';
    my @infile;
    my $rc = open_ds_file($ds_file, \@infile);
    if($rc != 0)
    {
        # We encountered an error opening the file. Just return.
        return $rc;
    }

    # Process the *_ds.conf file list.
    process_ds_file(\@infile, \@ds_dir_list, \@ds_file_list, \@ds_unknown_list,
                    \@ds_wild_list);

    # Next, get the list of files from the backup set. 
    @{$ignore_list_ref} = `/bin/tar -tzf $tarfile_path`;
    my $return_code = $? >> 8;
    if ($return_code != 0)
    {
        print STDERR 'The file specified does not exist or is not ' .
                     'an archive file: ' . "$tarfile_path\n";
        return 1;
    }

    # Get rid of extra newlines.
    chomp(@{$ignore_list_ref});

    # Process the restore list, and whatever is left in the ignore_list_ref
    # are the files that should be ignored during the restore.
    process_restore_list($ignore_list_ref, \@ds_file_list, \@ds_dir_list,
                         \@ds_unknown_list, \@ds_wild_list);


    # If this is the security set, we need to weed out a couple additional
    # files that could legally be in the dataset.
    if("$dataset" eq 'security')
    {
        handle_extra_security_items($ignore_list_ref);
    }

    # If this is the os set, we need to weed out a couple additional
    # files that could legally be in the dataset.
    if("$dataset" eq 'os')
    {
        handle_extra_os_items($ignore_list_ref);
    }

    # If we get here, return 0 for success.
    return 0;
}



#############################################################################
#
# function:     verify_restore_files_list($$@)
#
# description:  Verify that the files in the restore tarfile are all allowed
#               to be restored according to the file list that is provided.
#               The tarfile_path argument will contain the full path to the
#               tarfile that is being restored.  The next argument
#               is a reference to the array that will store any files that
#               should be ignored during a restore.  Finally, the last 
#               argument is the list of files and directories that are legal.
#       
#               Essentially, the function compares the provided list to the
#               list of files in the restore tarball.  If the tarball has
#               extra files, these files will be ignored during the restore.
#
# special considerations:
#               None
#
#############################################################################

sub verify_restore_files_list($$@)
{
    # Get the variables to be passed in.  Should be
    # a path to the restore file, a reference to the array 
    # that will contain the eventual list of files to ignore,
    # and a list of legal files. 
    #
    # NOTE: the legal_files array is expected to be similar to a
    #       ds.conf file listing.  For example:
    #       /etc/hosts
    #       /var/home
    #       /etc/login.defs
    #       /etc/sysconfig/network-scripts/ifcfg-*
    #
    #       It should be a list of files, directories, and wildcards
    #       that are legal for restoring. The process_ds_file
    #       function will work equally well for a regular list as it
    #       does for a list representing a *_ds.conf file.
    my ($tarfile_path, $ignore_list_ref, @legal_files) = @_;

    # Create some lists to store the different types
    # of files that we might find in the legal_files list.  We could
    # have directories, files, wildcard files, and some unknown
    # names as well.
    my @ds_dir_list;
    my @ds_file_list;
    my @ds_wild_list;
    my @ds_unknown_list;

    # Set the local path to something safe, in case the caller is using
    # taint mode.
    local $ENV{PATH} = '/bin';

    # Process the *_ds.conf file list.
    process_ds_file(\@legal_files, \@ds_dir_list, \@ds_file_list,
                    \@ds_unknown_list, \@ds_wild_list);

    # Next, get the list of files from the backup set. 
    @{$ignore_list_ref} = `/bin/tar -tzf $tarfile_path`;
    my $return_code = $? >> 8;
    if ($return_code != 0)
    {
        print STDERR 'The file specified does not exist or is not ' .
                     'an archive file: ' . "$tarfile_path\n";
        return 1;
    }

    # Get rid of extra newlines.
    chomp(@{$ignore_list_ref});

    # Process the restore list, and whatever is left in the ignore_list_ref
    # are the files that should be ignored during the restore.
    process_restore_list($ignore_list_ref, \@ds_file_list, \@ds_dir_list,
                         \@ds_unknown_list, \@ds_wild_list);

    # If we get here, return 0 for success.
    return 0;
}



#############################################################################
#
# function:     verify_restore_files_migration($$)
#
# description:  Verify that the files in the migration tarfile are all allowed
#               to be restored according to the file list that is made of 
#               all the other ds file lists being concatenated together.
#               The tarfile_path argument will contain the full path to the
#               tarfile that is being restored.  The next argument
#               is a reference to the array that will store any files that
#               should be ignored during a restore.
#
# special considerations:
#               None
#
#############################################################################

sub verify_restore_files_migration($$)
{
    # Get the variables to be passed in.  Should be
    # a path to the restore file and a reference to the array 
    # that will contain the eventual list of files to ignore.
    my ($tarfile_path, $ignore_list_ref) = @_;

    # Create some lists to store the different types
    # of files that we might find in the legal_files list.  We could
    # have directories, files, wildcard files, and some unknown
    # names as well.
    my @ds_dir_list;
    my @ds_file_list;
    my @ds_wild_list;
    my @ds_unknown_list;

    # Set the local path to something safe, in case the caller is using
    # taint mode.
    local $ENV{PATH} = '/bin';

    # In the case of a migration set, we are not sure which files could
    # potentially be included, so as a safeguard, we will concatenate
    # the os, security, and xln ds_files into one list to use for
    # verification.

    # Start out with the os dataset.
    my $backup_path = BACKUP_PATH;
    my @migration_list = `/bin/cat $backup_path/os_ds.conf`;

    # Add the security dataset.
    my @add_list = `/bin/cat $backup_path/security_ds.conf`;
    push(@migration_list, @add_list);

    # Finally, add the xln dataset.  All sets should be in the migration
    # list at this point.
    @add_list = `/bin/cat $backup_path/xln_ds.conf`;
    push(@migration_list, @add_list);

    # Process the *_ds.conf file list.
    process_ds_file(\@migration_list, \@ds_dir_list, \@ds_file_list,
                    \@ds_unknown_list, \@ds_wild_list);

    # Next, get the list of files from the backup set. 
    @{$ignore_list_ref} = `/bin/tar -tzf $tarfile_path`;
    my $return_code = $? >> 8;
    if ($return_code != 0)
    {
        print STDERR 'The file specified does not exist or is not ' .
                     'an archive file: ' . "$tarfile_path\n";
        return 1;
    }

    # Get rid of extra newlines.
    chomp(@{$ignore_list_ref});

    # Process the restore list, and whatever is left in the ignore_list_ref
    # are the files that should be ignored during the restore.
    process_restore_list($ignore_list_ref, \@ds_file_list, \@ds_dir_list,
                         \@ds_unknown_list, \@ds_wild_list);

    # Since this is a migration, we have six extra files that we can 
    # remove from the ignore list.  Actually, there are really only
    # three extras, but the initial migration testing found that they
    # may or may not start with a leading slash, so it is just best
    # to plan for any case.
    my @extra_files = ('/var/tmp/ecs_migrate', 
                       '/var/tmp/ecs_full_migrate',
                       '/var/tmp/lsfile_full_migrate',
                       'var/tmp/ecs_migrate', 
                       'var/tmp/ecs_full_migrate',
                       'var/tmp/lsfile_full_migrate');

    # Loop through the ignore list one last time and remove any of the
    # additional files in the extra_files list.
    my $i;
    for($i = 0; $i <= $#{$ignore_list_ref}; $i++)
    {
        if(check_file_list(${$ignore_list_ref}[$i], @extra_files) == 1)
        {
            # Remove the line from the ignore list.
            splice @{$ignore_list_ref}, $i, 1;
            $i--;
        }
    }

    # Also remove any additional files that might get included on the fly.
    # These might also be valid for a migration set.
    handle_extra_security_items($ignore_list_ref);
    handle_extra_os_items($ignore_list_ref);

    # If we get here, return 0 for success.
    return 0;
}



#############################################################################
#
# function:     handle_extra_security_items($)
#
# description:  If this is the security set, this function is called to
#               look through the leftover files in the ignore list to make
#               sure that none of them are other files that should still
#               be ok.  These other files are typically added to the 
#               security_ds.conf dynamically during the prebackup.
#
# special considerations:
#               None
#
#############################################################################

sub handle_extra_security_items($)
{
    my ($ignore_list_ref) = @_;

    # All of these files and directories are added during 
    # the security prebackup.
    my @extra_files = (
        '/etc/sd_pam.conf',
        '/etc/pam_safeword.cfg',
        '/etc/motd',
        '/etc/asg/asgfile',
        '/etc/esd.d/esd.ini',
        '/etc/esd.d/ldap.conf',
        '/etc/esd.d/cacert.pem',
        '/etc/esd.d/clientcert.pem',
        '/etc/opt/ecs/lsfile',
        '/etc/esd.d/keys.pem',
        '/var/home/defty/.hushlogin'
    );
    my @extra_dirs = ('/etc/aaa', '/var/ace');
    my @extra_wilds = ('/etc/opt/ecs/webProfiles/xmlWebProfile_*.conf');
    my @extra_unknowns = ();

    # Put dots in front of the ignore_list items that start with / in
    # order for process_restore_list to handle them correctly.
    my $i;
    for($i = 0; $i <= $#{$ignore_list_ref}; $i++)
    {
        if(${$ignore_list_ref}[$i] =~ m/(\/.*)/i)
        {
            ${$ignore_list_ref}[$i] = ".$1";
        }
    }

    # Process the restore list again with the additional files we have
    # listed above.
    process_restore_list($ignore_list_ref, \@extra_files, \@extra_dirs,
                         \@extra_unknowns, \@extra_wilds); 
}



#############################################################################
#
# function:     handle_extra_os_items($)
#
# description:  If this is the os set, this function is called to
#               look through the leftover files in the ignore list to make
#               sure that none of them are other files that should still
#               be ok.  These other files are typically added to the 
#               os_ds.conf dynamically during the prebackup.
#
# special considerations:
#               None
#
#############################################################################

sub handle_extra_os_items($)
{
    my ($ignore_list_ref) = @_;

    # These files get added in the ewl_chk file in the prebackup.
    my @extra_files = (
        '/etc/opt/ecs/alsfile',
        '/tftpboot/46xxsettings.txt',
        '/etc/opt/ecs/backup/ssh_knownhosts',
        '/etc/weburl.conf',
        '/etc/snmp/mvmgt.conf'
    );
    my @extra_dirs = ();
    my @extra_unknowns = ();
    my @extra_wilds = ();
    
    # Put dots in front of the ignore_list items that start with / in
    # order for process_restore_list to handle them correctly.
    my $i;
    for($i = 0; $i <= $#{$ignore_list_ref}; $i++)
    {
        if(${$ignore_list_ref}[$i] =~ m/(\/.*)/i)
        {
            ${$ignore_list_ref}[$i] = ".$1";
        }
    }

    # Process the restore list again with the additional files we have
    # listed above.
    process_restore_list($ignore_list_ref, \@extra_files, \@extra_dirs,
                             \@extra_unknowns, \@extra_wilds); 
}



#############################################################################
#
# function:     process_restore_list($$$$$)
#
# description:  This function goes through the files in the ignore list and
#               removes any of them that are ok to restore.  Note that in
#               an ideal restore situation, all of the files will be removed
#               from the list and subsequently restored.  
#
#               The remaining files in the ignore list will be used by
#               the calling function to know which files should not be
#               unpacked from the tar file.
#
# special considerations:
#               None
#
#############################################################################

sub process_restore_list($$$$$)
{
    # Get the list references that were passed in.
    my ($ignore_list_ref, $file_list_ref, $dir_list_ref, $unknown_list_ref,
        $wild_list_ref) = @_;

    # Loop through the list and compare in this order:
    #   1. Files
    #   2. Starts with a directory
    #   3. Matches a file from the wild list
    #   4. Matches a file on the unknown list
    #   5. Starts with a string (dir) from the unknown list
    #   6. Whatever is left should be ignored during the restore
    my $i = 0;
    my $backup_path = BACKUP_PATH;
    FILE: for($i = 0; $i <= $#{$ignore_list_ref}; $i++)
    {

        # Remove the trailing spaces and make sure the format looks correct.
        if(${$ignore_list_ref}[$i] =~ m/^\.?(\/?.*)\s*$/i)
        {
            ${$ignore_list_ref}[$i] = $1;
        }
        else
        {
            # The way that tar and backup currently work, we should not ever
            # end up in this block.  However, just in case we do, we should
            # issue some kind of warning to indicate possible malfunction.
            print STDERR 'Strange file found during restore list processing' .
                         ": ${$ignore_list_ref}[$i]\n";
            next FILE;
        }

        # Make sure that the pattern starts with a slash.  This is being
        # introduced because audix tarfiles are a little different.
        if(${$ignore_list_ref}[$i] !~ m/^\/.*$/)
        {
            ${$ignore_list_ref}[$i] = '/' . ${$ignore_list_ref}[$i];
        }

        # Discard any files that contain a sequence of /../ that would
        # indicate some sort of malicious archive.  I don't this this
        # will ever happen, but it is best to be safe at the beginning.
        if(${$ignore_list_ref}[$i] =~ m/\/\.\.\//i)
        {
            print STDERR 'File contains illegal pattern (/../): ' .
                         "${$ignore_list_ref}[$i]\n";
            next FILE;
        }

        # Discard the info file.
        if(${$ignore_list_ref}[$i] =~ m/^$backup_path.*\.info$/i)
        {
            # Remove the line from the ignore list.
            splice @{$ignore_list_ref}, $i, 1;
            $i--;
            next FILE;
        }

        # See if this file matches a file in the file list.
        if(check_file_list(${$ignore_list_ref}[$i], @$file_list_ref) == 1)
        {
            # Remove the line from the ignore list.
            splice @{$ignore_list_ref}, $i, 1;
            $i--;
            next FILE;
        }

        # See if this file matches a dir in the dir list.
        if(check_dir_list(${$ignore_list_ref}[$i], @$dir_list_ref) == 1)
        {
            # Remove the line from the ignore list.
            splice @{$ignore_list_ref}, $i, 1;
            $i--;
            next FILE;
        }

        # See if this file matches a wildcard pattern.
        if(check_wild_list(${$ignore_list_ref}[$i], @$wild_list_ref) == 1)
        {
            # Remove the line from the ignore list.
            splice @{$ignore_list_ref}, $i, 1;
            $i--;
            next FILE;
        }

        # See if this file matches an unknown pattern as a file.
        if(check_file_list(${$ignore_list_ref}[$i], @$unknown_list_ref) == 1)
        {
            # Remove the line from the ignore list.
            splice @{$ignore_list_ref}, $i, 1;
            $i--;
            next FILE;
        }

        # See if this file matches an unknown pattern as a directory.
        if(check_dir_list(${$ignore_list_ref}[$i], @$unknown_list_ref) == 1)
        {
            # Remove the line from the ignore list.
            splice @{$ignore_list_ref}, $i, 1;
            $i--;
            next FILE;
        }

        # At this point, the file will remain in the ignore list, and this
        # is exactly how it is intented to work.
    }
}



#############################################################################
#
# function:     open_ds_file($$)
#
# description:  Opens the *_ds.conf file specified and extracts its contents.
#
# special considerations:
#               None
#
#############################################################################

sub open_ds_file($$)
{
    # Get the path to the ds.conf file and the reference to the array.
    my ($ds_file, $infile) = @_;

    # Make sure the file exists and is a regular file. 
    if( ! -f $ds_file)
    {
        # Not a regular file or does not exist.
        print STDERR 'Dataset file does not exist or is not a ' .
                     'regular file: ' . "$ds_file\n";
        return 1;
    }

    # Open the file so we can get a list of files from it.
    if(!open(INFILE, $ds_file))
    {
        # If the file cannot be opened, print an error and exit.
        print STDERR "Error opening $ds_file\n";
        return 2;
    }

    # Store the data in an array and close the file.
    @$infile = <INFILE>;
    close(INFILE);

    # If we get here, return 0 for success.
    return 0;
}



#############################################################################
#
# function:     process_ds_file($$$$$)
#
# description:  Splits the data in the *_ds.conf file into 4 lists.  It 
#               chooses the correct list by first checking to see if it is
#               a directory, then checking to see if it is a regular file,
#               then seeing if it matches a non-wildcard string, and 
#               finally checking to see if it matches a wildcard.  Any lines
#               that make it through all the tests cause a warning to be
#               be displayed.
#
# special considerations:
#               None
#
#############################################################################

sub process_ds_file($$$$$)
{
    # Get the local list reference variables that we are expecting.
    my ($infile_ref, $dir_list_ref, $file_list_ref, $unknown_list_ref,
        $wild_list_ref) = @_;

    # Remove extra newlines.
    chomp(@$infile_ref);

    # At this point, we have all the contents of the file in the array.
    # Now let's loop through the array and process files and directories.
    my $line = '';
    LINE: foreach $line (@$infile_ref)
    {
        # Ignore lines that don't start with a full path.
        if($line !~ m/^\//i)
        {
            next LINE;
        }

        # Get rid of extra space characters at the end of the line.
        $line =~ s/\s+$//;

        # Get rid of any trailing / characters.
        $line =~ s/\/$//;

        # Check for a valid directory.
        if( -d $line) 
        {
            # Push the valid directory into the array, and continue 
            # to the next line.
            push @$dir_list_ref,$line;
            next LINE;
        }
        elsif( -f $line)
        {
            # Valid file found, so push it into the file array and continue.
            push @$file_list_ref,$line;
            next LINE;
        }
        elsif($line =~ m/^(\/[-\w_\.\+\/]+)\s*$/i)
        {
            # Valid unknown type found, so push it into the unknown 
            # array and continue.
            push @$unknown_list_ref,$1;
            next LINE;
        }
        elsif($line =~ m/^(\/[-\w_\.\+\/\*]+)\s*$/i)
        {
            # Valid wildcard found, so push it into the wild 
            # array and continue.
            push @$wild_list_ref,$1;
            next LINE;
        }
        else
        {
            # Must be some other strange type of file. I don't think we
            # should ever get here, but we should be ready to handle
            # it just in case. The plan is to print an error message to
            # warn the user of this issue.
            print STDERR 'Strange file type encountered in ds file: ' .
                         "$line...\n";
            next LINE;
        }
    }
}



#############################################################################
#
# function:     check_wild_list($@)
#
# description:  See if the filename stored in arg1 matches any of the 
#               wildcards in the list kept in arg2.  
#
# special considerations:
#               The only character that is expected to be expanded in this
#               function is the *.  Other characters with special meaning
#               are taken literally with the backslash character.
#
#############################################################################

sub check_wild_list($@)
{
    my ($search_file, @list_of_wildcards) = @_;

    # Note: an obvious optimization would be to process all the wildcards
    # and save them in a list, and then send that list to this function
    # and not have to add the backslashes here.  However, this will not
    # really affect performance greatly, and therefore it is not necessary
    # at this time.
    my $wild;
    LOOP: foreach $wild (@list_of_wildcards)
    {
        # See if the filename matches this wildcard pattern. First, we
        # need to quote out the characters that will be interpreted.  We
        # only want the * character to be interpreted, so build a new
        # string.

        # First, make sure the wildcard doesn't have any unexpected chars.
        # In the future, if this subset is too strict, we can enhance
        # this routine to just quote every possible metacharacter with
        # a backslash before evaluating the expression.
        if($wild !~ m/^[-_\w+*.\/]+$/)
        {
            next LOOP;
        }
        
        # First, put a backslash before any slash.
        $wild =~ s/\//\\\//g;

        # Next, put a backslash before any plus sign.
        $wild =~ s/\+/\\\+/g;

        # Next, put a backslash before any period.
        $wild =~ s/\./\\\./g;

        # Next, put an end of item metacharacter at the end.
        $wild =~ s/$/\$/g;

        # Finally, add a period in front of the * character to match
        # the patterns.  In the future, if we don't want to allow
        # any additional directories to be expanded, we should use
        # the next couple commands that are commented out to prevent
        # a slash in the expansion.  For now, we will just weed
        # out files that have a /../ in them in the verify_restore_files
        # function.
        $wild =~ s/\*/\.\*/g;

        # Next, limit the * character to anything that does not include
        # an extra directory.  This prevents *'s at the end of the line
        # from allowing "../" to get back to other important files.
        #$wild =~ s/\*/[\^\\\/]\*/g;

        # Finally, see if it matches.
        if($search_file =~ m/^$wild/)
        {
            return 1;
        }
    }

    # If we get here, we didn't find it, so return 0.
    return 0;
}



#############################################################################
#
# function:     check_dir_list($@)
#
# description:  Examines the filename in arg1 to see if it begins with any
#               of the directories stored in the list in arg2. Returns 1
#               if a match is found, 0 otherwise.
#
# special considerations:
#               None
#
#############################################################################

sub check_dir_list($@)
{
    # Copy the arguments to local variables.  The $search_file is the name
    # that we will examine to see if it starts with one of the values in
    # the @list_of_dirs.
    my ($search_file, @list_of_dirs) = @_;

    # Look at each dir in the list of dirs.
    my $dir;
    LOOP: foreach $dir (@list_of_dirs)
    {
        # See if the filename starts with this directory followed by '/'.
        # The \Q and \E make the $dir variable be taken literally and
        # not expanded (so a '+' sign in the directory name is not taken 
        # to be part of the regex).
        if($search_file =~ m/^\Q$dir\E\//)
        {
            # Found it, so return 1 for success.
            return 1;
        }
    }

    # If we get here, we didn't find it, so return 0.
    return 0;
}



#############################################################################
#
# function:     check_file_list($@)
#
# description:  Looks for the filename held by arg1 in the list of filenames
#               held in arg2.  Returns 1 if the filename is found.  Returns
#               0 if the filename is not found in the list.
#
# special considerations:
#               None
#
#############################################################################

sub check_file_list($@)
{
    # Copy the arguments to local variables. The $search_file is the file
    # we are looking for in the @list_of_files.
    my ($search_file, @list_of_files) = @_;

    # Look through each file in the list of files.
    my $file;
    LOOP: foreach $file (@list_of_files)
    {
        # See if the search file matches this particular file. If it
        # does, return 1 for success.
        if("$search_file" eq "$file") 
        {
            return 1;
        }
    }

    # If we get here, we didn't find it, so return 0.
    return 0;
}



#############################################################################
#
# function:     print_list(@)
#
# description:  Prints out the items in the list passed into the function.  
#               This is really only needed for debugging.
#
# special considerations:
#               None
#
#############################################################################

sub print_list(@)
{
    # Copy the list to a local variable.
    my @list = @_;

    # Print out the name of each file in the list that is passed in.
    foreach my $file (@list)
    {
        print "$file\n";
    }
}



