|
|
|
@ -26,9 +26,9 @@ use vars qw/ $progname $ourversion $dstrap $extra @aptsources
|
|
|
|
|
$dir $include $arch $foreign $suite $url $unpack $sourcedir
|
|
|
|
|
@e $sourcesname $libdir $dpkgdir @debootstrap %suites $mirror $etcdir
|
|
|
|
|
$repo @dirs @touch %sources $section %keys $host $key $value $type
|
|
|
|
|
$file $config $tidy $noauth $keyring %keyrings /;
|
|
|
|
|
$file $config $tidy $noauth $keyring %keyrings $deflist /;
|
|
|
|
|
$progname = basename($0);
|
|
|
|
|
$ourversion = "0.0.6";
|
|
|
|
|
$ourversion = "0.0.7";
|
|
|
|
|
$unpack = "true";
|
|
|
|
|
|
|
|
|
|
while( @ARGV ) {
|
|
|
|
@ -114,18 +114,40 @@ foreach $section (sort keys %keys)
|
|
|
|
|
print "$progname $ourversion using $file\n";
|
|
|
|
|
$host = `dpkg-architecture -qDEB_BUILD_ARCH`;
|
|
|
|
|
chomp ($host);
|
|
|
|
|
if (not defined $arch)
|
|
|
|
|
{
|
|
|
|
|
$arch = $host;
|
|
|
|
|
printf ("Defaulting architecture to native: %s\n",$arch);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
printf ("Using foreign architecture: %s\n", $arch);
|
|
|
|
|
}
|
|
|
|
|
$foreign++ if ($host ne $arch);
|
|
|
|
|
print "$progname building '$arch' multistrap on '$host'\n";
|
|
|
|
|
|
|
|
|
|
unless (keys %sources and @aptsources)
|
|
|
|
|
{
|
|
|
|
|
my $msg = sprintf("No sources defined for a foreign multistrap
|
|
|
|
|
Using your existing apt sources. To use different sources,
|
|
|
|
|
and list them with aptsources= in '%s'.", $file);
|
|
|
|
|
warn ("$progname: $msg\n");
|
|
|
|
|
$deflist = prepare_sources_list();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf ("%s building %s multistrap on '%s'\n", $progname, $arch, $host);
|
|
|
|
|
$cachedir = "var/cache/apt/"; # archives
|
|
|
|
|
$libdir = "var/lib/apt/"; # lists
|
|
|
|
|
$etcdir = "etc/apt/"; # sources
|
|
|
|
|
$dpkgdir = "var/lib/dpkg/"; # state
|
|
|
|
|
|
|
|
|
|
mkdir ("$dir") if (not -d "$dir");
|
|
|
|
|
system ("mkdir -p ${dir}${cachedir}");
|
|
|
|
|
system ("mkdir -p ${dir}${libdir}");
|
|
|
|
|
system ("mkdir -p ${dir}${dpkgdir}");
|
|
|
|
|
system ("mkdir -p ${dir}etc/apt/sources.list.d/");
|
|
|
|
|
system ("mkdir -p ${dir}${cachedir}") if (not -d "${dir}${cachedir}");
|
|
|
|
|
system ("mkdir -p ${dir}${libdir}") if (not -d "${dir}${libdir}");
|
|
|
|
|
system ("mkdir -p ${dir}${dpkgdir}") if (not -d "${dir}${dpkgdir}");
|
|
|
|
|
system ("mkdir -p ${dir}etc/apt/sources.list.d/")
|
|
|
|
|
if (not -d "${dir}etc/apt/sources.list.d/");
|
|
|
|
|
system ("mkdir -p ${dir}etc/apt/preferences.d/")
|
|
|
|
|
if (not -d "${dir}etc/apt/preferences.d/");
|
|
|
|
|
@dirs = qw/ alternatives info parts updates/;
|
|
|
|
|
@touch = qw/ diversions statoverride status lock/;
|
|
|
|
|
foreach my $dpkgd (@dirs) {
|
|
|
|
@ -173,10 +195,17 @@ foreach $repo (sort keys %suites)
|
|
|
|
|
}
|
|
|
|
|
foreach my $aptsrc (@aptsources)
|
|
|
|
|
{
|
|
|
|
|
if (-d "${dir}etc/apt/")
|
|
|
|
|
if (defined $deflist)
|
|
|
|
|
{
|
|
|
|
|
open (SOURCES, ">>${dir}etc/apt/sources.list.d/multistrap.sources.list")
|
|
|
|
|
or die "Cannot open sources list $!";
|
|
|
|
|
print SOURCES $deflist;
|
|
|
|
|
close SOURCES;
|
|
|
|
|
}
|
|
|
|
|
elsif (-d "${dir}etc/apt/")
|
|
|
|
|
{
|
|
|
|
|
open (SOURCES, ">>${dir}etc/apt/sources.list.d/multistrap.sources.list")
|
|
|
|
|
or die _g("Cannot open sources list"). $!;
|
|
|
|
|
$mirror = $sources{$aptsrc};
|
|
|
|
|
$suite = $suites{$aptsrc};
|
|
|
|
|
print SOURCES<<END;
|
|
|
|
@ -190,13 +219,13 @@ my $k;
|
|
|
|
|
foreach my $pkg (values %keyrings)
|
|
|
|
|
{
|
|
|
|
|
next if (not defined $pkg);
|
|
|
|
|
my $status = `dpkg -s $pkg`;
|
|
|
|
|
my $status = `LC_ALL=C dpkg -s $pkg`;
|
|
|
|
|
next if $status =~ /Status: install ok installed/;
|
|
|
|
|
$k .= "$pkg ";
|
|
|
|
|
}
|
|
|
|
|
if (defined $k)
|
|
|
|
|
{
|
|
|
|
|
my $e=`printenv`;
|
|
|
|
|
my $e=`LC_ALL=C printenv`;
|
|
|
|
|
my $str = ($e =~ /\nUSER=root\n/) ? "" : "sudo ";
|
|
|
|
|
$str = (-f "/usr/bin/sudo") ? "$str" : "";
|
|
|
|
|
print "I: Installing $k\n";
|
|
|
|
@ -214,9 +243,12 @@ $config_str .= " -o Dir::Etc=${dir}${etcdir}";
|
|
|
|
|
$sourcesname = "sources.list.d/multistrap.sources.list";
|
|
|
|
|
$config_str .= " -o Dir::Etc::SourceList=${dir}${etcdir}$sourcesname";
|
|
|
|
|
$config_str .= " -o Dir::State=${dir}${libdir}";
|
|
|
|
|
$config_str .= " -o Dir::State::Status=${dir}${dpkgdir}/status";
|
|
|
|
|
$config_str .= " -o Dir::State::Status=${dir}${dpkgdir}status";
|
|
|
|
|
$config_str .= " -o Dir::Cache=${dir}${cachedir}";
|
|
|
|
|
system ("apt-get $config_str update");
|
|
|
|
|
printf ("Getting package lists: apt-get %s update\n", $config_str);
|
|
|
|
|
$retval = system ("apt-get $config_str update");
|
|
|
|
|
die (sprintf("apt update failed. Exit value: ").($retval/256)."\n")
|
|
|
|
|
if ($retval != 0);
|
|
|
|
|
$str = join (' ', values %packages) . " ";
|
|
|
|
|
chomp($str);
|
|
|
|
|
$str .= join (' ', values %keyrings) . " ";
|
|
|
|
@ -233,7 +265,7 @@ die ("apt download failed. Exit value: ".($retval/256)."\n")
|
|
|
|
|
system ("touch ${dir}${libdir}lists/lock");
|
|
|
|
|
&native if (not defined ($foreign));
|
|
|
|
|
(not defined $tidy) ? system ("apt-get $config_str update") : &tidy_apt;
|
|
|
|
|
print "\nMultistrap system installed successfully in $dir.\n\n";
|
|
|
|
|
printf ("\nMultistrap system installed successfully in %s.\n\n", $dir);
|
|
|
|
|
exit 0;
|
|
|
|
|
|
|
|
|
|
sub force_unpack
|
|
|
|
@ -246,8 +278,8 @@ sub force_unpack
|
|
|
|
|
print "I: Calculating obsolete packages\n";
|
|
|
|
|
foreach $deb (sort @archives)
|
|
|
|
|
{
|
|
|
|
|
my $version = `dpkg -f ${dir}${cachedir}archives/$deb Version`;
|
|
|
|
|
my $package = `dpkg -f ${dir}${cachedir}archives/$deb Package`;
|
|
|
|
|
my $version = `LC_ALL=C dpkg -f ${dir}${cachedir}archives/$deb Version`;
|
|
|
|
|
my $package = `LC_ALL=C dpkg -f ${dir}${cachedir}archives/$deb Package`;
|
|
|
|
|
chomp ($version);
|
|
|
|
|
chomp ($package);
|
|
|
|
|
if (exists $unpack{$package})
|
|
|
|
@ -260,13 +292,13 @@ sub force_unpack
|
|
|
|
|
{
|
|
|
|
|
my $old = $deb;
|
|
|
|
|
$old =~ s/$version/$unpack{$package}/;
|
|
|
|
|
print "I: Removing $old\n";
|
|
|
|
|
printf ("I: Removing %s\n", $old);
|
|
|
|
|
unlink "${dir}${cachedir}archives/$old";
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
print "I: Removing $deb\n";
|
|
|
|
|
printf ("I: Removing %s\n", $deb);
|
|
|
|
|
unlink "${dir}${cachedir}archives/$deb";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -283,10 +315,10 @@ sub force_unpack
|
|
|
|
|
chdir ("${dir}");
|
|
|
|
|
foreach $deb (sort @archives)
|
|
|
|
|
{
|
|
|
|
|
print "I: Extracting $deb...\n";
|
|
|
|
|
printf ("I: Extracting %s...\n", $deb);
|
|
|
|
|
system ("ar -p \"./${cachedir}archives/$deb\" data.tar.gz | zcat | tar -xf -");
|
|
|
|
|
my $ver=`dpkg -f ./${cachedir}archives/$deb Version`;
|
|
|
|
|
my $pkg=`dpkg -f ./${cachedir}archives/$deb Package`;
|
|
|
|
|
my $ver=`LC_ALL=C dpkg -f ./${cachedir}archives/$deb Version`;
|
|
|
|
|
my $pkg=`LC_ALL=C dpkg -f ./${cachedir}archives/$deb Package`;
|
|
|
|
|
chomp ($ver);
|
|
|
|
|
chomp ($pkg);
|
|
|
|
|
mkdir ("./tmp");
|
|
|
|
@ -333,7 +365,7 @@ sub force_unpack
|
|
|
|
|
if ( -f "./${dpkgdir}info/$pkg.conffiles")
|
|
|
|
|
{
|
|
|
|
|
print STATUS "Conffiles:\n";
|
|
|
|
|
print " -> Processing conffiles for $pkg\n";
|
|
|
|
|
printf (" -> Processing conffiles for %s\n", $pkg);
|
|
|
|
|
open (CONF, "./${dpkgdir}info/$pkg.conffiles");
|
|
|
|
|
my @lines=<CONF>;
|
|
|
|
|
close (CONF);
|
|
|
|
@ -399,10 +431,14 @@ sub tidy_apt
|
|
|
|
|
sub native
|
|
|
|
|
{
|
|
|
|
|
print "I: Native mode - configuring unpacked packages . . .\n";
|
|
|
|
|
my $e=`printenv`;
|
|
|
|
|
my $e=`LC_ALL=C printenv`;
|
|
|
|
|
my $str = ($e =~ /\nUSER=root\n/) ? "" : "sudo";
|
|
|
|
|
$str = (-f "/usr/bin/sudo") ? "$str" : "";
|
|
|
|
|
system ("$str chroot $dir dpkg --configure -a");
|
|
|
|
|
my $env = "DEBIAN_FRONTEND=noninteractive ".
|
|
|
|
|
"DEBCONF_NONINTERACTIVE_SEEN=true ".
|
|
|
|
|
"LC_ALL=C LANGUAGE=C LANG=C";
|
|
|
|
|
print "I: dpkg configuration settings:\n\t$env\n";
|
|
|
|
|
system ("$str $env chroot $dir dpkg --configure -a");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub get_required_debs
|
|
|
|
@ -414,7 +450,7 @@ sub get_required_debs
|
|
|
|
|
my @required=();
|
|
|
|
|
my @debs=();
|
|
|
|
|
opendir (PKGS, "${dir}${libdir}lists/")
|
|
|
|
|
or die ("Cannot open ${dir}${libdir}lists/ directory. $!\n");
|
|
|
|
|
or die sprintf("Cannot open %s directory. %s\n","${dir}${libdir}lists/", $!);
|
|
|
|
|
my @lists=grep(/_Packages$/, readdir (PKGS));
|
|
|
|
|
closedir (PKGS);
|
|
|
|
|
foreach my $strap (@debootstrap)
|
|
|
|
@ -439,13 +475,42 @@ sub get_required_debs
|
|
|
|
|
return \@debs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# inherited from apt-cross
|
|
|
|
|
sub prepare_sources_list
|
|
|
|
|
{
|
|
|
|
|
my @source_list=();
|
|
|
|
|
# collate all available/configured sources into one list
|
|
|
|
|
if (-e "/etc/apt/sources.list") {
|
|
|
|
|
open (SOURCES, "/etc/apt/sources.list")
|
|
|
|
|
or die _g("cannot open apt sources list. %s",$!);
|
|
|
|
|
@source_list = <SOURCES>;
|
|
|
|
|
close (SOURCES);
|
|
|
|
|
}
|
|
|
|
|
if (-d "/etc/apt/sources.list.d/") {
|
|
|
|
|
opendir (FILES, "/etc/apt/sources.list.d/")
|
|
|
|
|
or die _g("cannot open apt sources.list directory %s\n",$!);
|
|
|
|
|
my @files = grep(!/^\.\.?$/, readdir FILES);
|
|
|
|
|
foreach my $f (@files) {
|
|
|
|
|
next if ($f =~ /\.ucf-old$/);
|
|
|
|
|
open (SOURCES, "/etc/apt/sources.list.d/$f") or
|
|
|
|
|
die _g("cannot open /etc/apt/sources.list.d/%s %s",$f, $!);
|
|
|
|
|
while(<SOURCES>) {
|
|
|
|
|
push @source_list, $_;
|
|
|
|
|
}
|
|
|
|
|
close (SOURCES);
|
|
|
|
|
}
|
|
|
|
|
closedir (FILES);
|
|
|
|
|
}
|
|
|
|
|
return \@source_list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub usageversion {
|
|
|
|
|
print(STDERR <<END)
|
|
|
|
|
$progname version $ourversion
|
|
|
|
|
printf STDERR ("
|
|
|
|
|
%s version %s
|
|
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
|
$progname [-a ARCH] [-d DIR] -f CONFIG_FILE
|
|
|
|
|
$progname -?|-h|--help|--version
|
|
|
|
|
%s [-a ARCH] [-d DIR] -f CONFIG_FILE
|
|
|
|
|
%s -?|-h|--help|--version
|
|
|
|
|
|
|
|
|
|
Command:
|
|
|
|
|
-f|--file CONFIG_FILE: path the the multistrap configuration file.
|
|
|
|
@ -458,7 +523,7 @@ Options:
|
|
|
|
|
-?|-h|--help: print this usage message and exit
|
|
|
|
|
--version: print this usage message and exit
|
|
|
|
|
|
|
|
|
|
$progname extends debootstrap to provide support for multiple
|
|
|
|
|
%s extends debootstrap to provide support for multiple
|
|
|
|
|
repositories, using a configuration file to specify the relevant suites,
|
|
|
|
|
architecture, extra packages and the mirror to use for each repository.
|
|
|
|
|
|
|
|
|
@ -499,8 +564,8 @@ General settings:
|
|
|
|
|
'directory' specifies the top level directory where the debootstrap
|
|
|
|
|
will be created - it is not packed into a .tgz once complete.
|
|
|
|
|
|
|
|
|
|
END
|
|
|
|
|
|| die "$progname: failed to write usage: $!\n";
|
|
|
|
|
", $progname, $ourversion, $progname, $progname, $progname)
|
|
|
|
|
or die "$progname: "."failed to write usage:". "$!\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
=pod
|
|
|
|
|