| #************************************************************** |
| # |
| # 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 already 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; |