#!/usr/bin/perl
# set fileencoding=utf-8

##########################################################################
 # Copyright (C) 2007 Philipp Marek.
 #
 # This program is free software;  you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 as
 # published by the Free Software Foundation.
##########################################################################

####
# 
# A script to prepare a chroot environment for the fsvs-chrooter helper 
# program.
# The list of libraries for *my* system is at the end.
#
####

$destdir=shift() || die "Where should I put the libraries?\n";

if (!-d $destdir)
{
	print "The destination directory\n",
				"   $destdir\n",
				"does not exist. Shall I create it (Y/N) ?\n";
	$answer=<STDIN>;

	die "No valid destination.\n" if ($answer !~ m/^y/i);

# we put the fsvs binary in /bin.
	system qw(mkdir -p),$destdir . "/bin";
	die "mkdir $destdir/bin failed.\n" if $? || !-d $destdir;
}

# We simply use rsync, which creates all needed directories.
# But either we would copy only the links, or only their data ... both is  
# not pretty.
# So we send a list to copy, and copy symlinks too.
open(RSYNC, "| rsync -aH --files-from=- / '$destdir/' ") # --stats")
|| die "cannot start rsync: $!";
while (<DATA>)
{
	chomp;
	next if m#^\s*$#;

# Maybe not the whole list would be necessary, as a single library might 
# bring in all others ... but who wants to parse the tree of dependencies?
# Could be a later version.
	$needed_libs{$1}++
		if m#/(lib[^/]+\.so\.\d+[^/]*)$#;

	$pre="";
	while (1)
	{
		print $pre,$_;
		print RSYNC $_,"\n";
		last if  !-l;
		$pre=" -> ";
		$n=readlink($_);
		if ($n =~ m#^/#) { $_=$n; }
		else { s*/[^/]+$*/$n*; }
	}

	print "\n";
}
close(RSYNC) || die "Copying failed? $!";

print "Library copying finished.\n\n\n";


$binary="";
for $bin (grep(m#.# && -e $_, `which fsvs 2> /dev/null`, "./fsvs"))
{
	system "cp", "-a", $bin, "$destdir/bin/";
	print "Copying $bin failed: $?",next if $?;

	print "$bin was successfully copied into the destination directory.\n\n";
	$binary=$bin;
	last;
}

print "Your fsvs binary could not be found. Please copy it into your\n",
			"chroot jail, eg. into $destdir/bin/.\n\n",
			"As a consequence library name elimination could not be fully done -\n",
			"your list of libraries to be imported is longer than necessary.\n\n" 
			if !$binary;


%libs_deps=();
$cur_bin=$binary;
while (keys %needed_libs)
{
# Get dependencies

	for (`ldd "$cur_bin" 2>/dev/null`)
	{
		next unless m#=> .*/(lib[^/\s]+\.so\.[^/\s]+)#;
		$libs_deps{$1}{$cur_bin}++;
		# This library is required by another, so we need not preload it 
		# explicitly.
#		print "$1 needed by $cur_bin\n";
		delete $needed_libs{$1};
	}

	last;
}

# Choose upper-most libraries.
$libnames = join(" ", sort keys %needed_libs);


$name="/tmp/fsvs-chrooter.ex.sh-$$";
open(T, "> $name") || die "open($name): $!";
print T "#!/bin/sh

# fsvs-chrooter call script.
# Autogenerated on " . localtime() . '

export FSVS_CHROOT_LIBS="' . $libnames . '"
exec fsvs-chrooter "$@"
';
close T;
chmod 0755, $name;


print "A shell script named\n",
			"\t$name\n",
			"has been written; you probably want to put that, along with ",
			"fsvs-chrooter\n",
			"(on the *other* machine!!) in a directory in your PATH.\n\n";

exit;

__DATA__
/etc/ld.so.cache
/lib/ld-linux.so.2
/lib/libcom_err.so.2
/lib/libcrypt.so.1
/lib/libc.so.6
/lib/libdl.so.2
/lib/libkeyutils.so.1
/lib/libm.so.6
/lib/libnsl.so.1
/lib/libnss_compat.so.2
/lib/libnss_dns.so.2
/lib/libnss_files.so.2
/lib/libpthread.so.0
/lib/libresolv.so.2
/lib/librt.so.1
/lib/libuuid.so.1
/usr/lib/gconv/gconv-modules.cache
/usr/lib/i686/cmov/libcrypto.so.0.9.8
/usr/lib/i686/cmov/libssl.so.0.9.8
/usr/lib/libapr-1.so.0
/usr/lib/libaprutil-1.so.0
/usr/lib/libdb-4.4.so
/usr/lib/libexpat.so.1
/usr/lib/libgcrypt.so.11
/usr/lib/libgdbm.so.3
/usr/lib/libgnutls.so.13
/usr/lib/libgpg-error.so.0
/usr/lib/libgssapi_krb5.so.2
/usr/lib/libk5crypto.so.3
/usr/lib/libkrb5.so.3
/usr/lib/libkrb5support.so.0
/usr/lib/liblber.so.2
/usr/lib/libldap_r.so.2
/usr/lib/libm.so
/usr/lib/libneon.so.26
/usr/lib/libpcre.so.3
/usr/lib/libpq.so.5
/usr/lib/libsasl2.so.2
/usr/lib/libsqlite3.so.0
/usr/lib/libsvn_client-1.so.1
/usr/lib/libsvn_delta-1.so.1
/usr/lib/libsvn_diff-1.so.1
/usr/lib/libsvn_fs-1.so.1
/usr/lib/libsvn_fs_base-1.so.1
/usr/lib/libsvn_fs_fs-1.so.1
/usr/lib/libsvn_ra-1.so.1
/usr/lib/libsvn_ra_dav-1.so.1
/usr/lib/libsvn_ra_local-1.so.1
/usr/lib/libsvn_ra_svn-1.so.1
/usr/lib/libsvn_repos-1.so.1
/usr/lib/libsvn_subr-1.so.1
/usr/lib/libsvn_wc-1.so.1
/usr/lib/libtasn1.so.3
/usr/lib/libxml2.so.2
/usr/lib/libz.so.1
/usr/lib/locale/locale-archive
/usr/share/locale/de/LC_MESSAGES/libc.mo
/usr/share/locale/locale.alias
