2
# Chroot.pm: chroot library for sbuild
3
# Copyright (C) 2005 Ryan Murray <rmurray@debian.org>
4
# Copyright (C) 2005-2006 Roger Leigh <rleigh@debian.org>
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License as
8
# published by the Free Software Foundation; either version 2 of the
9
# License, or (at your option) any later version.
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
# General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
# $Id: Sbuild.pm,v 1.2 2006/03/07 16:58:12 rleigh Exp $
23
package Sbuild::Chroot;
38
@EXPORT = qw(begin_session end_session get_command run_command
39
exec_command get_apt_command run_apt_command
44
my $schroot_session = "";
48
sub _get_schroot_info {
51
my %tmp = ('Priority' => 0,
53
'Session Managed' => 0);
54
open CHROOT_DATA, '-|', $Sbuild::Conf::schroot, '--info', '--chroot', $chroot or die "Can't run $Sbuild::Conf::schroot to get chroot data";
55
while (<CHROOT_DATA>) {
57
if (/^\s*Type:?\s+(.*)$/) {
60
if (/^\s*Location:?\s+(.*)$/ &&
61
$tmp{'Location'} eq "") {
62
$tmp{'Location'} = $1;
64
if (/^\s*Mount Location:?\s+(.*)$/ &&
65
$tmp{'Location'} eq "") {
66
$tmp{'Location'} = $1;
68
# Path takes priority over Location and Mount Location.
69
if (/^\s*Path:?\s+(.*)$/) {
70
$tmp{'Location'} = $1;
72
if (/^\s*Priority:?\s+(\d+)$/) {
73
$tmp{'Priority'} = $1;
75
if (/^\s*Session Managed\s+(.*)$/) {
77
$tmp{'Session Managed'} = 1;
82
close CHROOT_DATA or die "Can't close schroot pipe getting chroot data";
84
# "plain" chroots are never session-capable, even if they say
86
if ($chroot_type eq "plain") {
87
$tmp{'Session Managed'} = 0;
90
if ($Sbuild::Conf::debug) {
91
print STDERR "Found schroot chroot: $chroot\n";
92
foreach (sort keys %tmp) {
93
print STDERR " $_ $tmp{$_}\n";
97
$chroots{$chroot} = \%tmp;
101
foreach (glob("${Sbuild::Conf::build_dir}/chroot-*")) {
102
my %tmp = ('Priority' => 0,
104
'Session Managed' => 0);
105
if (-d $tmp{'Location'}) {
107
$name =~ s/\Q${Sbuild::Conf::build_dir}\/chroot-\E//;
108
print STDERR "Found chroot $name\n"
109
if $Sbuild::Conf::debug;
110
$chroots{$name} = \%tmp;
114
# Pick up available chroots and dist_order from schroot
115
if ($Sbuild::Conf::chroot_mode eq "schroot") {
117
open CHROOTS, '-|', $Sbuild::Conf::schroot, '--list' or die "Can't run $Sbuild::Conf::schroot";
121
print STDERR "Getting info for $chroot chroot"
122
if $Sbuild::Conf::debug;
123
_get_schroot_info($chroot);
125
close CHROOTS or die "Can't close schroot pipe";
130
my $distribution = shift;
132
if (defined($chroots{$distribution}) &&
133
-d $chroots{"$distribution"}->{'Location'}) {
134
my $chroot_dir = $chroots{"$distribution"}->{'Location'};
135
$chroots{"$distribution"}->{'Build Location'} = "$chroot_dir/build/$Sbuild::Conf::username/";
136
my $srcdep_lock_dir = "$chroot_dir/$Sbuild::Conf::srcdep_lock_dir";
137
$chroots{"$distribution"}->{'Srcdep Lock Dir'} = $srcdep_lock_dir;
138
$chroots{"$distribution"}->{'Install Lock'} = "$srcdep_lock_dir/install";
140
my $aptconf = "/var/lib/sbuild/apt.conf";
141
if ($Sbuild::Conf::chroot_mode ne "schroot") {
142
$chroots{"$distribution"}->{'APT Options'} =
143
"-o Dir::State::status=$chroot_dir/var/lib/dpkg/status".
144
" -o DPkg::Options::=--root=$chroot_dir".
145
" -o DPkg::Run-Directory=$chroot_dir";
147
$chroots{"$distribution"}->{'APT Options'} = ""
150
# schroot uses an absolute path inside the chroot,
151
# rather than on the host system.
152
my $chroot_aptconf = "$chroot_dir/$aptconf";
153
if ($Sbuild::Conf::chroot_mode eq "schroot") {
154
$ENV{'APT_CONFIG'} = $aptconf;
156
$ENV{'APT_CONFIG'} = $chroot_aptconf;
159
# Always write out apt.conf, because it gets outdated
160
# if the chroot_mode is changed...
161
if (my $F = new File::Temp( TEMPLATE => "$aptconf.XXXXXX",
165
if ($Sbuild::Conf::chroot_mode ne "schroot") {
166
print $F "Dir \"$chroot_dir\";\n";
168
print $F "APT::Get::AllowUnauthenticated true;\n";
170
if (! rename $F->filename, $chroot_aptconf) {
171
die "Can't rename $F->filename to $chroot_aptconf: $!\n";
175
if ($Sbuild::Conf::chroot_mode ne "schroot") {
176
$chroots{"$distribution"}->{'APT Options'} =
177
" -o Dir::State=$chroot_dir/var/lib/apt".
178
" -o Dir::Cache=$chroot_dir/var/cache/apt".
179
" -o Dir::Etc=$chroot_dir/etc/apt";
182
} elsif ($Sbuild::Conf::chroot_only) {
183
die "$distribution chroot does not exist and in chroot only mode -- exiting\n";
188
my $distribution = shift;
190
if ($Sbuild::Conf::chroot_mode eq "schroot") {
191
if (defined($chroots{"${distribution}-sbuild"})) {
192
$distribution = "${distribution}-sbuild";
194
$schroot_session=`$Sbuild::Conf::schroot -c $distribution --begin-session`;
195
chomp($schroot_session);
197
print STDERR "Chroot setup failed\n";
200
print STDERR "Setting up chroot $distribution (session id $schroot_session)\n"
201
if $Sbuild::Conf::debug;
202
_get_schroot_info($schroot_session);
203
_setup_options($schroot_session);
204
$current = $chroots{$schroot_session};
206
_setup_options($distribution);
207
$current = $chroots{$distribution};
214
if ($Sbuild::Conf::chroot_mode eq "schroot" && $schroot_session ne "") {
215
system("$Sbuild::Conf::schroot -c $schroot_session --end-session");
217
print STDERR "Chroot cleanup failed\n";
225
my $msg = shift; # Message to log
226
my $priority = shift; # Priority of log message
228
if (((defined($priority) && $priority >= 1) || $Sbuild::Conf::debug) &&
229
$$current{'APT Options'} ne "") {
230
$msg =~ s/\Q$$current{'APT Options'}\E/CHROOT_APT_OPTIONS/g;
231
print STDERR "$msg\n";
235
sub get_command_internal {
236
my $command = shift; # Command to run
237
my $user = shift; # User to run command under
238
if (!defined $user || $user eq "") {
239
$user = $Sbuild::Conf::username;
241
my $chroot = shift; # Run in chroot?
242
if (!defined $chroot) {
247
if ($chroot != 0) { # Run command inside chroot
248
if ($Sbuild::Conf::chroot_mode eq "schroot") {
249
$cmdline = "$Sbuild::Conf::schroot -c $schroot_session --run-session $Sbuild::Conf::schroot_options -u $user -p -- /bin/sh -c '$command'";
251
$cmdline = "$Sbuild::Conf::sudo /usr/sbin/chroot $$current{'Location'} $Sbuild::Conf::su -p $user -s /bin/sh -c '$command'";
253
} else { # Run command outside chroot
254
if ($user ne $Sbuild::Conf::username) {
255
$cmdline = "$Sbuild::Conf::sudo ";
256
if ($user ne "root") {
257
$cmdline .= "-u $Sbuild::Conf::username ";
260
$cmdline .= "/bin/sh -c '$command'";
267
my $command = shift; # Command to run
268
my $user = shift; # User to run command under
269
my $chroot = shift; # Run in chroot?
270
my $priority = shift; # Priority of log message
271
my $cmdline = get_command_internal($command, $user, $chroot);
273
if ($Sbuild::Conf::debug) {
274
log_command($cmdline, $priority);
276
log_command($command, $priority);
280
chdir($Sbuild::Conf::cwd);
285
# Note, do not run with $user="root", and $chroot=0, because sudo
286
# access to the host system is not required.
288
my $command = shift; # Command to run
289
my $user = shift; # User to run command under
290
my $chroot = shift; # Run in chroot?
291
my $priority = shift; # Priority of log message
292
my $cmdline = get_command_internal($command, $user, $chroot);
294
if ($Sbuild::Conf::debug) {
295
log_command($cmdline, $priority);
297
log_command($command, $priority);
301
chdir($Sbuild::Conf::cwd);
303
return system($cmdline);
307
my $command = shift; # Command to run
308
my $user = shift; # User to run command under
309
my $chroot = shift; # Run in chroot?
310
my $priority = shift; # Priority of log message
311
my $cmdline = get_command_internal($command, $user, $chroot);
313
if ($Sbuild::Conf::debug) {
314
log_command($cmdline, $priority);
316
log_command($command, $priority);
320
chdir($Sbuild::Conf::cwd);
325
sub get_apt_command_internal {
326
my $aptcommand = shift; # Command to run
327
my $options = shift; # Command options
328
$aptcommand .= " $$current{'APT Options'} $options";
333
sub get_apt_command {
334
my $command = shift; # Command to run
335
my $options = shift; # Command options
336
my $user = shift; # User to run command under
337
my $priority = shift; # Priority of log message
339
my $aptcommand = get_apt_command_internal($command, $options);
342
if ($Sbuild::Conf::chroot_mode eq "schroot") {
346
my $cmdline = get_command($aptcommand, $user, $chroot, $priority);
348
chdir($Sbuild::Conf::cwd);
352
sub run_apt_command {
353
my $command = shift; # Command to run
354
my $options = shift; # Command options
355
my $user = shift; # User to run command under
356
my $priority = shift; # Priority of log message
358
my $aptcommand = get_apt_command_internal($command, $options);
361
if ($Sbuild::Conf::chroot_mode eq "schroot") {
365
chdir($Sbuild::Conf::cwd);
366
return run_command($aptcommand, $user, $chroot, $priority);