~ubuntu-branches/ubuntu/gutsy/sbuild/gutsy

« back to all changes in this revision

Viewing changes to Sbuild/Chroot.pm

  • Committer: Bazaar Package Importer
  • Author(s): Roger Leigh
  • Date: 2006-10-21 21:23:16 UTC
  • mfrom: (2.1.6 edgy)
  • Revision ID: james.westby@ubuntu.com-20061021212316-nh89o5rnhyk1epnn
Tags: 0.52
* New upstream release.
* sbuild: Remove incorrect WannaBuild:: prefix from version_compare.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
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>
 
5
#
 
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.
 
10
#
 
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.
 
15
#
 
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
 
19
#
 
20
# $Id: Sbuild.pm,v 1.2 2006/03/07 16:58:12 rleigh Exp $
 
21
#
 
22
 
 
23
package Sbuild::Chroot;
 
24
 
 
25
use Sbuild::Conf;
 
26
 
 
27
use strict;
 
28
use POSIX;
 
29
use FileHandle;
 
30
use File::Temp ();
 
31
 
 
32
BEGIN {
 
33
    use Exporter ();
 
34
    our (@ISA, @EXPORT);
 
35
 
 
36
    @ISA = qw(Exporter);
 
37
 
 
38
    @EXPORT = qw(begin_session end_session get_command run_command
 
39
                 exec_command get_apt_command run_apt_command
 
40
                 current);
 
41
}
 
42
 
 
43
my %chroots = ();
 
44
my $schroot_session = "";
 
45
 
 
46
our $current;
 
47
 
 
48
sub _get_schroot_info {
 
49
        my $chroot = shift;
 
50
        my $chroot_type = "";
 
51
        my %tmp = ('Priority' => 0,
 
52
                   'Location' => "",
 
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>) {
 
56
                chomp;
 
57
                if (/^\s*Type:?\s+(.*)$/) {
 
58
                    $chroot_type = $1;
 
59
                }
 
60
                if (/^\s*Location:?\s+(.*)$/ &&
 
61
                    $tmp{'Location'} eq "") {
 
62
                        $tmp{'Location'} = $1;
 
63
                }
 
64
                if (/^\s*Mount Location:?\s+(.*)$/ &&
 
65
                    $tmp{'Location'} eq "") {
 
66
                        $tmp{'Location'} = $1;
 
67
                }
 
68
                # Path takes priority over Location and Mount Location.
 
69
                if (/^\s*Path:?\s+(.*)$/) {
 
70
                        $tmp{'Location'} = $1;
 
71
                }
 
72
                if (/^\s*Priority:?\s+(\d+)$/) {
 
73
                        $tmp{'Priority'} = $1;
 
74
                }
 
75
                if (/^\s*Session Managed\s+(.*)$/) {
 
76
                        if ($1 eq "true") {
 
77
                                $tmp{'Session Managed'} = 1;
 
78
                        }
 
79
                }
 
80
        }
 
81
 
 
82
        close CHROOT_DATA or die "Can't close schroot pipe getting chroot data";
 
83
 
 
84
        # "plain" chroots are never session-capable, even if they say
 
85
        # they are.
 
86
        if ($chroot_type eq "plain") {
 
87
                $tmp{'Session Managed'} = 0;
 
88
        }
 
89
 
 
90
        if ($Sbuild::Conf::debug) {
 
91
                print STDERR "Found schroot chroot: $chroot\n";
 
92
                foreach (sort keys %tmp) {
 
93
                        print STDERR "  $_ $tmp{$_}\n";
 
94
                }
 
95
        }
 
96
 
 
97
        $chroots{$chroot} = \%tmp;
 
98
}
 
99
 
 
100
sub init {
 
101
        foreach (glob("${Sbuild::Conf::build_dir}/chroot-*")) {
 
102
                my %tmp = ('Priority' => 0,
 
103
                           'Location' => $_,
 
104
                           'Session Managed' => 0);
 
105
                if (-d $tmp{'Location'}) {
 
106
                        my $name = $_;
 
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;
 
111
                }
 
112
        }
 
113
 
 
114
        # Pick up available chroots and dist_order from schroot
 
115
        if ($Sbuild::Conf::chroot_mode eq "schroot") {
 
116
                %chroots = ();
 
117
                open CHROOTS, '-|', $Sbuild::Conf::schroot, '--list' or die "Can't run $Sbuild::Conf::schroot";
 
118
                while (<CHROOTS>) {
 
119
                        chomp;
 
120
                        my $chroot = $_;
 
121
                        print STDERR "Getting info for $chroot chroot"
 
122
                                if $Sbuild::Conf::debug;
 
123
                        _get_schroot_info($chroot);
 
124
                }
 
125
                close CHROOTS or die "Can't close schroot pipe";
 
126
        }
 
127
}
 
128
 
 
129
sub _setup_options {
 
130
        my $distribution = shift;
 
131
 
 
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";
 
139
 
 
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";
 
146
                } else {
 
147
                        $chroots{"$distribution"}->{'APT Options'} = ""
 
148
                }
 
149
 
 
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;
 
155
                } else {
 
156
                        $ENV{'APT_CONFIG'} = $chroot_aptconf;
 
157
                }
 
158
 
 
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",
 
162
                                            DIR => $chroot_dir,
 
163
                                            UNLINK => 0) ) {
 
164
 
 
165
                        if ($Sbuild::Conf::chroot_mode ne "schroot") {
 
166
                                print $F "Dir \"$chroot_dir\";\n";
 
167
                        }
 
168
                        print $F "APT::Get::AllowUnauthenticated true;\n";
 
169
 
 
170
                        if (! rename $F->filename, $chroot_aptconf) {
 
171
                                die "Can't rename $F->filename to $chroot_aptconf: $!\n";
 
172
                        }
 
173
 
 
174
                } else {
 
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";
 
180
                        }
 
181
                }
 
182
        } elsif ($Sbuild::Conf::chroot_only) {
 
183
                die "$distribution chroot does not exist and in chroot only mode -- exiting\n";
 
184
        }
 
185
}
 
186
 
 
187
sub begin_session {
 
188
        my $distribution = shift;
 
189
 
 
190
        if ($Sbuild::Conf::chroot_mode eq "schroot") {
 
191
                if (defined($chroots{"${distribution}-sbuild"})) {
 
192
                        $distribution = "${distribution}-sbuild";
 
193
                }
 
194
                $schroot_session=`$Sbuild::Conf::schroot -c $distribution --begin-session`;
 
195
                chomp($schroot_session);
 
196
                if ($?) {
 
197
                        print STDERR "Chroot setup failed\n";
 
198
                        return 0;
 
199
                }
 
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};
 
205
        } else {
 
206
                _setup_options($distribution);
 
207
                $current = $chroots{$distribution};
 
208
        }
 
209
        return 1;
 
210
}
 
211
 
 
212
sub end_session {
 
213
        $current = undef;
 
214
        if ($Sbuild::Conf::chroot_mode eq "schroot" && $schroot_session ne "") {
 
215
                system("$Sbuild::Conf::schroot -c $schroot_session --end-session");
 
216
                if ($?) {
 
217
                        print STDERR "Chroot cleanup failed\n";
 
218
                        return 0;
 
219
                }
 
220
        }
 
221
        return 1;
 
222
}
 
223
 
 
224
sub log_command {
 
225
        my $msg = shift;      # Message to log
 
226
        my $priority = shift; # Priority of log message
 
227
 
 
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";
 
232
        }
 
233
}
 
234
 
 
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;
 
240
        }
 
241
        my $chroot = shift;  # Run in chroot?
 
242
        if (!defined $chroot) {
 
243
                $chroot = 1;
 
244
        }
 
245
 
 
246
        my $cmdline;
 
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'";
 
250
                } else {
 
251
                        $cmdline = "$Sbuild::Conf::sudo /usr/sbin/chroot $$current{'Location'} $Sbuild::Conf::su -p $user -s /bin/sh -c '$command'";
 
252
                }
 
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 ";
 
258
                        }
 
259
                }
 
260
                $cmdline .= "/bin/sh -c '$command'";
 
261
        }
 
262
 
 
263
        return $cmdline;
 
264
}
 
265
 
 
266
sub get_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);
 
272
 
 
273
        if ($Sbuild::Conf::debug) {
 
274
                log_command($cmdline, $priority);
 
275
        } else {
 
276
                log_command($command, $priority);
 
277
        }
 
278
 
 
279
        if ($chroot != 0) {
 
280
                chdir($Sbuild::Conf::cwd);
 
281
        }
 
282
        return $cmdline;
 
283
}
 
284
 
 
285
# Note, do not run with $user="root", and $chroot=0, because sudo
 
286
# access to the host system is not required.
 
287
sub run_command {
 
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);
 
293
 
 
294
        if ($Sbuild::Conf::debug) {
 
295
                log_command($cmdline, $priority);
 
296
        } else {
 
297
                log_command($command, $priority);
 
298
        }
 
299
 
 
300
        if ($chroot != 0) {
 
301
                chdir($Sbuild::Conf::cwd);
 
302
        }
 
303
        return system($cmdline);
 
304
}
 
305
 
 
306
sub exec_command {
 
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);
 
312
 
 
313
        if ($Sbuild::Conf::debug) {
 
314
                log_command($cmdline, $priority);
 
315
        } else {
 
316
                log_command($command, $priority);
 
317
        }
 
318
 
 
319
        if ($chroot != 0) {
 
320
                chdir($Sbuild::Conf::cwd);
 
321
        }
 
322
        exec $cmdline;
 
323
}
 
324
 
 
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";
 
329
 
 
330
        return $aptcommand;
 
331
}
 
332
 
 
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
 
338
 
 
339
        my $aptcommand = get_apt_command_internal($command, $options);
 
340
 
 
341
        my $chroot = 0;
 
342
        if ($Sbuild::Conf::chroot_mode eq "schroot") {
 
343
                $chroot = 1;
 
344
        }
 
345
 
 
346
        my $cmdline = get_command($aptcommand, $user, $chroot, $priority);
 
347
 
 
348
        chdir($Sbuild::Conf::cwd);
 
349
        return $cmdline;
 
350
}
 
351
 
 
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
 
357
 
 
358
        my $aptcommand = get_apt_command_internal($command, $options);
 
359
 
 
360
        my $chroot = 0;
 
361
        if ($Sbuild::Conf::chroot_mode eq "schroot") {
 
362
                $chroot = 1;
 
363
        }
 
364
 
 
365
        chdir($Sbuild::Conf::cwd);
 
366
        return run_command($aptcommand, $user, $chroot, $priority);
 
367
}
 
368
 
 
369
1;