blob: 6931b37bff4ae8549b7fe460feafc3556b327309 [file] [log] [blame]
#**************************************************************
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
#**************************************************************
package installer::patch::FileOperations;
use File::Basename;
use File::Copy;
use IO::Compress::Bzip2;
use IO::Uncompress::Bunzip2;
my $CompressionMethod = "bzip2";
=head1 NAME
package installer::patch::FileOperations - Class for collecting, checking and executing file operations.
=cut
sub new ($)
{
my ($class) = (@_);
my $self = {
'operations' => []
};
bless($self, $class);
return $self;
}
sub AddCopyOperation ($$$)
{
my ($self, $source_name, $target_name) = @_;
push
@{$self->{'operations'}},
[
'copy',
$source_name,
$target_name
];
}
sub AddMakeDirectoryOperation ($$)
{
my ($self, $path) = @_;
push
@{$self->{'operations'}},
[
'mkdir',
$path
];
}
sub AddCompressOperation ($$)
{
my ($self, $filename) = @_;
push
@{$self->{'operations'}},
[
'compress',
$filename
];
}
sub AddUncompressOperation ($$$)
{
my ($self, $source_name, $target_name) = @_;
push
@{$self->{'operations'}},
[
'uncompress',
$source_name,
$target_name
];
}
sub Check ($)
{
my ($self) = @_;
# Keep track of which directories or files would be created to check if
# operations that depend on these files will succeed.
my %files = ();
my %directories = ();
my @error_messages = ();
foreach my $operation (@{$self->{'operations'}})
{
my $command = $operation->[0];
if ($command eq "copy")
{
my ($source_name, $destination_name) = ($operation->[1], $operation->[2]);
if ( ! -f $source_name)
{
push @error_messages, sprintf("%s is not a regular file and can not be copied", $source_name);
}
my $destination_path = dirname($destination_name);
if ( ! -d $destination_path && ! defined $directories{$destination_path})
{
push @error_messages, sprintf("destination path %s does not exist", $destination_path);
}
if ( -f $destination_name)
{
# The destination file already exists. We have to overwrite it.
if ( ! -w $destination_name)
{
push @error_messges, sprintf("destination file %s exists but can not be overwritten", $destination_name);
}
}
$files{$destination_name} = 1;
}
elsif ($command eq "mkdir")
{
my $path = $operation->[1];
if ( -d $path)
{
# Directory already exists. That is OK, the mkdir command will be silently ignored.
}
else
{
$directories{$path} = 1;
}
}
elsif ($command eq "compress")
{
my $filename = $operation->[1];
if ( ! -f $filename && ! defined $files{$filename})
{
# File does not exist and will not be created by an earlier operation.
push @error_messages, sprintf("file %s does not exist and can not be compressed", $filename);
}
}
elsif ($command eq "uncompress")
{
my ($source_filename, $destination_filename) = ($operation->[1], $operation->[2]);
if ($CompressionMethod eq "bzip2")
{
$source_filename .= ".bz2";
}
if ( ! -f $source_filename && ! defined $files{$source_filename})
{
# File does not exist and will not be created by an earlier operation.
push @error_messages, sprintf("file %s does not exist and can not be decompressed", $source_filename);
}
if ( -f $destination_filename && ! -w $destination_filename)
{
# Destination file aleady exists but can not be replaced.
push @error_messages, sprintf("compress destination file %s exists but can not be replaced", $destination_filename);
}
}
else
{
push @error_messages, sprintf("unknown operation %s", $command);
}
}
return @error_messages;
}
sub CheckAndExecute ($)
{
my ($self) = @_;
my @error_messages = $self->Check();
if (scalar @error_messages > 0)
{
$installer::logger::Lang->printf("can not execute all operations:\n");
for my $message (@error_messages)
{
$installer::logger::Lang->printf("ERROR: %s\n", $message);
}
return 0;
}
else
{
return $self->Execute();
}
}
sub Execute ($)
{
my ($self) = @_;
foreach my $operation (@{$self->{'operations'}})
{
my $command = $operation->[0];
if ($command eq "copy")
{
my ($source_name, $destination_name) = ($operation->[1], $operation->[2]);
$installer::logger::Lang->printf("copy from %s\n to %s\n", $source_name, $destination_name);
if ( ! $DryRun)
{
my $result = copy($source_name, $destination_name);
if ( ! $result)
{
$installer::logger::Lang->printf("ERROR: copying from %s to %s failed",
$source_name, $destination_name);
}
}
}
elsif ($command eq "mkdir")
{
my $path = $operation->[1];
if ( -d $path)
{
# Path exists already. Do nothing.
}
else
{
$installer::logger::Lang->printf("creating directory %s\n", $path);
if ( ! $DryRun)
{
if (File::Path::make_path($path, {'mode' => 0775}) == 0)
{
$installer::logger::Lang->printf("could not create directory %s\n", $path);
}
}
}
}
elsif ($command eq "compress")
{
my $filename = $operation->[1];
$installer::logger::Lang->printf("compressing %s\n", $filename);
if ( ! $DryRun)
{
my $result = 0;
if ($CompressionMethod eq "bzip2")
{
$result = IO::Compress::Bzip2::bzip2($filename => $filename.".bz2");
}
if ($result == 0)
{
$installer::logger::Lang->printf("ERROR: could not compress %s\n", $filename);
}
else
{
unlink($filename);
}
}
}
elsif ($command eq "uncompress")
{
my ($source_name, $destination_name) = ($operation->[1], $operation->[2]);
if ($CompressionMethod eq "bzip2")
{
$source_name .= ".bz2";
}
$installer::logger::Lang->printf("uncompressing %s to %s\n", $source_name, $destination_name);
my $destination_base_name = basename($destination_name);
if ( ! $DryRun)
{
my $result = 0;
if ($CompressionMethod eq "bzip2")
{
$result = IO::Uncompress::Bunzip2::bunzip2($source_name => $destination_name);
}
if ($result == 0)
{
$installer::logger::Lang->printf("ERROR: failed to extract content of '%s' from '%s'\n",
$destination_name, $source_name);
return 0;
}
}
}
else
{
die "unknown operation $command\n";
}
}
return 1;
}
sub GetOperationCount ($)
{
my ($self) = @_;
return scalar @{$self->{'operations'}};
}
1;