source: branches/3.2/MondoRescue/lib/MondoRescue/File.pm @ 3447

Last change on this file since 3447 was 3447, checked in by Bruno Cornec, 4 years ago
  • Adds a mr-device-mounted binary to MondoRescue? (replaces the code of the C function is_this_device_mounted) and the corresponding perl function (mr_device_mounted) to handle cases where a mounted device has a different name than the one seen on mount (e.g. /dev/rhel/root and /dev/mapper/rhel-root)
  • Adds perl function mr_file_copy_and_erase_hash to empty the hash generated in mr_file_read_all_link and thus avoid filling the hash it generates, which is useful for a recursive function, but not when called multiple times from another perl script. To be improved later on.
  • Adapt build procedure to the new binary (tested on Mageia 5 and RHEL7)
File size: 5.7 KB
Line 
1#!/usr/bin/perl -w
2#
3# File subroutines brought by the MondoRescue project
4#
5# $Id$
6#
7# Copyright B. Cornec 2008-2014
8# Provided under the GPL v2
9
10package MondoRescue::File;
11
12use strict 'vars';
13use Data::Dumper;
14use English;
15use Cwd;
16use File::Basename;
17use ProjectBuilder::Base;
18use lib qw (lib);
19
20# Inherit from the "Exporter" module which handles exporting functions.
21
22use Exporter;
23
24# Export, by default, all the functions into the namespace of
25# any code which uses this module.
26
27our @ISA = qw(Exporter);
28our @EXPORT = qw(mr_file_read_all_link mr_file_process_ldd mr_file_normalize mr_file_copy_and_erase_hash);
29
30=pod
31
32=head1 NAME
33
34MondoRescue::File, part of the mondorescue.org
35
36=head1 DESCRIPTION
37
38This modules provides low level and generic functions for the Mondorescue project
39
40=head1 USAGE
41
42=over 4
43
44=item B<mr_file_normalize>
45
46This function normalize a path by removing .., . or // in paths given as parameters
47
48=cut
49
50#$pbdebug = 2;
51
52sub mr_file_normalize {
53
54my $f = shift;
55my $dir = shift || undef;
56
57# We modify based on the current dir,
58# except when we're asked to use another one (case of a target link)
59my $newpath = cwd;
60$newpath = $dir if (defined $dir);
61
62return($f) if (not defined $f);
63
64pb_log(2,"mr_file_normalize file: **$f**\n");
65pb_log(2,"mr_file_normalize dir : **$dir**\n") if (defined $dir);
66
67# Handle case of . at the start in path
68if ($f =~ /^\.\//) {
69    $f =~ s/^\.\//$newpath\//;
70}
71# Handle case of .. at the start in path
72if ($f =~ /^\.\.\//) {
73    my $dn = dirname(dirname($newpath));
74    $f =~ s/^\.\.\//$dn\//;
75}
76# Now handles .. and . in the middle
77$f =~ s|([^/]*)/([^/]+)/\.\./([^/]+)|$1/$3|g;
78$f =~ s|([^/]*)/([^/]+)/\./([^/]+)|$1/$2/$3|g;
79# Handle double /
80$f =~ s|//|/|g;
81
82return($f);
83}
84
85=over 4
86
87=item B<mr_file_erase_hash>
88
89This function erases all elements in the hash passed in parameter (such as the one created in mr_file_read_all_link)
90Takes as param the hash to delete and returns a new fresh one
91
92=cut
93
94sub mr_file_copy_and_erase_hash {
95
96my $files = shift;
97my %h;
98
99foreach my $i (keys %$files) {
100    $h{$i} = $files->{$i};
101    delete $files->{$i};
102}
103return(\%h);
104}
105
106=over 4
107
108=item B<mr_file_read_all_link>
109
110This function returns all the links found for a given file passed as parameter
111Example: mr_file_read_all_link(/lib64) returns (/lib64,/usr/lib64) on a system having a link from /lib64 to /usr/lib64
112The return value is a hash of all input files pointing to the hash of their links
113That hash needs to be cleaned up after usage
114
115=cut
116
117sub mr_file_read_all_link {
118
119# TODO: Can be parallelized
120# use "our" to keep info between recursive calls
121our $files;
122
123
124foreach my $f (@_) {
125    pb_log(2,"mr_file_read_all_link: **$f**\n");
126    # Normalize the path if with .. or . or // in it
127    $f = mr_file_normalize($f);
128
129    my @fullpath = split(/\//,$f);
130    my $curdir = "";
131    while (@fullpath) {
132        my $dir = shift @fullpath;
133        pb_log(2,"curdir is now: $curdir** and dir: $dir**\n");
134        next if ($dir eq "");
135       
136        my $link = readlink("$curdir/$dir");
137        if (defined $link) {
138            $link = mr_file_normalize($link,"$curdir/$dir");
139            # It's a real symlink so handle it
140            $files->{$f}->{"$curdir/$dir"} = 1;
141            if (substr($link,0,1) eq "/") {
142                $curdir = $link;
143            } else {
144                my $dn = "";
145                $dn = $curdir if ($curdir ne "");
146                $curdir = "$dn/$link";
147            }
148            if ((-e $curdir) && ((! -d $curdir) || (-l $curdir))) {
149                my $h = mr_file_read_all_link($curdir);
150                pb_log(2,"After Return h:\n".Dumper($h)."\n");
151                foreach my $k (keys %$h) {
152                    foreach my $l (keys %$k) {
153                        # Use $f as key as we affects all the files
154                        # found in recursion to the current managed file
155                        $files->{$f}->{$l} = 1;
156                    }
157                }
158                pb_log(2,"After Return files:\n".Dumper($files)."\n");
159            }
160        } else {
161            $curdir .= "/$dir";
162        }
163    }
164    pb_log(2,"curdir is now: $curdir**\n");
165    $files->{$f}->{$curdir} = 1 if (-e $curdir);
166}
167pb_log(1,"mr_file_read_all_link returns:\n".Dumper($files)."\n");
168return($files);
169}
170
171=over 4
172
173=item B<mr_file_process_ldd>
174
175This function keeps track of the dependencies of a binary with its dynamic libraries by analyzing the return of ldd on that binary and recursing on all the dependencies to provide the complete list of files needed to have this binary run in a mindi or chroot context
176It takes a list of parameters which are the path of the binaries to analyze and for which we want its dependencies to be included
177
178=cut
179
180sub mr_file_process_ldd {
181
182my $files;
183
184foreach my $f (@_) {
185    pb_log(2,"mr_file_process_ldd: **$f**\n");
186    open(CMD,"ldd $f 2> /dev/null |") || die "You need ldd for mindi support";
187    # Format is something like this:
188    #  linux-vdso.so.1 (0x00007fff7c0ee000)
189    #  libtermcap.so.2 => /lib64/libtermcap.so.2 (0x00007ff1f0b1b000)
190    #  libdl.so.2 => /lib64/libdl.so.2 (0x00007ff1f0917000)
191    #  libc.so.6 => /lib64/libc.so.6 (0x00007ff1f0564000)
192    #  /lib64/ld-linux-x86-64.so.2 (0x00007ff1f0d1f000)
193    my $answer = undef;
194    while (<CMD>) {
195        my ($empty,$orig,$symb,$dest,$hexa) = split(/\s+/);
196        # print "**$orig**$symb**$dest**$hexa\n";
197        $answer = $orig if ($orig =~ /^\//);
198        $answer = $dest if ((defined $dest) && ($dest =~ /^\//));
199        push @{$files->{$f}},$answer if (defined $answer);
200    }
201}
202close(CMD);
203
204return($files);
205}
206
207=back
208
209=head1 WEB SITES
210
211The main Web site of the project is available at L<http://www.mondorescue.org>. Bug reports should be filled using the trac instance of the project at L<http://trac.mondorescue.org/>.
212
213=head1 USER MAILING LIST
214
215For community exchanges around MondoRescue please use the list L<http://sourceforge.net/mailarchive/forum.php?forum_name=mondo-devel>
216
217=head1 AUTHORS
218
219The MondoRescue team lead by Bruno Cornec L<mailto:bruno@mondorescue.org>.
220
221=head1 COPYRIGHT
222
223MondoRescue is distributed under the GPL v2.0 license or later,
224described in the file C<COPYING> included with the distribution.
225
226=cut
227
228
Note: See TracBrowser for help on using the repository browser.