~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/canonical/buildd/sbuild

  • Committer: mbp at canonical
  • Date: 2011-11-20 23:37:23 UTC
  • mto: This revision was merged to the branch mainline in revision 14344.
  • Revision ID: mbp@canonical.com-20111120233723-370p96db2crru5tm
Delete canonical.buildd again

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#! /usr/bin/perl
2
 
#
3
 
# sbuild: build packages, obeying source dependencies
4
 
# Copyright (C) 1998-2000 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 
#
20
 
# $Id: sbuild,v 1.170 2002/10/10 18:50:44 rnhodek Exp $
21
 
#
22
 
# $Log: sbuild,v $
23
 
# Revision 1.170  2002/10/10 18:50:44  rnhodek
24
 
# Security/accepted autobuilding patch by Ryan.
25
 
#
26
 
# Revision 1.169  2002/03/11 09:49:55  rnhodek
27
 
# chroot_apt_options: don't just set Dir::Etc::sourcelist, but whole
28
 
# Dir::Etc, to avoid new preferences.
29
 
#
30
 
# Revision 1.168  2002/02/07 09:12:25  rnhodek
31
 
# Fixed sudo call for running scripts.
32
 
#
33
 
# Revision 1.167  2002/01/22 08:53:10  rnhodek
34
 
# Use capitalized "Noninteractive" das DEBIAN_FRONTENT.
35
 
#
36
 
# Revision 1.166  2001/11/08 09:32:10  rnhodek
37
 
# fetch_source_file: in case of apt, need to pass up a $dscfile with
38
 
# epoch stripped.
39
 
#
40
 
# Revision 1.165  2001/11/07 18:04:31  rnhodek
41
 
# Argl.. I should learn perl first :)
42
 
#
43
 
# Revision 1.164  2001/11/07 09:25:59  rnhodek
44
 
# fetch_source_files: after apt-get, fix $dscfile not to contain epoch.
45
 
#
46
 
# Revision 1.163  2001/11/06 15:11:24  rnhodek
47
 
# fetch_source_files: don't touch symlinks generated by apt-get.
48
 
#
49
 
# Revision 1.162  2001/11/06 12:29:22  rnhodek
50
 
# New config var $use_FetchFile (default 0).
51
 
# Integrated patches for using apt-get to download sources; modified so
52
 
#   that old code (using FetchFile.pm) still present.
53
 
# run_apt: Fix parsing error of apt-output (\s matched ^M printed by
54
 
#   pre-configuring).
55
 
#
56
 
# Revision 1.161  2001/10/29 12:20:41  rnhodek
57
 
# Added $fakeroot var.
58
 
#
59
 
# Revision 1.160  2001/10/29 08:27:53  rnhodek
60
 
# Fix typo in message.
61
 
#
62
 
# Revision 1.159  2001/06/18 09:57:55  rnhodek
63
 
# Use --database option when wanna_build_dbbase set in config.
64
 
#
65
 
# Revision 1.158  2001/06/01 09:54:36  rnhodek
66
 
# Fix two typos.
67
 
#
68
 
# Revision 1.157  2001/05/31 08:08:08  rnhodek
69
 
# Fixed thinko in conflicts checking (tnx James)
70
 
#
71
 
# Revision 1.156  2001/05/30 08:20:05  rnhodek
72
 
# Use /var/lib/apt as Dir::State if exists (newer apt versions use that)
73
 
# (tnx to Ryan Murray).
74
 
#
75
 
# Revision 1.155  2001/05/30 08:17:01  rnhodek
76
 
# Print also architecture at start of log.
77
 
#
78
 
# Revision 1.154  2001/05/29 07:33:54  rnhodek
79
 
# Also handle versioned Build-Conflicts.
80
 
#   (Tnx to David Schleef <ds@schleef.org>)
81
 
#
82
 
# Revision 1.153  2001/03/13 08:45:17  rnhodek
83
 
# Run chmod -R on source tree only after unpacking.
84
 
#
85
 
# Revision 1.152  2001/02/19 09:23:24  rnhodek
86
 
# Fix typo.
87
 
#
88
 
# Revision 1.151  2001/02/19 08:43:22  rnhodek
89
 
# Fix wrong arch logic.
90
 
#
91
 
# Revision 1.150  2001/01/22 12:56:16  rnhodek
92
 
# Fix handling of arch-restricted build-deps (tnx to Ryan Murray).
93
 
#
94
 
# Revision 1.149  2001/01/15 11:17:36  rnhodek
95
 
# Fixed typo.
96
 
#
97
 
# Revision 1.148  2001/01/15 10:59:18  rnhodek
98
 
# Shortcut when looking for non-dsc files: first try to fetch from same
99
 
# dir as .dsc and FF_search only if that fails.
100
 
#
101
 
# Revision 1.147  2001/01/10 16:16:48  rnhodek
102
 
# Move all built files from chroot dir, not only *.deb.
103
 
#
104
 
# Revision 1.146  2000/10/23 10:39:24  rnhodek
105
 
# Before doing chmod on /etc/ld.so.conf, test if it exists at all.
106
 
#
107
 
# Revision 1.145  2000/10/19 09:08:35  rnhodek
108
 
# A couple of little fixes from Ben.
109
 
# Checks and assures that /etc/ld.so.conf is readable.
110
 
# Support for local overrides with $conf::srcdep_over.
111
 
#
112
 
# Revision 1.144  2000/06/27 12:34:00  rnhodek
113
 
# Implemented new 'prepre' and 'unpack' sections for special targets;
114
 
# the first is a script run before package installation, and the latter
115
 
# can list source packages that should be unpacked in the build dir.
116
 
#
117
 
# Revision 1.143  2000/06/20 14:39:59  rnhodek
118
 
# Call apt-get with some options for relocating various files instead of
119
 
# chrooting it; this avoids that the archive must be available in chroot
120
 
# environment; same is true for dpkg and apt-cache calls.
121
 
# If chrooted, call dpkg with the chroot dir as cwd to avoid "cannot get
122
 
# current directory" errors; same for apt option DPkg::Run-Directory.
123
 
#
124
 
# Revision 1.142  2000/06/19 14:09:00  rnhodek
125
 
# Fix syntax error.
126
 
#
127
 
# Revision 1.141  2000/06/19 14:05:38  rnhodek
128
 
# Call buildd-addpkg with --chroot=DIR options for each dist that is >=
129
 
# the one building for (to run apt-get update in the chroot
130
 
# environments).
131
 
#
132
 
# Revision 1.140  2000/06/19 09:10:24  rnhodek
133
 
# Obey new config var @ignore_watches_no_build_deps, i.e. don't flag
134
 
# watches that are listed there if the package doesn't have build deps.
135
 
# In check_watches(), strip $chroot_dir instead of $chroot_build_dir
136
 
# from pathname.
137
 
#
138
 
# Revision 1.139  2000/06/13 10:54:43  rnhodek
139
 
# Also execute special dependency scripts in chroot environment.
140
 
#
141
 
# Revision 1.138  2000/06/09 12:47:52  rnhodek
142
 
# File .dsc filename for rbuilder (with URL).
143
 
#
144
 
# Revision 1.137  2000/06/09 09:15:21  rnhodek
145
 
# Always install built package (if already) when building chroot; i.e.
146
 
# the $system_level test is not necessary when chrooted.
147
 
#
148
 
# Revision 1.136  2000/06/09 08:20:52  rnhodek
149
 
# Fixed su usage in sub build.
150
 
#
151
 
# Revision 1.135  2000/06/08 14:02:11  rnhodek
152
 
# After changing to chroot dir, change back to be the normal user again
153
 
# and start dpkg-buildpackage with -rsudo again; some packages require
154
 
# that the build target is executed as non-root.
155
 
#
156
 
# Revision 1.134  2000/06/08 13:01:54  rnhodek
157
 
# apt-cache calls need sudo, too, when using chroot.
158
 
#
159
 
# Revision 1.133  2000/06/08 09:13:31  rnhodek
160
 
# Implemented chroot builds; there are a few new global variables
161
 
# $main::chroot_*; major changes are in build, where the source tree is
162
 
# unpacked somewhere else, dpkg-buildpackage called under chroot and
163
 
# built packages are moved back again; also all apt-get and dpkg calls
164
 
# are chroot-ed and /var/lib/dpkg/status is accessed from the chroot
165
 
# environment; also watches are checked under the new root dir.
166
 
#
167
 
# Revision 1.132  2000/06/06 14:37:05  rnhodek
168
 
# New option --source (-s): Also build source package, i.e. don't pass
169
 
# -b or -B to dpkg-buildpackage.
170
 
#
171
 
# Revision 1.131  2000/05/30 15:41:34  rnhodek
172
 
# Call buildd-addpkg with --dist option.
173
 
# Install freshly built packages only if $conf::system_level >= $dist.
174
 
#
175
 
# Revision 1.130  2000/05/16 12:34:20  rnhodek
176
 
# Insert a chmod -R go+rX on the build tree to make files readable; it
177
 
# happens sometimes that files in a .orig.tar.gz have restrictive
178
 
# permissions and this can be inconvenient.
179
 
#
180
 
# Revision 1.129  2000/03/01 14:43:34  rnhodek
181
 
# Also match error message "dpkg: status database area is locked" from
182
 
# apt and retry call later.
183
 
#
184
 
# Revision 1.128  2000/02/16 15:21:33  rnhodek
185
 
# Fix a print message in merge_pkg_build_deps.
186
 
#
187
 
# Revision 1.127  2000/02/16 15:20:38  rnhodek
188
 
# Print version number of sbuild in package log.
189
 
#
190
 
# Revision 1.126  2000/02/16 15:15:15  rnhodek
191
 
# Fix regexp for finding !needs-no-XXX packages.
192
 
# Move !needs-no-XXX from central deps to $main::additional_deps so that
193
 
# they can be found by prepare_watches later.
194
 
#
195
 
# Revision 1.125  2000/02/15 14:40:35  rnhodek
196
 
# Remove forgotten debugging code.
197
 
#
198
 
# Revision 1.124  2000/02/15 11:12:43  rnhodek
199
 
# Expand virtual packages in package build dependencies for comparing
200
 
# with central deps.
201
 
#
202
 
# Revision 1.123  2000/02/11 11:17:07  rnhodek
203
 
# Do not activate watches for packages XXX if a negative dependency
204
 
# needs-no-XXX exists (used to be just a comment, now really processed
205
 
# by sbuild.)
206
 
# Also do not activate watches for dependencies of pkg build deps.
207
 
#
208
 
# Revision 1.122  2000/02/09 15:57:25  rnhodek
209
 
# In merge_pkg_build_deps, do not show warnings about missing
210
 
# !this-package-does-not-exist or !needs-no-xxx dependencies.
211
 
#
212
 
# Revision 1.121  2000/02/04 14:04:18  rnhodek
213
 
# Use --no-down-propagation.
214
 
#
215
 
# Revision 1.120  2000/02/01 12:05:56  rnhodek
216
 
# In binNMU mode, a '_' was missing in the job name.
217
 
#
218
 
# Revision 1.119  2000/01/28 14:54:43  rnhodek
219
 
# Accept abbrevs for distribution options (-ds, -df, -du) here, too.
220
 
# New option --make-binNMU=entry.
221
 
# New binNMU hack to modify debian/changelog; it will add a new entry
222
 
# for the NMU version.
223
 
# New helper function binNMU_version to generate a new version number.
224
 
#
225
 
# Revision 1.118  2000/01/13 14:32:30  rnhodek
226
 
# For compiling on slink systems, pass the --force-confold option to
227
 
# dpkg only for versions < 1.4.1.18 (that don't understand it yet).
228
 
#
229
 
# Revision 1.117  1999/12/17 13:49:50  rnhodek
230
 
# Improved output about missing central deps: build-essential (act.
231
 
# policy) and dependencies of pkg build deps are filtered out and
232
 
# printed separately.
233
 
# New functions cmp_dep_lists, read_build_essential,
234
 
# expand_dependencies, and get_dependencies for the above.
235
 
#
236
 
# Revision 1.116  1999/12/17 11:04:43  rnhodek
237
 
# When pkg build-deps were read from debian/sbuild-build-deps, a wrong
238
 
# package name was used.
239
 
#
240
 
# Revision 1.115  1999/12/09 09:54:42  rnhodek
241
 
# Again fixed a fatal typo...
242
 
#
243
 
# Revision 1.114  1999/12/08 12:33:16  rnhodek
244
 
# merge_pkg_build_deps: Fix printing of overrides.
245
 
#
246
 
# Revision 1.113  1999/12/08 12:25:34  rnhodek
247
 
# Special dependencies are implicitly overrides, i.e. are added to the
248
 
# package-provided build deps.
249
 
#
250
 
# Revision 1.112  1999/12/08 11:31:38  rnhodek
251
 
# get_dpkg_status: don't reset $res{$pkg}->{Installed} to 0 if $pkg is
252
 
# provided.
253
 
#
254
 
# Revision 1.111  1999/12/08 10:37:33  rnhodek
255
 
# Change parsing of .dsc file so that multi-line build dependencies are
256
 
# allowed.
257
 
# Make warning about missing central deps a bit bigger.
258
 
#
259
 
# Revision 1.110  1999/12/06 15:00:33  rnhodek
260
 
# Fix comparison with old deps (must copy them, not only the reference).
261
 
#
262
 
# Revision 1.109  1999/12/06 08:35:53  rnhodek
263
 
# Fixed typo.
264
 
#
265
 
# Revision 1.108  1999/12/03 09:58:16  rnhodek
266
 
# If a pkg has its own build deps, compare them with the central ones
267
 
# and report missing ones.
268
 
#
269
 
# Revision 1.107  1999/11/30 13:54:38  rnhodek
270
 
# Print a message if build deps from the .dsc are used (to avoid confusion).
271
 
# If a pkg has build deps, store them in debian/.sbuild-build-deps to
272
 
# have them available when rebuilding later (no .dsc anymore); also
273
 
# check for this file and read deps from it if building without a .dsc
274
 
# in unpacked source.
275
 
#
276
 
# Revision 1.106  1999/11/15 12:30:15  rnhodek
277
 
# merge_pkg_build_deps: added missing if $main::debug.
278
 
#
279
 
# Revision 1.105  1999/11/03 14:56:32  rnhodek
280
 
# When running apt, set env var DEBIAN_FRONTEND to noninteractive to
281
 
# stop debconf from asking questions or complaining that /dev/tty can't
282
 
# be opened.
283
 
#
284
 
# Revision 1.104  1999/11/02 16:43:51  rnhodek
285
 
# check_inst_packages: also upgrade dependencies of src-deps (if they're
286
 
# already installed); some -dev packages fail to correctly require an
287
 
# identical versioned shlib pkg, so in some cases only the -dev pkg was
288
 
# installed.
289
 
#
290
 
# Revision 1.103  1999/11/02 15:45:43  rnhodek
291
 
# build: Use epoch-stripped version number for the .changes file.
292
 
# check_inst_packages: forgot a if $main::debug.
293
 
#
294
 
# Revision 1.102  1999/10/29 13:07:49  rnhodek
295
 
# New option --stats-dir=DIR; if used, a "1" is appended to
296
 
# DIR/give-back each time a package is given back.
297
 
#
298
 
# Revision 1.101  1999/10/29 12:32:24  rnhodek
299
 
# If using an already unpacked source tree, check (with
300
 
# dpkg-parsechangelog) if it's really the requested version.
301
 
# Make apt-get run dpkg with --force-confold, as the </dev/null trick
302
 
# doesn't work anymore with dpkg >= 1.4.1.18.
303
 
#
304
 
# Revision 1.100  1999/10/25 12:12:21  rnhodek
305
 
# check_inst_packages: Add packages to @deps_inst only if they're not
306
 
# already to be installed.
307
 
#
308
 
# Revision 1.99  1999/10/22 09:01:36  rnhodek
309
 
# Minor changes to output of check_inst_packages.
310
 
#
311
 
# Revision 1.98  1999/10/21 14:21:57  rnhodek
312
 
# Oops... call check_inst_packages only if build was successful.
313
 
#
314
 
# Revision 1.97  1999/10/21 11:46:50  rnhodek
315
 
# Deleted RCS logs for < 1.50.
316
 
# New option --store-built-packages.
317
 
# Fix package name parsing: \w also matches '_' which is unwanted;
318
 
# replace by a-zA-Z.
319
 
# Read reverse sourcedeps of $main::store_built_packages.
320
 
# New sub check_inst_packages.
321
 
#
322
 
# Revision 1.96  1999/09/27 11:18:10  rnhodek
323
 
# Added a missing PLOG.
324
 
#
325
 
# Revision 1.95  1999/09/15 09:10:25  rnhodek
326
 
# Additionally print a warning if a special dep has a version relation.
327
 
#
328
 
# Revision 1.94  1999/09/15 09:08:12  rnhodek
329
 
# Changed parsing of dependencies a bit so that special deps can have
330
 
# arch restrictions, too.
331
 
#
332
 
# Revision 1.93  1999/08/30 09:44:35  rnhodek
333
 
# get_dpkg_status: don't exit too early if a pkg isn't in the arg list,
334
 
# as it might be provided only.
335
 
#
336
 
# Revision 1.92  1999/08/27 13:32:04  rnhodek
337
 
# --auto-give-back has a new optional argument, the user and hostname
338
 
# where to call wanna-build (like $conf::sshcmd); this is needed that
339
 
# sbuild can do give-backs when there's no local wanna-build.
340
 
#
341
 
# Revision 1.91  1999/08/23 12:53:02  rnhodek
342
 
# Support for alternatives.
343
 
# Support for [ARCH1 !ARCH2] arch restriction on dependencies.
344
 
# Parses only src-deps which are needed for packages to be built.
345
 
# Reads Build-{Depends,Conflicts}{,-Indep}: fields from .dsc if present;
346
 
# those override the central src-deps, except those marked as override
347
 
# (& prefix).
348
 
# Implemented abbrevs as kind of macros in src-deps.
349
 
# New option --add-depends (-a).
350
 
# New option --arch-all (-A).
351
 
#
352
 
# Revision 1.90  1999/08/11 15:28:11  rnhodek
353
 
# Insert missing wait call in run_script to get correct return value.
354
 
#
355
 
# Revision 1.89  1999/08/10 14:01:49  rnhodek
356
 
# Virtual packages as dependencies didn't work really yet -- the
357
 
# consistency check didn't see them (dpkg --status doesn't know them)
358
 
# and thus aborted the build; solution: get_dpkg_status now directly
359
 
# reads the status file (which should be a bit faster, too) and extracts
360
 
# Provides: fields of all installed packages and considers those virtual
361
 
# packages installed, too.
362
 
# Print "Source-dependencies not satisfied" message to package log, not
363
 
# to sbuild log.
364
 
# Same in run_apt for virtual package handling.
365
 
# Fix stdout/stderr redirecting when running scripts.
366
 
#
367
 
# Revision 1.88  1999/07/13 07:23:55  rnhodek
368
 
# Use GDBM for time/space databases, as perl-5.004 seems not to contain
369
 
# DB_File anymore.
370
 
#
371
 
# Revision 1.87  1999/06/21 12:52:00  rnhodek
372
 
# Seems apt has a new error message if a cached Packages file isn't
373
 
# up-to-date anymore -- recognize this msg, too, and reun apt-get update.
374
 
#
375
 
# Revision 1.86  1999/06/09 15:05:38  rnhodek
376
 
# Fix loop in apply_patches.
377
 
# Don't fail due to failed patch if a global patch.
378
 
# Global patches are no syntax error when parsing src-deps...
379
 
#
380
 
# Revision 1.85  1999/06/04 09:47:02  rnhodek
381
 
# Add support for global patches, which will be tried on any package;
382
 
# their names in source-dependencies start with "**".
383
 
#
384
 
# Revision 1.84  1999/06/04 08:17:17  rnhodek
385
 
# When calling wanna-build --give-back, don't forget the --dist argument!
386
 
# Added support for virtual packages as source dependencies: apt-get tells us
387
 
# which alternatives are possible, and one of these is selected either by
388
 
# %conf::alternatives or by random.
389
 
#
390
 
# Revision 1.83  1999/06/02 09:07:47  rnhodek
391
 
# With --batch, write each finished job to SBUILD-FINISHED; buildd can pick up
392
 
# this file if sbuild crashes and needs not rebuild already done stuff. The file
393
 
# is removed on normal exit and if sbuild dumps to REDO during a shutdown.
394
 
#
395
 
# Revision 1.82  1999/06/02 08:47:39  rnhodek
396
 
# Remove as many die's as possible -- the bad exit status can cause
397
 
# buildd to retry all packages of an sbuild run; better let this one
398
 
# package fail.
399
 
# Make sure that after build() we're in the correct directory: some
400
 
# chdir()s were missing; also don't chdir("..") because this can be
401
 
# wrong if we followed a symlink, use $main::cwd instead.
402
 
# If the package directory already exists as a symlink, abort the build.
403
 
#
404
 
# Revision 1.81  1999/05/31 12:59:41  rnhodek
405
 
# Run du after build under sudo, to avoid error messages about
406
 
# unreadable dirs.
407
 
#
408
 
# Revision 1.80  1999/05/27 13:28:04  rnhodek
409
 
# Oops, missed an epoch fix (when constructing the .changes file name).
410
 
#
411
 
# Revision 1.79  1999/05/26 11:34:11  rnhodek
412
 
# Ignore epochs for fetching files.
413
 
#
414
 
# Revision 1.78  1999/05/26 09:48:23  rnhodek
415
 
# If dpkg-source fails, remove .tmp-nest dir.
416
 
#
417
 
# Revision 1.77  1999/05/05 07:56:51  rnhodek
418
 
# Need to empty %main::this_watches before filling it for a new package;
419
 
# otherwise we have some spurious reports :-)
420
 
#
421
 
# Revision 1.76  1999/05/04 14:51:40  rnhodek
422
 
# Some more minor stuff for avg-build-space: Reset global
423
 
# $main::this_space to 0 before each build to avoid using the figure of
424
 
# the previous package in case of errors; don't write a 0 value into the
425
 
# database.
426
 
#
427
 
# Revision 1.75  1999/05/04 14:43:01  rnhodek
428
 
# Fix parsing of a single dependency: package name never should contain
429
 
# a '('.
430
 
#
431
 
# Revision 1.74  1999/05/04 14:29:51  rnhodek
432
 
# Determine how much space is required for a build (final build dir +
433
 
# generated .debs) after dpkg-buildpackage is finished; display figure
434
 
# in package log and also store it in $conf::avg_space_db (analogous to
435
 
# avg_time_db).
436
 
#
437
 
# Revision 1.73  1999/05/03 12:53:25  rnhodek
438
 
# After unpacking src dir, run "chmod -R g-s ." on it; some
439
 
# .orig.tar.gz's are packed with the setgid bit, which causes the debian
440
 
# dir and all subdirs to be created setgid, too, and later dpkg-deb
441
 
# --build complains about this.
442
 
#
443
 
# Revision 1.72  1999/04/22 14:16:25  rnhodek
444
 
# Don't kill tee process if verbose but --nolog set -- $pkg_tee_pid
445
 
# undefined then!
446
 
#
447
 
# Revision 1.71  1999/04/21 14:54:10  rnhodek
448
 
# Implemented watches if certain binaries have been used during a build
449
 
# without a source dependency.
450
 
#
451
 
# Revision 1.70  1999/03/12 10:29:32  rnhodek
452
 
# New option --force-depends (-f) to override src-deps of a package.
453
 
#
454
 
 
455
 
BEGIN {
456
 
        ($main::HOME = $ENV{'HOME'})
457
 
                or die "HOME not defined in environment!\n";
458
 
        push( @INC, "$main::HOME/lib" );
459
 
}
460
 
 
461
 
chomp( $main::HOSTNAME = `hostname` );
462
 
 
463
 
package conf;
464
 
$HOME = $main::HOME;
465
 
# defaults:
466
 
@dist_parts = qw(main contrib non-free);
467
 
$source_dependencies = "/etc/source-dependencies";
468
 
$mailprog = "/usr/sbin/sendmail";
469
 
$dpkg = "/usr/bin/dpkg";
470
 
$sudo = "/usr/bin/sudo";
471
 
$su = "/bin/su";
472
 
$fakeroot = "/usr/bin/fakeroot";
473
 
$apt_get = "/usr/bin/apt-get";
474
 
$apt_cache = "/usr/bin/apt-cache";
475
 
$dpkg_source = "/usr/bin/dpkg-source";
476
 
$build_env_cmnd = "";
477
 
$pgp_options = "-us -uc";
478
 
$log_dir = "$main::HOME/logs";
479
 
$mailto = "";
480
 
$purge_build_directory = "successful";
481
 
@toolchain_regex = ( 'binutils$', 'gcc-[\d.]+$', 'g\+\+-[\d.]+$', 'libstdc\+\+', 'libc[\d.]+-dev$', 'linux-kernel-headers$', 'dpkg-dev$', 'make$' );
482
 
$stalled_pkg_timeout = 90; # minutes
483
 
$srcdep_lock_wait = 1; # minutes
484
 
%individual_stalled_pkg_timeout = ();
485
 
$path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin:/usr/games";
486
 
# read conf files
487
 
require "/etc/sbuild.conf" if -r "/etc/sbuild.conf";
488
 
require "$HOME/.sbuildrc" if -r "$HOME/.sbuildrc";
489
 
# some checks
490
 
#die "mailprog binary $conf::mailprog does not exist or isn't executable\n"
491
 
#       if !-x $conf::mailprog;
492
 
die "sudo binary $conf::sudo does not exist or isn't executable\n"
493
 
        if !-x $conf::sudo;
494
 
die "apt-get binary $conf::apt_get does not exist or isn't executable\n"
495
 
        if !-x $conf::apt_get;
496
 
die "apt-cache binary $conf::apt_cache does not exist or isn't executable\n"
497
 
        if !-x $conf::apt_cache;
498
 
die "dpkg-source binary $conf::dpkg_source does not exist or isn't executable\n"
499
 
        if !-x $conf::dpkg_source;
500
 
#die "$conf::log_dir is not a directory\n" if ! -d $conf::log_dir;
501
 
die "$conf::srcdep_lock_dir is not a directory\n" if ! -d $conf::srcdep_lock_dir;
502
 
die "conf::mailto not set\n" if !$conf::mailto;
503
 
package main;
504
 
 
505
 
use strict;
506
 
use GDBM_File;
507
 
use POSIX;
508
 
use FileHandle;
509
 
use Cwd;
510
 
 
511
 
# avoid intermixing of stdout and stderr
512
 
$| = 1;
513
 
 
514
 
# We should not ignore HUP for our children - it breaks test suites.
515
 
# in case the terminal disappears, the build should continue
516
 
#$SIG{'HUP'} = 'IGNORE';
517
 
 
518
 
$main::distribution = "";
519
 
$main::distribution = $conf::default_distribution if $conf::default_distribution;
520
 
 
521
 
chomp( $main::arch = `$conf::dpkg --print-architecture` );
522
 
$main::username = (getpwuid($<))[0] || $ENV{'LOGNAME'} || $ENV{'USER'};
523
 
$main::debug = 0;
524
 
$main::verbose = 0;
525
 
$main::batchmode = 0;
526
 
$main::auto_giveback = 0;
527
 
$main::nomail = 0;
528
 
$main::build_arch_all = 0;
529
 
$main::build_source = 0;
530
 
$main::jobs_file = cwd() . "/build-progress";
531
 
$main::max_lock_trys = 120;
532
 
$main::lock_interval = 5;
533
 
$main::cwd = cwd();
534
 
$main::ilock_file = "$conf::srcdep_lock_dir/install";
535
 
$main::srcdep_lock_cnt = 0;
536
 
$main::chroot_dir = "";
537
 
$main::chroot_build_dir = "";
538
 
$main::chroot_apt_options = "";
539
 
@main::toolchain_pkgs = ();
540
 
$main::component="";
541
 
$main::nr_processors = $ENV{'NR_PROCESSORS'} if $ENV{'NR_PROCESSORS'};
542
 
 
543
 
umask(022);
544
 
 
545
 
$main::new_dpkg = 0;
546
 
check_dpkg_version();
547
 
 
548
 
while( @ARGV && $ARGV[0] =~ /^-/ ) {
549
 
        $_ = shift @ARGV;
550
 
        if (/^-v$/ || /^--verbose$/) {
551
 
                $main::verbose++;
552
 
        }
553
 
        elsif (/^-D$/ || /^--debug$/) {
554
 
                $main::debug++;
555
 
        }
556
 
        elsif (/^-b$/ || /^--batch$/) {
557
 
                $main::batchmode = 1;
558
 
        }
559
 
        elsif (/^-n$/ || /^--nolog$/) {
560
 
                $main::nolog = 1;
561
 
        }
562
 
        elsif (/^-A$/ || /^--arch-all$/) {
563
 
                $main::build_arch_all++;
564
 
        }
565
 
        elsif (/^-s$/ || /^--source$/) {
566
 
                $main::build_source++;
567
 
                $conf::purge_build_directory = "never";
568
 
        }
569
 
        elsif (/^--architecture=(.)/) {
570
 
                $conf::arch=$1.$';
571
 
        }
572
 
        elsif (/^--archive=(.)/) {
573
 
                $main::archive=$1.$';
574
 
        }
575
 
        elsif (/^--comp=(.)/) {
576
 
                $main::component=$1.$';
577
 
        }
578
 
        elsif (/^--purpose=(.)/) {
579
 
                $main::purpose=$1.$';
580
 
        }
581
 
        elsif (/^--build-debug-symbols$/) {
582
 
                $main::build_debug_symbols = 1;
583
 
        }
584
 
        elsif (/^-d/ || /^--dist/) {
585
 
                if (/^-d(.)/ || /^--dist=(.)/) {
586
 
                        $main::distribution = $1.$';
587
 
                }
588
 
                elsif (!@ARGV) {
589
 
                        die "$_ option missing argument\n";
590
 
                }
591
 
                else {
592
 
                        $main::distribution = shift @ARGV;
593
 
                }
594
 
                $main::distribution = "stable"   if $main::distribution eq "s";
595
 
                $main::distribution = "testing"  if $main::distribution eq "t";
596
 
                $main::distribution = "unstable" if $main::distribution eq "u";
597
 
        }
598
 
        elsif (/^-p/ || /^--purge/) {
599
 
                if (/^-p(.)/ || /^--purge=(.)/) {
600
 
                        $conf::purge_build_directory = $1.$';
601
 
                }
602
 
                elsif (!@ARGV) {
603
 
                        die "$_ option missing argument\n";
604
 
                }
605
 
                else {
606
 
                        $conf::purge_build_directory = shift @ARGV;
607
 
                }
608
 
                die "Bad purge mode\n"
609
 
                        if !isin($conf::purge_build_directory, qw(always successful never));
610
 
        }
611
 
        elsif (/^-m/ || /^--maintainer/) {
612
 
                if (/^-m(.)/ || /^--maintainer=(.)/) {
613
 
                        $conf::maintainer_name = $1.$';
614
 
                }
615
 
                elsif (!@ARGV) {
616
 
                        die "$_ option missing argument\n";
617
 
                }
618
 
                else {
619
 
                        $conf::maintainer_name = shift @ARGV;
620
 
                }
621
 
        }
622
 
        elsif (/^-f/ || /^--force-depends/) {
623
 
                if (/^-f(.)/ || /^--force-depends=(.)/) {
624
 
                        push( @main::manual_srcdeps, "f".$1.$' );
625
 
                }
626
 
                elsif (!@ARGV) {
627
 
                        die "$_ option missing argument\n";
628
 
                }
629
 
                else {
630
 
                        push( @main::manual_srcdeps, "f".(shift @ARGV) );
631
 
                }
632
 
        }
633
 
        elsif (/^-a/ || /^--add-depends/) {
634
 
                if (/^-a(.)/ || /^--add-depends=(.)/) {
635
 
                        push( @main::manual_srcdeps, "a".$1.$' );
636
 
                }
637
 
                elsif (!@ARGV) {
638
 
                        die "$_ option missing argument\n";
639
 
                }
640
 
                else {
641
 
                        push( @main::manual_srcdeps, "a".(shift @ARGV) );
642
 
                }
643
 
        }
644
 
        elsif (/^--auto-give-back(=(.*))?$/) {
645
 
                $main::auto_giveback = 1;
646
 
                if ($2) {
647
 
                        my @parts = split( '@', $2 );
648
 
                        $main::auto_giveback_socket  = "$main::HOME/build" if @parts > 3;
649
 
                        $main::auto_giveback_socket .= $parts[$#parts-3] if @parts > 3;
650
 
                        $main::auto_giveback_wb_user = $parts[$#parts-2] if @parts > 2;
651
 
                        $main::auto_giveback_user    = $parts[$#parts-1] if @parts > 1;
652
 
                        $main::auto_giveback_host    = $parts[$#parts];
653
 
                }
654
 
        }
655
 
        elsif (/^--database=(.+)$/) {
656
 
                $main::database = $1;
657
 
        }
658
 
        elsif (/^--stats-dir=(.+)$/) {
659
 
                $main::stats_dir = $1;
660
 
        }
661
 
        elsif (/^--make-binNMU=(.+)$/) {
662
 
                $main::binNMU = $1;
663
 
                $main::binNMUver ||= 1;
664
 
        }
665
 
        elsif (/^--binNMU=(\d+)$/) {
666
 
                $main::binNMUver = $1;
667
 
        }
668
 
        elsif (/^--use-snapshot$/) {
669
 
                $main::useSNAP = 1;
670
 
                $main::ld_library_path = "/usr/lib/gcc-snapshot/lib";
671
 
                $conf::path = "/usr/lib/gcc-snapshot/bin:$conf::path";
672
 
        }
673
 
        else {
674
 
                die "Unknown option: $_\n";
675
 
        }
676
 
}
677
 
 
678
 
die "Need distribution\n" if $main::distribution eq "";
679
 
 
680
 
$conf::mailto = $conf::mailto{$main::distribution}
681
 
        if $conf::mailto{$main::distribution};
682
 
 
683
 
$main::arch = $conf::arch if $conf::arch;
684
 
 
685
 
# variables for scripts:
686
 
open_log();
687
 
$SIG{'INT'} = \&shutdown;
688
 
$SIG{'TERM'} = \&shutdown;
689
 
$SIG{'ALRM'} = \&shutdown;
690
 
$SIG{'PIPE'} = \&shutdown;
691
 
read_deps( map { m,(?:.*/)?([^_/]+)[^/]*, } @ARGV );
692
 
if (-d "chroot-autobuild") {
693
 
        $main::chroot_dir = "chroot-autobuild";
694
 
        $main::chroot_build_dir = "$main::chroot_dir/build/$main::username/";
695
 
        $conf::srcdep_lock_dir = "$main::chroot_dir/var/debbuild/srcdep-lock";
696
 
        $main::ilock_file = "$conf::srcdep_lock_dir/install";
697
 
        my $absroot = "$main::cwd/$main::chroot_dir";
698
 
        $main::chroot_apt_options =
699
 
                "-o APT::Architecture=$main::arch ".
700
 
                "-o Dir::State=$absroot/var/".
701
 
                        (-d "$absroot/var/lib/apt" ? "lib":"state")."/apt ".
702
 
                "-o Dir::State::status=$absroot/var/lib/dpkg/status ".
703
 
                "-o Dir::Cache=$absroot/var/cache/apt ".
704
 
                "-o Dir::Etc=$absroot/etc/apt ".
705
 
                "-o DPkg::Options::=--root=$absroot ".
706
 
                "-o DPkg::Options::=--force-architecture ".
707
 
                "-o DPkg::Run-Directory=$absroot";
708
 
        $main::chroot_apt_op = '$CHROOT_OPTIONS';
709
 
}
710
 
write_jobs_file();
711
 
 
712
 
my( $pkgv, $pkg );
713
 
foreach $pkgv (@ARGV) {
714
 
        my $urlbase;
715
 
 
716
 
        
717
 
        ($urlbase, $pkgv) = ($1, $3) if $pkgv =~ m,^(\w+://(\S+/)?)([^/]+)$,;
718
 
        $pkgv =~ s/\.dsc$//;
719
 
        next if !open_pkg_log( $pkgv );
720
 
        (my $pkg = $pkgv) =~ s/_.*$//;
721
 
        $main::pkg_start_time = time;
722
 
        $main::this_space = 0;
723
 
        $main::pkg_status = "failed"; # assume for now
724
 
        $main::current_job = $main::binNMU_name || $pkgv;
725
 
        $main::additional_deps = [];
726
 
        write_jobs_file( "currently building" );
727
 
        if (should_skip( $pkgv )) {
728
 
                $main::pkg_status = "skipped";
729
 
                goto cleanup_close;
730
 
        }
731
 
        my $dscfile = $pkgv.".dsc";
732
 
        $main::pkg_fail_stage = "fetch-src";
733
 
        my @files_to_rm = fetch_source_files( \$dscfile );
734
 
        if (@files_to_rm && $files_to_rm[0] eq "ERROR") {
735
 
                shift @files_to_rm;
736
 
                goto cleanup_symlinks;
737
 
        }
738
 
                
739
 
        $main::pkg_fail_stage = "install-deps";
740
 
        if (!install_deps( $pkg )) {
741
 
                print PLOG "Source-dependencies not satisfied; skipping $pkg\n";
742
 
                goto cleanup_packages;
743
 
        }
744
 
 
745
 
        my $dscbase = basename( $dscfile );
746
 
        $main::pkg_status = "successful" if build( $dscbase, $pkgv );
747
 
        chdir( $main::cwd );
748
 
        write_jobs_file( $main::pkg_status );
749
 
        append_to_FINISHED( $main::current_job );
750
 
 
751
 
  cleanup_packages:
752
 
        undo_specials();
753
 
        uninstall_deps();
754
 
        remove_srcdep_lock_file();
755
 
  cleanup_symlinks:
756
 
        remove_files( @files_to_rm );
757
 
  cleanup_close:
758
 
        analyze_fail_stage( $pkgv );
759
 
        if( $main::pkg_status eq 'failed' ) {
760
 
                $main::pkg_status = 'failed ' . $main::pkg_fail_stage;
761
 
        }
762
 
        write_jobs_file( $main::pkg_status );
763
 
        close_pkg_log( $pkgv );
764
 
        $main::current_job = "";
765
 
        if ( $main::batchmode and (-f "$main::HOME/EXIT-DAEMON-PLEASE") ) {
766
 
            main::shutdown("NONE (flag file exit)");
767
 
        }
768
 
}
769
 
write_jobs_file();
770
 
 
771
 
close_log();
772
 
#unlink( $main::jobs_file ) if $main::batchmode;
773
 
unlink( "SBUILD-FINISHED" ) if $main::batchmode;
774
 
exit 0;
775
 
 
776
 
sub fetch_source_files {
777
 
        my $dscfile_ref = shift;
778
 
        my $dscfile = $$dscfile_ref;
779
 
        my ($dir, $dscbase, $files, @other_files, $dscarchs, @made);
780
 
        my ($build_depends, $build_depends_indep, $build_conflicts,
781
 
                $build_conflicts_indep);
782
 
        local( *F );
783
 
 
784
 
        $dscfile =~ m,^(.*)/([^/]+)$,;
785
 
        ($dir, $dscbase) = ($1, $2);
786
 
        my $urlbase;
787
 
        $urlbase = $1 if $dscfile =~ m,^(\w+://(\S+/)?)([^/]+)$,;
788
 
        (my $pkgv = $dscfile) =~ s,^(.*/)?([^/]+)\.dsc$,$2,;
789
 
        my ($pkg, $version) = split /_/, $pkgv;
790
 
        @main::have_dsc_build_deps = ();
791
 
 
792
 
        if (-d $dscfile) {
793
 
                if (-f "$dscfile/debian/.sbuild-build-deps") {
794
 
                        open( F, "<$dscfile/debian/.sbuild-build-deps" );
795
 
                        my $pkg;
796
 
                        while( <F> ) {
797
 
                                /^Package:\s*(.*)\s*$/i and $pkg = $1;
798
 
                                /^Build-Depends:\s*(.*)\s*$/i and $build_depends = $1;
799
 
                                /^Build-Depends-Indep:\s*(.*)\s*$/i and $build_depends_indep = $1;
800
 
                                /^Build-Conflicts:\s*(.*)\s*$/i and $build_conflicts = $1;
801
 
                                /^Build-Conflicts-Indep:\s*(.*)\s*$/i and $build_conflicts_indep = $1;
802
 
                        }
803
 
                        close( F );
804
 
                        if ($build_depends || $build_depends_indep || $build_conflicts ||
805
 
                                $build_conflicts_indep) {
806
 
                                merge_pkg_build_deps( $pkg, $build_depends,
807
 
                                                                          $build_depends_indep, $build_conflicts,
808
 
                                                                          $build_conflicts_indep );
809
 
                        }
810
 
                }
811
 
                return;
812
 
        }
813
 
 
814
 
        if ($dir ne ".") {
815
 
                {
816
 
                        if (-f "${pkgv}.dsc") {
817
 
                                print PLOG "${pkgv}.dsc exists in cwd\n";
818
 
                        }
819
 
                        else {
820
 
                                my %entries;
821
 
                                my $retried = 0;
822
 
 
823
 
                          retry:
824
 
                                print PLOG "Checking available source versions...\n";
825
 
                                if (!open( PIPE, "$conf::sudo /usr/sbin/chroot ".
826
 
                                                   "$main::chroot_dir $conf::apt_cache ".
827
 
                                                   "-q showsrc $pkg 2>&1 </dev/null |" )) {
828
 
                                        print PLOG "Can't open pipe to apt-cache: $!\n";
829
 
                                        return ("ERROR");
830
 
                                }
831
 
                                { local($/) = "";
832
 
                                  while( <PIPE> ) {
833
 
                                          my $ver = $1 if /^Version:\s+(\S+)\s*$/mi;
834
 
                                          my $tfile = $1 if /^Files:\s*\n((\s+.*\s*\n)+)/mi;
835
 
                                          @{$entries{$ver}} = map { (split( /\s+/, $_ ))[3] }
836
 
                                                  split( "\n", $tfile );
837
 
                                  }
838
 
                            }
839
 
                                close( PIPE );
840
 
                                if ($?) {
841
 
                                        print PLOG "$conf::apt_cache failed\n";
842
 
                                        return ("ERROR");
843
 
                                }
844
 
                                
845
 
                                if (!defined($entries{$version})) {
846
 
                                        if (!$retried) {
847
 
                                                # try to update apt's cache if nothing found
848
 
                                                system "$conf::sudo /usr/sbin/chroot ".
849
 
                                                           "$main::chroot_dir $conf::apt_get ".
850
 
                                                           "update >/dev/null";
851
 
                                                $retried = 1;
852
 
                                                goto retry;
853
 
                                        }
854
 
                                        print PLOG "Can't find source for $pkgv\n";
855
 
                                        print PLOG "(only different version(s) ",
856
 
                                                           join( ", ", sort keys %entries), " found)\n"
857
 
                                                if %entries;
858
 
                                        return( "ERROR" );
859
 
                                }
860
 
 
861
 
                                print PLOG "Fetching source files...\n";
862
 
                                @made = @{$entries{$version}};
863
 
                                if (!open( PIPE, "$conf::apt_get $main::chroot_apt_options ".
864
 
                                                   "--only-source -q -d source $pkg=$version 2>&1 </dev/null |" )) {
865
 
                                        print PLOG "Can't open pipe to $conf::apt_get: $!\n";
866
 
                                        return ("ERROR", @made);
867
 
                                }
868
 
                                while( <PIPE> ) {
869
 
                                        print PLOG $_;
870
 
                                }
871
 
                                close( PIPE );
872
 
                                if ($?) {
873
 
                                        print PLOG "$conf::apt_get for sources failed\n";
874
 
                                        return( "ERROR", @made );
875
 
                                }
876
 
                                # touch the downloaded files, otherwise buildd-watcher
877
 
                                # will complain that they're old :)
878
 
                                $$dscfile_ref = $dscfile = (grep { /\.dsc$/ } @made)[0];
879
 
                        }
880
 
                }
881
 
        }
882
 
        
883
 
        if (!open( F, "<$dscfile" )) {
884
 
                print PLOG "Can't open $dscfile: $!\n";
885
 
                return( "ERROR", @made );
886
 
        }
887
 
        my $dsctext;
888
 
        { local($/); $dsctext = <F>; }
889
 
        close( F );
890
 
 
891
 
        $dsctext =~ /^Build-Depends:\s*((.|\n\s+)*)\s*$/mi
892
 
                and $build_depends = $1;
893
 
        $dsctext =~ /^Build-Depends-Indep:\s*((.|\n\s+)*)\s*$/mi
894
 
                and $build_depends_indep = $1;
895
 
        $dsctext =~ /^Build-Conflicts:\s*((.|\n\s+)*)\s*$/mi
896
 
                and $build_conflicts = $1;
897
 
        $dsctext =~ /^Build-Conflicts-Indep:\s*((.|\n\s+)*)\s*$/mi
898
 
                and $build_conflicts_indep = $1;
899
 
        $build_depends =~ s/\n\s+/ /g if defined $build_depends;
900
 
        $build_depends_indep =~ s/\n\s+/ /g if defined $build_depends_indep;
901
 
        $build_conflicts =~ s/\n\s+/ /g if defined $build_conflicts;
902
 
        $build_conflicts_indep =~ s/\n\s+/ /g if defined $build_conflicts_indep;
903
 
 
904
 
        $dsctext =~ /^Architecture:\s*(.*)$/mi and $dscarchs = $1;
905
 
 
906
 
        $dsctext =~ /^Files:\s*\n((\s+.*\s*\n)+)/mi and $files = $1;
907
 
        @other_files = map { (split( /\s+/, $_ ))[3] } split( "\n", $files );
908
 
 
909
 
        if (!$dscarchs) {
910
 
                print PLOG "$dscbase has no Architecture: field -- skipping arch check!\n";
911
 
        }
912
 
        else {
913
 
                my $valid_arch;
914
 
                for my $a (split(/\s+/, $dscarchs)) {
915
 
                        if (system('dpkg-architecture', '-a' . $main::arch, '-i' . $a) eq 0) {
916
 
                                $valid_arch = 1;
917
 
                                last;
918
 
                        }
919
 
                }
920
 
                if ($dscarchs ne "any" && !($valid_arch) &&
921
 
                    !($dscarchs eq "all" && $main::build_arch_all) ) {
922
 
                        my $msg = "$dscbase: $main::arch not in arch list or does not match any arch ";
923
 
                        $msg .= "wildcards: $dscarchs -- skipping\n";
924
 
                        print PLOG $msg;
925
 
                        $main::pkg_fail_stage = "arch-check";
926
 
                        return( "ERROR", @made );
927
 
                }
928
 
        }
929
 
        print "Arch check ok ($main::arch included in $dscarchs)\n"
930
 
                if $main::debug;
931
 
 
932
 
        if ($build_depends || $build_depends_indep || $build_conflicts ||
933
 
                $build_conflicts_indep) {
934
 
                @main::have_dsc_build_deps = ($build_depends, $build_depends_indep,
935
 
                                                                          $build_conflicts,$build_conflicts_indep);
936
 
                merge_pkg_build_deps( $pkg, $build_depends, $build_depends_indep,
937
 
                                                          $build_conflicts, $build_conflicts_indep );
938
 
        }
939
 
 
940
 
        return @made;
941
 
}
942
 
 
943
 
sub build {
944
 
        my $dsc = shift;
945
 
        my $pkgv = shift;
946
 
        my( $dir, $rv, $changes );
947
 
        my $do_apply_patches = 1;
948
 
        local( *PIPE, *F, *F2 );
949
 
 
950
 
        fixup_pkgv( \$pkgv );
951
 
        print PLOG "-"x78, "\n";
952
 
        # count build time from now, ignoring the installation of source deps
953
 
        $main::pkg_start_time = time;
954
 
        $main::this_space = 0;
955
 
        $pkgv =~ /^([a-zA-Z\d.+-]+)_([a-zA-Z\d:.+~-]+)/;
956
 
        my ($pkg, $version) = ($1,$2);
957
 
        (my $sversion = $version) =~ s/^\d+://;
958
 
        my $tmpunpackdir = $dsc;
959
 
        $tmpunpackdir =~ s/-.*$/.orig.tmp-nest/;
960
 
        $tmpunpackdir =~ s/_/-/;
961
 
        $tmpunpackdir = "$main::chroot_build_dir$tmpunpackdir";
962
 
        
963
 
        if (-d "$main::chroot_build_dir$dsc" && -l "$main::chroot_build_dir$dsc") {
964
 
                # if the package dir already exists but is a symlink, complain
965
 
                print PLOG "Cannot unpack source: a symlink to a directory with the\n",
966
 
                                   "same name already exists.\n";
967
 
                return 0;
968
 
        }
969
 
        if (! -d "$main::chroot_build_dir$dsc") {
970
 
                $main::pkg_fail_stage = "unpack";
971
 
                # dpkg-source refuses to remove the remanants of an
972
 
                # aborted dpkg-source extraction, so we will if necessary.
973
 
                if (-d $tmpunpackdir) {
974
 
                    system ("rm -fr $tmpunpackdir");
975
 
                }
976
 
                $main::sub_pid = open( PIPE, "-|" );
977
 
                if (!defined $main::sub_pid) {
978
 
                        print PLOG "Can't spawn dpkg-source: $!\n";
979
 
                        return 0;
980
 
                }
981
 
                if ($main::sub_pid == 0) {
982
 
                        setpgrp( 0, $$ );
983
 
                        if ($main::chroot_build_dir && !chdir( $main::chroot_build_dir )) {
984
 
                                print PLOG "Couldn't cd to $main::chroot_build_dir: $!\n";
985
 
                                system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir;
986
 
                                exit 1;
987
 
                        }
988
 
 
989
 
                        my @files;
990
 
                        push( @files, $dsc );
991
 
                        if (!open( F, "<$main::cwd/$dsc" )) {
992
 
                                print PLOG "Can't open $main::cwd/$dsc: $!\n";
993
 
                                return 0;
994
 
                        }
995
 
                        my $dsctext;
996
 
                        { local($/); $dsctext = <F>; }
997
 
                        close( F );
998
 
                        my $files;
999
 
                        $dsctext =~ /^Files:\s*\n((\s+.*\s*\n)+)/mi and $files = $1;
1000
 
                        push(@files, map { (split( /\s+/, $_ ))[3] } split( "\n", $files ));
1001
 
 
1002
 
                        my $file;
1003
 
                        foreach $file (@files) {
1004
 
                                system ("cp", "$main::cwd/$file", "$file");
1005
 
                        }
1006
 
                        exec "$conf::sudo", "/usr/sbin/chroot", "$main::cwd/$main::chroot_dir",
1007
 
                                "$conf::su", $main::username, "-s", "/bin/sh", "-c",
1008
 
                                "cd /build/$main::username && $conf::dpkg_source -sn -x $dsc 2>&1";
1009
 
                        unlink @files;
1010
 
                }
1011
 
                $main::sub_task = "dpkg-source";
1012
 
                
1013
 
                while( <PIPE> ) {
1014
 
                        print PLOG $_;
1015
 
                        $dir = $1 if /^dpkg-source: (?:info: )?extracting \S+ in (\S+)/;
1016
 
                        $main::pkg_fail_stage = "unpack-check"
1017
 
                                if /^dpkg-source: error: file.*instead of expected/;
1018
 
                }
1019
 
                close( PIPE );
1020
 
                undef $main::sub_pid;
1021
 
                if ($?) {
1022
 
                        print PLOG "FAILED [dpkg-source died]\n";
1023
 
                
1024
 
                    system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir;
1025
 
                        return 0;
1026
 
                }
1027
 
                if (!$dir) {
1028
 
                        print PLOG "Couldn't find directory of $dsc in dpkg-source output\n";
1029
 
                    system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir;
1030
 
                        return 0;
1031
 
                }
1032
 
                $dir = "$main::chroot_build_dir$dir";
1033
 
 
1034
 
                if (system( "chmod -R g-s,go+rX $dir" ) != 0) {
1035
 
                        print PLOG "chmod -R g-s,go+rX $dir failed.\n";
1036
 
                        return 0;
1037
 
                }
1038
 
                
1039
 
                if (@main::have_dsc_build_deps && !defined $main::build_source) {
1040
 
                        my ($d, $di, $c, $ci) = @main::have_dsc_build_deps;
1041
 
                        open( F, ">$dir/debian/.sbuild-build-deps" );
1042
 
                        print F "Package: $pkg\n";
1043
 
                        print F "Build-Depends: $d\n" if $d;
1044
 
                        print F "Build-Depends-Indep: $di\n" if $di;
1045
 
                        print F "Build-Conflicts: $c\n" if $c;
1046
 
                        print F "Build-Conflicts-Indep: $ci\n" if $ci;
1047
 
                        close( F );
1048
 
                }
1049
 
        }
1050
 
        else {
1051
 
                $dir = "$main::chroot_build_dir$dsc";
1052
 
                $do_apply_patches = 0;
1053
 
 
1054
 
                $main::pkg_fail_stage = "check-unpacked-version";
1055
 
                # check if the unpacked tree is really the version we need
1056
 
                $main::sub_pid = open( PIPE, "-|" );
1057
 
                if (!defined $main::sub_pid) {
1058
 
                        print PLOG "Can't spawn dpkg-parsechangelog: $!\n";
1059
 
                        return 0;
1060
 
                }
1061
 
                if ($main::sub_pid == 0) {
1062
 
                        setpgrp( 0, $$ );
1063
 
                        chdir( $dir );
1064
 
                        exec "dpkg-parsechangelog 2>&1";
1065
 
                }
1066
 
                $main::sub_task = "dpkg-parsechangelog";
1067
 
 
1068
 
                my $clog = "";
1069
 
                while( <PIPE> ) {
1070
 
                        $clog .= $_;
1071
 
                }
1072
 
                close( PIPE );
1073
 
                undef $main::sub_pid;
1074
 
                if ($?) {
1075
 
                        print PLOG "FAILED [dpkg-parsechangelog died]\n";
1076
 
                        return 0;
1077
 
                }
1078
 
                if ($clog !~ /^Version:\s*(.+)\s*$/mi) {
1079
 
                        print PLOG "dpkg-parsechangelog didn't print Version:\n";
1080
 
                        return 0;
1081
 
                }
1082
 
                my $tree_version = $1;
1083
 
                my $cmp_version = ($main::binNMU && -f "$dir/debian/.sbuild-binNMU-done") ?
1084
 
                        binNMU_version($version) : $version;
1085
 
                if ($tree_version ne $cmp_version) {
1086
 
                        print PLOG "The unpacked source tree $dir is version ".
1087
 
                                           "$tree_version, not wanted $cmp_version!\n";
1088
 
                        return 0;
1089
 
                }
1090
 
        }
1091
 
 
1092
 
        if (!chdir( $dir )) {
1093
 
                print PLOG "Couldn't cd to $dir: $!\n";
1094
 
                system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir;
1095
 
                return 0;
1096
 
        }
1097
 
 
1098
 
        $main::pkg_fail_stage = "check-space";
1099
 
        my $current_usage = `/usr/bin/du -s .`;
1100
 
        $current_usage =~ /^(\d+)/;
1101
 
        $current_usage = $1;
1102
 
        if ($current_usage) {
1103
 
                my $free = df( "." );
1104
 
                if ($free < 2*$current_usage) {
1105
 
                        print PLOG "Disk space is propably not enough for building.\n".
1106
 
                                           "(Source needs $current_usage KB, free are $free KB.)\n";
1107
 
                        print PLOG "Purging $dir\n";
1108
 
                        chdir( $main::cwd );
1109
 
                        system "$conf::sudo rm -rf $dir";
1110
 
                        return 0;
1111
 
                }
1112
 
        }
1113
 
 
1114
 
        $main::pkg_fail_stage = "hack-binNMU";
1115
 
        if ($main::binNMU && ! -f "debian/.sbuild-binNMU-done") {
1116
 
                if (open( F, "<debian/changelog" )) {
1117
 
                        my($firstline, $text);
1118
 
                        $firstline = <F> while $firstline =~ /^$/;
1119
 
                        { local($/); undef $/; $text = <F>; }
1120
 
                        close( F );
1121
 
                        $firstline =~ /^(\S+)\s+\((\S+)\)\s+([^;]+)\s*;\s*urgency=(\S+)\s*$/;
1122
 
                        my ($name, $version, $dists, $urgent) = ($1, $2, $3, $4);
1123
 
                        my $NMUversion = binNMU_version($version);
1124
 
                        chomp( my $date = `822-date` );
1125
 
                        if (!open( F, ">debian/changelog" )) {
1126
 
                                print PLOG "Can't open debian/changelog for binNMU hack: $!\n";
1127
 
                                chdir( $main::cwd );
1128
 
                                return 0;
1129
 
                        }
1130
 
                        $dists = $main::distribution;
1131
 
                        print F "$name ($NMUversion) $dists; urgency=low\n\n";
1132
 
                        print F "  * Binary-only non-maintainer upload for $main::arch; ",
1133
 
                                        "no source changes.\n";
1134
 
                        print F "  * ", join( "    ", split( "\n", $main::binNMU )), "\n\n";
1135
 
                        print F " -- $conf::maintainer_name  $date\n\n";
1136
 
 
1137
 
                        print F $firstline, $text;
1138
 
                        close( F );
1139
 
                        system "touch debian/.sbuild-binNMU-done";
1140
 
                        print PLOG "*** Created changelog entry for bin-NMU version $NMUversion\n";
1141
 
                }
1142
 
                else {
1143
 
                        print PLOG "Can't open debian/changelog -- no binNMU hack!\n";
1144
 
                }
1145
 
        }
1146
 
        
1147
 
        if ($do_apply_patches) {
1148
 
                if (!apply_patches( $pkg )) {
1149
 
                        chdir( $main::cwd );
1150
 
                        return 0;
1151
 
                }
1152
 
        }
1153
 
        
1154
 
        if (-f "debian/files") {
1155
 
                local( *FILES );
1156
 
                my @lines;
1157
 
                open( FILES, "<debian/files" );
1158
 
                chomp( @lines = <FILES> );
1159
 
                close( FILES );
1160
 
                @lines = map { my $ind = 68-length($_);
1161
 
                                           $ind = 0 if $ind < 0;
1162
 
                                           "| $_".(" " x $ind)." |\n"; } @lines;
1163
 
                
1164
 
                print PLOG <<"EOF";
1165
 
 
1166
 
+----------------------------------------------------------------------+
1167
 
| sbuild Warning:                                                      |
1168
 
| ---------------                                                      |
1169
 
| After unpacking, there exists a file debian/files with the contents: |
1170
 
|                                                                      |
1171
 
EOF
1172
 
                print PLOG @lines;
1173
 
                print PLOG <<"EOF";
1174
 
|                                                                      |
1175
 
| This should be reported as a bug.                                    |
1176
 
| The file has been removed to avoid dpkg-genchanges errors.           |
1177
 
+----------------------------------------------------------------------+
1178
 
 
1179
 
EOF
1180
 
                unlink "debian/files";
1181
 
        }
1182
 
 
1183
 
        open CURRENT, ">$main::cwd/$main::chroot_dir/CurrentlyBuilding" or die "$main::cwd/$main::chroot_dir/CurrentlyBuilding open failed";
1184
 
        # Package: must be first
1185
 
        print CURRENT "Package: $pkg\nComponent: $main::component\n";
1186
 
        print CURRENT "Suite: $main::distribution\n" if $main::distribution;
1187
 
        print CURRENT "Purpose: $main::purpose\n" if $main::purpose;
1188
 
        print CURRENT "Build-Debug-Symbols: yes\n" if $main::build_debug_symbols;
1189
 
        close CURRENT;
1190
 
 
1191
 
        $main::build_start_time = time;
1192
 
        $main::pkg_fail_stage = "build";
1193
 
        $main::sub_pid = open( PIPE, "-|" );
1194
 
        if (!defined $main::sub_pid) {
1195
 
                print PLOG "Can't spawn dpkg-buildpackage: $!\n";
1196
 
                chdir( $main::cwd );
1197
 
                return 0;
1198
 
        }
1199
 
        if ($main::sub_pid == 0) {
1200
 
                setpgrp( 0, $$ );
1201
 
                my $binopt = $main::build_source ? "" :
1202
 
                                         $main::build_arch_all ? "-b" : "-B";
1203
 
                my $env_cmnd = $conf::build_env_cmnd;
1204
 
                $env_cmnd = $conf::build_env_cmnd{$pkg} if $conf::build_env_cmnd{$pkg};
1205
 
                if ($main::chroot_dir) {
1206
 
                        my $bdir = $dir;
1207
 
                        $bdir =~ s/^\Q$main::chroot_dir\E//;
1208
 
                        if (-f "$main::chroot_dir/etc/ld.so.conf" &&
1209
 
                            ! -r "$main::chroot_dir/etc/ld.so.conf") {
1210
 
                                system "$conf::sudo chmod a+r $main::chroot_dir/etc/ld.so.conf";
1211
 
                                print PLOG "ld.so.conf was not readable! Fixed.\n";
1212
 
                        }
1213
 
                        exec "$conf::sudo", "/usr/sbin/chroot", "$main::cwd/$main::chroot_dir",
1214
 
                                "$conf::su", $main::username, "-s", "/bin/sh", "-c",
1215
 
                                "cd $bdir && PATH=$conf::path ".
1216
 
                                (defined($main::nr_processors) ?
1217
 
                                "DEB_BUILD_OPTIONS=\"parallel=".$main::nr_processors."\" " : "").
1218
 
                                (defined($main::ld_library_path) ?
1219
 
                                "LD_LIBRARY_PATH=".$main::ld_library_path." " : "").
1220
 
                                "exec $env_cmnd dpkg-buildpackage $conf::pgp_options ".
1221
 
                                "$binopt -m'$conf::maintainer_name' -r$conf::fakeroot 2>&1";
1222
 
                }
1223
 
                else {
1224
 
                        if (-f "/etc/ld.so.conf" && ! -r "/etc/ld.so.conf") {
1225
 
                                system "$conf::sudo chmod a+r /etc/ld.so.conf";
1226
 
                                print PLOG "ld.so.conf was not readable! Fixed.\n";
1227
 
                        }
1228
 
                        exec "$env_cmnd dpkg-buildpackage $conf::pgp_options $binopt ".
1229
 
                                "-m'$conf::maintainer_name' -r$conf::fakeroot 2>&1";
1230
 
                }
1231
 
        }
1232
 
        $main::sub_task = "dpkg-buildpackage";
1233
 
 
1234
 
        # We must send the signal as root, because some subprocesses of
1235
 
        # dpkg-buildpackage could run as root. So we have to use a shell
1236
 
        # command to send the signal... but /bin/kill can't send to
1237
 
        # process groups :-( So start another Perl :-)
1238
 
        my $timeout = $conf::individual_stalled_pkg_timeout{$pkg} ||
1239
 
                                  $conf::stalled_pkg_timeout;
1240
 
        $timeout *= 60;
1241
 
        my $timed_out = 0;
1242
 
        my(@timeout_times, @timeout_sigs, $last_time);
1243
 
        $SIG{'ALRM'} = sub {
1244
 
                my $signal = ($timed_out > 0) ? 9 : 15;
1245
 
                system "$conf::sudo perl -e 'kill( -$signal, $main::sub_pid )'";
1246
 
                $timeout_times[$timed_out] = time - $last_time;
1247
 
                $timeout_sigs[$timed_out] = $signal;
1248
 
                $timed_out++;
1249
 
                $timeout = 5*60; # only wait 5 minutes until next signal
1250
 
        };
1251
 
 
1252
 
        alarm( $timeout );
1253
 
        while( <PIPE> ) {
1254
 
                alarm( $timeout );
1255
 
                $last_time = time;
1256
 
                print PLOG $_;
1257
 
        }
1258
 
        close( PIPE );
1259
 
        undef $main::sub_pid;
1260
 
        alarm( 0 );
1261
 
        $rv = $?;
1262
 
 
1263
 
        my $i;
1264
 
        for( $i = 0; $i < $timed_out; ++$i ) {
1265
 
                print PLOG "Build killed with signal ", $timeout_sigs[$i],
1266
 
                                   " after ", int($timeout_times[$i]/60),
1267
 
                                   " minutes of inactivity\n";
1268
 
        }
1269
 
        $main::pkg_end_time = time;
1270
 
        my $date = `date +%Y%m%d-%H%M`;
1271
 
        print PLOG "*"x78, "\n";
1272
 
        print PLOG "Build finished at $date";
1273
 
        chdir( $main::cwd );
1274
 
 
1275
 
        my @space_files = ("$dir");
1276
 
        if (!$main::nolog and defined $conf::exit_hook and open TMP, '-|', "$conf::exit_hook <$main::pkg_logfile") {
1277
 
                local $/ = undef;
1278
 
                my $log = <TMP>;
1279
 
                close TMP;
1280
 
                $rv |= $?;
1281
 
                print PLOG $log;
1282
 
        }
1283
 
        if ($rv) {
1284
 
                print PLOG "FAILED [dpkg-buildpackage died]\n";
1285
 
        }
1286
 
        else {
1287
 
                my $trans_oldfmt="$main::chroot_build_dir${pkg}_${version}_translations.tar.gz";
1288
 
                my $trans_newfmt="$main::chroot_build_dir${pkg}_${version}_${main::arch}_translations.tar.gz";
1289
 
                my $translations="";
1290
 
                if (-r $trans_newfmt) {
1291
 
                        $translations = $trans_newfmt;
1292
 
                } elsif (-r $trans_oldfmt) {
1293
 
                        $translations = $trans_oldfmt;
1294
 
                }
1295
 
                if ($translations) {
1296
 
                        print PLOG "Publishing $translations for rosetta.\n";
1297
 
                        my $date = strftime '%Y%m%d',gmtime;
1298
 
                        my $target = "$main::HOME/public_html/translations/$date/";
1299
 
                        system "mkdir -p $target";
1300
 
                        if (system("cp",$translations,$target) != 0) {
1301
 
                                print PLOG "ERROR: Could not move $translations to $target\n";
1302
 
                        } else {
1303
 
                                open TRANS, ">>$target/translations.txt";
1304
 
                                print TRANS     "File: " . basename(${translations}) . "\n".
1305
 
                                                "Distribution: ${main::archive}\n".
1306
 
                                                "Release: ${main::distribution}\n".
1307
 
                                                "Component: ${main::component}\n".
1308
 
                                                "Source: ${pkg}\n".
1309
 
                                                "Version: ${version}\n\n";
1310
 
                                close TRANS;
1311
 
                                system("chmod -R go+rX $main::HOME/public_html/translations");
1312
 
                            }
1313
 
                    }
1314
 
 
1315
 
                my $ddebtar = "";
1316
 
                my $ddebstring = "";
1317
 
                if (-r glob("$main::chroot_build_dir/*.ddeb")) {
1318
 
                    my @ddeblist = glob("$main::chroot_build_dir/*.ddeb");
1319
 
                    $ddebtar="${pkg}_${version}_${main::arch}_ddebs.tar";
1320
 
                    while (@ddeblist) {
1321
 
                        $ddebstring .= basename(@ddeblist[0]) . " ";
1322
 
                        shift @ddeblist;
1323
 
                    }
1324
 
                }
1325
 
                if ($ddebstring) {
1326
 
                    print PLOG "Publishing debug debs.\n";
1327
 
                    my $date = strftime '%Y%m%d',gmtime;
1328
 
                    my $target = "$main::HOME/public_html/ddebs/$date/";
1329
 
                    system "mkdir -p $target";
1330
 
                    if (system("tar -C $main::chroot_build_dir -chf $target/$ddebtar $ddebstring") != 0) {
1331
 
                        print PLOG "ERROR: Could not create $ddebtar in $target\n";
1332
 
                    } else {
1333
 
                        open TRANS, ">>$target/ddebs.txt";
1334
 
                        print TRANS "File: " . basename(${ddebtar}) . "\n".
1335
 
                        "Distribution: ${main::archive}\n".
1336
 
                        "Release: ${main::distribution}\n".
1337
 
                        "Component: ${main::component}\n".
1338
 
                        "Source: ${pkg}\n".
1339
 
                        "Version: ${version}\n\n";
1340
 
                    close TRANS;
1341
 
                        system("chmod -R go+rX $main::HOME/public_html/ddebs");
1342
 
                    }
1343
 
                }
1344
 
 
1345
 
                if (-r "$dir/debian/files") {
1346
 
                        my @debs;
1347
 
                        my @files;
1348
 
                        open( F, "<$dir/debian/files" );
1349
 
                        while( <F> ) {
1350
 
                                my $f = (split( /\s+/, $_ ))[0];
1351
 
                                push( @files, "$main::chroot_build_dir$f" );
1352
 
                                if ($main::build_arch_all) {
1353
 
                                        next if ($f !~ /$main::arch\.[\w\d.-]*$/ && $f !~ /all\.[\w\d.-]*$/);
1354
 
                                } else {
1355
 
                                        next if ($f !~ /$main::arch\.[\w\d.-]*$/);
1356
 
                                }
1357
 
                                push( @debs, "$main::chroot_build_dir$f" );
1358
 
                                push( @space_files, $f );
1359
 
                        }
1360
 
                        close( F );
1361
 
                        my @debs2 = @debs;
1362
 
                        foreach (@debs) {
1363
 
                                print PLOG "\n$_:\n";
1364
 
                                if (!open( PIPE, "dpkg --info $_ 2>&1 |" )) {
1365
 
                                        print PLOG "Can't spawn dpkg: $! -- can't dump infos\n";
1366
 
                                }
1367
 
                                else {
1368
 
                                        print PLOG $_ while( <PIPE> );
1369
 
                                        close( PIPE );
1370
 
                                }
1371
 
                        }
1372
 
                        foreach (@debs2) {
1373
 
                                print PLOG "\n$_:\n";
1374
 
                                if (!open( PIPE, "dpkg --contents $_ 2>&1 |" )) {
1375
 
                                        print PLOG "Can't spawn dpkg: $! -- can't dump infos\n";
1376
 
                                }
1377
 
                                else {
1378
 
                                        print PLOG $_ while( <PIPE> );
1379
 
                                        close( PIPE );
1380
 
                                }
1381
 
                        }
1382
 
                        if ($main::chroot_build_dir) {
1383
 
                                foreach (@files) {
1384
 
                                        system "mv", $_, "."
1385
 
                                                and print PLOG "ERROR: Could not move $_ to .\n";
1386
 
                                }
1387
 
                        }
1388
 
                }
1389
 
 
1390
 
                if (-r $translations) {
1391
 
                    system("rm",$translations);
1392
 
                }
1393
 
 
1394
 
                $changes = "${pkg}_".
1395
 
                        ($main::binNMU ? binNMU_version($sversion) : $sversion).
1396
 
                        "_$main::arch.changes";
1397
 
                if (-r "$main::chroot_build_dir$changes") {
1398
 
                        my(@do_dists, @saved_dists);
1399
 
                        print PLOG "\n$changes:\n";
1400
 
                        open( F, "<$main::chroot_build_dir$changes" );
1401
 
                        if (open( F2, ">$changes.new" )) {
1402
 
                                while( <F> ) {
1403
 
                                        if (/^Distribution:\s*(.*)\s*$/) {
1404
 
                                                print PLOG "Distribution: $main::distribution\n";
1405
 
                                                print F2 "Distribution: $main::distribution\n";
1406
 
                                        }
1407
 
                                        else {
1408
 
                                                print F2 $_;
1409
 
                                                while (length $_ > 989)
1410
 
                                                {
1411
 
                                                        my $index = rindex($_,' ',989);
1412
 
                                                        print PLOG substr ($_,0,$index) . "\n";
1413
 
                                                        $_ = '        ' . substr ($_,$index+1);
1414
 
                                                }
1415
 
                                                print PLOG $_;
1416
 
                                        }
1417
 
                                }
1418
 
                                close( F2 );
1419
 
                                rename( "$changes.new", "$changes" )
1420
 
                                        or print PLOG "$changes.new could not be renamed ".
1421
 
                                                                  "to $changes: $!\n";
1422
 
                                unlink( "$main::chroot_build_dir$changes" )
1423
 
                                        if $main::chroot_build_dir;
1424
 
                        }
1425
 
                        else {
1426
 
                                print PLOG "Cannot create $changes.new: $!\n";
1427
 
                                print PLOG "Distribution field may be wrong!!!\n";
1428
 
                                if ($main::chroot_build_dir) {
1429
 
                                        system "mv", "$main::chroot_build_dir$changes", "."
1430
 
                                                and print PLOG "ERROR: Could not move $_ to .\n";
1431
 
                                }
1432
 
                        }
1433
 
                        close( F );
1434
 
                        print PLOG "\n";
1435
 
                }
1436
 
                else {
1437
 
                        print PLOG "Can't find $changes -- can't dump infos\n";
1438
 
                }
1439
 
 
1440
 
                print PLOG "*"x78, "\n";
1441
 
                print PLOG "Built successfully\n";
1442
 
        }
1443
 
 
1444
 
        check_watches();
1445
 
        check_space( @space_files );
1446
 
 
1447
 
        if ($conf::purge_build_directory eq "always" ||
1448
 
                ($conf::purge_build_directory eq "successful" && $rv == 0)) {
1449
 
                print PLOG "Purging $dir\n";
1450
 
                system "$conf::sudo rm -rf $dir";
1451
 
        }
1452
 
        
1453
 
        print PLOG "-"x78, "\n";
1454
 
        return $rv == 0 ? 1 : 0;
1455
 
}
1456
 
 
1457
 
sub apply_patches {
1458
 
        my $pkg = shift;
1459
 
        my $name;
1460
 
        
1461
 
        $main::pkg_fail_stage = "apply-patch";
1462
 
        foreach $name ((map { $_->{'Package'} } @{$main::deps{$pkg}}),
1463
 
                                   @main::global_patches) {
1464
 
                if ($name =~ /^\*/ && exists $main::specials{$name}->{'patch'}) {
1465
 
                        if (exists $main::specials{$name}->{'patchcond'}) {
1466
 
                                print "Testing condition for $name patch:\n"
1467
 
                                        if $main::debug;
1468
 
                                if (run_script("+e",$main::specials{$name}->{'patchcond'})!=0){
1469
 
                                        print PLOG "Condition for $name patch not true -- ",
1470
 
                                                                "not applying\n" if $name !~ /^\*\*/;
1471
 
                                        next;
1472
 
                                }
1473
 
                                print PLOG "Condition for $name patch ok\n";
1474
 
                        }
1475
 
                        print PLOG "Applying $name patch\n";
1476
 
                        $main::sub_pid = open( PIPE, "|-" );
1477
 
                        if (!defined $main::sub_pid) {
1478
 
                                print PLOG "Can't spawn patch: $! -- can't patch\n";
1479
 
                                return 0;
1480
 
                        }
1481
 
                        if ($main::sub_pid == 0) {
1482
 
                                setpgrp( 0, $$ );
1483
 
                                open( STDOUT, ">&PLOG" );
1484
 
                                open( STDERR, ">&PLOG" );
1485
 
                                exec "patch --batch --quiet -p1 -E -N --no-backup-if-mismatch";
1486
 
                        }
1487
 
                        $main::sub_task = "patch";
1488
 
 
1489
 
                        print PIPE $main::specials{$name}->{'patch'};
1490
 
                        close( PIPE );
1491
 
                        undef $main::sub_pid;
1492
 
                        if ($name !~ /^\*\*/ && $?) {
1493
 
                                print PLOG "FAILED [patch died]\n";
1494
 
                                return 0;
1495
 
                        }
1496
 
                }
1497
 
        }
1498
 
        return 1;
1499
 
}
1500
 
 
1501
 
sub analyze_fail_stage {
1502
 
        my $pkgv = shift;
1503
 
        
1504
 
        return if $main::pkg_status ne "failed";
1505
 
        return if !$main::auto_giveback;
1506
 
        if (isin( $main::pkg_fail_stage,
1507
 
                          qw(find-dsc fetch-src unpack-check check-space install-deps-env))) {
1508
 
                $main::pkg_status = "given-back";
1509
 
                print PLOG "Giving back package $pkgv after failure in ".
1510
 
                               "$main::pkg_fail_stage stage.\n";
1511
 
                chdir( $main::cwd );
1512
 
                my $cmd = "";
1513
 
                $cmd = "ssh -l$main::auto_giveback_user $main::auto_giveback_host "
1514
 
                        if $main::auto_giveback_host;
1515
 
                $cmd .= "-S $main::auto_giveback_socket "
1516
 
                        if ($main::auto_giveback_socket and -S "$main::auto_giveback_socket");
1517
 
                $cmd .= "wanna-build --give-back --no-down-propagation ".
1518
 
                            "--dist=$main::distribution";
1519
 
                $cmd .= " --database=$main::database" if $main::database;
1520
 
                $cmd .= " --user=$main::auto_giveback_wb_user "
1521
 
                        if $main::auto_giveback_wb_user;
1522
 
                $cmd .= " $pkgv";
1523
 
                system $cmd;
1524
 
                if ($?) {
1525
 
                        print PLOG "wanna-build failed with status $?\n";
1526
 
                }
1527
 
                else {
1528
 
                        add_givenback( $pkgv, time );
1529
 
                        if ($main::stats_dir) {
1530
 
                                local( *F );
1531
 
                                lock_file( "$main::stats_dir" );
1532
 
                                open( F, ">>$main::stats_dir/give-back" );
1533
 
                                print F "1\n";
1534
 
                                close( F );
1535
 
                                unlock_file( "$main::stats_dir" );
1536
 
                        }
1537
 
                }
1538
 
        }
1539
 
}
1540
 
 
1541
 
sub remove_files {
1542
 
 
1543
 
        foreach (@_) {
1544
 
                unlink $_;
1545
 
                print "Removed $_\n" if $main::debug;
1546
 
        }
1547
 
}
1548
 
 
1549
 
 
1550
 
sub install_deps {
1551
 
        my $pkg = shift;
1552
 
        my( @positive, @negative, @special, @instd, @rmvd );
1553
 
 
1554
 
        if (!exists $main::deps{$pkg}) {
1555
 
                prepare_watches( [] );
1556
 
                return 1;
1557
 
        }
1558
 
        
1559
 
        my $dep = $main::deps{$pkg};
1560
 
        if ($main::debug) {
1561
 
                print "Source dependencies of $pkg: ", format_deps(@$dep), "\n";
1562
 
        }
1563
 
 
1564
 
  repeat:
1565
 
        lock_file( "$main::ilock_file", 1 );
1566
 
        
1567
 
        print "Filtering dependencies\n" if $main::debug;
1568
 
        if (!filter_dependencies( $dep, \@positive, \@negative, \@special )) {
1569
 
                print PLOG "Package installation not possible\n";
1570
 
                unlock_file( "$main::ilock_file" );
1571
 
                return 0;
1572
 
        }
1573
 
 
1574
 
        print PLOG "Checking for source dependency conflicts...\n";
1575
 
        if (!run_apt( "-s", \@instd, \@rmvd, @positive )) {
1576
 
                print PLOG "Test what should be installed failed.\n";
1577
 
                unlock_file( "$main::ilock_file" );
1578
 
                return 0;
1579
 
        }
1580
 
        # add negative deps as to be removed for checking srcdep conflicts
1581
 
        push( @rmvd, @negative );
1582
 
        my @confl;
1583
 
        if (@confl = check_srcdep_conflicts( \@instd, \@rmvd, \@special )) {
1584
 
                print PLOG "Waiting for job(s) @confl to finish\n";
1585
 
 
1586
 
                unlock_file( "$main::ilock_file" );
1587
 
                wait_for_srcdep_conflicts( @confl );
1588
 
                goto repeat;
1589
 
        }
1590
 
        
1591
 
        write_srcdep_lock_file( $dep, \@special );
1592
 
        
1593
 
        foreach my $sp (@special) {
1594
 
                next if $sp !~ /^\*/ || !exists $main::specials{$sp}->{'prepre'};
1595
 
                print PLOG "Running prepre script for $sp\n";
1596
 
                if (run_script( "-e", $main::specials{$sp}->{'prepre'} ) != 0) {
1597
 
                        print PLOG "prepre script of special dependency $sp failed\n";
1598
 
                        unlock_file( "$main::ilock_file" );
1599
 
                        return 0;
1600
 
                }
1601
 
        }
1602
 
 
1603
 
        print "Installing positive dependencies: @positive\n" if $main::debug;
1604
 
        if (!run_apt( "-y", \@instd, \@rmvd, @positive )) {
1605
 
                print PLOG "Package installation failed\n";
1606
 
                # try to reinstall removed packages
1607
 
                print PLOG "Trying to reinstall removed packages:\n";
1608
 
                print "Reinstalling removed packages: @rmvd\n" if $main::debug;
1609
 
                my (@instd2, @rmvd2);
1610
 
                print PLOG "Failed to reinstall removed packages!\n"
1611
 
                        if !run_apt( "-y", \@instd2, \@rmvd2, @rmvd );
1612
 
                print "Installed were: @instd2\n" if $main::debug;
1613
 
                print "Removed were: @rmvd2\n" if $main::debug;
1614
 
                # remove additional packages
1615
 
                print PLOG "Trying to uninstall newly installed packages:\n";
1616
 
                uninstall_debs( $main::chroot_dir ? "purge" : "remove", @instd );
1617
 
                unlock_file( "$main::ilock_file" );
1618
 
                return 0;
1619
 
        }
1620
 
        set_installed( @instd );
1621
 
        set_removed( @rmvd );
1622
 
        
1623
 
        print "Removing negative dependencies: @negative\n" if $main::debug;
1624
 
        if (!uninstall_debs( $main::chroot_dir ? "purge" : "remove", @negative )) {
1625
 
                print PLOG "Removal of packages failed\n";
1626
 
                unlock_file( "$main::ilock_file" );
1627
 
                return 0;
1628
 
        }
1629
 
        set_removed( @negative );
1630
 
        
1631
 
        my $fail = check_dependencies( $dep );
1632
 
        if ($fail) {
1633
 
                print PLOG "After installing, the following source dependencies are ".
1634
 
                         "still unsatisfied:\n$fail\n";
1635
 
                unlock_file( "$main::ilock_file" );
1636
 
                return 0;
1637
 
        }
1638
 
 
1639
 
        foreach my $sp (@special) {
1640
 
                next if $sp !~ /^\*/ ||
1641
 
                            (!exists $main::specials{$sp}->{'pre'} &&
1642
 
                             !exists $main::specials{$sp}->{'post'} &&
1643
 
                             !exists $main::specials{$sp}->{'unpack'});
1644
 
                if (exists $main::specials{$sp}->{'unpack'}) {
1645
 
                        my $s = $main::specials{$sp}->{'unpack'};
1646
 
                        $s =~ s/^\s+//mg;
1647
 
                        $s =~ s/\s+$//mg;
1648
 
                        my @s = split( /\s+/, $s );
1649
 
                        my @rem;
1650
 
                        print PLOG "Unpacking special sources $sp: @s\n";
1651
 
                        if (!(@rem = unpack_special_source( @s ))) {
1652
 
                                print PLOG "unpacking of special dependency sources for $sp failed\n";
1653
 
                                unlock_file( "$main::ilock_file" );
1654
 
                                return 0;
1655
 
                        }
1656
 
                        $main::changes->{'unpacked'}->{$sp} = \@rem;
1657
 
                }
1658
 
                if (exists $main::specials{$sp}->{'pre'}) {
1659
 
                        print PLOG "Running pre script for $sp\n";
1660
 
                        $main::changes->{'specials'}->{$sp} = 1;
1661
 
                        if (run_script( "-e", $main::specials{$sp}->{'pre'} ) != 0) {
1662
 
                                print PLOG "pre script of special dependency $sp failed\n";
1663
 
                                unlock_file( "$main::ilock_file" );
1664
 
                                return 0;
1665
 
                        }
1666
 
                }
1667
 
        }
1668
 
        
1669
 
        local (*F);
1670
 
        if (open( F, "| $conf::sudo /usr/sbin/chroot $main::chroot_dir $conf::dpkg --set-selections")) {
1671
 
                foreach my $tpkg (@instd) {
1672
 
                        print F $tpkg . " purge\n";
1673
 
                }
1674
 
                close( F );
1675
 
                if ($?) {
1676
 
                        print PLOG "$conf::dpkg --set-selections failed";
1677
 
                }
1678
 
        }
1679
 
 
1680
 
        unlock_file( "$main::ilock_file" );
1681
 
 
1682
 
        prepare_watches( $dep, @instd );
1683
 
        return 1;
1684
 
}
1685
 
 
1686
 
sub unpack_special_source {
1687
 
        my @s = @_;
1688
 
        my (@files, @dirs);
1689
 
        local (*PIPE);
1690
 
 
1691
 
        foreach my $s (@s) {
1692
 
                my $dsc;
1693
 
 
1694
 
                {
1695
 
                        if (!open( PIPE, "$conf::apt_get $main::chroot_apt_options ".
1696
 
                       "--only-source -q -d source $s 2>&1 </dev/null |" )) {
1697
 
                                print PLOG "Can't open pipe to apt-get: $!\n";
1698
 
                                goto failed;
1699
 
                        }
1700
 
                        while( <PIPE> ) {
1701
 
                                $dsc = "$1_$2.dsc" if /(\S+) (?:[^:]+:)?(\S+) \(dsc\)/;
1702
 
                                print PLOG $_;
1703
 
                        }
1704
 
                        close( PIPE );
1705
 
                        if ($?) {
1706
 
                                print PLOG "Apt-get of special unpack sources failed\n";
1707
 
                                goto failed;
1708
 
                        }
1709
 
                        push( @files, $dsc );
1710
 
                        if (!open( F, "<$dsc" )) {
1711
 
                                print PLOG "Can't open $dsc: $!\n";
1712
 
                                goto failed;
1713
 
                        }
1714
 
                        my $dsctext;
1715
 
                        { local($/); $dsctext = <F>; }
1716
 
                        close( F );
1717
 
                        my $files;
1718
 
                        $dsctext =~ /^Files:\s*\n((\s+.*\s*\n)+)/mi and $files = $1;
1719
 
                        push(@files, map { (split( /\s+/, $_ ))[3] } split( "\n", $files ));
1720
 
                }
1721
 
 
1722
 
                my $pid = open( PIPE, "-|" );
1723
 
                if (!defined $pid) {
1724
 
                        print PLOG "Can't spawn dpkg-source: $! -- special unpack failed\n";
1725
 
                        goto failed;
1726
 
                }
1727
 
                if ($pid == 0) {
1728
 
                        setpgrp( 0, $$ );
1729
 
                        if ($main::chroot_build_dir && !chdir( $main::chroot_build_dir )) {
1730
 
                                print PLOG "Couldn't cd to $main::chroot_build_dir: $! -- special unpack failed\n";
1731
 
                                exit 1;
1732
 
                        }
1733
 
                        exec "$conf::dpkg_source -sn -x $main::cwd/$dsc 2>&1";
1734
 
                }
1735
 
                my $dir;
1736
 
                while( <PIPE> ) {
1737
 
                        print PLOG $_;
1738
 
                        $dir = $1 if /^dpkg-source: (?:info: )?extracting \S+ in (\S+)/;
1739
 
                }
1740
 
                close( PIPE );
1741
 
                if ($?) {
1742
 
                        print PLOG "dpkg-source failure -- special unpack failed\n";
1743
 
                        goto failed;
1744
 
                }
1745
 
                push( @dirs, "$main::chroot_build_dir$dir" );
1746
 
                unlink( @files );
1747
 
        }
1748
 
 
1749
 
        return @dirs;
1750
 
        
1751
 
  failed:
1752
 
        unlink( @files );
1753
 
        system( "rm", "-rf", @dirs );
1754
 
        return ();
1755
 
}
1756
 
        
1757
 
sub wait_for_srcdep_conflicts {
1758
 
        my @confl = @_;
1759
 
        
1760
 
        for(;;) {
1761
 
                sleep( $conf::srcdep_lock_wait*60 );
1762
 
                my $allgone = 1;
1763
 
                for (@confl) {
1764
 
                        /^(\d+)-(\d+)$/;
1765
 
                        my $pid = $1;
1766
 
                        if (-f "$conf::srcdep_lock_dir/$_") {
1767
 
                                if (kill( 0, $pid ) == 0 && $! == ESRCH) {
1768
 
                                        print PLOG "Ignoring stale src-dep lock $_\n";
1769
 
                                        unlink( "$conf::srcdep_lock_dir/$_" ) or
1770
 
                                                print PLOG "Cannot remove $conf::srcdep_lock_dir/$_: $!\n";
1771
 
                                }
1772
 
                                else {
1773
 
                                        $allgone = 0;
1774
 
                                        last;
1775
 
                                }
1776
 
                        }
1777
 
                }
1778
 
                last if $allgone;
1779
 
        }
1780
 
}
1781
 
 
1782
 
sub uninstall_deps {
1783
 
        my( @pkgs, @instd, @rmvd );
1784
 
 
1785
 
        lock_file( "$main::ilock_file", 1 );
1786
 
 
1787
 
        @pkgs = keys %{$main::changes->{'removed'}};
1788
 
        print "Reinstalling removed packages: @pkgs\n" if $main::debug;
1789
 
        print PLOG "Failed to reinstall removed packages!\n"
1790
 
                if !run_apt( "-y", \@instd, \@rmvd, @pkgs );
1791
 
        print "Installed were: @instd\n" if $main::debug;
1792
 
        print "Removed were: @rmvd\n" if $main::debug;
1793
 
        unset_removed( @instd );
1794
 
        unset_installed( @rmvd );
1795
 
 
1796
 
        @pkgs = keys %{$main::changes->{'installed'}};
1797
 
        print "Removing installed packages: @pkgs\n" if $main::debug;
1798
 
        print PLOG "Failed to remove installed packages!\n"
1799
 
                if !uninstall_debs( "purge", @pkgs );
1800
 
        unset_installed( @pkgs );
1801
 
 
1802
 
        unlock_file( "$main::ilock_file" );
1803
 
}
1804
 
 
1805
 
sub uninstall_debs {
1806
 
        my $mode = shift;
1807
 
        local (*PIPE);
1808
 
        
1809
 
        return 1 if !@_;
1810
 
        print "Uninstalling packages: @_\n" if $main::debug;
1811
 
        print PLOG "  $conf::sudo dpkg --$mode @_\n";
1812
 
  repeat:
1813
 
        my $output;
1814
 
        if (!open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir $conf::dpkg --$mode @_ 2>&1 </dev/null |")) {
1815
 
                print PLOG "Can't open pipe to dpkg: $!\n";
1816
 
                return 0;
1817
 
        }
1818
 
        while ( <PIPE> ) {
1819
 
                $output .= $_;
1820
 
                print PLOG $_;
1821
 
        }
1822
 
        close( PIPE );
1823
 
 
1824
 
        if ($output =~ /status database area is locked/mi) {
1825
 
                print PLOG "Another dpkg is running -- retrying later\n";
1826
 
                $output = "";
1827
 
                sleep( 2*60 );
1828
 
                goto repeat;
1829
 
        }
1830
 
        print PLOG "dpkg run to remove packages (@_) failed!\n" if $?;
1831
 
        return $? == 0;
1832
 
}
1833
 
 
1834
 
sub undo_specials {
1835
 
        my $sp;
1836
 
 
1837
 
        print "Running post scripts of special dependencies:\n" if $main::debug;
1838
 
        foreach $sp (keys %{$main::changes->{'specials'}}) {
1839
 
                print PLOG "Running post script for $sp\n";
1840
 
                if (run_script( "-e", $main::specials{$sp}->{'post'} ) != 0) {
1841
 
                        print PLOG "post script of special dependency $sp failed\n";
1842
 
                }
1843
 
                delete $main::changes->{'specials'}->{$sp};
1844
 
        }
1845
 
        foreach $sp (keys %{$main::changes->{'unpacked'}}) {
1846
 
                my @dirs = @{$main::changes->{'unpacked'}->{$sp}};
1847
 
                print PLOG "Removing special unpacked sources for $sp: @dirs\n";
1848
 
                system "rm", "-rf", @dirs;
1849
 
                delete $main::changes->{'unpacked'}->{$sp};
1850
 
        }
1851
 
}
1852
 
 
1853
 
 
1854
 
sub run_apt {
1855
 
        my $mode = shift;
1856
 
        my $inst_ret = shift;
1857
 
        my $rem_ret = shift;
1858
 
        my @to_install = @_;
1859
 
        my( $msgs, $status, $pkgs, $rpkgs );
1860
 
        local (*PIPE);
1861
 
        local (%ENV) = %ENV; # make local environment
1862
 
        # hardwire frontend for debconf to non-interactive
1863
 
        $ENV{'DEBIAN_FRONTEND'} = "noninteractive";
1864
 
 
1865
 
        @$inst_ret = ();
1866
 
        @$rem_ret = ();
1867
 
        return 1 if !@to_install;
1868
 
  repeat:
1869
 
        print PLOG "  $conf::sudo $conf::apt_get --purge $main::chroot_apt_op -q $mode install @to_install\n"
1870
 
                if $mode ne "-s";
1871
 
        $msgs = "";
1872
 
        # redirection of stdin from /dev/null so that conffile question are
1873
 
        # treated as if RETURN was pressed.
1874
 
        # dpkg since 1.4.1.18 issues an error on the conffile question if it reads
1875
 
        # EOF -- hardwire the new --force-confold option to avoid the questions.
1876
 
        if (!open( PIPE, "$conf::sudo /usr/sbin/chroot ".
1877
 
                           "$main::chroot_dir $conf::apt_get --purge ".
1878
 
                           ($main::new_dpkg ? "-o DPkg::Options::=--force-confold " : "").
1879
 
                           "-q $mode install @to_install 2>&1 </dev/null |" )) {
1880
 
                print PLOG "Can't open pipe to apt-get: $!\n";
1881
 
                return 0;
1882
 
        }
1883
 
        while( <PIPE> ) {
1884
 
                $msgs .= $_;
1885
 
                print PLOG $_ if $mode ne "-s" || $main::debug;
1886
 
        }
1887
 
        close( PIPE );
1888
 
        $status = $?;
1889
 
 
1890
 
        if ($status != 0 && $msgs =~ /^E: Packages file \S+ (has changed|is out of sync)/mi) {
1891
 
                print PLOG "$conf::sudo $conf::apt_get $main::chroot_apt_op -q update\n";
1892
 
                if (!open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir $conf::apt_get -q update 2>&1 |" )) {
1893
 
                        print PLOG "Can't open pipe to apt-get: $!\n";
1894
 
                        return 0;
1895
 
                }
1896
 
                $msgs = "";
1897
 
                while( <PIPE> ) {
1898
 
                        $msgs .= $_;
1899
 
                        print PLOG $_;
1900
 
                }
1901
 
                close( PIPE );
1902
 
                print PLOG "apt-get update failed\n" if $?;
1903
 
                $msgs = "";
1904
 
                goto repeat;
1905
 
        }
1906
 
 
1907
 
        if ($status != 0 && $msgs =~ /^Package (\S+) is a virtual package provided by:\n((^\s.*\n)*)/mi) {
1908
 
                my $to_replace = $1;
1909
 
                my @providers;
1910
 
                foreach (split( "\n", $2 )) {
1911
 
                        s/^\s*//;
1912
 
                        push( @providers, (split( /\s+/, $_ ))[0] );
1913
 
                }
1914
 
                print PLOG "$to_replace is a virtual package provided by: @providers\n";
1915
 
                my $selected;
1916
 
                if (@providers == 1) {
1917
 
                        $selected = $providers[0];
1918
 
                        print PLOG "Using $selected (only possibility)\n";
1919
 
                }
1920
 
                elsif (exists $conf::alternatives{$to_replace}) {
1921
 
                        $selected = $conf::alternatives{$to_replace};
1922
 
                        print PLOG "Using $selected (selected in sbuildrc)\n";
1923
 
                }
1924
 
                else {
1925
 
                        $selected = $providers[0];
1926
 
                        print PLOG "Using $selected (no default, using first one)\n";
1927
 
                }
1928
 
                
1929
 
                @to_install = grep { $_ ne $to_replace } @to_install;
1930
 
                push( @to_install, $selected );
1931
 
                
1932
 
                goto repeat;
1933
 
        }
1934
 
        
1935
 
        if ($status != 0 && ($msgs =~ /^E: Could( not get lock|n.t lock)/mi ||
1936
 
                                                 $msgs =~ /^dpkg: status database area is locked/mi)) {
1937
 
                print PLOG "Another apt-get or dpkg is running -- retrying later\n";
1938
 
                sleep( 2*60 );
1939
 
                goto repeat;
1940
 
        }
1941
 
 
1942
 
        # check for errors that are probably caused by something broken in
1943
 
        # the build environment, and give back the packages.
1944
 
        if ($status != 0 && $mode ne "-s" &&
1945
 
                (($msgs =~ /^E: dpkg was interrupted, you must manually run 'dpkg --configure -a' to correct the problem./mi) ||
1946
 
                ($msgs =~ /^dpkg: parse error, in file `\/.+\/var\/lib\/dpkg\/(?:available|status)' near line/mi) ||
1947
 
                ($msgs =~ /^E: Unmet dependencies. Try 'apt-get -f install' with no packages \(or specify a solution\)\./mi))) {
1948
 
                print PLOG "Build environment unusable, giving back\n";
1949
 
                $main::pkg_fail_stage = "install-deps-env";
1950
 
        }
1951
 
 
1952
 
        if ($status != 0 && $mode ne "-s" &&
1953
 
                (($msgs =~ /^E: Unable to fetch some archives, maybe run apt-get update or try with/mi))) {
1954
 
                print PLOG "Unable to fetch build-depends\n";
1955
 
                $main::pkg_fail_stage = "install-deps-env";
1956
 
        }
1957
 
        
1958
 
        $pkgs = $rpkgs = "";
1959
 
        if ($msgs =~ /NEW packages will be installed:\n((^[     ].*\n)*)/mi) {
1960
 
                ($pkgs = $1) =~ s/^[    ]*((.|\n)*)\s*$/$1/m;
1961
 
                $pkgs =~ s/\*//g;
1962
 
        }
1963
 
        if ($msgs =~ /packages will be REMOVED:\n((^[   ].*\n)*)/mi) {
1964
 
                ($rpkgs = $1) =~ s/^[   ]*((.|\n)*)\s*$/$1/m;
1965
 
                $rpkgs =~ s/\*//g;
1966
 
        }
1967
 
        @$inst_ret = split( /\s+/, $pkgs );
1968
 
        @$rem_ret = split( /\s+/, $rpkgs );
1969
 
 
1970
 
        print PLOG "apt-get failed.\n" if $status && $mode ne "-s";
1971
 
        return $mode eq "-s" || $status == 0;
1972
 
}
1973
 
 
1974
 
sub filter_dependencies {
1975
 
        my $dependencies = shift;
1976
 
        my $pos_list = shift;
1977
 
        my $neg_list = shift;
1978
 
        my $special_list = shift;
1979
 
        my($dep, $d, $name, %names);
1980
 
 
1981
 
        print PLOG "Checking for already installed source dependencies...\n";
1982
 
        
1983
 
        @$pos_list = @$neg_list = @$special_list = ();
1984
 
        foreach $d (@$dependencies) {
1985
 
                my $name = $d->{'Package'};
1986
 
                $names{$name} = 1 if $name !~ /^\*/;
1987
 
                foreach (@{$d->{'Alternatives'}}) {
1988
 
                        my $name = $_->{'Package'};
1989
 
                        $names{$name} = 1 if $name !~ /^\*/;
1990
 
                }
1991
 
        }
1992
 
        my $status = get_dpkg_status( keys %names );
1993
 
 
1994
 
        foreach $dep (@$dependencies) {
1995
 
                $name = $dep->{'Package'};
1996
 
                next if !$name;
1997
 
                if ($name =~ /^\*/) {
1998
 
                        my $doit = 1;
1999
 
                        if (exists $main::specials{$name}->{'condition'}) {
2000
 
                                print "Testing condition for special dependency $name:\n"
2001
 
                                        if $main::debug;
2002
 
                                if (run_script("+e",$main::specials{$name}->{'condition'})!=0){
2003
 
                                        print "Condition false -> not running scripts\n"
2004
 
                                                if $main::debug;
2005
 
                                        $doit = 0;
2006
 
                                }
2007
 
                        }
2008
 
                        push( @$special_list, $name ) if $doit;
2009
 
                        next;
2010
 
                }
2011
 
                my $stat = $status->{$name};
2012
 
                if ($dep->{'Neg'}) {
2013
 
                        if ($stat->{'Installed'}) {
2014
 
                                my ($rel, $vers) = ($dep->{'Rel'}, $dep->{'Version'});
2015
 
                                my $ivers = $stat->{'Version'};
2016
 
                                if (!$rel || version_cmp( $ivers, $rel, $vers )){
2017
 
                                        print "$name: neg dep, installed, not versioned or ",
2018
 
                                                  "version relation satisfied --> remove\n" if $main::debug;
2019
 
                                        print PLOG "$name: installed (negative dependency)";
2020
 
                                        print PLOG " (bad version $ivers $rel $vers)"
2021
 
                                                if $rel;
2022
 
                                        print PLOG "\n";
2023
 
                                        push( @$neg_list, $name );
2024
 
                                }
2025
 
                                else {
2026
 
                                        print PLOG "$name: installed (negative dependency)",
2027
 
                                                           "(but version ok $ivers $rel $vers)\n";
2028
 
                                }
2029
 
                        }
2030
 
                        else {
2031
 
                                print "$name: neg dep, not installed\n" if $main::debug;
2032
 
                                print PLOG "$name: already deinstalled\n";
2033
 
                        }
2034
 
                        next;
2035
 
                }
2036
 
                
2037
 
                my $is_satisfied = 0;
2038
 
                my $installable = "";
2039
 
                my $upgradeable = "";
2040
 
                my $downgradeable = "";
2041
 
                foreach $d ($dep, @{$dep->{'Alternatives'}}) {
2042
 
                        my ($name, $rel, $vers) =
2043
 
                                ($d->{'Package'}, $d->{'Rel'}, $d->{'Version'});
2044
 
                        my $stat = $status->{$name};
2045
 
                        if (!$stat->{'Installed'}) {
2046
 
                                print "$name: pos dep, not installed\n" if $main::debug;
2047
 
                                print PLOG "$name: missing\n";
2048
 
                                my $exists = package_exists($name);
2049
 
                                print PLOG "$name: does not exist\n" if not $exists;
2050
 
                                $installable = $name if !$installable and $exists;
2051
 
                                next;
2052
 
                        }
2053
 
                        my $ivers = $stat->{'Version'};
2054
 
                        if (!$rel || version_cmp( $ivers, $rel, $vers )) {
2055
 
                                print "$name: pos dep, installed, no versioned dep or ",
2056
 
                                          "version ok\n" if $main::debug;
2057
 
                                print PLOG "$name: already installed ($ivers";
2058
 
                                print PLOG " $rel $vers is satisfied"
2059
 
                                        if $rel;
2060
 
                                print PLOG ")\n";
2061
 
                                $is_satisfied = 1;
2062
 
                                last;
2063
 
                        }
2064
 
                        print "$name: vers dep, installed $ivers ! $rel $vers\n"
2065
 
                                if $main::debug;
2066
 
                        print PLOG "$name: non-matching version installed ",
2067
 
                                  "($ivers ! $rel $vers)\n";
2068
 
                        if ($rel =~ /^</ ||
2069
 
                                ($rel eq '=' && version_cmp($ivers, '>>', $vers))) {
2070
 
                                print "$name: would be a downgrade!\n" if $main::debug;
2071
 
                                print PLOG "$name: would have to downgrade!\n";
2072
 
                                $downgradeable = $name if !$downgradeable;
2073
 
                        }
2074
 
                        else {
2075
 
                                $upgradeable = $name if !$upgradeable;
2076
 
                        }
2077
 
                }
2078
 
                if (!$is_satisfied) {
2079
 
                        if ($upgradeable) {
2080
 
                                print "using $upgradeable for upgrade\n" if $main::debug;
2081
 
                                push( @$pos_list, $upgradeable );
2082
 
                        }
2083
 
                        elsif ($installable) {
2084
 
                                print "using $installable for install\n" if $main::debug;
2085
 
                                push( @$pos_list, $installable );
2086
 
                        }
2087
 
                        elsif ($downgradeable) {
2088
 
                                print PLOG "To satisfy this dependency the package(s) would ",
2089
 
                                                   "have\n",
2090
 
                                                   "to be downgraded; this is not implemented.\n";
2091
 
                                return 0;
2092
 
                        }
2093
 
                        else {
2094
 
                                # None of the build-deps exist. Return the
2095
 
                                # first one so that we get a useful dep-wait.
2096
 
                                $installable = $dep->{'Package'};
2097
 
                                print "using $installable for install (does not exist)\n" if $main::debug;
2098
 
                                push( @$pos_list, $installable );
2099
 
                        }
2100
 
                }
2101
 
        }
2102
 
 
2103
 
        return 1;
2104
 
}
2105
 
 
2106
 
sub check_dependencies {
2107
 
        my $dependencies = shift;
2108
 
        my $fail = "";
2109
 
        my($dep, $d, $name, %names);
2110
 
 
2111
 
        print PLOG "Checking correctness of source dependencies...\n";
2112
 
        
2113
 
        foreach $d (@$dependencies) {
2114
 
                my $name = $d->{'Package'};
2115
 
                $names{$name} = 1 if $name !~ /^\*/;
2116
 
                foreach (@{$d->{'Alternatives'}}) {
2117
 
                        my $name = $_->{'Package'};
2118
 
                        $names{$name} = 1 if $name !~ /^\*/;
2119
 
                }
2120
 
        }
2121
 
        foreach $name (@main::toolchain_pkgs) {
2122
 
                $names{$name} = 1;
2123
 
        }
2124
 
        my $status = get_dpkg_status( keys %names );
2125
 
 
2126
 
        foreach $dep (@$dependencies) {
2127
 
                $name = $dep->{'Package'};
2128
 
                next if $name =~ /^\*/;
2129
 
                my $stat = $status->{$name};
2130
 
                if ($dep->{'Neg'}) {
2131
 
                    if ($stat->{'Installed'}) {
2132
 
                                if (!$dep->{'Rel'}) {
2133
 
                                        $fail .= "$name(still installed) ";
2134
 
                                }
2135
 
                                elsif (version_cmp($stat->{'Version'}, $dep->{'Rel'},
2136
 
                                                                   $dep->{'Version'})) {
2137
 
                                        $fail .= "$name(inst $stat->{'Version'} $dep->{'Rel'} ".
2138
 
                                                         "conflicted $dep->{'Version'})\n";
2139
 
                                }
2140
 
                        }
2141
 
                }
2142
 
                else {
2143
 
                        my $is_satisfied = 0;
2144
 
                        my $f = "";
2145
 
                        foreach $d ($dep, @{$dep->{'Alternatives'}}) {
2146
 
                                my $name = $d->{'Package'};
2147
 
                                my $stat = $status->{$name};
2148
 
                                if (!$stat->{'Installed'}) {
2149
 
                                        $f =~ s/ $/\|/ if $f;
2150
 
                                        $f .= "$name(missing) ";
2151
 
                                }
2152
 
                                elsif ($d->{'Rel'} &&
2153
 
                                           !version_cmp( $stat->{'Version'}, $d->{'Rel'},
2154
 
                                                                         $d->{'Version'} )) {
2155
 
                                        $f =~ s/ $/\|/ if $f;
2156
 
                                        $f .= "$name(inst $stat->{'Version'} ! $d->{'Rel'} ".
2157
 
                                                  "wanted $d->{'Version'}) ";
2158
 
                                }
2159
 
                                else {
2160
 
                                        $is_satisfied = 1;
2161
 
                                }
2162
 
                        }
2163
 
                        if (!$is_satisfied) {
2164
 
                                $fail .= $f;
2165
 
                        }
2166
 
                }
2167
 
        }
2168
 
        $fail =~ s/\s+$//;
2169
 
        if (!$fail && @main::toolchain_pkgs) {
2170
 
                print PLOG "Toolchain package versions:";
2171
 
                foreach $name (@main::toolchain_pkgs) {
2172
 
                        print PLOG ' ' . $name . '_' . $status->{$name}->{'Version'};
2173
 
                }
2174
 
                print PLOG "\n";
2175
 
        }
2176
 
 
2177
 
        return $fail;
2178
 
}
2179
 
 
2180
 
sub get_dpkg_status {
2181
 
        my @interest = @_;
2182
 
        my %result;
2183
 
        local( *STATUS );
2184
 
 
2185
 
        return () if !@_;
2186
 
        print "Requesting dpkg status for packages: @interest\n"
2187
 
                if $main::debug;
2188
 
        if (!open( STATUS, "<$main::chroot_dir/var/lib/dpkg/status" )) {
2189
 
                print PLOG "Can't open $main::chroot_dir/var/lib/dpkg/status: $!\n";
2190
 
                return ();
2191
 
        }
2192
 
        local( $/ ) = "";
2193
 
        while( <STATUS> ) {
2194
 
                my( $pkg, $status, $version, $provides );
2195
 
                /^Package:\s*(.*)\s*$/mi and $pkg = $1;
2196
 
                /^Status:\s*(.*)\s*$/mi and $status = $1;
2197
 
                /^Version:\s*(.*)\s*$/mi and $version = $1;
2198
 
                /^Provides:\s*(.*)\s*$/mi and $provides = $1;
2199
 
                if (!$pkg) {
2200
 
                        print PLOG "sbuild: parse error in $main::chroot_dir/var/lib/dpkg/status: ",
2201
 
                                           "no Package: field\n";
2202
 
                        next;
2203
 
                }
2204
 
                print "$pkg ($version) status: $status\n" if $main::debug >= 2;
2205
 
                if (!$status) {
2206
 
                        print PLOG "sbuild: parse error in $main::chroot_dir/var/lib/dpkg/status: ",
2207
 
                                           "no Status: field for package $pkg\n";
2208
 
                        next;
2209
 
                }
2210
 
                if ($status !~ /\sinstalled$/) {
2211
 
                        $result{$pkg}->{'Installed'} = 0
2212
 
                                if !(exists($result{$pkg}) &&
2213
 
                                         $result{$pkg}->{'Version'} eq '=*=PROVIDED=*=');
2214
 
                        next;
2215
 
                }
2216
 
                if (!$version) {
2217
 
                        print PLOG "sbuild: parse error in $main::chroot_dir/var/lib/dpkg/status: ",
2218
 
                                           "no Version: field for package $pkg\n";
2219
 
                        next;
2220
 
                }
2221
 
                $result{$pkg} = { Installed => 1, Version => $version }
2222
 
                        if isin( $pkg, @interest );
2223
 
                if ($provides) {
2224
 
                        foreach (split( /\s*,\s*/, $provides )) {
2225
 
                                $result{$_} = { Installed => 1, Version => '=*=PROVIDED=*=' }
2226
 
                                        if (isin( $_, @interest ) &&
2227
 
                                                $result{$_}->{'Installed'} != 1);
2228
 
                        }
2229
 
                }
2230
 
        }
2231
 
        close( STATUS );
2232
 
        return \%result;
2233
 
}
2234
 
 
2235
 
sub version_cmp {
2236
 
        my $v1 = shift;
2237
 
        my $rel = shift;
2238
 
        my $v2 = shift;
2239
 
        if ($v1 eq "=*=PROVIDED=*=") {
2240
 
                return 0;
2241
 
        }
2242
 
        
2243
 
        system "$conf::dpkg", "--compare-versions", $v1, $rel, $v2;
2244
 
        return $? == 0;
2245
 
}
2246
 
 
2247
 
sub run_script {
2248
 
        my $e_mode = shift;
2249
 
        my $x_mode = "";
2250
 
        my $script = shift;
2251
 
 
2252
 
        if ($main::debug >= 2) {
2253
 
                $x_mode = "set -x -v\n";
2254
 
        }
2255
 
        elsif ($main::debug)  {
2256
 
                print "Running script:\n  ",
2257
 
                join( "\n  ", split( "\n", "set $e_mode\n$script" )), "\n";
2258
 
        }
2259
 
        my $pid = fork();
2260
 
        if (!defined $pid) {
2261
 
                print PLOG "Can't fork: $! -- can't execute script\n";
2262
 
                return 1;
2263
 
        }
2264
 
        if ($pid == 0) {
2265
 
                setpgrp( 0, $$ );
2266
 
                open( STDOUT, ">&PLOG" );
2267
 
                open( STDERR, ">&PLOG" );
2268
 
                if ($main::chroot_dir) {
2269
 
                        exec "$conf::sudo", "/usr/sbin/chroot", "$main::cwd/$main::chroot_dir",
2270
 
                                 "$conf::su", $main::username, "-s", "/bin/sh", "-c",
2271
 
                                 "cd /build/$main::username\nset $e_mode\n$x_mode$script";
2272
 
                }
2273
 
                else {
2274
 
                        exec "/bin/sh", "-c", "set $e_mode\n$x_mode$script";
2275
 
                }
2276
 
                die "Can't exec /bin/sh: $!\n";
2277
 
        }
2278
 
        wait;
2279
 
        print "Script return value: $?\n" if $main::debug;
2280
 
        return $?
2281
 
}
2282
 
 
2283
 
 
2284
 
sub read_deps {
2285
 
        my @for_pkgs = @_;
2286
 
        my $fname;
2287
 
        local( *F );
2288
 
 
2289
 
        open( F, $fname = "<$conf::source_dependencies-$main::distribution" )
2290
 
                or open( F, $fname = "<$conf::source_dependencies" )
2291
 
                or die "Cannot open $conf::source_dependencies: $!\n";
2292
 
        $fname = substr( $fname, 1 );
2293
 
        print "Reading source dependencies from $fname\n"
2294
 
                if $main::debug;
2295
 
        while( <F> ) {
2296
 
                chomp;
2297
 
                next if /^\s*$/ || /^\s*#/;
2298
 
                while( /\\$/ ) {
2299
 
                        chop;
2300
 
                        $_ .= <F>;
2301
 
                        chomp;
2302
 
                }
2303
 
                if (/^(\*\*?[\w\d.+-]+):\s*$/) {
2304
 
                        # is a special definition
2305
 
                        my $sp = $1;
2306
 
                        get_special( $fname, $sp, \*F );
2307
 
                        next;
2308
 
                }
2309
 
                if (/^abbrev\s+([\w\d.+-]+)\s*=\s*(.*)\s*$/) {
2310
 
                        my ($abbrev, $def) = ($1, $2);
2311
 
                        parse_one_srcdep( $abbrev, $def, \%main::abbrevs );
2312
 
                        next;
2313
 
                }
2314
 
                if (!/^([a-zA-Z\d.+-]+):\s*(.*)\s*$/) {
2315
 
                        warn "Syntax error in line $. in $fname\n";
2316
 
                        next;
2317
 
                }
2318
 
                my( $pkg, $deps ) = ($1, $2);
2319
 
                if (exists $main::deps{$pkg}) {
2320
 
                        warn "Ignoring double entry for package $pkg at line $. ".
2321
 
                                 "in $fname\n";
2322
 
                        next;
2323
 
                }
2324
 
                next if !isin( $pkg, @for_pkgs );
2325
 
                parse_one_srcdep( $pkg, $deps, \%main::deps );
2326
 
        }
2327
 
        close( F );
2328
 
 
2329
 
        foreach (@main::manual_srcdeps) {
2330
 
                if (!/^([fa])([a-zA-Z\d.+-]+):\s*(.*)\s*$/) {
2331
 
                        warn "Syntax error in manual source dependency: ",
2332
 
                                 substr( $_, 1 ), "\n";
2333
 
                        next;
2334
 
                }
2335
 
                my ($mode, $pkg, $deps) = ($1, $2, $3);
2336
 
                next if !isin( $pkg, @for_pkgs );
2337
 
                @{$main::deps{$pkg}} = () if $mode eq 'f';
2338
 
                parse_one_srcdep( $pkg, $deps, \%main::deps );
2339
 
        }
2340
 
 
2341
 
        # substitute abbrevs and warn about undefined special deps
2342
 
        my( $pkg, $i, %warned );
2343
 
        foreach $pkg (keys %main::deps) {
2344
 
          repeat:
2345
 
                my $dl = $main::deps{$pkg};
2346
 
                for( $i = 0; $i < @$dl; ++$i ) {
2347
 
                        my $dep = $dl->[$i];
2348
 
                        my $name = $dep->{'Package'};
2349
 
                        if ($name =~ /^\*/) {
2350
 
                                if (!$warned{$name} && !exists $main::specials{$name}) {
2351
 
                                        warn "Warning: $pkg: No definition for special ",
2352
 
                                                 "dependency $name!\n";
2353
 
                                        $warned{$name}++;
2354
 
                                }
2355
 
                        }
2356
 
                        elsif (defined $main::abbrevs{$name}) {
2357
 
                                my @l = @{$main::abbrevs{$name}};
2358
 
                                if (defined $dep->{'Alternatives'}) {
2359
 
                                        warn "Warning: $pkg: abbrev $name not allowed ",
2360
 
                                                 "in alternative\n";
2361
 
                                        @l = ();
2362
 
                                }
2363
 
                                if ($dep->{'Neg'}) {
2364
 
                                        warn "Warning: $pkg: Negation of abbrev $name ",
2365
 
                                                 "not allowed\n";
2366
 
                                        @l = ();
2367
 
                                }
2368
 
                                if ($dep->{'Rel'}) {
2369
 
                                        warn "Warning: $pkg: No relation with abbrev $name ",
2370
 
                                                 "allowed\n";
2371
 
                                        @l = ();
2372
 
                                }
2373
 
                                if (my $ov = $dep->{'Override'}) {
2374
 
                                        @l = map { my $x = copy($_);
2375
 
                                                           $x->{'Override'} = $ov; $x } @l;
2376
 
                                }
2377
 
                                splice @$dl, $i, 1, @l;
2378
 
                                goto repeat;
2379
 
                        }
2380
 
                        elsif (defined $dep->{'Alternatives'}) {
2381
 
                                my $alt;
2382
 
                                foreach $alt (@{$dep->{'Alternatives'}}) {
2383
 
                                        if (defined $main::abbrevs{$alt->{'Package'}}) {
2384
 
                                                warn "Warning: $pkg: abbrev $alt->{'Package'} not ",
2385
 
                                                         "allowed in alternative\n";
2386
 
                                                splice @$dl, $i, 1;
2387
 
                                        }
2388
 
                                }
2389
 
                        }
2390
 
                }
2391
 
        }
2392
 
}
2393
 
 
2394
 
sub copy {
2395
 
        my $r = shift;
2396
 
        my $new;
2397
 
 
2398
 
        if (ref($r) eq "HASH") {
2399
 
                $new = { };
2400
 
                foreach (keys %$r) {
2401
 
                        $new->{$_} = copy($r->{$_});
2402
 
                }
2403
 
        }
2404
 
        elsif (ref($r) eq "ARRAY") {
2405
 
                my $i;
2406
 
                $new = [ ];
2407
 
                for( $i = 0; $i < @$r; ++$i ) {
2408
 
                        $new->[$i] = copy($r->[$i]);
2409
 
                }
2410
 
        }
2411
 
        elsif (!ref($r)) {
2412
 
                $new = $r;
2413
 
        }
2414
 
        else {
2415
 
                die "unknown ref type in copy\n";
2416
 
        }
2417
 
        
2418
 
        return $new;
2419
 
}
2420
 
 
2421
 
sub merge_pkg_build_deps {
2422
 
        my $pkg = shift;
2423
 
        my $depends = shift;
2424
 
        my $dependsi = shift;
2425
 
        my $conflicts = shift;
2426
 
        my $conflictsi = shift;
2427
 
        my (@l, $dep);
2428
 
 
2429
 
        print PLOG "** Using build dependencies supplied by package:\n";
2430
 
        print PLOG "Build-Depends: $depends\n" if $depends;
2431
 
        print PLOG "Build-Depends-Indep: $dependsi\n" if $dependsi;
2432
 
        print PLOG "Build-Conflicts: $conflicts\n" if $conflicts;
2433
 
        print PLOG "Build-Conflicts-Indep: $conflictsi\n" if $conflictsi;
2434
 
 
2435
 
        my $old_deps = copy($main::deps{$pkg});
2436
 
        # keep deps from the central file marked as overrides (& prefix)
2437
 
        if ( $main::useSNAP ) {
2438
 
            $dep->{'Package'} = "gcc-snapshot";
2439
 
            $dep->{'Override'} = 1;
2440
 
            push( @{$main::deps{$pkg}}, $dep );
2441
 
        }
2442
 
        foreach $dep (@{$main::deps{$pkg}}) {
2443
 
                if ($dep->{'Override'}) {
2444
 
                        print PLOG "Added override: ",
2445
 
                                  (map { ($_->{'Neg'} ? "!" : "") .
2446
 
                                             $_->{'Package'} .
2447
 
                                                 ($_->{'Rel'} ? " ($_->{'Rel'} $_->{'Version'})":"") }
2448
 
                                        scalar($dep), @{$dep->{'Alternatives'}}), "\n";
2449
 
                        push( @l, $dep );
2450
 
                }
2451
 
        }
2452
 
 
2453
 
        $conflicts = join( ", ", map { "!$_" } split( /\s*,\s*/, $conflicts ));
2454
 
        $conflictsi = join( ", ", map { "!$_" } split( /\s*,\s*/, $conflictsi ));
2455
 
        
2456
 
        my $deps = $depends . ", " . $conflicts;
2457
 
        $deps .= ", " . $dependsi . ", " . $conflictsi if $main::build_arch_all;
2458
 
        # For the moment, we treat multiarch-annotated build-dependencies as
2459
 
        # the same as any others because we're not implementing a
2460
 
        # cross-buildd.
2461
 
        $deps =~ s/:any//g;
2462
 
        $deps =~ s/:native//g;
2463
 
 
2464
 
        @{$main::deps{$pkg}} = @l;
2465
 
        print "Merging pkg deps: $deps\n" if $main::debug;
2466
 
        parse_one_srcdep( $pkg, $deps, \%main::deps );
2467
 
 
2468
 
        my $missing = (cmp_dep_lists( $old_deps, $main::deps{$pkg} ))[1];
2469
 
 
2470
 
        # read list of build-essential packages (if not yet done) and expand their
2471
 
        # dependencies (those are implicitly essential)
2472
 
        if (!defined($main::deps{'ESSENTIAL'})) {
2473
 
                my $ess = read_build_essential();
2474
 
                parse_one_srcdep( 'ESSENTIAL', $ess, \%main::deps );
2475
 
        }
2476
 
        my ($exp_essential, $exp_pkgdeps, $filt_essential, $filt_pkgdeps);
2477
 
        $exp_essential = expand_dependencies( $main::deps{'ESSENTIAL'} );
2478
 
        print "Dependency-expanded build essential packages:\n",
2479
 
                  format_deps(@$exp_essential), "\n" if $main::debug;
2480
 
 
2481
 
        # populate toolchain_pkgs from toolchain_regexes and essential packages.
2482
 
        @main::toolchain_pkgs = ();
2483
 
        foreach my $tpkg (@$exp_essential) {
2484
 
                foreach my $regex (@conf::toolchain_regex) {
2485
 
                        push @main::toolchain_pkgs,$tpkg->{'Package'}
2486
 
                                if $tpkg->{'Package'} =~ m,^$regex,;
2487
 
                }
2488
 
        }
2489
 
        return if !@$missing;
2490
 
 
2491
 
        # remove missing central deps that are essential
2492
 
        ($filt_essential, $missing) = cmp_dep_lists( $missing, $exp_essential );
2493
 
        print PLOG "** Filtered missing central deps that are build-essential:\n",
2494
 
                           format_deps(@$filt_essential), "\n"
2495
 
                                   if @$filt_essential;
2496
 
 
2497
 
        # if some build deps are virtual packages, replace them by an alternative
2498
 
        # over all providing packages
2499
 
        $exp_pkgdeps = expand_virtuals( $main::deps{$pkg} );
2500
 
        print "Provided-expanded build deps:\n",
2501
 
                  format_deps(@$exp_pkgdeps), "\n" if $main::debug;
2502
 
 
2503
 
        # now expand dependencies of package build deps
2504
 
        $exp_pkgdeps = expand_dependencies( $exp_pkgdeps );
2505
 
        print "Dependency-expanded build deps:\n",
2506
 
                  format_deps(@$exp_pkgdeps), "\n" if $main::debug;
2507
 
        $main::additional_deps = $exp_pkgdeps;
2508
 
 
2509
 
        # remove missing central deps that are dependencies of build deps
2510
 
        ($filt_pkgdeps, $missing) = cmp_dep_lists( $missing, $exp_pkgdeps );
2511
 
        print PLOG "** Filtered missing central deps that are dependencies of ",
2512
 
                           "or provide build-deps:\n",
2513
 
                           format_deps(@$filt_pkgdeps), "\n"
2514
 
                                   if @$filt_pkgdeps;
2515
 
 
2516
 
        # remove comment package names
2517
 
        push( @$main::additional_deps,
2518
 
                  grep { $_->{'Neg'} && $_->{'Package'} =~ /^needs-no-/ } @$missing );
2519
 
        $missing = [ grep { !($_->{'Neg'} &&
2520
 
                                              ($_->{'Package'} =~ /^this-package-does-not-exist/ ||
2521
 
                                                   $_->{'Package'} =~ /^needs-no-/)) } @$missing ];
2522
 
 
2523
 
        print PLOG "**** Warning:\n",
2524
 
                           "**** The following central src deps are ",
2525
 
                           "(probably) missing:\n  ", format_deps(@$missing), "\n"
2526
 
                                   if @$missing;
2527
 
}
2528
 
 
2529
 
sub cmp_dep_lists {
2530
 
        my $list1 = shift;
2531
 
        my $list2 = shift;
2532
 
        my ($dep, @common, @missing);
2533
 
 
2534
 
        foreach $dep (@$list1) {
2535
 
                my $found = 0;
2536
 
 
2537
 
                if ($dep->{'Neg'}) {
2538
 
                        foreach (@$list2) {
2539
 
                                if ($dep->{'Package'} eq $_->{'Package'} && $_->{'Neg'}) {
2540
 
                                        $found = 1;
2541
 
                                        last;
2542
 
                                }
2543
 
                        }
2544
 
                }
2545
 
                else {
2546
 
                        my $al = get_altlist($dep);
2547
 
                        foreach (@$list2) {
2548
 
                                if (is_superset( get_altlist($_), $al )) {
2549
 
                                        $found = 1;
2550
 
                                        last;
2551
 
                                }
2552
 
                        }
2553
 
                }
2554
 
 
2555
 
                if ($found) {
2556
 
                        push( @common, $dep );
2557
 
                }
2558
 
                else {
2559
 
                        push( @missing, $dep );
2560
 
                }
2561
 
        }
2562
 
        return (\@common, \@missing);
2563
 
}
2564
 
 
2565
 
sub get_altlist {
2566
 
        my $dep = shift;
2567
 
        my %l;
2568
 
 
2569
 
        foreach (scalar($dep), @{$dep->{'Alternatives'}}) {
2570
 
                $l{$_->{'Package'}} = 1 if !$_->{'Neg'};
2571
 
        }
2572
 
        return \%l;
2573
 
}
2574
 
 
2575
 
sub is_superset {
2576
 
        my $l1 = shift;
2577
 
        my $l2 = shift;
2578
 
 
2579
 
        foreach (keys %$l2) {
2580
 
                return 0 if !exists $l1->{$_};
2581
 
        }
2582
 
        return 1;
2583
 
}
2584
 
 
2585
 
sub read_build_essential {
2586
 
        my @essential;
2587
 
        local (*F);
2588
 
 
2589
 
        if (open( F, "$main::chroot_dir/usr/share/doc/build-essential/essential-packages-list" )) {
2590
 
                while( <F> ) {
2591
 
                        last if $_ eq "\n";
2592
 
                }
2593
 
                while( <F> ) {
2594
 
                        chomp;
2595
 
                        push( @essential, $_ ) if $_ !~ /^\s*$/;
2596
 
                }
2597
 
                close( F );
2598
 
        }
2599
 
        else {
2600
 
                warn "Cannot open $main::chroot_dir/usr/share/doc/build-essential/essential-packages-list: $!\n";
2601
 
        }
2602
 
 
2603
 
        if (open( F, "$main::chroot_dir/usr/share/doc/build-essential/list" )) {
2604
 
                while( <F> ) {
2605
 
                        last if $_ eq "BEGIN LIST OF PACKAGES\n";
2606
 
                }
2607
 
                while( <F> ) {
2608
 
                        chomp;
2609
 
                        last if $_ eq "END LIST OF PACKAGES";
2610
 
                        next if /^\s/ || /^$/;
2611
 
                        push( @essential, $_ );
2612
 
                }
2613
 
                close( F );
2614
 
        }
2615
 
        else {
2616
 
                warn "Cannot open $main::chroot_dir/usr/share/doc/build-essential/list: $!\n";
2617
 
        }
2618
 
 
2619
 
        return join( ", ", @essential );
2620
 
}
2621
 
 
2622
 
sub expand_dependencies {
2623
 
        my $dlist = shift;
2624
 
        my (@to_check, @result, %seen, $check, $dep);
2625
 
 
2626
 
        foreach $dep (@$dlist) {
2627
 
                next if $dep->{'Neg'} || $dep->{'Package'} =~ /^\*/;
2628
 
                foreach (scalar($dep), @{$dep->{'Alternatives'}}) {
2629
 
                        my $name = $_->{'Package'};
2630
 
                        push( @to_check, $name );
2631
 
                        $seen{$name} = 1;
2632
 
                }
2633
 
                push( @result, copy($dep) );
2634
 
        }
2635
 
 
2636
 
        while( @to_check ) {
2637
 
                my $deps = get_dependencies( @to_check );
2638
 
                my @check = @to_check;
2639
 
                @to_check = ();
2640
 
                foreach $check (@check) {
2641
 
                        foreach (split( /\s*,\s*/, $deps->{$check} )) {
2642
 
                                foreach (split( /\s*\|\s*/, $_ )) {
2643
 
                                        my $pkg = (/^([^\s([]+)/)[0];
2644
 
                                        if (!$seen{$pkg}) {
2645
 
                                                push( @to_check, $pkg );
2646
 
                                                push( @result, { Package => $pkg, Neg => 0 } );
2647
 
                                                $seen{$pkg} = 1;
2648
 
                                        }
2649
 
                                }
2650
 
                        }
2651
 
                }
2652
 
        }
2653
 
        
2654
 
        return \@result;
2655
 
}
2656
 
 
2657
 
sub expand_virtuals {
2658
 
        my $dlist = shift;
2659
 
        my ($dep, %names, @new_dlist);
2660
 
 
2661
 
        foreach $dep (@$dlist) {
2662
 
                foreach (scalar($dep), @{$dep->{'Alternatives'}}) {
2663
 
                        $names{$_->{'Package'}} = 1;
2664
 
                }
2665
 
        }
2666
 
        my $provided_by = get_virtuals( keys %names );
2667
 
 
2668
 
        foreach $dep (@$dlist) {
2669
 
                my %seen;
2670
 
                foreach (scalar($dep), @{$dep->{'Alternatives'}}) {
2671
 
                        my $name = $_->{'Package'};
2672
 
                        $seen{$name} = 1;
2673
 
                        if (exists $provided_by->{$name}) {
2674
 
                                foreach( keys %{$provided_by->{$name}} ) {
2675
 
                                        $seen{$_} = 1;
2676
 
                                }
2677
 
                        }
2678
 
                }
2679
 
                my @l = map { { Package => $_, Neg => 0 } } keys %seen;
2680
 
                my $l = shift @l;
2681
 
                foreach (@l) {
2682
 
                        push( @{$l->{'Alternatives'}}, $_ );
2683
 
                }
2684
 
                push( @new_dlist, $l );
2685
 
        }
2686
 
 
2687
 
        return \@new_dlist;
2688
 
}
2689
 
                
2690
 
sub get_dependencies {
2691
 
        local(*PIPE);
2692
 
        my %deps;
2693
 
        
2694
 
        open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir $conf::apt_cache show @_ 2>&1 |" )
2695
 
                or die "Cannot start $conf::apt_cache $main::chroot_apt_op: $!\n";
2696
 
        local($/) = "";
2697
 
        while( <PIPE> ) {
2698
 
                my ($name, $dep, $predep);
2699
 
                /^Package:\s*(.*)\s*$/mi and $name = $1;
2700
 
                next if !$name || $deps{$name};
2701
 
                /^Depends:\s*(.*)\s*$/mi and $dep = $1;
2702
 
                /^Pre-Depends:\s*(.*)\s*$/mi and $predep = $1;
2703
 
                $dep .= ", " if $dep && $predep;
2704
 
                $dep .= $predep;
2705
 
                $deps{$name} = $dep;
2706
 
        }
2707
 
        close( PIPE );
2708
 
        die "$conf::apt_cache exit status $?\n" if $?;
2709
 
 
2710
 
        return \%deps;
2711
 
}
2712
 
                
2713
 
sub get_virtuals {
2714
 
        local(*PIPE);
2715
 
 
2716
 
        open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir $conf::apt_cache showpkg @_ 2>&1 |" )
2717
 
                or die "Cannot start $conf::apt_cache $main::chroot_apt_op: $!\n";
2718
 
        my $name;
2719
 
        my $in_rprov = 0;
2720
 
        my %provided_by;
2721
 
        while( <PIPE> ) {
2722
 
                if (/^Package:\s*(\S+)\s*$/) {
2723
 
                        $name = $1;
2724
 
                }
2725
 
                elsif (/^Reverse Provides: $/) {
2726
 
                        $in_rprov = 1;
2727
 
                }
2728
 
                elsif ($in_rprov && /^(\w+):\s/) {
2729
 
                        $in_rprov = 0;
2730
 
                }
2731
 
                elsif ($in_rprov && /^(\S+)\s*\S+\s*$/) {
2732
 
                        $provided_by{$name}->{$1} = 1;
2733
 
                }
2734
 
        }
2735
 
        close( PIPE );
2736
 
        die "$conf::apt_cache exit status $?\n" if $?;
2737
 
 
2738
 
        return \%provided_by;
2739
 
}
2740
 
 
2741
 
# Try to figure out if a package exists. We need to take account of virtual
2742
 
# packages, so showpkg is the best tool I can think of; but that shows
2743
 
# packages which only exist as (reverse) dependencies. As such, we make
2744
 
# sure that either Versions: or Reverse Provides: has some content.
2745
 
sub package_exists {
2746
 
        local(*PIPE);
2747
 
 
2748
 
        open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir ".
2749
 
                    "$conf::apt_cache showpkg @_ 2>&1 |" )
2750
 
                or die "Cannot start $conf::apt_cache $main::chroot_apt_op: $!\n";
2751
 
        my $name;
2752
 
        my $in_versions = 0;
2753
 
        my $in_rprov = 0;
2754
 
        my $real = 0;
2755
 
        while( <PIPE> ) {
2756
 
                if (/^Package:\s*(\S+)\s*$/) {
2757
 
                        $name = $1;
2758
 
                }
2759
 
                elsif (/^Versions: $/) {
2760
 
                        $in_versions = 1;
2761
 
                        $in_rprov = 0;
2762
 
                }
2763
 
                elsif (/^Reverse Provides: $/) {
2764
 
                        $in_rprov = 1;
2765
 
                        $in_versions = 0;
2766
 
                }
2767
 
                elsif (($in_versions || $in_rprov) && /^(\w.*):\s/) {
2768
 
                        $in_versions = 0;
2769
 
                        $in_rprov = 0;
2770
 
                }
2771
 
                elsif (($in_versions || $in_rprov) && /^\S/) {
2772
 
                        $real = 1;
2773
 
                }
2774
 
        }
2775
 
        close( PIPE );
2776
 
        if (defined $name and $real) {
2777
 
                return 1;
2778
 
        } else {
2779
 
                return 0;
2780
 
        }
2781
 
}
2782
 
 
2783
 
sub parse_one_srcdep {
2784
 
        my $pkg = shift;
2785
 
        my $deps = shift;
2786
 
        my $hash = shift;
2787
 
        
2788
 
        $deps =~ s/^\s*(.*)\s*$/$1/;
2789
 
        foreach (split( /\s*,\s*/, $deps )) {
2790
 
                my @l;
2791
 
                my $override;
2792
 
                if (/^\&/) {
2793
 
                        $override = 1;
2794
 
                        s/^\&\s+//;
2795
 
                }
2796
 
                my @alts = split( /\s*\|\s*/, $_ );
2797
 
                my $special_seen = 0;
2798
 
                my $neg_seen = 0;
2799
 
                foreach (@alts) {
2800
 
                        if (!/^([^\s([]+)\s*(\(\s*([<=>]+)\s*(\S+)\s*\))?(\s*\[([^]]+)\])?/) {
2801
 
                                warn "Warning: syntax error in dependency '$_' of $pkg\n";
2802
 
                                next;
2803
 
                        }
2804
 
                        my( $dep, $rel, $relv, $archlist ) = ($1, $3, $4, $6);
2805
 
                        if ($archlist) {
2806
 
                                $archlist =~ s/^\s*(.*)\s*$/$1/;
2807
 
                                my @archs = split( /\s+/, $archlist );
2808
 
                                my ($use_it, $ignore_it, $include) = (0, 0, 0);
2809
 
                                foreach (@archs) {
2810
 
                                        # Use 'dpkg-architecture' to support architecture
2811
 
                                        # wildcards.
2812
 
                                        if (/^!/) {
2813
 
                                                $ignore_it = 1 if system('dpkg-architecture', '-a' . $main::arch, '-i' . substr($_, 1)) eq 0;
2814
 
                                        }
2815
 
                                        else {
2816
 
                                                $use_it = 1 if system('dpkg-architecture', '-a' . $main::arch, '-i' . $_) eq 0;
2817
 
                                                $include = 1;
2818
 
                                        }
2819
 
                                }
2820
 
                                warn "Warning: inconsistent arch restriction on ",
2821
 
                                         "$pkg: $dep depedency\n"
2822
 
                                                 if $ignore_it && $use_it;
2823
 
                                next if $ignore_it || ($include && !$use_it);
2824
 
                        }
2825
 
                        if ($dep =~ /^\*/) {
2826
 
                                warn "Warning: $pkg: ignoring version relation on ".
2827
 
                                         "special dependency $dep\n"
2828
 
                                                 if $rel || $relv;
2829
 
                                push( @l, { Package => $dep, Override => 1 } );
2830
 
                                $special_seen = 1;
2831
 
                                next;
2832
 
                        }
2833
 
                        my $neg = 0;
2834
 
                        if ($dep =~ /^!/) {
2835
 
                                $dep =~ s/^!\s*//;
2836
 
                                $neg = 1;
2837
 
                                $neg_seen = 1;
2838
 
                        }
2839
 
                        if ($conf::srcdep_over{$dep}) {
2840
 
                                if ($main::verbose) {
2841
 
                                        print PLOG "Replacing source dep $dep";
2842
 
                                        print PLOG " ($rel $relv)" if $relv;
2843
 
                                        print PLOG " with $conf::srcdep_over{$dep}[0]";
2844
 
                                        print PLOG " ($conf::srcdep_over{$dep}[1] $conf::srcdep_over{$dep}[2])"
2845
 
                                          if $conf::srcdep_over{$dep}[1];
2846
 
                                        print PLOG ".\n";
2847
 
                                }
2848
 
                                $dep = $conf::srcdep_over{$dep}[0];
2849
 
                                $rel = $conf::srcdep_over{$dep}[1];
2850
 
                                $relv = $conf::srcdep_over{$dep}[2];
2851
 
                        }
2852
 
                        my $h = { Package => $dep, Neg => $neg };
2853
 
                        if ($rel && $relv) {
2854
 
                                $h->{'Rel'} = $rel;
2855
 
                                $h->{'Version'} = $relv;
2856
 
                        }
2857
 
                        $h->{'Override'} = $override if $override;
2858
 
                        push( @l, $h );
2859
 
                }
2860
 
                if (@alts > 1 && $special_seen) {
2861
 
                        warn "Warning: $pkg: alternatives with special dependencies ",
2862
 
                                 "forbidden -- skipped\n";
2863
 
                }
2864
 
                elsif (@alts > 1 && $neg_seen) {
2865
 
                        warn "Warning: $pkg: alternatives with negative dependencies ",
2866
 
                                 "forbidden -- skipped\n";
2867
 
                }
2868
 
                elsif (@l) {
2869
 
                        my $l = shift @l;
2870
 
                        foreach (@l) {
2871
 
                                push( @{$l->{'Alternatives'}}, $_ );
2872
 
                        }
2873
 
                        push( @{$hash->{$pkg}}, $l );
2874
 
                }
2875
 
        }
2876
 
}
2877
 
 
2878
 
sub get_special {
2879
 
        my $fname = shift;
2880
 
        my $sp = shift;
2881
 
        my $sub = "";
2882
 
        
2883
 
        while( <F> ) {
2884
 
                last if /^$/;
2885
 
                if (/^\s*(\w+)\s*\{\s*$/) {
2886
 
                        if ($sub) {
2887
 
                                warn "Syntax error in line $. in $fname:\n";
2888
 
                                warn "  Start of special subsection inside ".
2889
 
                                        "another one.\n";
2890
 
                        }
2891
 
                        else {
2892
 
                                $sub = $1;
2893
 
                                $main::specials{$sp}->{$sub} = "";
2894
 
                        }
2895
 
                }
2896
 
                elsif (/^\s*\}\s*$/) {
2897
 
                        if (!$sub) {
2898
 
                                warn "Syntax error in line $. in $fname:\n";
2899
 
                                warn "  }  outside of special subsection\n";
2900
 
                        }
2901
 
                        else {
2902
 
                                $sub = "";
2903
 
                        }
2904
 
                }
2905
 
                elsif ($sub) {
2906
 
                        $main::specials{$sp}->{$sub} .= $_;
2907
 
                }
2908
 
                else {
2909
 
                        warn "Syntax error in line $. in $fname:\n";
2910
 
                        warn "  Subsection start expected\n";
2911
 
                }
2912
 
        }
2913
 
        if ($sub) {
2914
 
                warn "Syntax error in line $. in $fname:\n";
2915
 
                warn "  Subsection not finished with }\n";
2916
 
        }
2917
 
 
2918
 
        push( @main::global_patches, $sp ) if $sp =~ /^\*\*/;
2919
 
}
2920
 
 
2921
 
 
2922
 
sub open_log {
2923
 
        my $date = `date +%Y%m%d-%H%M`;
2924
 
        chomp( $date );
2925
 
 
2926
 
        if ($main::nolog) {
2927
 
                open( LOG, ">&STDOUT" );
2928
 
                open( PLOG, ">&LOG" ) or warn "Can't redirect PLOG\n";
2929
 
                select( LOG );
2930
 
                return;
2931
 
        }
2932
 
 
2933
 
        $main::main_logfile = "build-$date.log";
2934
 
 
2935
 
        if ($main::verbose) {
2936
 
                my $pid;
2937
 
                ($pid = open( LOG, "|-")) || exec "tee $main::main_logfile";
2938
 
                if (!defined $pid) {
2939
 
                        warn "Cannot open pipe to 'tee $main::main_logfile': $!\n";
2940
 
                }
2941
 
                else {
2942
 
                        $main::tee_pid = $pid;
2943
 
                }
2944
 
        }
2945
 
        else {
2946
 
                open( LOG, ">$main::main_logfile" )
2947
 
                        or warn "Cannot open log file $main::main_logfile: $!\n";
2948
 
        }
2949
 
        select( (select( LOG ), $| = 1)[0] );
2950
 
        open( STDOUT, ">&LOG" ) or warn "Can't redirect stdout\n";
2951
 
        open( STDERR, ">&LOG" ) or warn "Can't redirect stderr\n";
2952
 
        open( PLOG, ">&LOG" ) or warn "Can't redirect PLOG\n";
2953
 
}
2954
 
 
2955
 
sub close_log {
2956
 
        my $date = `date +%Y%m%d-%H%M`;
2957
 
        chomp( $date );
2958
 
 
2959
 
        kill( 15, $main::tee_pid ) if $main::verbose;
2960
 
        close( LOG );
2961
 
        if (!$main::nolog && !$main::verbose &&
2962
 
                -s $main::main_logfile && $conf::mailto) {
2963
 
                send_mail( $conf::mailto, "Log from sbuild $date",
2964
 
                                   $main::main_logfile ) if $conf::mailto;
2965
 
        }
2966
 
        elsif (!$main::nolog && !$main::verbose && ! -s $main::main_logfile) {
2967
 
                unlink( $main::main_logfile );
2968
 
        }
2969
 
}
2970
 
 
2971
 
sub open_pkg_log {
2972
 
        my $date = `date +%Y%m%d-%H%M`;
2973
 
        my $pkg = shift;
2974
 
 
2975
 
        if ($main::nolog) {
2976
 
                open( PLOG, ">&STDOUT" );
2977
 
        }
2978
 
        else {
2979
 
                $pkg = basename( $pkg );
2980
 
                if ($main::binNMU) {
2981
 
                        $pkg =~ /^([^_]+)_([^_]+)(.*)$/;
2982
 
                        $pkg = $1."_".binNMU_version($2);
2983
 
                        $main::binNMU_name = $pkg;
2984
 
                        $pkg .= $3;
2985
 
                }
2986
 
                $main::pkg_logfile = "$conf::log_dir/${pkg}_$date";
2987
 
                if ($main::verbose) {
2988
 
                        my $pid;
2989
 
                        ($pid = open( PLOG, "|-")) || exec "tee $main::pkg_logfile";
2990
 
                        if (!defined $pid) {
2991
 
                                warn "Cannot open pipe to 'tee $main::pkg_logfile': $!\n";
2992
 
                        }
2993
 
                        else {
2994
 
                                $main::pkg_tee_pid = $pid;
2995
 
                        }
2996
 
                }
2997
 
                else {
2998
 
                        if (!open( PLOG, ">$main::pkg_logfile" )) {
2999
 
                                warn "Can't open logfile $main::pkg_logfile: $!\n";
3000
 
                                return 0;
3001
 
                        }
3002
 
                }
3003
 
        }
3004
 
        select( (select( PLOG ), $| = 1)[0] );
3005
 
 
3006
 
        my $revision = '$Revision: 1.170.5 $';
3007
 
        $revision =~ /([\d.]+)/;
3008
 
        $revision = $1;
3009
 
 
3010
 
        print PLOG "Automatic build of $pkg on $main::HOSTNAME by ".
3011
 
                           "sbuild/$main::arch $revision\n";
3012
 
        print PLOG "Build started at $date";
3013
 
        print PLOG "*"x78, "\n";
3014
 
        return 1;
3015
 
}
3016
 
 
3017
 
sub close_pkg_log {
3018
 
        my $date = `date +%Y%m%d-%H%M`;
3019
 
        my $pkg = shift;
3020
 
        my $t = $main::pkg_end_time - $main::pkg_start_time;
3021
 
        
3022
 
        $pkg = basename( $pkg );
3023
 
        $t = 0 if $t < 0;
3024
 
        if ($main::pkg_status eq "successful") {
3025
 
                add_time_entry( $pkg, $t );
3026
 
                add_space_entry( $pkg, $main::this_space );
3027
 
        }
3028
 
        print PLOG "*"x78, "\n";
3029
 
        printf PLOG "Finished at ${date}Build needed %02d:%02d:%02d, %dk disk space\n",
3030
 
                   int($t/3600), int(($t%3600)/60), int($t%60), $main::this_space;
3031
 
        kill( 15, $main::pkg_tee_pid ) if $main::verbose && !$main::nolog;
3032
 
        close( PLOG );
3033
 
        open( PLOG, ">&LOG" ) or warn "Can't redirect PLOG\n";
3034
 
        send_mail( $conf::mailto,
3035
 
                           "Log for $main::pkg_status build of ".
3036
 
                           ($main::binNMU_name || $pkg)." (dist=$main::distribution)",
3037
 
                           $main::pkg_logfile ) if !$main::nolog && $conf::mailto;
3038
 
}
3039
 
 
3040
 
sub add_time_entry {
3041
 
        my $pkg = shift;
3042
 
        my $t = shift;
3043
 
 
3044
 
        return if !$conf::avg_time_db;
3045
 
        my %db;
3046
 
        if (!tie %db, 'GDBM_File',$conf::avg_time_db,GDBM_WRCREAT,0664) {
3047
 
                print "Can't open average time db $conf::avg_time_db\n";
3048
 
                return;
3049
 
        }
3050
 
        $pkg =~ s/_.*//;
3051
 
                
3052
 
        if (exists $db{$pkg}) {
3053
 
                my @times = split( /\s+/, $db{$pkg} );
3054
 
                push( @times, $t );
3055
 
                my $sum = 0;
3056
 
                foreach (@times[1..$#times]) { $sum += $_; }
3057
 
                $times[0] = $sum / (@times-1);
3058
 
                $db{$pkg} = join( ' ', @times );
3059
 
        }
3060
 
        else {
3061
 
                $db{$pkg} = "$t $t";
3062
 
        }
3063
 
        untie %db;
3064
 
}
3065
 
 
3066
 
sub check_space {
3067
 
        my @files = @_;
3068
 
        local( *PIPE );
3069
 
 
3070
 
        if (!open( PIPE, "sudo /usr/bin/du -s @files 2>/dev/null |" )) {
3071
 
                print PLOG "Cannot determine space needed (du failed): $!\n";
3072
 
                return;
3073
 
        }
3074
 
        my $sum = 0;
3075
 
        while( <PIPE> ) {
3076
 
                next if !/^(\d+)/;
3077
 
                $sum += $1;
3078
 
        }
3079
 
        close( PIPE );
3080
 
        $main::this_space = $sum;
3081
 
}
3082
 
 
3083
 
sub add_space_entry {
3084
 
        my $pkg = shift;
3085
 
        my $t = shift;
3086
 
 
3087
 
        my $keepvals = 4;
3088
 
        
3089
 
        return if !$conf::avg_space_db || $main::this_space == 0;
3090
 
        my %db;
3091
 
        if (!tie %db, 'GDBM_File',$conf::avg_space_db,GDBM_WRCREAT,0664) {
3092
 
                print "Can't open average space db $conf::avg_space_db\n";
3093
 
                return;
3094
 
        }
3095
 
        $pkg =~ s/_.*//;
3096
 
                
3097
 
        if (exists $db{$pkg}) {
3098
 
                my @values = split( /\s+/, $db{$pkg} );
3099
 
                shift @values;
3100
 
                unshift( @values, $t );
3101
 
                pop @values if @values > $keepvals;
3102
 
                my ($sum, $n, $weight, $i) = (0, 0, scalar(@values));
3103
 
                for( $i = 0; $i < @values; ++$i) {
3104
 
                        $sum += $values[$i] * $weight;
3105
 
                        $n += $weight;
3106
 
                }
3107
 
                unshift( @values, $sum/$n );
3108
 
                $db{$pkg} = join( ' ', @values );
3109
 
        }
3110
 
        else {
3111
 
                $db{$pkg} = "$t $t";
3112
 
        }
3113
 
        untie %db;
3114
 
}
3115
 
 
3116
 
sub file_for_name {
3117
 
        my $name = shift;
3118
 
        my @x = grep { /^\Q$name\E_/ } @_;
3119
 
        return $x[0];
3120
 
}
3121
 
                                
3122
 
sub write_jobs_file {
3123
 
        my $news = shift;
3124
 
        my $job;
3125
 
        local( *F );
3126
 
        
3127
 
        $main::job_state{$main::current_job} = $news
3128
 
                if $news && $main::current_job;
3129
 
 
3130
 
        return if !$main::batchmode;
3131
 
        
3132
 
        return if !open( F, ">$main::jobs_file" );
3133
 
        foreach $job (@ARGV) {
3134
 
                print F ($job eq $main::current_job) ? "" : "  ",
3135
 
                                $job,
3136
 
                                ($main::job_state{$job} ? ": $main::job_state{$job}" : ""),
3137
 
                                "\n";
3138
 
        }
3139
 
        close( F );
3140
 
}
3141
 
 
3142
 
sub append_to_FINISHED {
3143
 
        my $pkg = shift;
3144
 
        local( *F );
3145
 
 
3146
 
        return if !$main::batchmode;
3147
 
        
3148
 
        open( F, ">>SBUILD-FINISHED" );
3149
 
        print F "$pkg\n";
3150
 
        close( F );
3151
 
}
3152
 
 
3153
 
sub write_srcdep_lock_file {
3154
 
        my $deps = shift;
3155
 
        my $specials = shift;
3156
 
        local( *F );
3157
 
 
3158
 
        ++$main::srcdep_lock_cnt;
3159
 
        my $f = "$conf::srcdep_lock_dir/$$-$main::srcdep_lock_cnt";
3160
 
        if (!open( F, ">$f" )) {
3161
 
                print "Warning: cannot create srcdep lock file $f: $!";
3162
 
                return;
3163
 
        }
3164
 
        print "Writing srcdep lock file $f:\n" if $main::debug;
3165
 
 
3166
 
        chomp( my $user = `/usr/bin/whoami` );
3167
 
        print F "$main::current_job $$ $user\n";
3168
 
        print "Job $main::current_job pid $$ user $user\n" if $main::debug;
3169
 
        foreach (@$deps) {
3170
 
                my $name = $_->{'Package'};
3171
 
                # add special deps only if they affect global state ("global" sub)
3172
 
                next if $name =~ /^\*/ &&
3173
 
                            (!isin( $name, @$specials ) ||
3174
 
                                 $main::specials{$name}->{'global'} !~ /yes/m);
3175
 
                print F ($_->{'Neg'} ? "!" : ""), "$name\n";
3176
 
                print "  ", ($_->{'Neg'} ? "!" : ""), "$name\n" if $main::debug;
3177
 
        }
3178
 
        close( F );
3179
 
}
3180
 
 
3181
 
sub check_srcdep_conflicts {
3182
 
        my $to_inst = shift;
3183
 
        my $to_remove = shift;
3184
 
        my $special = shift;
3185
 
        local( *F, *DIR );
3186
 
        my $mypid = $$;
3187
 
        my %conflict_builds;
3188
 
 
3189
 
        if (!opendir( DIR, $conf::srcdep_lock_dir )) {
3190
 
                print PLOG "Cannot opendir $conf::srcdep_lock_dir: $!\n";
3191
 
                return 1;
3192
 
        }
3193
 
        my @files = grep { !/^\.\.?$/ && !/^install\.lock/ && !/^$mypid-\d+$/ }
3194
 
                                         readdir(DIR);
3195
 
        closedir(DIR);
3196
 
 
3197
 
        my $file;
3198
 
        foreach $file (@files) {
3199
 
                if (!open( F, "<$conf::srcdep_lock_dir/$file" )) {
3200
 
                        print PLOG "Cannot open $conf::srcdep_lock_dir/$file: $!\n";
3201
 
                        next;
3202
 
                }
3203
 
                <F> =~ /^(\S+)\s+(\S+)\s+(\S+)/;
3204
 
                my ($job, $pid, $user) = ($1, $2, $3);
3205
 
 
3206
 
                # ignore (and remove) a lock file if associated process doesn't exist
3207
 
                # anymore
3208
 
                if (kill( 0, $pid ) == 0 && $! == ESRCH) {
3209
 
                        close( F );
3210
 
                        print PLOG "Found stale srcdep lock file $file -- removing it\n";
3211
 
                        print PLOG "Cannot remove: $!\n"
3212
 
                                if !unlink( "$conf::srcdep_lock_dir/$file" );
3213
 
                        next;
3214
 
                }
3215
 
 
3216
 
                print "Reading srclock file $file by job $job user $user\n"
3217
 
                        if $main::debug;
3218
 
 
3219
 
                while( <F> ) {
3220
 
                        my ($neg, $pkg) = /^(!?)(\S+)/;
3221
 
                        print "Found ", ($neg ? "neg " : ""), "entry $pkg\n"
3222
 
                                if $main::debug;
3223
 
 
3224
 
                        if ($pkg =~ /^\*/) {
3225
 
                                print PLOG "Build of $job by $user (pid $pid) has ",
3226
 
                                                   "installed the global special dependency $pkg.\n";
3227
 
                                $conflict_builds{$file} = 1;
3228
 
                        }
3229
 
                        else {
3230
 
                                if (isin( $pkg, @$to_inst, @$to_remove )) {
3231
 
                                        print PLOG "Source dependency conflict with build of ",
3232
 
                                                           "$job by $user (pid $pid):\n";
3233
 
                                        print PLOG "  $job ", ($neg ? "conflicts with" : "needs"),
3234
 
                                                           " $pkg\n";
3235
 
                                        print PLOG "  $main::current_job wants to ",
3236
 
                                                           (isin( $pkg, @$to_inst ) ? "update" : "remove"),
3237
 
                                                           " $pkg\n";
3238
 
                                        $conflict_builds{$file} = 1;
3239
 
                                }
3240
 
                        }
3241
 
                }
3242
 
                close( F );
3243
 
        }
3244
 
 
3245
 
        foreach (@$special) {
3246
 
                if ($main::specials{$_}->{'global'} =~ /yes/m) {
3247
 
                        print PLOG "$main::current_job wants to apply global ",
3248
 
                                           "special dependency $_\n",
3249
 
                                           "Must wait for other builds to finish\n";
3250
 
                        foreach (@files) {
3251
 
                                $conflict_builds{$_} = 1;
3252
 
                        }
3253
 
                }
3254
 
        }
3255
 
 
3256
 
        my @conflict_builds = keys %conflict_builds;
3257
 
        if (@conflict_builds) {
3258
 
                print "Srcdep conflicts with: @conflict_builds\n" if $main::debug;
3259
 
        }
3260
 
        else {
3261
 
                print "No srcdep conflicts\n" if $main::debug;
3262
 
        }
3263
 
        return @conflict_builds;
3264
 
}
3265
 
 
3266
 
sub remove_srcdep_lock_file {
3267
 
        my $f = "$conf::srcdep_lock_dir/$$-$main::srcdep_lock_cnt";
3268
 
 
3269
 
        print "Removing srcdep lock file $f\n" if $main::debug;
3270
 
        if (!unlink( $f )) {
3271
 
                print "Warning: cannot remove srcdep lock file $f: $!\n"
3272
 
                        if $! != ENOENT;
3273
 
        }
3274
 
}
3275
 
 
3276
 
sub prepare_watches {
3277
 
        my $dependencies = shift;
3278
 
        my @instd = @_;
3279
 
        my(@dep_on, $dep, $pkg, $prg);
3280
 
 
3281
 
        @dep_on = @instd;
3282
 
        foreach $dep (@$dependencies, @$main::additional_deps) {
3283
 
                if ($dep->{'Neg'} && $dep->{'Package'} =~ /^needs-no-(\S+)/) {
3284
 
                        push( @dep_on, $1 );
3285
 
                }
3286
 
                elsif ($dep->{'Package'} !~ /^\*/ && !$dep->{'Neg'}) {
3287
 
                        foreach (scalar($dep), @{$dep->{'Alternatives'}}) {
3288
 
                                push( @dep_on, $_->{'Package'} );
3289
 
                        }
3290
 
                }
3291
 
        }
3292
 
        # init %this_watches to names of packages which have not been installed as
3293
 
        # source dependencies
3294
 
        undef %main::this_watches;
3295
 
        foreach $pkg (keys %conf::watches) {
3296
 
                if (isin( $pkg, @dep_on )) {
3297
 
                        print "Excluding from watch: $pkg\n" if $main::debug;
3298
 
                        next;
3299
 
                }
3300
 
                foreach $prg (@{$conf::watches{$pkg}}) {
3301
 
                        $prg = "/usr/bin/$prg" if $prg !~ m,^/,;
3302
 
                        $main::this_watches{"$main::chroot_dir$prg"} = $pkg;
3303
 
                        print "Will watch for $prg ($pkg)\n" if $main::debug;
3304
 
                }
3305
 
        }
3306
 
}
3307
 
 
3308
 
sub check_watches {
3309
 
        my($prg, @st, %used);
3310
 
 
3311
 
        foreach $prg (keys %main::this_watches) {
3312
 
                if (!(@st = stat( $prg ))) {
3313
 
                        print "Watch: $prg: stat failed\n" if $main::debug;
3314
 
                        next;
3315
 
                }
3316
 
                if ($st[8] > $main::build_start_time) {
3317
 
                        my $pkg = $main::this_watches{$prg};
3318
 
                        my $prg2 = $prg;
3319
 
                        $prg2 =~ s/^\Q$main::chroot_dir\E// if $main::chroot_dir;
3320
 
                        push( @{$used{$pkg}}, $prg2 )
3321
 
                                if @main::have_dsc_build_deps ||
3322
 
                                   !isin( $pkg, @conf::ignore_watches_no_build_deps );
3323
 
                }
3324
 
                else {
3325
 
                        print "Watch: $prg: untouched\n" if $main::debug;
3326
 
                }
3327
 
        }
3328
 
        return if !%used;
3329
 
 
3330
 
        print PLOG <<EOF;
3331
 
 
3332
 
NOTE: The package could have used binaries from the following packages
3333
 
(access time changed) without a source dependency:
3334
 
EOF
3335
 
        foreach (keys %used) {
3336
 
                print PLOG "  $_: @{$used{$_}}\n";
3337
 
        }
3338
 
        print PLOG "\n";
3339
 
}
3340
 
 
3341
 
sub should_skip {
3342
 
        my $pkgv = shift;
3343
 
 
3344
 
        fixup_pkgv( \$pkgv );
3345
 
        lock_file( "SKIP" );
3346
 
        goto unlock if !open( F, "SKIP" );
3347
 
        my @pkgs = <F>;
3348
 
        close( F );
3349
 
 
3350
 
        if (!open( F, ">SKIP" )) {
3351
 
                print "Can't open SKIP for writing: $!\n",
3352
 
                          "Would write: @pkgs\nminus $pkgv\n";
3353
 
                goto unlock;
3354
 
        }
3355
 
        my $found = 0;
3356
 
        foreach (@pkgs) {
3357
 
                if (/^\Q$pkgv\E$/) {
3358
 
                        ++$found;
3359
 
                        print PLOG "$pkgv found in SKIP file -- skipping building it\n";
3360
 
                }
3361
 
                else {
3362
 
                        print F $_;
3363
 
                }
3364
 
        }
3365
 
        close( F );
3366
 
  unlock:
3367
 
        unlock_file( "SKIP" );
3368
 
        return $found;
3369
 
}
3370
 
 
3371
 
sub add_givenback {
3372
 
        my $pkgv = shift;
3373
 
        my $time = shift;
3374
 
        local( *F );
3375
 
 
3376
 
        lock_file( "SBUILD-GIVEN-BACK" );
3377
 
 
3378
 
        if (open( F, ">>SBUILD-GIVEN-BACK" )) {
3379
 
                print F "$pkgv $time\n";
3380
 
                close( F );
3381
 
        }
3382
 
        else {
3383
 
                print PLOG "Can't open SBUILD-GIVEN-BACK: $!\n";
3384
 
        }
3385
 
 
3386
 
  unlock:
3387
 
        unlock_file( "SBUILD-GIVEN-BACK" );
3388
 
}
3389
 
 
3390
 
sub send_mail {
3391
 
        my $to = shift;
3392
 
        my $subject = shift;
3393
 
        my $file = shift;
3394
 
        local( *MAIL, *F );
3395
 
 
3396
 
        if (!open( F, "<$file" )) {
3397
 
                warn "Cannot open $file for mailing: $!\n";
3398
 
                return 0;
3399
 
        }
3400
 
        local $SIG{'PIPE'} = 'IGNORE';
3401
 
        
3402
 
        if (!open( MAIL, "|$conf::mailprog -oem $to" )) {
3403
 
                warn "Could not open pipe to $conf::mailprog: $!\n";
3404
 
                close( F );
3405
 
                return 0;
3406
 
        }
3407
 
 
3408
 
        print MAIL "Subject: $subject\n\n";
3409
 
        while( <F> ) {
3410
 
                print MAIL "." if $_ eq ".\n";
3411
 
                print MAIL $_;
3412
 
        }
3413
 
        
3414
 
        close( F );
3415
 
        if (!close( MAIL )) {
3416
 
                warn "$conf::mailprog failed (exit status $?)\n";
3417
 
                return 0;
3418
 
        }
3419
 
        return 1;
3420
 
}
3421
 
 
3422
 
 
3423
 
sub set_installed {
3424
 
        foreach (@_) {
3425
 
                $main::changes->{'installed'}->{$_} = 1;
3426
 
        }
3427
 
        print "Added to installed list: @_\n" if $main::debug;
3428
 
}
3429
 
 
3430
 
sub set_removed {
3431
 
        foreach (@_) {
3432
 
                $main::changes->{'removed'}->{$_} = 1;
3433
 
                if (exists $main::changes->{'installed'}->{$_}) {
3434
 
                        delete $main::changes->{'installed'}->{$_};
3435
 
                        $main::changes->{'auto-removed'}->{$_} = 1;
3436
 
                        print "Note: $_ was installed\n" if $main::debug;
3437
 
                }
3438
 
        }
3439
 
        print "Added to removed list: @_\n" if $main::debug;
3440
 
}
3441
 
 
3442
 
sub unset_installed {
3443
 
        foreach (@_) {
3444
 
                delete $main::changes->{'installed'}->{$_};
3445
 
        }
3446
 
        print "Removed from installed list: @_\n" if $main::debug;
3447
 
}
3448
 
 
3449
 
sub unset_removed {
3450
 
        foreach (@_) {
3451
 
                delete $main::changes->{'removed'}->{$_};
3452
 
                if (exists $main::changes->{'auto-removed'}->{$_}) {
3453
 
                        delete $main::changes->{'auto-removed'}->{$_};
3454
 
                        $main::changes->{'installed'}->{$_} = 1;
3455
 
                        print "Note: revived $_ to installed list\n" if $main::debug;
3456
 
                }
3457
 
        }
3458
 
        print "Removed from removed list: @_\n" if $main::debug;
3459
 
}
3460
 
 
3461
 
sub basename {
3462
 
        my $b = $_[0];
3463
 
        $b =~ s,^.*/,,;
3464
 
        return $b;
3465
 
}
3466
 
 
3467
 
sub df {
3468
 
        my $dir = shift;
3469
 
 
3470
 
        my $free = `/bin/df $dir | tail -1`;
3471
 
        my @free = split( /\s+/, $free );
3472
 
        return $free[3];
3473
 
}
3474
 
 
3475
 
sub isin {
3476
 
        my $val = shift;
3477
 
        return grep( $_ eq $val, @_ );
3478
 
}
3479
 
 
3480
 
sub fixup_pkgv {
3481
 
        my $pkgv = shift;
3482
 
        
3483
 
        $$pkgv =~ s,^.*/,,; # strip path
3484
 
        $$pkgv =~ s/\.(dsc|diff\.gz|tar\.gz|deb)$//; # strip extension
3485
 
        $$pkgv =~ s/_[a-zA-Z\d+~-]+\.(changes|deb)$//; # strip extension
3486
 
}
3487
 
 
3488
 
sub format_deps {
3489
 
        return join( ", ",
3490
 
                   map { join( "|",
3491
 
                                 map { ($_->{'Neg'} ? "!" : "") .
3492
 
                                           $_->{'Package'} .
3493
 
                                           ($_->{'Rel'} ? " ($_->{'Rel'} $_->{'Version'})":"")}
3494
 
                                 scalar($_), @{$_->{'Alternatives'}}) } @_ );
3495
 
}
3496
 
 
3497
 
sub lock_file {
3498
 
        my $file = shift;
3499
 
        my $for_srcdep = shift;
3500
 
        my $lockfile = "$file.lock";
3501
 
        my $try = 0;
3502
 
        
3503
 
  repeat:
3504
 
        if (!sysopen( F, $lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644 )){
3505
 
                if ($! == EEXIST) {
3506
 
                        # lock file exists, wait
3507
 
                        goto repeat if !open( F, "<$lockfile" );
3508
 
                        my $line = <F>;
3509
 
                        my ($pid, $user);
3510
 
                        close( F );
3511
 
                        if ($line !~ /^(\d+)\s+([\w\d.-]+)$/) {
3512
 
                                warn "Bad lock file contents ($lockfile) -- still trying\n";
3513
 
                        }
3514
 
                        else {
3515
 
                                ($pid, $user) = ($1, $2);
3516
 
                                if (kill( 0, $pid ) == 0 && $! == ESRCH) {
3517
 
                                        # process doesn't exist anymore, remove stale lock
3518
 
                                        warn "Removing stale lock file $lockfile ".
3519
 
                                                 " (pid $pid, user $user)\n";
3520
 
                                        unlink( $lockfile );
3521
 
                                        goto repeat;
3522
 
                                }
3523
 
                        }
3524
 
                        ++$try;
3525
 
                        if (!$for_srcdep && $try > $main::max_lock_trys) {
3526
 
                                warn "Lockfile $lockfile still present after ".
3527
 
                                     $main::max_lock_trys*$main::lock_interval.
3528
 
                                         " seconds -- giving up\n";
3529
 
                                return;
3530
 
                        }
3531
 
                        print PLOG "Another sbuild process ($pid by $user) is currently ",
3532
 
                                           "installing or\n",
3533
 
                                           "removing packages -- waiting...\n"
3534
 
                                                   if $for_srcdep && $try == 1;
3535
 
                        sleep $main::lock_interval;
3536
 
                        goto repeat;
3537
 
                }
3538
 
                warn "Can't create lock file $lockfile: $!\n";
3539
 
        }
3540
 
        F->print("$$ $ENV{'LOGNAME'}\n");
3541
 
        F->close();
3542
 
}
3543
 
 
3544
 
sub unlock_file {
3545
 
        my $file = shift;
3546
 
        my $lockfile = "$file.lock";
3547
 
 
3548
 
        unlink( $lockfile );
3549
 
}
3550
 
 
3551
 
sub check_dpkg_version {
3552
 
        my $t = `$conf::dpkg --version`;
3553
 
        my $version = ($t =~ /version\s+(\S+)/)[0];
3554
 
 
3555
 
        $main::new_dpkg = 1
3556
 
                if 0 == system "$conf::dpkg --compare-versions '$version' ge 1.4.1.18";
3557
 
}
3558
 
 
3559
 
sub binNMU_version {
3560
 
        my $v = shift;
3561
 
 
3562
 
        if ($v =~ /^(.*)-([^-]+)$/) {
3563
 
                my ($upstream, $debian) = ($1, $2);
3564
 
                my @parts = split( /\./, $debian );
3565
 
                if (@parts == 1) {
3566
 
                        return "$upstream-$debian.0.$main::binNMUver";
3567
 
                }
3568
 
                elsif (@parts == 2) {
3569
 
                        return "$upstream-$debian.$main::binNMUver";
3570
 
                }
3571
 
                else {
3572
 
                        $parts[$#parts]+=$main::binNMUver;
3573
 
                        return "$upstream-".join( ".", @parts );
3574
 
                }
3575
 
        }
3576
 
        else {
3577
 
                return "$v.0.$main::binNMUver";
3578
 
        }
3579
 
}
3580
 
 
3581
 
sub shutdown {
3582
 
        my $signame = shift;
3583
 
        my($job,@npkgs,@pkgs);
3584
 
        local( *F );
3585
 
 
3586
 
        $SIG{'INT'} = 'IGNORE';
3587
 
        $SIG{'QUIT'} = 'IGNORE';
3588
 
        $SIG{'TERM'} = 'IGNORE';
3589
 
        $SIG{'ALRM'} = 'IGNORE';
3590
 
        $SIG{'PIPE'} = 'IGNORE';
3591
 
        print PLOG "sbuild received SIG$signame -- shutting down\n";
3592
 
        chdir( $main::cwd );
3593
 
 
3594
 
        goto not_ni_shutdown if !$main::batchmode;
3595
 
        
3596
 
        # most important: dump out names of unfinished jobs to REDO
3597
 
        foreach $job (@ARGV) {
3598
 
                my $job2 = $job;
3599
 
                fixup_pkgv( \$job2 );
3600
 
                push( @npkgs, $job2 )
3601
 
                        if !$main::job_state{$job} || $job eq $main::current_job;
3602
 
        }
3603
 
        print LOG "The following jobs were not finished: @npkgs\n";
3604
 
 
3605
 
        my $f = "$main::HOME/build/REDO";
3606
 
        if (-f "$main::HOME/build/REDO.lock") {
3607
 
                # if lock file exists, write to a different file -- timing may
3608
 
                # be critical
3609
 
                $f = "$main::HOME/build/REDO2";
3610
 
        }
3611
 
        if (open( F, "<$f" )) {
3612
 
                @pkgs = <F>;
3613
 
                close( F );
3614
 
        }
3615
 
        if (open( F, ">>$f" )) {
3616
 
                foreach $job (@npkgs) {
3617
 
                        next if grep( /^\Q$job\E\s/, @pkgs );
3618
 
                        print F "$job $main::distribution $main::component\n";
3619
 
                }
3620
 
                close( F );
3621
 
        }
3622
 
        else {
3623
 
                print "Cannot open $f: $!\n";
3624
 
        }
3625
 
        open( F, ">SBUILD-REDO-DUMPED" );
3626
 
        close( F );
3627
 
        print LOG "SBUILD-REDO-DUMPED created\n";
3628
 
        unlink( "SBUILD-FINISHED" );
3629
 
 
3630
 
        # next: say which packages should be uninstalled
3631
 
        @pkgs = keys %{$main::changes->{'installed'}};
3632
 
        if (@pkgs) {
3633
 
                if (open( F, ">>NEED-TO-UNINSTALL" )) {
3634
 
                        print F "@pkgs\n";
3635
 
                        close( F );
3636
 
                }
3637
 
                print "The following packages still need to be uninstalled ",
3638
 
                          "(--purge):\n@pkgs\n";
3639
 
        }
3640
 
        
3641
 
  not_ni_shutdown:
3642
 
        # next: kill currently running command (if one)
3643
 
        if ($main::sub_pid) {
3644
 
                print "Killing $main::sub_task subprocess $main::sub_pid\n";
3645
 
                system "$conf::sudo perl -e 'kill( -15, $main::sub_pid )'";
3646
 
        }
3647
 
        remove_srcdep_lock_file();
3648
 
 
3649
 
        # close logs and send mails
3650
 
        if ( $main::current_job ) {
3651
 
                fixup_pkgv( \$main::current_job );
3652
 
                close_pkg_log( $main::current_job );
3653
 
        }
3654
 
        close_log();
3655
 
        unlink( $main::jobs_file ) if $main::batchmode;
3656
 
        $? = 0; $! = 0;
3657
 
        exit 0;
3658
 
}