source: MondoRescue/branches/3.3/MondoRescue/lib/MondoRescue/File.pm@ 3742

Last change on this file since 3742 was 3742, checked in by Bruno Cornec, 4 years ago

Fix non working mr-device-mounted

File size: 6.0 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_erase_hash 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)
90
91=cut
92
93sub mr_file_erase_hash {
94
95my $files = shift;
96
97foreach my $i (keys %$files) {
98 delete $files->{$i};
99}
100return();
101}
102
103
104=over 4
105
106=item B<mr_file_copy_and_erase_hash>
107
108This function erases all elements in the hash passed in parameter (such as the one created in mr_file_read_all_link)
109Takes as param the hash to delete and returns a new fresh one
110
111=cut
112
113sub mr_file_copy_and_erase_hash {
114
115my $files = shift;
116my %h;
117
118foreach my $i (keys %$files) {
119 $h{$i} = $files->{$i};
120 delete $files->{$i};
121}
122return(\%h);
123}
124
125=over 4
126
127=item B<mr_file_read_all_link>
128
129This function returns all the links found for a given file passed as parameter
130Example: mr_file_read_all_link(/lib64) returns (/lib64,/usr/lib64) on a system having a link from /lib64 to /usr/lib64
131The return value is a hash of all input files pointing to the hash of their links
132That hash needs to be cleaned up after usage
133
134=cut
135
136sub mr_file_read_all_link {
137
138# TODO: Can be parallelized
139# use "our" to keep info between recursive calls
140our $files;
141
142
143foreach my $f (@_) {
144 pb_log(2,"mr_file_read_all_link: **$f**\n");
145 # Normalize the path if with .. or . or // in it
146 $f = mr_file_normalize($f);
147
148 my @fullpath = split(/\//,$f);
149 my $curdir = "";
150 while (@fullpath) {
151 my $dir = shift @fullpath;
152 pb_log(2,"curdir is now: $curdir** and dir: $dir**\n");
153 next if ($dir eq "");
154
155 my $link = readlink("$curdir/$dir");
156 if (defined $link) {
157 $link = mr_file_normalize($link,"$curdir/$dir");
158 # It's a real symlink so handle it
159 $files->{$f}->{"$curdir/$dir"} = 1;
160 if (substr($link,0,1) eq "/") {
161 $curdir = $link;
162 } else {
163 my $dn = "";
164 $dn = $curdir if ($curdir ne "");
165 $curdir = "$dn/$link";
166 }
167 if ((-e $curdir) && ((! -d $curdir) || (-l $curdir))) {
168 my $h = mr_file_read_all_link($curdir);
169 pb_log(2,"After Return h:\n".Dumper($h)."\n");
170 foreach my $k (keys %$h) {
171 foreach my $l (keys %$k) {
172 # Use $f as key as we affects all the files
173 # found in recursion to the current managed file
174 $files->{$f}->{$l} = 1;
175 }
176 }
177 pb_log(2,"After Return files:\n".Dumper($files)."\n");
178 }
179 } else {
180 $curdir .= "/$dir";
181 }
182 }
183 pb_log(2,"curdir is now: $curdir**\n");
184 $files->{$f}->{$curdir} = 1 if (-e $curdir);
185}
186pb_log(1,"mr_file_read_all_link returns:\n".Dumper($files)."\n");
187return($files);
188}
189
190=over 4
191
192=item B<mr_file_process_ldd>
193
194This 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
195It takes a list of parameters which are the path of the binaries to analyze and for which we want its dependencies to be included
196
197=cut
198
199sub mr_file_process_ldd {
200
201my $files;
202
203foreach my $f (@_) {
204 pb_log(2,"mr_file_process_ldd: **$f**\n");
205 open(CMD,"ldd $f 2> /dev/null |") || die "You need ldd for mindi support";
206 # Format is something like this:
207 # linux-vdso.so.1 (0x00007fff7c0ee000)
208 # libtermcap.so.2 => /lib64/libtermcap.so.2 (0x00007ff1f0b1b000)
209 # libdl.so.2 => /lib64/libdl.so.2 (0x00007ff1f0917000)
210 # libc.so.6 => /lib64/libc.so.6 (0x00007ff1f0564000)
211 # /lib64/ld-linux-x86-64.so.2 (0x00007ff1f0d1f000)
212 my $answer = undef;
213 while (<CMD>) {
214 my ($empty,$orig,$symb,$dest,$hexa) = split(/\s+/);
215 # print "**$orig**$symb**$dest**$hexa\n";
216 $answer = $orig if ($orig =~ /^\//);
217 $answer = $dest if ((defined $dest) && ($dest =~ /^\//));
218 push @{$files->{$f}},$answer if (defined $answer);
219 }
220}
221close(CMD);
222
223return($files);
224}
225
226=back
227
228=head1 WEB SITES
229
230The 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/>.
231
232=head1 USER MAILING LIST
233
234For community exchanges around MondoRescue please use the list L<http://sourceforge.net/mailarchive/forum.php?forum_name=mondo-devel>
235
236=head1 AUTHORS
237
238The MondoRescue team lead by Bruno Cornec L<mailto:bruno@mondorescue.org>.
239
240=head1 COPYRIGHT
241
242MondoRescue is distributed under the GPL v2.0 license or later,
243described in the file C<COPYING> included with the distribution.
244
245=cut
246
247
Note: See TracBrowser for help on using the repository browser.