xref: /trunk/main/solenv/bin/modules/installer/patch/FileOperations.pm (revision d620b54767df0d2c7d9557af4be4c7303d55d13c)
1c9b362f6SAndre Fischer#**************************************************************
2c9b362f6SAndre Fischer#
3c9b362f6SAndre Fischer#  Licensed to the Apache Software Foundation (ASF) under one
4c9b362f6SAndre Fischer#  or more contributor license agreements.  See the NOTICE file
5c9b362f6SAndre Fischer#  distributed with this work for additional information
6c9b362f6SAndre Fischer#  regarding copyright ownership.  The ASF licenses this file
7c9b362f6SAndre Fischer#  to you under the Apache License, Version 2.0 (the
8c9b362f6SAndre Fischer#  "License"); you may not use this file except in compliance
9c9b362f6SAndre Fischer#  with the License.  You may obtain a copy of the License at
10c9b362f6SAndre Fischer#
11c9b362f6SAndre Fischer#    http://www.apache.org/licenses/LICENSE-2.0
12c9b362f6SAndre Fischer#
13c9b362f6SAndre Fischer#  Unless required by applicable law or agreed to in writing,
14c9b362f6SAndre Fischer#  software distributed under the License is distributed on an
15c9b362f6SAndre Fischer#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16c9b362f6SAndre Fischer#  KIND, either express or implied.  See the License for the
17c9b362f6SAndre Fischer#  specific language governing permissions and limitations
18c9b362f6SAndre Fischer#  under the License.
19c9b362f6SAndre Fischer#
20c9b362f6SAndre Fischer#**************************************************************
21c9b362f6SAndre Fischer
22c9b362f6SAndre Fischerpackage installer::patch::FileOperations;
23c9b362f6SAndre Fischer
24c9b362f6SAndre Fischeruse File::Basename;
25c9b362f6SAndre Fischeruse File::Copy;
26c9b362f6SAndre Fischeruse IO::Compress::Bzip2;
27c9b362f6SAndre Fischeruse IO::Uncompress::Bunzip2;
28c9b362f6SAndre Fischer
29c9b362f6SAndre Fischermy $CompressionMethod = "bzip2";
30c9b362f6SAndre Fischer
31c9b362f6SAndre Fischer
32c9b362f6SAndre Fischer=head1 NAME
33c9b362f6SAndre Fischer
34c9b362f6SAndre Fischer    package installer::patch::FileOperations - Class for collecting, checking and executing file operations.
35c9b362f6SAndre Fischer
36c9b362f6SAndre Fischer=cut
37c9b362f6SAndre Fischer
38c9b362f6SAndre Fischer
39c9b362f6SAndre Fischersub new ($)
40c9b362f6SAndre Fischer{
41c9b362f6SAndre Fischer    my ($class) = (@_);
42c9b362f6SAndre Fischer
43c9b362f6SAndre Fischer    my $self = {
44c9b362f6SAndre Fischer        'operations' => []
45c9b362f6SAndre Fischer    };
46c9b362f6SAndre Fischer    bless($self, $class);
47c9b362f6SAndre Fischer
48c9b362f6SAndre Fischer    return $self;
49c9b362f6SAndre Fischer}
50c9b362f6SAndre Fischer
51c9b362f6SAndre Fischer
52c9b362f6SAndre Fischer
53c9b362f6SAndre Fischer
54c9b362f6SAndre Fischersub AddCopyOperation ($$$)
55c9b362f6SAndre Fischer{
56c9b362f6SAndre Fischer    my ($self, $source_name, $target_name) = @_;
57c9b362f6SAndre Fischer
58c9b362f6SAndre Fischer    push
59c9b362f6SAndre Fischer        @{$self->{'operations'}},
60c9b362f6SAndre Fischer        [
61c9b362f6SAndre Fischer            'copy',
62c9b362f6SAndre Fischer            $source_name,
63c9b362f6SAndre Fischer            $target_name
64c9b362f6SAndre Fischer        ];
65c9b362f6SAndre Fischer}
66c9b362f6SAndre Fischer
67c9b362f6SAndre Fischer
68c9b362f6SAndre Fischer
69c9b362f6SAndre Fischer
70c9b362f6SAndre Fischersub AddMakeDirectoryOperation ($$)
71c9b362f6SAndre Fischer{
72c9b362f6SAndre Fischer    my ($self, $path) = @_;
73c9b362f6SAndre Fischer
74c9b362f6SAndre Fischer    push
75c9b362f6SAndre Fischer        @{$self->{'operations'}},
76c9b362f6SAndre Fischer        [
77c9b362f6SAndre Fischer            'mkdir',
78c9b362f6SAndre Fischer            $path
79c9b362f6SAndre Fischer        ];
80c9b362f6SAndre Fischer}
81c9b362f6SAndre Fischer
82c9b362f6SAndre Fischer
83c9b362f6SAndre Fischer
84c9b362f6SAndre Fischer
85c9b362f6SAndre Fischersub AddCompressOperation ($$)
86c9b362f6SAndre Fischer{
87c9b362f6SAndre Fischer    my ($self, $filename) = @_;
88c9b362f6SAndre Fischer
89c9b362f6SAndre Fischer    push
90c9b362f6SAndre Fischer        @{$self->{'operations'}},
91c9b362f6SAndre Fischer        [
92c9b362f6SAndre Fischer            'compress',
93c9b362f6SAndre Fischer            $filename
94c9b362f6SAndre Fischer        ];
95c9b362f6SAndre Fischer}
96c9b362f6SAndre Fischer
97c9b362f6SAndre Fischer
98c9b362f6SAndre Fischer
99c9b362f6SAndre Fischer
100c9b362f6SAndre Fischersub AddUncompressOperation ($$$)
101c9b362f6SAndre Fischer{
102c9b362f6SAndre Fischer    my ($self, $source_name, $target_name) = @_;
103c9b362f6SAndre Fischer
104c9b362f6SAndre Fischer    push
105c9b362f6SAndre Fischer        @{$self->{'operations'}},
106c9b362f6SAndre Fischer        [
107c9b362f6SAndre Fischer            'uncompress',
108c9b362f6SAndre Fischer            $source_name,
109c9b362f6SAndre Fischer            $target_name
110c9b362f6SAndre Fischer        ];
111c9b362f6SAndre Fischer}
112c9b362f6SAndre Fischer
113c9b362f6SAndre Fischer
114c9b362f6SAndre Fischer
115c9b362f6SAndre Fischer
116c9b362f6SAndre Fischersub Check ($)
117c9b362f6SAndre Fischer{
118c9b362f6SAndre Fischer    my ($self) = @_;
119c9b362f6SAndre Fischer
120c9b362f6SAndre Fischer    # Keep track of which directories or files would be created to check if
121c9b362f6SAndre Fischer    # operations that depend on these files will succeed.
122c9b362f6SAndre Fischer    my %files = ();
123c9b362f6SAndre Fischer    my %directories = ();
124c9b362f6SAndre Fischer
125c9b362f6SAndre Fischer    my @error_messages = ();
126c9b362f6SAndre Fischer    foreach my $operation (@{$self->{'operations'}})
127c9b362f6SAndre Fischer    {
128c9b362f6SAndre Fischer        my $command = $operation->[0];
129c9b362f6SAndre Fischer
130c9b362f6SAndre Fischer        if ($command eq "copy")
131c9b362f6SAndre Fischer        {
132c9b362f6SAndre Fischer            my ($source_name, $destination_name) = ($operation->[1], $operation->[2]);
133c9b362f6SAndre Fischer            if ( ! -f $source_name)
134c9b362f6SAndre Fischer            {
135c9b362f6SAndre Fischer                push @error_messages, sprintf("%s is not a regular file and can not be copied", $source_name);
136c9b362f6SAndre Fischer            }
137c9b362f6SAndre Fischer            my $destination_path = dirname($destination_name);
138c9b362f6SAndre Fischer            if ( ! -d $destination_path && ! defined $directories{$destination_path})
139c9b362f6SAndre Fischer            {
140c9b362f6SAndre Fischer                push @error_messages, sprintf("destination path %s does not exist", $destination_path);
141c9b362f6SAndre Fischer            }
142c9b362f6SAndre Fischer            if ( -f $destination_name)
143c9b362f6SAndre Fischer            {
144c9b362f6SAndre Fischer                # The destination file already exists. We have to overwrite it.
145c9b362f6SAndre Fischer                if ( ! -w $destination_name)
146c9b362f6SAndre Fischer                {
147c9b362f6SAndre Fischer                    push @error_messges, sprintf("destination file %s exists but can not be overwritten", $destination_name);
148c9b362f6SAndre Fischer                }
149c9b362f6SAndre Fischer            }
150c9b362f6SAndre Fischer            $files{$destination_name} = 1;
151c9b362f6SAndre Fischer        }
152c9b362f6SAndre Fischer        elsif ($command eq "mkdir")
153c9b362f6SAndre Fischer        {
154c9b362f6SAndre Fischer            my $path = $operation->[1];
155c9b362f6SAndre Fischer            if ( -d $path)
156c9b362f6SAndre Fischer            {
157c9b362f6SAndre Fischer                # Directory already exists.  That is OK, the mkdir command will be silently ignored.
158c9b362f6SAndre Fischer            }
159c9b362f6SAndre Fischer            else
160c9b362f6SAndre Fischer            {
161c9b362f6SAndre Fischer                $directories{$path} = 1;
162c9b362f6SAndre Fischer            }
163c9b362f6SAndre Fischer        }
164c9b362f6SAndre Fischer        elsif ($command eq "compress")
165c9b362f6SAndre Fischer        {
166c9b362f6SAndre Fischer            my $filename = $operation->[1];
167c9b362f6SAndre Fischer            if ( ! -f $filename && ! defined $files{$filename})
168c9b362f6SAndre Fischer            {
169c9b362f6SAndre Fischer                # File does not exist and will not be created by an earlier operation.
170c9b362f6SAndre Fischer                push @error_messages, sprintf("file %s does not exist and can not be compressed", $filename);
171c9b362f6SAndre Fischer            }
172c9b362f6SAndre Fischer        }
173c9b362f6SAndre Fischer        elsif ($command eq "uncompress")
174c9b362f6SAndre Fischer        {
175c9b362f6SAndre Fischer            my ($source_filename, $destination_filename) = ($operation->[1], $operation->[2]);
176c9b362f6SAndre Fischer            if ($CompressionMethod eq "bzip2")
177c9b362f6SAndre Fischer            {
178c9b362f6SAndre Fischer                $source_filename .= ".bz2";
179c9b362f6SAndre Fischer            }
180c9b362f6SAndre Fischer            if ( ! -f $source_filename && ! defined $files{$source_filename})
181c9b362f6SAndre Fischer            {
182c9b362f6SAndre Fischer                # File does not exist and will not be created by an earlier operation.
183c9b362f6SAndre Fischer                push @error_messages, sprintf("file %s does not exist and can not be decompressed", $source_filename);
184c9b362f6SAndre Fischer            }
185c9b362f6SAndre Fischer            if ( -f $destination_filename && ! -w $destination_filename)
186c9b362f6SAndre Fischer            {
187*30acf5e8Spfg                # Destination file already exists but can not be replaced.
188c9b362f6SAndre Fischer                push @error_messages, sprintf("compress destination file %s exists but can not be replaced", $destination_filename);
189c9b362f6SAndre Fischer            }
190c9b362f6SAndre Fischer        }
191c9b362f6SAndre Fischer        else
192c9b362f6SAndre Fischer        {
193c9b362f6SAndre Fischer            push @error_messages, sprintf("unknown operation %s", $command);
194c9b362f6SAndre Fischer        }
195c9b362f6SAndre Fischer    }
196c9b362f6SAndre Fischer
197c9b362f6SAndre Fischer    return @error_messages;
198c9b362f6SAndre Fischer}
199c9b362f6SAndre Fischer
200c9b362f6SAndre Fischer
201c9b362f6SAndre Fischer
202c9b362f6SAndre Fischer
203c9b362f6SAndre Fischersub CheckAndExecute ($)
204c9b362f6SAndre Fischer{
205c9b362f6SAndre Fischer    my ($self) = @_;
206c9b362f6SAndre Fischer
207c9b362f6SAndre Fischer    my @error_messages = $self->Check();
208c9b362f6SAndre Fischer    if (scalar @error_messages > 0)
209c9b362f6SAndre Fischer    {
210c9b362f6SAndre Fischer        $installer::logger::Lang->printf("can not execute all operations:\n");
211c9b362f6SAndre Fischer        for my $message (@error_messages)
212c9b362f6SAndre Fischer        {
213c9b362f6SAndre Fischer            $installer::logger::Lang->printf("ERROR: %s\n", $message);
214c9b362f6SAndre Fischer        }
215c9b362f6SAndre Fischer        return 0;
216c9b362f6SAndre Fischer    }
217c9b362f6SAndre Fischer    else
218c9b362f6SAndre Fischer    {
219c9b362f6SAndre Fischer        return $self->Execute();
220c9b362f6SAndre Fischer    }
221c9b362f6SAndre Fischer}
222c9b362f6SAndre Fischer
223c9b362f6SAndre Fischer
224c9b362f6SAndre Fischer
225c9b362f6SAndre Fischer
226c9b362f6SAndre Fischersub Execute ($)
227c9b362f6SAndre Fischer{
228c9b362f6SAndre Fischer    my ($self) = @_;
229c9b362f6SAndre Fischer
230c9b362f6SAndre Fischer    foreach my $operation (@{$self->{'operations'}})
231c9b362f6SAndre Fischer    {
232c9b362f6SAndre Fischer        my $command = $operation->[0];
233c9b362f6SAndre Fischer
234c9b362f6SAndre Fischer        if ($command eq "copy")
235c9b362f6SAndre Fischer        {
236c9b362f6SAndre Fischer            my ($source_name, $destination_name) = ($operation->[1], $operation->[2]);
237c9b362f6SAndre Fischer            $installer::logger::Lang->printf("copy from %s\n    to %s\n", $source_name, $destination_name);
238c9b362f6SAndre Fischer            if ( ! $DryRun)
239c9b362f6SAndre Fischer            {
240c9b362f6SAndre Fischer                my $result = copy($source_name, $destination_name);
241c9b362f6SAndre Fischer                if ( ! $result)
242c9b362f6SAndre Fischer                {
243c9b362f6SAndre Fischer                    $installer::logger::Lang->printf("ERROR: copying from %s to %s failed",
244c9b362f6SAndre Fischer                        $source_name, $destination_name);
245c9b362f6SAndre Fischer                }
246c9b362f6SAndre Fischer            }
247c9b362f6SAndre Fischer        }
248c9b362f6SAndre Fischer        elsif ($command eq "mkdir")
249c9b362f6SAndre Fischer        {
250c9b362f6SAndre Fischer            my $path = $operation->[1];
251c9b362f6SAndre Fischer            if ( -d $path)
252c9b362f6SAndre Fischer            {
253c9b362f6SAndre Fischer                # Path exists already. Do nothing.
254c9b362f6SAndre Fischer            }
255c9b362f6SAndre Fischer            else
256c9b362f6SAndre Fischer            {
257c9b362f6SAndre Fischer                $installer::logger::Lang->printf("creating directory %s\n", $path);
258c9b362f6SAndre Fischer                if ( ! $DryRun)
259c9b362f6SAndre Fischer                {
260c9b362f6SAndre Fischer                    if (File::Path::make_path($path, {'mode' => 0775}) == 0)
261c9b362f6SAndre Fischer                    {
262c9b362f6SAndre Fischer                        $installer::logger::Lang->printf("could not create directory %s\n", $path);
263c9b362f6SAndre Fischer                    }
264c9b362f6SAndre Fischer                }
265c9b362f6SAndre Fischer            }
266c9b362f6SAndre Fischer        }
267c9b362f6SAndre Fischer        elsif ($command eq "compress")
268c9b362f6SAndre Fischer        {
269c9b362f6SAndre Fischer            my $filename = $operation->[1];
270c9b362f6SAndre Fischer            $installer::logger::Lang->printf("compressing %s\n", $filename);
271c9b362f6SAndre Fischer            if ( ! $DryRun)
272c9b362f6SAndre Fischer            {
273c9b362f6SAndre Fischer                my $result = 0;
274c9b362f6SAndre Fischer                if ($CompressionMethod eq "bzip2")
275c9b362f6SAndre Fischer                {
276c9b362f6SAndre Fischer                    $result = IO::Compress::Bzip2::bzip2($filename => $filename.".bz2");
277c9b362f6SAndre Fischer                }
278c9b362f6SAndre Fischer                if ($result == 0)
279c9b362f6SAndre Fischer                {
280c9b362f6SAndre Fischer                    $installer::logger::Lang->printf("ERROR: could not compress %s\n", $filename);
281c9b362f6SAndre Fischer                }
282c9b362f6SAndre Fischer                else
283c9b362f6SAndre Fischer                {
284c9b362f6SAndre Fischer                    unlink($filename);
285c9b362f6SAndre Fischer                }
286c9b362f6SAndre Fischer            }
287c9b362f6SAndre Fischer        }
288c9b362f6SAndre Fischer        elsif ($command eq "uncompress")
289c9b362f6SAndre Fischer        {
290c9b362f6SAndre Fischer            my ($source_name, $destination_name) = ($operation->[1], $operation->[2]);
291c9b362f6SAndre Fischer            if ($CompressionMethod eq "bzip2")
292c9b362f6SAndre Fischer            {
293c9b362f6SAndre Fischer                $source_name .= ".bz2";
294c9b362f6SAndre Fischer            }
295c9b362f6SAndre Fischer            $installer::logger::Lang->printf("uncompressing %s to %s\n", $source_name, $destination_name);
296c9b362f6SAndre Fischer
297c9b362f6SAndre Fischer            my $destination_base_name = basename($destination_name);
298c9b362f6SAndre Fischer
299c9b362f6SAndre Fischer            if ( ! $DryRun)
300c9b362f6SAndre Fischer            {
301c9b362f6SAndre Fischer                my $result = 0;
302c9b362f6SAndre Fischer                if ($CompressionMethod eq "bzip2")
303c9b362f6SAndre Fischer                {
304c9b362f6SAndre Fischer                    $result = IO::Uncompress::Bunzip2::bunzip2($source_name => $destination_name);
305c9b362f6SAndre Fischer                }
306c9b362f6SAndre Fischer                if ($result == 0)
307c9b362f6SAndre Fischer                {
308c9b362f6SAndre Fischer                    $installer::logger::Lang->printf("ERROR: failed to extract content of '%s' from '%s'\n",
309c9b362f6SAndre Fischer                        $destination_name, $source_name);
310c9b362f6SAndre Fischer                    return 0;
311c9b362f6SAndre Fischer                }
312c9b362f6SAndre Fischer            }
313c9b362f6SAndre Fischer        }
314c9b362f6SAndre Fischer
315c9b362f6SAndre Fischer        else
316c9b362f6SAndre Fischer        {
317c9b362f6SAndre Fischer            die "unknown operation $command\n";
318c9b362f6SAndre Fischer        }
319c9b362f6SAndre Fischer    }
320c9b362f6SAndre Fischer
321c9b362f6SAndre Fischer    return 1;
322c9b362f6SAndre Fischer}
323c9b362f6SAndre Fischer
324c9b362f6SAndre Fischer
325c9b362f6SAndre Fischer
326c9b362f6SAndre Fischersub GetOperationCount ($)
327c9b362f6SAndre Fischer{
328c9b362f6SAndre Fischer    my ($self) = @_;
329c9b362f6SAndre Fischer    return scalar @{$self->{'operations'}};
330c9b362f6SAndre Fischer}
331c9b362f6SAndre Fischer
332c9b362f6SAndre Fischer
333c9b362f6SAndre Fischer1;
334