#!/usr/bin/perl -w
#
# File subroutines brought by the MondoRescue project
#
# $Id$
#
# Copyright B. Cornec 2008-2014
# Provided under the GPL v2

package MondoRescue::File;

use strict 'vars';
use Data::Dumper;
use English;
#use File::Basename;
use lib qw (lib);

# Inherit from the "Exporter" module which handles exporting functions.

use Exporter;

# Export, by default, all the functions into the namespace of
# any code which uses this module.

our @ISA = qw(Exporter);
our @EXPORT = qw(mr_file_read_all_link mr_file_process_ldd);

=pod

=head1 NAME

MondoRescue::File, part of the mondorescue.org

=head1 DESCRIPTION

This modules provides low level and generic functions for the Mondorescue project

=head1 USAGE

=over 4

=item B<mr_file_read_all_link>

This function returns all the links found for a given file passed as parameter
Example: mr_file_read_all_link(/lib64) returns (/lib64,/usr/lib64) on a system having a link from /lib64 to /usr/lib64

=cut

sub mr_file_read_all_link {

# TODO: Can be parallelized
my %files;

foreach my $f (@_) {
	print "Processing $f**\n";
	# Normalize the path if with .. in it or //
	$f =~ s|([^/]*)/([^/]+)/\.\./([^/]+)|$1/$3|g;
	$f =~ s|//|/|g;
	my @fullpath = split(/\//,$f);
	my $curdir = "";
	while (@fullpath) {
		my $dir = shift @fullpath;
		print "curdir is now: $curdir** and dir: $dir**\n";
		next if (($dir eq ".") || ($dir eq ""));
		my $link = readlink("$curdir/$dir");
		if (defined $link) {
			# It's a real symlink so handle it
			if (defined $files{$f}) {
				$files{$f} .= "$curdir/$dir|";
			} else {
				$files{$f} = "$curdir/$dir|";
			}
			if (substr($link,0,1) eq "/") {
				$curdir = $link;
			} else {
				my $dn = "";
				$dn = $curdir if ($curdir ne "");
				$curdir = "$dn/$link";
			}
			if ((! -d $curdir) || (-l $curdir)) {
				my $h = mr_file_read_all_link($curdir);
				print "File: $curdir - Return:\n".Dumper($h)."\n";
				foreach my $k (keys %$h) {
					$files{$f} .= $h->{$k}."|";
				}
			}
		} else {
			$curdir .= "/$dir";
		}
	}
	$files{$f} .= "$curdir";
}
return(\%files);
}

=over 4

=item B<mr_file_process_ldd>

This 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
It takes a list of parameters which are the path of the binaries to analyze and for which we want its dependencies to be included

=cut

sub mr_file_process_ldd {

my %files;

foreach my $f (@_) {
	open(CMD,"ldd $f 2> /dev/null |") || die "You need ldd for mindi support";
	# Format is something like this:
	#  linux-vdso.so.1 (0x00007fff7c0ee000)
	#  libtermcap.so.2 => /lib64/libtermcap.so.2 (0x00007ff1f0b1b000)
	#  libdl.so.2 => /lib64/libdl.so.2 (0x00007ff1f0917000)
	#  libc.so.6 => /lib64/libc.so.6 (0x00007ff1f0564000)
	#  /lib64/ld-linux-x86-64.so.2 (0x00007ff1f0d1f000)
	my $answer = undef;
	while (<CMD>) {
		my ($empty,$orig,$symb,$dest,$hexa) = split(/\s+/);
		# print "**$orig**$symb**$dest**$hexa\n";
		$answer = $orig if ($orig =~ /^\//);
		$answer = $dest if ((defined $dest) && ($dest =~ /^\//));
		$files{$answer} = $answer if (defined $answer);
	}
}
close(CMD);

return(\%files);
}

=back

=head1 WEB SITES

The 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/>.

=head1 USER MAILING LIST

For community exchanges around MondoRescue please use the list L<http://sourceforge.net/mailarchive/forum.php?forum_name=mondo-devel>

=head1 AUTHORS

The MondoRescue team lead by Bruno Cornec L<mailto:bruno@mondorescue.org>.

=head1 COPYRIGHT

MondoRescue is distributed under the GPL v2.0 license or later,
described in the file C<COPYING> included with the distribution.

=cut


