Merge lp:~cjwatson/britney/honour-updates into lp:britney

Proposed by Colin Watson
Status: Superseded
Proposed branch: lp:~cjwatson/britney/honour-updates
Merge into: lp:britney
Diff against target: 7270 lines (+7121/-0) (has conflicts)
28 files modified
README (+107/-0)
britney (+491/-0)
fauxpkg/FauxPackages (+59/-0)
fauxpkg/README (+50/-0)
fauxpkg/fauxpkg.py (+181/-0)
fauxpkg/noremove.d/README (+3/-0)
scripts/backlog-report (+86/-0)
scripts/ood_report.py (+101/-0)
scripts/udeb-report (+49/-0)
update_out/.gitignore (+6/-0)
update_out/Makefile (+33/-0)
update_out/README (+32/-0)
update_out/assert.c (+11/-0)
update_out/britney-py.c (+871/-0)
update_out/checklib.c (+185/-0)
update_out/dpkg-lib.cpp (+34/-0)
update_out/dpkg.c (+2013/-0)
update_out/dpkg.h (+207/-0)
update_out/freelist.c (+188/-0)
update_out/freelist.h (+14/-0)
update_out/index.html (+18/-0)
update_out/memory.c (+389/-0)
update_out/memory.h (+47/-0)
update_out/memory2.c (+20/-0)
update_out/memory3.c (+209/-0)
update_out/templates.h (+277/-0)
update_out/thoughts (+13/-0)
update_out/update_out.py (+1427/-0)
Text conflict in README
To merge this branch: bzr merge lp:~cjwatson/britney/honour-updates
Reviewer Review Type Date Requested Status
Ubuntu Package Archive Administrators Pending
Review via email: mp+250308@code.launchpad.net

This proposal has been superseded by a proposal from 2015-02-19.

Commit message

Include $SERIES-updates in the baseline Sources/Packages data files.

Description of the change

For stable releases, we need to include $SERIES-updates in the baseline Sources/Packages data files that britney.py itself uses for suite comparison, because -proposed is allowed to depend on things only in -updates. I've checked that britney2 uses the highest version of a package it finds in any suite.

To post a comment you must log in.

Unmerged revisions

275. By Colin Watson

Include $SERIES-updates in the baseline Sources/Packages data files.

274. By Steve Langasek

Merge lp:~cjwatson/britney/output-prefix

273. By Steve Langasek

Merge lp:~cjwatson/britney/sru-config

272. By Colin Watson

Publish update_excuses.yaml and archive copies of it.

271. By Colin Watson

adjust for new delta file name

270. By Colin Watson

FauxPackages: add ubuntu-emulator-images on amd64 and armhf, normally provided via multiarch

269. By Colin Watson

Change DEFAULT_NOREMOVE_ARCH to amd64.

268. By Colin Watson

utopic → vivid

267. By Colin Watson

FauxPackages: use ${unstable-version} more liberally

266. By Colin Watson

${unstable-version} needs Source if Source != Package

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README'
2--- README 2006-06-17 13:45:56 +0000
3+++ README 2015-02-19 13:49:56 +0000
4@@ -1,5 +1,112 @@
5+<<<<<<< TREE
6 README for britney v2.0
7 =======================
8
9 Please write here some useful stuff.
10
11+=======
12+Britney is run from /org/release.debian.org/britney. Some notes about
13+how it works, what to do and what not:
14+
15+ * the code is in code/b1, which is a git repo. Changes must be
16+ approved by Release Managers first, and all changes must be commited
17+ (i.e. nothing uncommited is allowed there).
18+
19+ Commit emails will be send to britney@release.debian.org, you can
20+ subscribe to that if you want them (along with cron mail from
21+ britney).
22+
23+ * the main script is code/b1/britney. It accepts a list of "actions"
24+ to perform. See ~release/etc/crontab.release for the default list,
25+ and see the "Actions" and "Re-running" sections below.
26+
27+ * input/ contains FauxPackages, edit if if you need, and an urgencies/
28+ subdirectory where dinstall places a summary of the uploads of that
29+ day.
30+
31+ * Heidi/, ssh/: see the "save" action below.
32+
33+ * d-i/: udeb handling is done by the release team too. See d-i/README
34+ for details (when Dato writes it; Dato takes care of udebs until then).
35+
36+
37+Actions
38+=======
39+
40+The main actions (read, the ones that are invoked from cron) are:
41+
42+ * urgencies: updates var/data/testing/Urgency with the data provided
43+ by dinstall.
44+
45+ * bugs: fetches bug counts from bugs.debian.org.
46+
47+ * pkglists: generates all needed Packages files according to the
48+ latest dinstall.
49+
50+ * run: the main action, running the update_out.py script. Takes
51+ hints, packages files, and tries to migrate stuff. When done, it
52+ writes a HeidiResult file used by "save" below *and rewrites the
53+ var/data/testing/Packags_* files*. That is important.
54+
55+ * save: commits the HeidiResult provided by update_out above. This is
56+ done by:
57+
58+ - taking HeidiResult, stripping unwanted stuff (faux packages),
59+ and put the result into a file under Heidi/set, named after the
60+ current timestamp.
61+
62+ - changing the "current" symlink under Heidi/set to point to this
63+ new file, gzipping the previous current.
64+
65+ - signaling ftpmaster scripts to import the new file. This is done
66+ with a ssh trigger, whose key is in ssh/.
67+
68+ IF YOU NEED TO UNDO ONE IMPORT: gunzip the previous file, point
69+ the "current" symlink to it, and:
70+
71+ % ssh -2 -i % ~release/britney/ssh/ftp-master_trigger_key dak@ries.debian.org
72+
73+ * stats: copies the resulting update.OUTPUT and update.EXCUSES files
74+ to www/britney, and checks for uninstallabilities.
75+
76+
77+Re-running
78+==========
79+
80+Re-runs can be incremental or not:
81+
82+ * incremental means that you run britney against the results of the
83+ previous run. This is done by just issuing `./britney run`.
84+
85+ WARNING: even if you don't save the results of an incremental
86+ re-run, following re-runs will start with the state the previous one
87+ left. This means it's a very very bad idea to use incremental
88+ re-runs to test force-hint hints; please always use a private
89+ britney instead.
90+
91+ * non-incremental means that you start from scratch against the state
92+ of the previous install. To do this, you need to do "pkglists" prior
93+ to "run".
94+
95+ IF THERE WERE ANY SUCCESSFUL HINTS IN THE PREVIOUS RUN, YOU MUST
96+ CHECK WITH THEIR OWNERS WHETHER IT'S OK TO RUN FROM SCRATCH. Or, in
97+ the worst case, you should check whether they have cleaned up their
98+ hints already, since in that case their work will be lost.
99+
100+ (For this reason it's not very wise to clean your hints before your
101+ stuff is dinstalled.)
102+
103+If you're satisfied with the result of your re-run, run `./britney save`.
104+
105+
106+Private britneys
107+================
108+
109+It is ok to run private britneys if you nice them, though Ganneff
110+prefers if you don't do it while dinstall is running.
111+
112+Do NOT run your britney against britney/var/data directly, use a
113+copy of your own.
114+
115+TODO(dato): Some HOWTO here.
116+>>>>>>> MERGE-SOURCE
117
118=== added file 'britney'
119--- britney 1970-01-01 00:00:00 +0000
120+++ britney 2015-02-19 13:49:56 +0000
121@@ -0,0 +1,491 @@
122+#!/bin/bash
123+
124+set -e
125+set -u
126+
127+ulimit -d 8000000 -m 8000000 -v 8000000
128+umask 002
129+
130+
131+OPTIONS="$@"
132+qoption () {
133+ for a in $OPTIONS; do if [ "$a" = "$1" ]; then return 0; fi; done
134+ return 1
135+}
136+
137+option () {
138+ for a in $OPTIONS; do if [ "$a" = "$1" ]; then date -uR; return 0; fi; done
139+ return 1
140+}
141+
142+LP_SERVICE="${LP_SERVICE:-production}"
143+DISTRIBUTION="${DISTRIBUTION:-ubuntu}"
144+DEFAULT_SERIES=vivid
145+SERIES="${SERIES:-$DEFAULT_SERIES}"
146+
147+# DATE
148+NOW=`date +"%F/%T" -u`
149+
150+# Dirs:
151+BASE=/home/ubuntu-archive/proposed-migration
152+DAK_LOCKDIR=/srv/ftp-master.debian.org/lock
153+FTP_MIRROR=/home/ubuntu-archive/mirror/$DISTRIBUTION
154+
155+D_I=$BASE/d-i
156+VAR=$BASE/var
157+SSH=$BASE/ssh
158+HEIDI=$BASE/Heidi
159+INPUT=$BASE/input
160+CODE=$BASE/code/b1
161+
162+DATA=$VAR/data
163+LOCKDIR=$VAR/lock
164+HEIDI_SET=$HEIDI/set
165+SCRIPTS=$CODE/scripts
166+FAUXDIR=$CODE/fauxpkg
167+UPDATE_OUT=$CODE/update_out
168+URGENCIES=$INPUT/urgencies
169+
170+LOCK=$LOCKDIR/britney-$DISTRIBUTION.lock
171+DAK_LOCK=$DAK_LOCKDIR/daily.lock
172+DAK_STOP=$DAK_LOCKDIR/archive.stop
173+
174+TESTING=$DATA/$SERIES
175+UNSTABLE=$DATA/$SERIES-proposed
176+TPU=$DATA/testing-proposed-updates
177+
178+FAUXPKG_SCRIPT=$FAUXDIR/fauxpkg.py
179+SSH_KEY=$SSH/ftp-master_trigger_key
180+
181+HTML=/home/ubuntu-archive/public_html/proposed-migration
182+if [ "$DISTRIBUTION" != ubuntu ]; then
183+ HTML="$HTML/$DISTRIBUTION"
184+fi
185+BOOTSTRAP_DIR=/home/ubuntu-archive/public_html/bootstrap
186+
187+# Britney 2
188+DATA_B2=$VAR/data-b2
189+CODE_B2=$BASE/code/b2
190+B2_OUTPUT=$DATA_B2/output
191+B2_CONFIG=${B2_CONFIG:-$CODE_B2/britney.conf}
192+B2_CONFIG_NOBREAKALL=${B2_CONFIG_NOBREAKALL:-$CODE_B2/britney_nobreakall.conf}
193+
194+if [ -f $DAK_STOP ]; then
195+ echo "$DAK_STOP exists, not running"
196+ exit 1
197+fi
198+
199+# 10800 seconds = 3 hours
200+# 129600 seconds = 36 hours
201+if ! lockfile -r0 -l129600 $LOCK 2>/dev/null >/dev/null; then
202+ echo "Could not get britney lockfile!"
203+ ls -l "$LOCK"
204+ exit 1
205+fi
206+
207+trap exit_function 0
208+exit_function () {
209+ rm -f $LOCK
210+}
211+
212+#eval $( dak admin config db-shell )
213+
214+suite_arches () {
215+ python -c '
216+from __future__ import print_function
217+
218+import os
219+import sys
220+
221+from launchpadlib.launchpad import Launchpad as _Launchpad
222+
223+# Work around non-multiple-instance-safety of launchpadlib (bug #459418).
224+class Launchpad(_Launchpad):
225+ @classmethod
226+ def _get_paths(cls, service_root, launchpadlib_dir=None):
227+ service_root, launchpadlib_dir, cache_path, service_root_dir = (
228+ _Launchpad._get_paths(
229+ service_root, launchpadlib_dir=launchpadlib_dir))
230+ cache_path += "-proposed-migration"
231+ if not os.path.exists(cache_path):
232+ os.makedirs(cache_path, 0o700)
233+ return service_root, launchpadlib_dir, cache_path, service_root_dir
234+
235+launchpad = Launchpad.login_anonymously("proposed-migration", sys.argv[1])
236+distro = launchpad.distributions[sys.argv[2]]
237+series_name = sys.argv[3].split("-")[0]
238+series = distro.getSeries(name_or_version=series_name)
239+print(" ".join(arch.architecture_tag for arch in series.architectures))
240+' "$LP_SERVICE" "$DISTRIBUTION" "$1"
241+}
242+
243+if ! qoption allowdaklock; then
244+ while [ -f $DAK_LOCK ]; do
245+ echo `date` $DAK_LOCK exists. Sleeping in 10 more minutes.
246+ sleep 600
247+ done
248+fi
249+
250+urgencies () {
251+ echo URGENCIES:
252+ cd $BASE
253+ for u in $URGENCIES/install-urgencies-*; do
254+ [ -e "$u" ] || continue
255+ cat "$u" >> $1/$SERIES/Urgency # XXX I'd rather not have this in $DATA --dato
256+ rm "$u"
257+ done
258+}
259+
260+if option urgencies; then
261+ urgencies $DATA_B2
262+fi
263+
264+bugs () {
265+ for suite in $SERIES $SERIES-proposed; do
266+ x="$1/${suite}/BugsV"
267+ wget --quiet -O "${x}.new" http://bugs.debian.org/release-critical/britney/${suite}-nr
268+ if [ -s ${x}.new ]; then mv ${x}.new $x; else rm $x.new; exit 1; fi
269+ done
270+}
271+if option bugs; then
272+ echo BUGS:
273+ bugs $DATA_B2
274+fi
275+
276+if option bugs_b1; then
277+ echo BUGS_B1:
278+ bugs $DATA
279+fi
280+
281+if option bugs_b2; then
282+ echo BUGS_B2:
283+ bugs $DATA_B2
284+fi
285+
286+blocks () {
287+ local tags
288+ [ "$DISTRIBUTION" = ubuntu ] || return
289+ mkdir -p "$1/$SERIES-proposed"
290+ if [ "$SERIES" = "$DEFAULT_SERIES" ]; then
291+ tags="block-proposed block-proposed-$SERIES"
292+ else
293+ tags="block-proposed-$SERIES"
294+ fi
295+ python -c '
296+from __future__ import print_function
297+
298+import calendar
299+import os
300+import sys
301+try:
302+ from urllib.parse import urlsplit
303+except ImportError:
304+ from urlparse import urlsplit
305+
306+from launchpadlib.launchpad import Launchpad as _Launchpad
307+
308+# Work around non-multiple-instance-safety of launchpadlib (bug #459418).
309+class Launchpad(_Launchpad):
310+ @classmethod
311+ def _get_paths(cls, service_root, launchpadlib_dir=None):
312+ service_root, launchpadlib_dir, cache_path, service_root_dir = (
313+ _Launchpad._get_paths(
314+ service_root, launchpadlib_dir=launchpadlib_dir))
315+ cache_path += "-proposed-migration"
316+ if not os.path.exists(cache_path):
317+ os.makedirs(cache_path, 0o700)
318+ return service_root, launchpadlib_dir, cache_path, service_root_dir
319+
320+launchpad = Launchpad.login_with("proposed-migration", sys.argv[1])
321+distro = launchpad.distributions[sys.argv[2]]
322+tags = sys.argv[3].split()
323+for task in distro.searchTasks(omit_targeted=False, tags=tags):
324+ target = task.target
325+ bug = task.bug
326+ if urlsplit(target.resource_type_link).fragment in (
327+ "distribution_source_package", "source_package"):
328+ for action in reversed(
329+ [a for a in bug.activity if a.whatchanged == "tags"]):
330+ oldtags = action.oldvalue.split()
331+ newtags = action.newvalue.split()
332+ gained_block = False
333+ for tag in tags:
334+ if tag not in oldtags and tag in newtags:
335+ gained_block = True
336+ break
337+ if gained_block:
338+ date = action.datechanged
339+ break
340+ else:
341+ date = bug.date_created
342+ print("%s %d %d" %
343+ (os.path.basename(target.self_link), bug.id,
344+ calendar.timegm(date.timetuple())))
345+' "$LP_SERVICE" "$DISTRIBUTION" "$tags" >"$1/$SERIES-proposed/Blocks.new"
346+ mv "$1/$SERIES-proposed/Blocks.new" "$1/$SERIES-proposed/Blocks"
347+}
348+if option blocks; then
349+ echo BLOCKS:
350+ blocks $DATA_B2
351+fi
352+
353+pkg_lists () {
354+ for suite in $SERIES $SERIES-proposed; do
355+ mkdir -p $1/$suite
356+ suite_dirs=$FTP_MIRROR/dists/$suite
357+ if [ "$suite" = "$SERIES" ]; then
358+ suite_dirs="$suite_dirs $FTP_MIRROR/dists/$SERIES-updates"
359+ fi
360+ >$1/$suite/Sources
361+ for suite_dir in $suite_dirs; do
362+ gzip -t $suite_dir/{main,restricted,universe,multiverse}/source/Sources.gz
363+ zcat $suite_dir/{main,restricted,universe,multiverse}/source/Sources.gz >>$1/$suite/Sources
364+ done
365+ for arch in `suite_arches $suite`; do
366+ >$1/$suite/Packages_$arch
367+ for suite_dir in $suite_dirs; do
368+ gzip -t $suite_dir/{main,restricted,universe,multiverse}/binary-$arch/Packages.gz
369+ zcat $suite_dir/{main,restricted,universe,multiverse}/binary-$arch/Packages.gz >>$1/$suite/Packages_$arch
370+ gzip -t $suite_dir/{main,restricted,universe,multiverse}/debian-installer/binary-$arch/Packages.gz
371+ zcat $suite_dir/{main,restricted,universe,multiverse}/debian-installer/binary-$arch/Packages.gz >>$1/$suite/Packages_$arch
372+ done
373+ done
374+ done
375+ $FAUXPKG_SCRIPT generate $1/$SERIES $1/$SERIES-proposed
376+}
377+
378+lite_sync () {
379+ cat <<EOF | rsync -a --files-from=- $1 $2
380+$SERIES/Dates
381+$SERIES/BugsV
382+$SERIES/Urgency
383+$SERIES-proposed/BugsV
384+$SERIES-proposed/Hints
385+EOF
386+
387+}
388+
389+if option pkglists; then
390+ echo PKGLISTS:
391+ cd $DATA_B2
392+ pkg_lists $DATA_B2
393+fi
394+
395+if option sync_b2; then
396+ rsync -ar $DATA/ $DATA_B2
397+fi
398+
399+# Give options to run a b2 from scratch after b1 has finished
400+if option pkglists_b2; then
401+ echo PKGLISTS_B2:
402+ cd $DATA_B2
403+ pkg_lists $DATA_B2
404+fi
405+
406+if option pkglists_b1; then
407+ echo PKGLISTS_B1:
408+ cd $DATA
409+ pkg_lists $DATA
410+fi
411+
412+if option sync_b2_lite; then
413+ lite_sync $DATA $DATA_B2
414+fi
415+
416+if option sync_b1; then
417+ rsync -ar $DATA_B2/ $DATA
418+fi
419+
420+if option sync_b1_lite; then
421+ lite_sync $DATA_B2 $DATA
422+fi
423+
424+if option hints_bzr; then
425+ echo HINTS_BZR:
426+ if [ "$DISTRIBUTION" = ubuntu ]; then
427+ if [ -d $DATA_B2/$SERIES-proposed/Hints ]; then
428+ bzr pull -q -d $DATA_B2/$SERIES-proposed/Hints
429+ elif [ "$SERIES" = "$DEFAULT_SERIES" ]; then
430+ bzr branch lp:~ubuntu-release/britney/hints-ubuntu $DATA_B2/$SERIES-proposed/Hints
431+ else
432+ bzr branch lp:~ubuntu-sru/britney/hints-ubuntu-$SERIES $DATA_B2/$SERIES-proposed/Hints
433+ fi
434+ if [ -d $DATA_B2/$SERIES-proposed/Hints/ubuntu-touch ]; then
435+ bzr pull -q -d $DATA_B2/$SERIES-proposed/Hints/ubuntu-touch
436+ elif [ "$SERIES" = "$DEFAULT_SERIES" ]; then
437+ bzr branch lp:~ubuntu-touch-release/britney/hints-ubuntu-touch $DATA_B2/$SERIES-proposed/Hints/ubuntu-touch
438+ fi
439+ elif [ "$DISTRIBUTION" = ubuntu-rtm ]; then
440+ if [ -d $DATA_B2/$SERIES-proposed/Hints ]; then
441+ bzr pull -q -d $DATA_B2/$SERIES-proposed/Hints
442+ else
443+ bzr branch lp:~ubuntu-release/britney/hints-ubuntu-rtm $DATA_B2/$SERIES-proposed/Hints
444+ fi
445+ fi
446+ # TODO do something for RTM
447+fi
448+
449+run_b1 () {
450+ cd $UPDATE_OUT
451+ ./update_out.py $TESTING $UNSTABLE $TPU
452+}
453+
454+b2_diff () {
455+ tmp_dir=`mktemp -d`
456+ master="b2"
457+ [ "$master" = "b1" ] && secondary="b2" || secondary="b1"
458+ (cd $tmp_dir
459+
460+ sort $TESTING/HeidiResult >HeidiResult_b1
461+ sort $B2_OUTPUT/$SERIES/HeidiResult >HeidiResult_b2
462+
463+ sed -e '/^<p>Generated: /d' $CODE/update_out/update.EXCUSES_py >excuses_b1.html
464+ sed -e '/^<p>Generated: /d' $B2_OUTPUT/$SERIES/excuses.html >excuses_b2.html
465+
466+ touch -m -r $TESTING/HeidiResult HeidiResult_b1
467+ touch -m -r $B2_OUTPUT/$SERIES/HeidiResult HeidiResult_b2
468+
469+ touch -m -r $CODE/update_out/update.EXCUSES_py excuses_b1.html
470+ touch -m -r $B2_OUTPUT/$SERIES/excuses.html excuses_b2.html
471+
472+ # NB: If you remove the "head" below, add a "|| true"; otherwise
473+ # set -e may not allow the HeidiResult diff to execute.
474+ diff -u excuses_${master}.html excuses_${secondary}.html | head -n 1000
475+ diff -u HeidiResult_${master} HeidiResult_${secondary} | head -n 1000)
476+ rm -rf $tmp_dir
477+}
478+
479+b2_diff_with_mail () {
480+ b2_diff
481+ b2_diff | ifne mail -s "britney2 diff `date -u +'%Y-%m-%d %H:%M'`" \
482+ -a "Reply-To: britney2@release.debian.org" britney2@release.debian.org
483+}
484+
485+run_b2 () {
486+ cd $BASE
487+ $CODE_B2/britney.py -c $B2_CONFIG -v --distribution=$DISTRIBUTION --series=$SERIES
488+}
489+
490+if option run; then
491+ echo RUN:
492+ run_b2
493+fi
494+
495+if option run_b1; then
496+ echo RUN_B1:
497+ run_b1
498+ # assume that this will have been run after a "run" which is b2
499+ b2_diff_with_mail
500+fi
501+
502+if option run_b2; then
503+ echo RUN_B2:
504+ run_b2
505+ b2_diff_with_mail
506+fi
507+
508+if option b2_diff; then
509+ b2_diff
510+fi
511+
512+lp_import() {
513+ # tell LP about the new delta
514+ promote-to-release -l "$LP_SERVICE" -d "$DISTRIBUTION" -s "$SERIES" -v "$1"
515+}
516+
517+save () {
518+ cd $BASE
519+ echo RESULTS:
520+ # process a delta
521+ if [ "$1" = "b1" ]; then
522+ DELTA="$TESTING/HeidiResultDelta"
523+ else
524+ DELTA="$B2_OUTPUT/$SERIES/HeidiResultDelta"
525+ fi
526+ echo Using data from $DELTA
527+ lp_import "$DELTA"
528+ printf " done\n"
529+}
530+
531+if option save_b1; then
532+ save b1
533+fi
534+if option save || option save_b2; then
535+ save b2
536+fi
537+
538+create_uninst_report () {
539+ $CODE_B2/britney.py -c $1 --distribution=$DISTRIBUTION --series=$SERIES --print-uninst >$HTML/$2.new
540+ echo -e "\n# Generated: `date -uR`" >>$HTML/$2.new
541+ mv $HTML/$2.new $HTML/$2
542+}
543+
544+create_ood_report () {
545+ $SCRIPTS/ood_report.py $1 >$HTML/$2.new
546+ echo -e "\n# Generated: `date -uR`" >>$HTML/$2.new
547+ mv $HTML/$2.new $HTML/$2
548+}
549+
550+stats () {
551+ echo STATS:
552+ mkdir -p "$HTML/$SERIES"
553+ if [ "$1" = "b1" ]; then
554+ cp $UPDATE_OUT/update.EXCUSES_py $HTML/$SERIES/update_excuses.html
555+ cp $UPDATE_OUT/update.OUTPUT_py $HTML/$SERIES/update_output.txt
556+ else
557+ cp $DATA_B2/output/$SERIES/excuses.html $HTML/$SERIES/update_excuses.html
558+ cp $DATA_B2/output/$SERIES/excuses.yaml $HTML/$SERIES/update_excuses.yaml
559+ cp $DATA_B2/output/$SERIES/output.txt $HTML/$SERIES/update_output.txt
560+ cp $DATA_B2/$SERIES-proposed/Blocks $HTML/$SERIES/blocks.txt
561+ fi
562+ #gzip -9 < $HTML/$SERIES/update_excuses.html > $HTML/$SERIES/update_excuses.html.gz
563+ #gzip -9 < $HTML/$SERIES/update_output.txt > $HTML/$SERIES/update_output.txt.gz
564+ mkdir -p "$HTML/update_output/$SERIES/${NOW%/*}"
565+ mkdir -p "$HTML/update_excuses/$SERIES/${NOW%/*}"
566+ gzip -9c $HTML/$SERIES/update_output.txt > $HTML/update_output/$SERIES/$NOW.txt.gz
567+ gzip -9c $HTML/$SERIES/update_excuses.html > $HTML/update_excuses/$SERIES/$NOW.html.gz
568+ gzip -9c $HTML/$SERIES/update_excuses.yaml > $HTML/update_excuses/$SERIES/$NOW.yaml.gz
569+
570+ # TODO: {stable,unstable}_uninst.txt -- needs support in b2, talk to Fabio
571+ # TODO: this creates uninstallability reports against b2 results, not b1's
572+ create_uninst_report $B2_CONFIG ${SERIES}_uninst.txt
573+ create_uninst_report $B2_CONFIG_NOBREAKALL ${SERIES}_uninst_full.txt
574+
575+ #if grep -q -e '-meta-faux' $HTML/testing_uninst.txt; then
576+ # echo >&2 'Warning! Some -meta-faux package is uninstallable!'
577+ #fi
578+
579+ #create_ood_report $DATA_B2/stable stable_outdate.txt
580+ #create_ood_report $DATA_B2/testing testing_outdate.txt
581+
582+ $SCRIPTS/backlog-report -o $HTML/$SERIES/update_excuses.csv $HTML/$SERIES/update_excuses.html
583+}
584+
585+if option stats_b1; then
586+ stats b1
587+fi
588+if option stats || option stats_b2; then
589+ stats b2
590+fi
591+
592+if option summary; then
593+ cd $BASE
594+ echo "Out of dates holding up testing:"
595+ TERM=vt100 w3m -dump $HTML/update_excuses.html | sed -n 's/^ *[^ ] *[^ ]*out of date on \([^ ]*\): .*$/\1/p' | sort | uniq -c | sort -n
596+ echo "Uninstallables holding up testing:"
597+ sed < $HTML/update_excuses.html -n 's/^ *<li>[^ ]* (\([^, ]*\),.*) uninstallable.*$/\1/p' | sort | uniq -c | sort -n
598+ #echo "wanna-build stats:"
599+ #for a in alpha arm hppa hurd-i386 i386 ia64 m68k mips mipsel powerpc s390 sparc; do
600+ # printf " %-12s " "$a:"
601+ # /srv/wanna-build/bin/wanna-build-statistics --database=$a/build-db |
602+ # grep "if also counting" || echo "-"
603+ #done
604+fi
605+
606+if option archivedata; then
607+ echo ARCHIVE:
608+ cd $VAR
609+ tar czf data_bkup/data-$(date +"%Y.%m.%d").tgz data/{stable,testing,unstable,testing-proposed-updates}
610+fi
611+
612+echo -n "Finished at: "; date -uR
613
614=== added directory 'fauxpkg'
615=== added file 'fauxpkg/FauxPackages'
616--- fauxpkg/FauxPackages 1970-01-01 00:00:00 +0000
617+++ fauxpkg/FauxPackages 2015-02-19 13:49:56 +0000
618@@ -0,0 +1,59 @@
619+Package: wine1.4-i386
620+Source: wine1.6
621+Version: ${unstable-version}
622+Architecture: amd64
623+Provides: wine-i386
624+Multi-Arch: foreign
625+
626+Package: wine1.6-i386
627+Source: wine1.6
628+Version: ${unstable-version}
629+Architecture: amd64
630+Provides: wine-i386
631+Multi-Arch: foreign
632+
633+Package: nspluginviewer
634+Source: nspluginwrapper
635+Version: ${unstable-version}
636+Architecture: amd64 arm64 armhf powerpc ppc64el
637+Multi-Arch: foreign
638+
639+Package: ocaml-mingw-w64-x86-64
640+Source: mingw-ocaml
641+Version: ${unstable-version}
642+Architecture: i386
643+Multi-Arch: foreign
644+
645+Package: claws-mail-extra-plugins-dbg
646+Version: 1:1
647+
648+Package: claws-mail-html2-viewer
649+Version: 1:1
650+
651+Package: ubuntu-emulator-images
652+Source: android
653+Version: ${unstable-version}
654+Architecture: amd64 armhf
655+Multi-Arch: foreign
656+
657+Package: ubuntu-emulator-runtime
658+Source: android
659+Version: ${unstable-version}
660+Architecture: amd64 armhf
661+Multi-Arch: foreign
662+
663+Package: libnss-mdns-i386
664+Source: nss-mdns
665+Version: ${unstable-version}
666+Architecture: amd64
667+Multi-Arch: foreign
668+
669+Package: unity8
670+Version: ${unstable-version}
671+Architecture: arm64 powerpc ppc64el
672+
673+Package: liboxideqt-qmlplugin
674+Source: oxide-qt
675+Version: ${unstable-version}
676+Architecture: arm64 powerpc ppc64el
677+
678
679=== added file 'fauxpkg/README'
680--- fauxpkg/README 1970-01-01 00:00:00 +0000
681+++ fauxpkg/README 2015-02-19 13:49:56 +0000
682@@ -0,0 +1,50 @@
683+Files and scripts in this directory are in charge on creating a list of
684+"faux" packages for britney. These are packages that do not exist in the
685+archive, but which we want britney to think they exist. At the moment
686+they are used for:
687+
688+ - allowing packages in contrib to migrate even if their dependencies
689+ are not satisfied within the archive. This is done by creating a
690+ faux package for each missing dependency.
691+
692+ - ensure some packages do not get accidentally removed, because they
693+ are needed by parts of testing which don't declare a Depends on
694+ them. In particular, to ensure packages needed by the installer and
695+ tasksel are not removed. This is done by creating faux packages that
696+ do depend on all packages which are not to be removed.
697+
698+To create packages of the first kind, just append suitable entries to
699+the toplevel FauxPackages file. These should have at least a Package and
700+Version fields. You can restrict their existance to certain architectures
701+by providing an Architecture field with a list of architectures. Other
702+fields are propagated verbatim to britney, eg. Provides.
703+
704+As for the second kind, you don't directly create faux packages, but
705+just append the packages which shouldn't be removed to the appropriate
706+file under the "noremove.d" directory. Those files just contain a list
707+of *binary* packages, one per line. A couple of important notes:
708+
709+ - if the binary package is not in testing, do not add it: wait until
710+ it migrates.
711+
712+ - if the binary package is not available on i386 (being arch:all would
713+ suffice), you have to qualify it with [arch], mentioning one arch in
714+ which it is available.
715+
716+ - the names of the files under noremove.d must be valid as package
717+ names, e.g. not contain underscores.
718+
719+The noremove.d/tasksel file is special: it gets generated automatically
720+by the fauxpkg.py script, by running the script with the "update-tasksel"
721+command. (Currently is it to be run by hand whenever the tasksel
722+maintainer notices our file is out of date.)
723+
724+One further caveat: if one of these faux meta-packages becomes uninstallable,
725+they stop working (since the removal of their dependencies does not increase
726+the uninstallability count). The britney script has a mechanism in place to
727+warn in case they become uninstallable. When adding packages to the lists,
728+make sure to watch the next britney mail, in case you added conflicting
729+packages. (In that case, you want to add such packages in different files
730+under noremove.d.)
731+
732+Please don't forget to commit your changes to files in this directory!
733
734=== added file 'fauxpkg/fauxpkg.py'
735--- fauxpkg/fauxpkg.py 1970-01-01 00:00:00 +0000
736+++ fauxpkg/fauxpkg.py 2015-02-19 13:49:56 +0000
737@@ -0,0 +1,181 @@
738+#! /usr/bin/python
739+## encoding: utf-8
740+#
741+# Copyright (c) 2008 Adeodato Simó (dato@net.com.org.es)
742+# Licensed under the terms of the MIT license.
743+
744+"""Handle the creation of britney faux packages.
745+
746+This program gets called from the "britney" script in order to append to the
747+Packages_<arch> files a list of faux packages. This is done with the "generate"
748+command, passing a list of britney suite directories:
749+
750+ % fauxpkg.py generate /home/release/britney/var/data/{testing,unstable}
751+
752+This automatically appeds to the Packages files the list of faux packages. See
753+the README file in this directory for the input files from which such list is
754+generated.
755+"""
756+
757+import os
758+import re
759+import sys
760+import glob
761+import tempfile
762+import subprocess
763+
764+import apt_pkg
765+apt_pkg.init()
766+
767+##
768+
769+BASEDIR = os.path.dirname(__file__)
770+
771+NOREMOVE_DIR = os.path.join(BASEDIR, 'noremove.d')
772+FAUX_PACKAGES = os.path.join(BASEDIR, 'FauxPackages')
773+
774+DEFAULT_NOREMOVE_ARCH = 'amd64'
775+
776+##
777+
778+def main():
779+ if not sys.argv[1:]:
780+ print >>sys.stderr, 'Usage: %s <generate | update-tasksel> [ britney_suite_dir1 ... ]' % (
781+ os.path.basename(sys.argv[0]))
782+ sys.exit(1)
783+ else:
784+ command = sys.argv.pop(1)
785+
786+ if command == 'generate':
787+ if not sys.argv[1:]:
788+ print >>sys.stderr, 'E: need at least one britney suite directory'
789+ sys.exit(1)
790+ else:
791+ do_generate(sys.argv[1:])
792+ elif command == 'update-tasksel':
793+ if sys.argv[1:]:
794+ print >>sys.stderr, 'E: extra arguments not allowed'
795+ sys.exit(1)
796+ else:
797+ do_update_tasksel()
798+ else:
799+ print >>sys.stderr, 'E: unknown command %s' % (command,)
800+
801+##
802+
803+def do_generate(directories):
804+ arches = set()
805+ allfaux = {}
806+
807+ for dir_ in directories:
808+ arches.update([ re.sub(r'^.*/Packages_', '', x)
809+ for x in glob.glob(os.path.join(dir_, 'Packages_*')) ])
810+
811+ unstable_versions = {}
812+ for dir_ in directories:
813+ with open(os.path.join(dir_, 'Sources')) as f:
814+ parser = apt_pkg.TagFile(f)
815+ for section in parser:
816+ if 'Package' in section and 'Version' in section:
817+ unstable_versions[section['Package']] = section['Version']
818+
819+ # First, FauxPackages
820+ try:
821+ parser = apt_pkg.TagFile(file(FAUX_PACKAGES))
822+ step = parser.step
823+ section = parser.section
824+ except AttributeError, e:
825+ parser = apt_pkg.ParseTagFile(file(FAUX_PACKAGES))
826+ step = parser.Step
827+ section = parser.Section
828+ while step():
829+ d = dict(section)
830+ d['Section'] = 'faux' # crucial; britney filters HeidiResult based on section
831+
832+ if not d.has_key('Architecture'):
833+ these_arches = arches
834+ else:
835+ these_arches = set(re.split(r'[, ]+', d['Architecture']))
836+
837+ d['Architecture'] = 'all' # same everywhere
838+
839+ if d.get('Version') == '${unstable-version}':
840+ source = d.get('Source', d.get('Package'))
841+ if source in unstable_versions:
842+ d['Version'] = unstable_versions[source]
843+
844+ for arch in these_arches:
845+ allfaux.setdefault(arch, []).append(d)
846+
847+ # Now, noremove.d
848+ for f in glob.glob(os.path.join(NOREMOVE_DIR, '*.list')):
849+ pkgs = {}
850+ basename = re.sub(r'.+/(.+)\.list', r'\1', f)
851+
852+ for line in file(f):
853+ line = line.strip()
854+ if re.match(r'^#', line):
855+ continue
856+ elif re.match(r'\S+$', line):
857+ pkg = line
858+ arch = DEFAULT_NOREMOVE_ARCH
859+ else:
860+ m = re.match(r'(\S+)\s+\[(.+)\]', line)
861+ if m:
862+ pkg, arch = m.groups()
863+ else:
864+ print >>sys.stderr, 'W: could not parse line %r' % (line,)
865+
866+ arch = re.split(r'[, ]+', arch)[0] # just in case
867+ pkgs.setdefault(arch, set()).add(pkg)
868+
869+ for arch in pkgs.keys():
870+ d = { 'Package': '%s-meta-faux' % (basename,), 'Version': '1',
871+ 'Section': 'faux', 'Architecture': '%s' % (arch,),
872+ 'Depends': ', '.join(pkgs[arch]) }
873+ allfaux.setdefault(arch, []).append(d)
874+
875+ # Write the result
876+ for arch in arches:
877+ if arch not in allfaux:
878+ continue
879+ for dir_ in directories:
880+ f = os.path.join(dir_, 'Packages_' + arch)
881+ if not os.path.exists(f):
882+ continue
883+ else:
884+ f = file(f, 'a')
885+ for d in allfaux[arch]:
886+ f.write('\n'.join('%s: %s' % (k, v) for k, v in d.iteritems()) + '\n\n')
887+
888+##
889+
890+def do_update_tasksel():
891+ p = subprocess.Popen('dak ls -f control-suite -s unstable -a source tasksel',
892+ shell=True, stdout=subprocess.PIPE)
893+ p.wait()
894+ version = p.stdout.readline().split()[1]
895+
896+ p = subprocess.Popen('dak ls -f control-suite -s unstable -S -a i386,all tasksel',
897+ shell=True, stdout=subprocess.PIPE)
898+ p.wait()
899+ tasks = []
900+
901+ for line in p.stdout:
902+ pkg = line.split()[0]
903+
904+ if pkg.startswith('task-'):
905+ tasks.append(pkg)
906+
907+ # Write the new file
908+ tmpfd, tmpname = tempfile.mkstemp(dir=NOREMOVE_DIR)
909+ os.write(tmpfd, '# Generated from tasksel-data %s\n' % (version,))
910+ os.write(tmpfd, '\n'.join(sorted(tasks)) + '\n')
911+ os.close(tmpfd)
912+ os.chmod(tmpname, 0644)
913+ os.rename(tmpname, os.path.join(NOREMOVE_DIR, 'tasksel.list'))
914+
915+##
916+
917+if __name__ == '__main__':
918+ main()
919
920=== added directory 'fauxpkg/noremove.d'
921=== added file 'fauxpkg/noremove.d/README'
922--- fauxpkg/noremove.d/README 1970-01-01 00:00:00 +0000
923+++ fauxpkg/noremove.d/README 2015-02-19 13:49:56 +0000
924@@ -0,0 +1,3 @@
925+Packages listed in these files are protected against accidental removals
926+from testing. Please mail debian-release@lists.debian.org if you think
927+some package should be added to any of these lists.
928
929=== added directory 'scripts'
930=== added file 'scripts/backlog-report'
931--- scripts/backlog-report 1970-01-01 00:00:00 +0000
932+++ scripts/backlog-report 2015-02-19 13:49:56 +0000
933@@ -0,0 +1,86 @@
934+#! /usr/bin/python
935+#
936+# Generate a report of the backlog in -proposed.
937+
938+from __future__ import print_function
939+
940+__metaclass__ = type
941+
942+import calendar
943+import csv
944+import gzip
945+import io
946+from optparse import OptionParser
947+import os
948+import re
949+import sys
950+import time
951+
952+
953+generated_re = re.compile(r"^<p>Generated: (.*)</p>$")
954+
955+
956+def import_excuses(csv_writer, path):
957+ generated_time = None
958+ valid_candidates = 0
959+ not_considered = 0
960+
961+ if path.endswith(".gz"):
962+ binary = gzip.open(path)
963+ else:
964+ binary = io.open(path, mode="rb")
965+ try:
966+ with io.BufferedReader(binary) as buffered:
967+ with io.TextIOWrapper(buffered) as text:
968+ for line in text:
969+ match = generated_re.match(line)
970+ if match:
971+ generated_time = time.strptime(
972+ match.group(1), "%Y.%m.%d %H:%M:%S +0000")
973+ elif line.startswith("<li>Valid candidate"):
974+ valid_candidates += 1
975+ elif line.startswith("<li>Not considered"):
976+ not_considered += 1
977+ finally:
978+ binary.close()
979+
980+ assert generated_time is not None
981+
982+ csv_writer.writerow({
983+ "time": calendar.timegm(generated_time) * 1000,
984+ "valid candidates": valid_candidates,
985+ "not considered": not_considered,
986+ "total": valid_candidates + not_considered,
987+ })
988+
989+
990+def main():
991+ parser = OptionParser(description="Generate a backlog report.")
992+ parser.add_option(
993+ "-o", "--output", help="Write output to this file (default: stdout).")
994+ options, args = parser.parse_args()
995+
996+ if options.output is not None:
997+ csv_is_new = not os.path.exists(options.output)
998+ if sys.version < "3":
999+ output = open(options.output, "ab")
1000+ else:
1001+ output = open(options.output, "a", newline="")
1002+ else:
1003+ csv_is_new = True
1004+ output = sys.stdout
1005+
1006+ try:
1007+ csv_writer = csv.DictWriter(
1008+ output, ["time", "valid candidates", "not considered", "total"])
1009+ if csv_is_new:
1010+ csv_writer.writeheader()
1011+ for arg in args:
1012+ import_excuses(csv_writer, arg)
1013+ finally:
1014+ if options.output is not None:
1015+ output.close()
1016+
1017+
1018+if __name__ == "__main__":
1019+ main()
1020
1021=== added file 'scripts/ood_report.py'
1022--- scripts/ood_report.py 1970-01-01 00:00:00 +0000
1023+++ scripts/ood_report.py 2015-02-19 13:49:56 +0000
1024@@ -0,0 +1,101 @@
1025+#! /usr/bin/python
1026+## encoding: utf-8
1027+#
1028+# Copyright (c) 2008 Adeodato Simó (dato@net.com.org.es)
1029+# Licensed under the terms of the MIT license.
1030+
1031+"""Create a report of packages that are out-of-date in each architecture.
1032+
1033+It expects a single "directory" argument, that should be a britney directory
1034+for a distribution, i.e. containing Packages_<arch> files and Sources.
1035+"""
1036+
1037+import os
1038+import re
1039+import sys
1040+import glob
1041+
1042+import apt_pkg
1043+apt_pkg.init()
1044+
1045+##
1046+
1047+def main():
1048+ if len(sys.argv) != 2:
1049+ print >>sys.stderr, 'Usage: %s <directory>'
1050+ sys.exit(1)
1051+ else:
1052+ directory = sys.argv[1]
1053+
1054+ pkgfiles = glob.glob(os.path.join(directory, 'Packages_*'))
1055+ versions = get_src_versions(os.path.join(directory, 'Sources'))
1056+
1057+ ood = {} # { arch1: { srcpk1: (oldver, [binpkg1, binpkg2, ...]), ... }, ... }
1058+
1059+ for pkgfile in pkgfiles:
1060+ arch = re.sub(r'^.*/Packages_', '', pkgfile)
1061+ try:
1062+ parser = apt_pkg.TagFile(file(pkgfile))
1063+ step = parser.step
1064+ get_section = parser.section
1065+ get_field = parser.section.get
1066+ except AttributeError, e:
1067+ parser = apt_pkg.ParseTagFile(file(pkgfile))
1068+ step = parser.Step
1069+ get_section = parser.Section
1070+ get_field = parser.Section.get
1071+ d = ood[arch] = {}
1072+
1073+ while step():
1074+ pkg = get_section['Package']
1075+ src = get_field('Source') or pkg
1076+
1077+ if ' ' in src:
1078+ m = re.match(r'(\S+) \((\S+)\)$', src)
1079+ src = m.group(1)
1080+ ver = m.group(2)
1081+ else:
1082+ ver = re.sub(r'\+b\d+$', '', get_section['Version'])
1083+
1084+ try:
1085+ distver = versions[src]
1086+ except KeyError:
1087+ pass # faux package
1088+ else:
1089+ if ver != distver:
1090+ d.setdefault(src, (ver, []))[1].append(pkg)
1091+
1092+ arches = sorted(ood.keys())
1093+
1094+ for arch in arches:
1095+ print '* %s' % (arch,)
1096+ for src, (oldver, binpkgs) in sorted(ood[arch].iteritems()):
1097+ # do not print binpkgs, I think it clutters the view too much
1098+ print ' %s (%s)' % (src, oldver)
1099+ print
1100+
1101+ print '* summary'
1102+ print '\n'.join(map(lambda x: '%4d %s' % (len(ood[x]), x), arches))
1103+
1104+##
1105+
1106+def get_src_versions(sources_file):
1107+ """Return a dict { srcname: version, ... }."""
1108+ mydict = {}
1109+ try:
1110+ parser = apt_pkg.TagFile(file(sources_file))
1111+
1112+ while parser.step():
1113+ mydict[parser.section['Package']] = parser.section['Version']
1114+ except AttributeError, e:
1115+ parser = apt_pkg.ParseTagFile(file(sources_file))
1116+
1117+ while parser.Step():
1118+ mydict[parser.Section['Package']] = parser.Section['Version']
1119+
1120+ return mydict
1121+
1122+##
1123+
1124+if __name__ == '__main__':
1125+ main()
1126
1127=== added file 'scripts/udeb-report'
1128--- scripts/udeb-report 1970-01-01 00:00:00 +0000
1129+++ scripts/udeb-report 2015-02-19 13:49:56 +0000
1130@@ -0,0 +1,49 @@
1131+#!/bin/sh
1132+
1133+# Generate a report with out-of-date udebs. Queries come from the
1134+# original "d-i" script by Jeroen van Wolffelaar. Modified not to emit
1135+# output for queries that return 0 rows by Adeodato Simó.
1136+
1137+# TODO(dato): rewrite these queries.
1138+
1139+export PAGER="cat"
1140+
1141+eval $(dak admin config db-shell)
1142+
1143+##
1144+
1145+maybe_print () {
1146+ if ! echo "$2" | grep -q -E '^\(0 rows\)$'; then
1147+ echo "$1"
1148+ echo "$2"
1149+ echo
1150+ fi
1151+}
1152+
1153+maybe_print "udeb's in testing that don't (anymore) correspond to any testing source:" \
1154+"`psql -c \"select b.package, b.version, (SELECT arch_string from
1155+architecture where b.architecture=architecture.id) as arch, s.source from
1156+bin_associations ba LEFT JOIN binaries b on (ba.bin=b.id) LEFT JOIN source s
1157+on (b.source=s.id) WHERE ba.suite=4 AND s.id NOT IN (SELECT source from
1158+src_associations WHERE suite=4) AND b.type = 'udeb' ORDER BY s.source,
1159+b.package, b.architecture;\"`"
1160+
1161+maybe_print "udeb's in unstable that should be in testing too:" \
1162+"`psql -c \"select b.package, b.version, (SELECT arch_string from
1163+architecture where b.architecture=architecture.id) as arch, s.source from
1164+bin_associations ba LEFT JOIN binaries b on (ba.bin=b.id) LEFT JOIN source s
1165+on (b.source=s.id) WHERE ba.suite=5 AND NOT EXISTS (SELECT 1 FROM
1166+bin_associations ba2 WHERE ba2.suite=4 AND ba2.bin=ba.bin) AND s.id IN (SELECT
1167+source from src_associations WHERE suite=4) AND b.type = 'udeb' AND
1168+b.architecture IN (SELECT architecture from suite_architectures where suite = 4)
1169+ORDER BY s.source, b.package, b.architecture;\"`"
1170+
1171+maybe_print "udeb's in t-p-u that should be in testing too:" \
1172+"`psql -c \"select b.package, b.version, (SELECT arch_string from
1173+architecture where b.architecture=architecture.id) as arch, s.source from
1174+bin_associations ba LEFT JOIN binaries b on (ba.bin=b.id) LEFT JOIN source s
1175+on (b.source=s.id) WHERE ba.suite=3 AND NOT EXISTS (SELECT 1 FROM
1176+bin_associations ba2 WHERE ba2.suite=4 AND ba2.bin=ba.bin) AND s.id IN (SELECT
1177+source from src_associations WHERE suite=4) AND b.type = 'udeb' AND
1178+b.architecture IN (SELECT architecture from suite_architectures where suite = 4)
1179+ORDER BY s.source, b.package, b.architecture;\"`"
1180
1181=== added directory 'update_out'
1182=== added file 'update_out/.gitignore'
1183--- update_out/.gitignore 1970-01-01 00:00:00 +0000
1184+++ update_out/.gitignore 2015-02-19 13:49:56 +0000
1185@@ -0,0 +1,6 @@
1186+*.o
1187+*.so
1188+/oldstuff
1189+/Makefile.dep
1190+/update.EXCUSES_py
1191+/update.OUTPUT_py
1192
1193=== added file 'update_out/Makefile'
1194--- update_out/Makefile 1970-01-01 00:00:00 +0000
1195+++ update_out/Makefile 2015-02-19 13:49:56 +0000
1196@@ -0,0 +1,33 @@
1197+
1198+CC = gcc
1199+CXX = g++
1200+CFLAGS = -fPIC -Wall -W -O2 -DNDEBUG -DMDEBUG0 -g -p # -DDIAGNOSE
1201+CXXFLAGS = $(CFLAGS)
1202+
1203+all : britneymodule.so # libajdpkg.a aptvercmp checklib freelist
1204+
1205+clean :
1206+ rm -f *.so *.o *~ Makefile.dep gmon.out
1207+ rm -f freelist aptvercmp checklib libajdpkg.a
1208+
1209+checklib : checklib.o dpkg.o dpkg-lib.o memory3.o freelist.o assert.o
1210+ $(CC) $(CFLAGS) -o checklib $^ -lapt-pkg # -lccmalloc -ldl
1211+
1212+aptvercmp : dpkg-lib.cpp
1213+ $(CXX) $(CFLAGS) -DTESTBIN -o aptvercmp dpkg-lib.cpp -lapt-pkg
1214+
1215+freelist : freelist.c assert.o
1216+ $(CC) $(CFLAGS) -DTESTBIN -o $@ $^
1217+
1218+#libajdpkg.a : dpkg.o dpkg-lib.o memory3.o freelist.o assert.o
1219+# ar rv $@ $^
1220+# ranlib $@
1221+
1222+britneymodule.so : britney-py.o dpkg.o dpkg-lib.o memory3.o freelist.o assert.o
1223+ $(CXX) -shared -o britneymodule.so $^ -lapt-pkg
1224+
1225+Makefile.dep :
1226+ @gcc -MM *.c *.cpp > Makefile.dep
1227+ @echo Makefile.dep : Makefile *.c *.h >> Makefile.dep
1228+
1229+-include Makefile.dep
1230
1231=== added file 'update_out/README'
1232--- update_out/README 1970-01-01 00:00:00 +0000
1233+++ update_out/README 2015-02-19 13:49:56 +0000
1234@@ -0,0 +1,32 @@
1235+
1236+BUILDING
1237+========
1238+
1239+Install libapt-pkg-dev
1240+
1241+testing/ $ make
1242+testing/ $ mkdir old cur out
1243+testing/ $ cd testing
1244+testing/testing/ $ perl Makefile.PL
1245+testing/testing/ $ make
1246+
1247+Add old and new packages files into old and cur, respectively.
1248+
1249+testing/ $ ./checklib i386 alpha
1250+
1251+Will generate some test stuff in out/
1252+
1253+TODO
1254+====
1255+
1256+Need some way of actually updating archives.
1257+Need some way of judging differences between Packages files.
1258+ (so I can see what hasn't been updated and work out why;
1259+ so I can check that Packages.gz matches dpkg-scanpackages output)
1260+Need some way of automatically explaining why packages aren't upgraded.
1261+ (shouldn't be hard?)
1262+
1263+BUGS
1264+====
1265+
1266+out/ directory must exist for checklib, or segfault
1267
1268=== added file 'update_out/assert.c'
1269--- update_out/assert.c 1970-01-01 00:00:00 +0000
1270+++ update_out/assert.c 2015-02-19 13:49:56 +0000
1271@@ -0,0 +1,11 @@
1272+#include <stdio.h>
1273+#include <stdlib.h>
1274+
1275+int _myassertbug(int line, char *file, char *err) {
1276+ fprintf(stderr, "Assertion failed: %s:%d: %s\n", file, line, err);
1277+ fprintf(stderr, "I HATE YOU!!!");
1278+ ((void(*)())0)();
1279+ abort();
1280+ return 0;
1281+}
1282+
1283
1284=== added file 'update_out/britney-py.c'
1285--- update_out/britney-py.c 1970-01-01 00:00:00 +0000
1286+++ update_out/britney-py.c 2015-02-19 13:49:56 +0000
1287@@ -0,0 +1,871 @@
1288+#include <python2.7/Python.h>
1289+
1290+#include "dpkg.h"
1291+
1292+#define MAKE_PY_LIST(L,S,E,I,V) \
1293+ do { \
1294+ L = PyList_New(0); \
1295+ if (!L) break; \
1296+ for (S; E; I) { \
1297+ PyObject *EL; \
1298+ EL = Py_BuildValue V; \
1299+ if (!EL) { \
1300+ Py_DECREF(L); \
1301+ L = NULL; \
1302+ break; \
1303+ } \
1304+ PyList_Append(L, EL); \
1305+ Py_DECREF(EL); \
1306+ } \
1307+ if (L) PyList_Sort(L); \
1308+ } while(0)
1309+
1310+/**************************************************************************
1311+ * britney.Packages -- dpkg_packages wrapper
1312+ *******************************************/
1313+
1314+typedef enum { DONTFREE, FREE } dpkgpackages_freeme;
1315+typedef struct {
1316+ PyObject_HEAD
1317+ dpkg_packages *pkgs;
1318+ PyObject *ref; /* object packages are "in" */
1319+ dpkgpackages_freeme freeme; /* free pkgs when deallocing? */
1320+} dpkgpackages;
1321+
1322+staticforward PyTypeObject Packages_Type;
1323+
1324+static PyObject *dpkgpackages_new(dpkg_packages *pkgs,
1325+ dpkgpackages_freeme freeme, PyObject *ref)
1326+{
1327+ dpkgpackages *res;
1328+
1329+ res = PyObject_NEW(dpkgpackages, &Packages_Type);
1330+ if (res == NULL) return NULL;
1331+
1332+ res->pkgs = pkgs;
1333+ res->ref = ref; Py_INCREF(res->ref);
1334+ res->freeme = freeme;
1335+
1336+ return (PyObject *) res;
1337+}
1338+
1339+static void dpkgpackages_dealloc(dpkgpackages *self) {
1340+ if (self->freeme == FREE) free_packages(self->pkgs);
1341+ Py_XDECREF(self->ref);
1342+ self->pkgs = NULL;
1343+ self->ref = NULL;
1344+ PyObject_DEL(self);
1345+}
1346+
1347+
1348+static dpkg_collected_package *dpkgpackages_lookuppkg(dpkgpackages *self,
1349+ char *pkgname)
1350+{
1351+ dpkg_collected_package *cpkg = NULL;
1352+ cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
1353+ if (!cpkg) {
1354+ PyErr_SetString(PyExc_ValueError, "Not a valid package");
1355+ }
1356+ return cpkg;
1357+}
1358+
1359+static PyObject *dpkgpackages_ispresent(dpkgpackages *self, PyObject *args) {
1360+ dpkg_collected_package *cpkg;
1361+ char *pkgname;
1362+ if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
1363+ cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
1364+ return cpkg ? Py_BuildValue("i", 1) : Py_BuildValue("i", 0);
1365+}
1366+
1367+static PyObject *dpkgpackages_getversion(dpkgpackages *self, PyObject *args) {
1368+ dpkg_collected_package *cpkg;
1369+ char *pkgname;
1370+ if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
1371+ cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
1372+ if (cpkg) return Py_BuildValue("s", cpkg->pkg->version);
1373+ else return Py_BuildValue("");
1374+}
1375+static PyObject *dpkgpackages_getsource(dpkgpackages *self, PyObject *args) {
1376+ dpkg_collected_package *cpkg;
1377+ char *pkgname;
1378+ if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
1379+ cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
1380+ if (cpkg) return Py_BuildValue("s", cpkg->pkg->source);
1381+ else return Py_BuildValue("");
1382+}
1383+static PyObject *dpkgpackages_getsourcever(dpkgpackages *self, PyObject *args) {
1384+ dpkg_collected_package *cpkg;
1385+ char *pkgname;
1386+ if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
1387+ cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
1388+ if (cpkg) return Py_BuildValue("s", cpkg->pkg->source_ver);
1389+ else return Py_BuildValue("");
1390+}
1391+static PyObject *dpkgpackages_isarchall(dpkgpackages *self, PyObject *args) {
1392+ dpkg_collected_package *cpkg;
1393+ char *pkgname;
1394+ if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
1395+ cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
1396+ if (cpkg) return Py_BuildValue("i", cpkg->pkg->arch_all);
1397+ else return Py_BuildValue("");
1398+}
1399+static PyObject *dpkgpackages_isntarchall(dpkgpackages *self, PyObject *args) {
1400+ dpkg_collected_package *cpkg;
1401+ char *pkgname;
1402+ if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
1403+ cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
1404+ if (cpkg) return Py_BuildValue("i", !cpkg->pkg->arch_all);
1405+ else return Py_BuildValue("");
1406+}
1407+static PyObject *dpkgpackages_getfield(dpkgpackages *self, PyObject *args) {
1408+ char *field;
1409+ char *pkgname;
1410+ int i;
1411+ dpkg_collected_package *cpkg;
1412+ dpkg_paragraph *para;
1413+ if (!PyArg_ParseTuple(args, "ss", &pkgname, &field)) return NULL;
1414+ cpkg = dpkgpackages_lookuppkg(self, pkgname);
1415+ if (!cpkg) return NULL;
1416+ para = cpkg->pkg->details;
1417+ for (i = 0; i < para->n_entries; i++) {
1418+ if (strcasecmp(para->entry[i].name, field) == 0) {
1419+ return Py_BuildValue("s", para->entry[i].value);
1420+ }
1421+ }
1422+ return Py_BuildValue("");
1423+}
1424+static PyObject *dpkgpackages_isinstallable(dpkgpackages *self, PyObject *args)
1425+{
1426+ char *pkgname;
1427+ if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
1428+ if (checkinstallable2(self->pkgs, pkgname)) {
1429+ return Py_BuildValue("i", 1);
1430+ } else {
1431+ return Py_BuildValue("");
1432+ }
1433+}
1434+static PyObject *dpkgpackages_isuninstallable(dpkgpackages *self,
1435+ PyObject *args)
1436+{
1437+ char *pkgname;
1438+ if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
1439+ if (!checkinstallable2(self->pkgs, pkgname)) {
1440+ return Py_BuildValue("i", 1);
1441+ } else {
1442+ return Py_BuildValue("");
1443+ }
1444+}
1445+static PyObject *dpkgpackages_unsatdeps(dpkgpackages *self, PyObject *args) {
1446+ /* arguments are:
1447+ * testingpkgs[arch].unsatisfiable_deps(unstablepkgs[arch], "netbase", "Depends")
1448+ * exciting, huh?
1449+ */
1450+
1451+ dpkgpackages *pkgpkgs;
1452+ char *pkgname, *fieldname;
1453+ dpkg_collected_package *cpkg;
1454+ int fieldidx;
1455+ int buflen = 100;
1456+ char *buf = malloc(buflen);
1457+ const char *fields[] = { "Pre-Depends", "Depends", "Recommends",
1458+ "Suggests", NULL };
1459+ satisfieddeplist *unsatdeps, *dl;
1460+ PyObject *res = Py_BuildValue("[]");
1461+
1462+ if (!PyArg_ParseTuple(args, "O!ss", &Packages_Type, &pkgpkgs, &pkgname, &fieldname)) return NULL;
1463+
1464+ cpkg = lookup_packagetbl(pkgpkgs->pkgs->packages, pkgname);
1465+ if (!cpkg) {
1466+ PyErr_SetString(PyExc_ValueError, "Not a valid package");
1467+ return NULL;
1468+ }
1469+
1470+ for (fieldidx = 0; fields[fieldidx]; fieldidx++) {
1471+ if (strcmp(fields[fieldidx], fieldname) == 0) break;
1472+ }
1473+ if (!fields[fieldidx]) {
1474+ PyErr_SetString(PyExc_ValueError, "Not a valid dependency field");
1475+ return NULL;
1476+ }
1477+
1478+ unsatdeps = checkunsatisfiabledeps(self->pkgs,
1479+ cpkg->pkg->depends[fieldidx]);
1480+ for (dl = unsatdeps; dl != NULL; dl = dl->next) {
1481+ int len;
1482+ packagelist *it;
1483+ PyObject *pkglist;
1484+ deplist *depl;
1485+ dependency *dep;
1486+
1487+ len = 0;
1488+ buf[0] = '\0';
1489+ for (depl = dl->value->depl; depl; depl = depl->next) {
1490+ dep = depl->value;
1491+ len += strlen(dep->package) + 4;
1492+ /* 4 = strlen(" | ") + 1 */
1493+ if (dep->op != dr_NOOP) {
1494+ len += strlen(dep->version) + 6;
1495+ /* 6 = strlen(" (>= )") */
1496+ }
1497+ if (len >= buflen) {
1498+ char *newbuf;
1499+ newbuf = realloc(buf, len + 100);
1500+ if (newbuf == NULL) {
1501+ free_satisfieddeplist(unsatdeps);
1502+ free(buf);
1503+ Py_DECREF(res);
1504+ PyErr_SetFromErrno(PyExc_MemoryError);
1505+ return NULL;
1506+ }
1507+ buf = newbuf;
1508+ buflen = len + 100;
1509+ }
1510+ if (buf[0] != '\0') strcat(buf, " | ");
1511+ strcat(buf, dep->package);
1512+ if (dep->op != dr_NOOP) {
1513+ sprintf(buf + strlen(buf), " (%s %s)",
1514+ dependency_relation_sym[dep->op],
1515+ dep->version);
1516+ }
1517+ }
1518+
1519+ MAKE_PY_LIST(pkglist, it = dl->value->pkgs, it, it = it->next,
1520+ ("s", it->value->package)
1521+ );
1522+
1523+ {
1524+ PyObject *depel = Py_BuildValue("(sN)", buf, pkglist);
1525+ PyList_Append(res, depel);
1526+ Py_DECREF(depel);
1527+ }
1528+ }
1529+
1530+ free_satisfieddeplist(unsatdeps);
1531+ free(buf);
1532+
1533+ return res;
1534+}
1535+
1536+static PyObject *dpkgpackages_getattr(dpkgpackages *self, char *name) {
1537+ static struct PyMethodDef dpkgsources_methods[] = {
1538+ { "is_present", (binaryfunc) dpkgpackages_ispresent,
1539+ METH_VARARGS, NULL },
1540+ { "get_version", (binaryfunc) dpkgpackages_getversion,
1541+ METH_VARARGS, NULL },
1542+ { "get_source", (binaryfunc) dpkgpackages_getsource,
1543+ METH_VARARGS, NULL },
1544+ { "get_sourcever", (binaryfunc) dpkgpackages_getsourcever,
1545+ METH_VARARGS, NULL },
1546+ { "is_arch_all", (binaryfunc) dpkgpackages_isarchall,
1547+ METH_VARARGS, NULL },
1548+ { "isnt_arch_all", (binaryfunc) dpkgpackages_isntarchall,
1549+ METH_VARARGS, NULL },
1550+ { "get_field", (binaryfunc) dpkgpackages_getfield,
1551+ METH_VARARGS, NULL },
1552+ { "is_installable", (binaryfunc) dpkgpackages_isinstallable,
1553+ METH_VARARGS, NULL },
1554+ { "is_uninstallable", (binaryfunc)dpkgpackages_isuninstallable,
1555+ METH_VARARGS, NULL },
1556+ { "unsatisfiable_deps", (binaryfunc) dpkgpackages_unsatdeps,
1557+ METH_VARARGS, NULL },
1558+ { NULL, NULL, 0, NULL }
1559+ };
1560+
1561+ if (strcmp(name, "packages") == 0) {
1562+ PyObject *packages;
1563+ packagetbl_iter it;
1564+ MAKE_PY_LIST(packages,
1565+ it = first_packagetbl(self->pkgs->packages),
1566+ !done_packagetbl(it), it = next_packagetbl(it),
1567+ ("s", it.k)
1568+ );
1569+ return packages;
1570+ }
1571+
1572+ return Py_FindMethod(dpkgsources_methods, (PyObject *)self, name);
1573+}
1574+
1575+static PyTypeObject Packages_Type = {
1576+ PyObject_HEAD_INIT(&PyType_Type)
1577+
1578+ 0, /* ob_size (0) */
1579+ "Packages", /* type name */
1580+ sizeof(dpkgpackages), /* basicsize */
1581+ 0, /* itemsize (0) */
1582+
1583+ (destructor) dpkgpackages_dealloc,
1584+ (printfunc) 0,
1585+ (getattrfunc) dpkgpackages_getattr,
1586+ (setattrfunc) 0,
1587+ (cmpfunc) 0,
1588+ (reprfunc) 0,
1589+
1590+ 0, /* number methods */
1591+ 0, /* sequence methods */
1592+ 0, /* mapping methods */
1593+
1594+ (hashfunc) 0, /* dict[x] ?? */
1595+ (ternaryfunc) 0, /* x() */
1596+ (reprfunc) 0 /* str(x) */
1597+};
1598+
1599+/**************************************************************************
1600+ * britney.Sources -- dpkg_sources wrapper
1601+ *****************************************/
1602+
1603+typedef struct {
1604+ PyObject_HEAD
1605+ dpkg_sources *srcs;
1606+} dpkgsources;
1607+
1608+staticforward PyTypeObject Sources_Type;
1609+
1610+static PyObject *dpkgsources_new(PyObject *self, PyObject *args) {
1611+ dpkgsources *res = NULL;
1612+ char *dir;
1613+ PyObject *arches;
1614+ char **archesStr = NULL;
1615+ int i, count;
1616+
1617+ (void)self; /* unused */
1618+
1619+ if (!PyArg_ParseTuple(args, "sO!", &dir, &PyList_Type, &arches)) {
1620+ goto end;
1621+ }
1622+
1623+ count = PyList_Size(arches);
1624+ if (count <= 0) {
1625+ PyErr_SetString(PyExc_TypeError, "No architectures specified");
1626+ goto end;
1627+ }
1628+
1629+ archesStr = malloc(sizeof(char *) * count);
1630+ if (!archesStr) {
1631+ PyErr_SetFromErrno(PyExc_MemoryError);
1632+ goto end;
1633+ }
1634+
1635+ for (i = 0; i < count; i++) {
1636+ PyObject *arch = PyList_GetItem(arches, i);
1637+ if (!PyString_Check(arch)) {
1638+ goto end;
1639+ }
1640+ archesStr[i] = PyString_AsString(arch);
1641+ }
1642+
1643+ res = PyObject_NEW(dpkgsources, &Sources_Type);
1644+ if (res == NULL) goto end;
1645+
1646+ res->srcs = read_directory(dir, count, archesStr);
1647+ if (!res->srcs) {
1648+ Py_DECREF(res);
1649+ res = NULL;
1650+ goto end;
1651+ }
1652+
1653+end:
1654+ if (archesStr) free(archesStr);
1655+ return (PyObject *) res;
1656+}
1657+
1658+static void dpkgsources_dealloc(dpkgsources *self) {
1659+ free_sources(self->srcs);
1660+ self->srcs = NULL;
1661+ PyObject_DEL(self);
1662+}
1663+
1664+static PyObject *dpkgsources_packages(dpkgsources *self, PyObject *args)
1665+{
1666+ char *arch;
1667+ dpkg_packages *pkgs;
1668+ if (!PyArg_ParseTuple(args, "s", &arch)) return NULL;
1669+ pkgs = get_architecture(self->srcs, arch);
1670+ return dpkgpackages_new(pkgs, FREE, (PyObject *) self);
1671+}
1672+
1673+static PyObject *dpkgsources_isfake(dpkgsources *self, PyObject *args) {
1674+ char *srcname;
1675+ dpkg_source *src;
1676+
1677+ if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
1678+ src = lookup_sourcetbl(self->srcs->sources, srcname);
1679+ if (src) return Py_BuildValue("i", src->fake);
1680+ else return Py_BuildValue("");
1681+}
1682+
1683+static PyObject *dpkgsources_getversion(dpkgsources *self, PyObject *args) {
1684+ char *srcname;
1685+ dpkg_source *src;
1686+
1687+ if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
1688+ src = lookup_sourcetbl(self->srcs->sources, srcname);
1689+ if (src) return Py_BuildValue("s", src->version);
1690+ else return Py_BuildValue("");
1691+}
1692+
1693+static PyObject *dpkgsources_getfield(dpkgsources *self, PyObject *args) {
1694+ char *srcname, *field;
1695+ dpkg_source *src;
1696+ int i;
1697+ dpkg_paragraph *para;
1698+
1699+ if (!PyArg_ParseTuple(args, "ss", &srcname, &field)) return NULL;
1700+ src = lookup_sourcetbl(self->srcs->sources, srcname);
1701+ if (!src) {
1702+ PyErr_SetString(PyExc_ValueError, "Not a valid source package");
1703+ return NULL;
1704+ }
1705+ para = src->details;
1706+ if (para) {
1707+ for (i = 0; i < para->n_entries; i++) {
1708+ if (strcasecmp(para->entry[i].name, field) == 0) {
1709+ return Py_BuildValue("s", para->entry[i].value);
1710+ }
1711+ }
1712+ }
1713+ return Py_BuildValue("");
1714+}
1715+
1716+static PyObject *dpkgsources_ispresent(dpkgsources *self, PyObject *args) {
1717+ char *srcname;
1718+ if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
1719+ if (lookup_sourcetbl(self->srcs->sources, srcname)) {
1720+ return Py_BuildValue("i", 1);
1721+ } else {
1722+ return Py_BuildValue("i", 0);
1723+ }
1724+}
1725+
1726+static PyObject *dpkgsources_binaries(dpkgsources *self, PyObject *args) {
1727+ char *srcname, *arch;
1728+ int archnum;
1729+ dpkg_source *src;
1730+ PyObject *res;
1731+ ownedpackagelist *p;
1732+
1733+ if (!PyArg_ParseTuple(args, "ss", &srcname, &arch)) return NULL;
1734+
1735+ for (archnum = 0; archnum < self->srcs->n_arches; archnum++) {
1736+ if (strcmp(arch, self->srcs->archname[archnum]) == 0) break;
1737+ }
1738+ if (archnum == self->srcs->n_arches) {
1739+ PyErr_SetString(PyExc_ValueError, "Not a valid architecture");
1740+ return NULL;
1741+ }
1742+
1743+ src = lookup_sourcetbl(self->srcs->sources, srcname);
1744+ if (src == NULL) {
1745+ PyErr_SetString(PyExc_ValueError, "Not a valid source package");
1746+ return NULL;
1747+ }
1748+
1749+ MAKE_PY_LIST(res, p = src->packages[archnum], p, p = p->next,
1750+ ("s", p->value->package)
1751+ );
1752+ return res;
1753+}
1754+
1755+static PyObject *dpkgsources_getattr(dpkgsources *self, char *name) {
1756+ static struct PyMethodDef dpkgsources_methods[] = {
1757+ { "Packages", (binaryfunc) dpkgsources_packages,
1758+ METH_VARARGS, NULL },
1759+ { "is_fake", (binaryfunc) dpkgsources_isfake,
1760+ METH_VARARGS, NULL },
1761+ { "get_version", (binaryfunc) dpkgsources_getversion,
1762+ METH_VARARGS, NULL },
1763+ { "get_field", (binaryfunc) dpkgsources_getfield,
1764+ METH_VARARGS, NULL },
1765+ { "is_present", (binaryfunc) dpkgsources_ispresent,
1766+ METH_VARARGS, NULL },
1767+ { "binaries", (binaryfunc) dpkgsources_binaries,
1768+ METH_VARARGS, NULL },
1769+ { NULL, NULL, 0, NULL }
1770+ };
1771+
1772+ if (strcmp(name, "arches") == 0) {
1773+ PyObject *arches;
1774+ int i;
1775+ MAKE_PY_LIST(arches, i = 0, i < self->srcs->n_arches, i++,
1776+ ("s", self->srcs->archname[i])
1777+ );
1778+ return arches;
1779+ } else if (strcmp(name, "sources") == 0) {
1780+ PyObject *sources;
1781+ sourcetbl_iter it;
1782+ MAKE_PY_LIST(sources,
1783+ it = first_sourcetbl(self->srcs->sources),
1784+ !done_sourcetbl(it), it = next_sourcetbl(it),
1785+ ("s", it.k)
1786+ );
1787+ return sources;
1788+ }
1789+
1790+ return Py_FindMethod(dpkgsources_methods, (PyObject *)self, name);
1791+}
1792+
1793+static PyTypeObject Sources_Type = {
1794+ PyObject_HEAD_INIT(&PyType_Type)
1795+
1796+ 0, /* ob_size (0) */
1797+ "Sources", /* type name */
1798+ sizeof(dpkgsources), /* basicsize */
1799+ 0, /* itemsize (0) */
1800+
1801+ (destructor) dpkgsources_dealloc,
1802+ (printfunc) 0,
1803+ (getattrfunc) dpkgsources_getattr,
1804+ (setattrfunc) 0,
1805+ (cmpfunc) 0,
1806+ (reprfunc) 0,
1807+
1808+ 0, /* number methods */
1809+ 0, /* sequence methods */
1810+ 0, /* mapping methods */
1811+
1812+ (hashfunc) 0, /* dict[x] ?? */
1813+ (ternaryfunc) 0, /* x() */
1814+ (reprfunc) 0 /* str(x) */
1815+};
1816+
1817+/**************************************************************************
1818+ * britney.SourcesNote -- dpkg_sourcesnote wrapper
1819+ *************************************************/
1820+
1821+typedef struct {
1822+ PyObject_HEAD
1823+ dpkg_sources_note *srcsn;
1824+ PyObject *refs; /* list of referenced dpkgsources */
1825+} dpkgsrcsn;
1826+
1827+staticforward PyTypeObject SourcesNote_Type;
1828+
1829+static PyObject *dpkgsrcsn_new(PyObject *self, PyObject *args) {
1830+ dpkgsrcsn *res = NULL;
1831+ PyObject *arches;
1832+ char **archesStr = NULL;
1833+ int i, count;
1834+
1835+ (void)self; /* unused */
1836+
1837+ if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &arches)) {
1838+ goto end;
1839+ }
1840+
1841+ count = PyList_Size(arches);
1842+ if (count <= 0) {
1843+ PyErr_SetString(PyExc_TypeError, "No architectures specified");
1844+ goto end;
1845+ }
1846+
1847+ archesStr = malloc(sizeof(char *) * count);
1848+ if (!archesStr) {
1849+ PyErr_SetFromErrno(PyExc_MemoryError);
1850+ goto end;
1851+ }
1852+
1853+ for (i = 0; i < count; i++) {
1854+ PyObject *arch = PyList_GetItem(arches, i);
1855+ if (!PyString_Check(arch)) {
1856+ goto end;
1857+ }
1858+ archesStr[i] = PyString_AsString(arch);
1859+ }
1860+
1861+ res = PyObject_NEW(dpkgsrcsn, &SourcesNote_Type);
1862+ if (res == NULL) goto end;
1863+
1864+ res->refs = PyList_New(0);
1865+ res->srcsn = new_sources_note(count, archesStr);
1866+ if (!res->refs || !res->srcsn) {
1867+ Py_DECREF(res);
1868+ res = NULL;
1869+ goto end;
1870+ }
1871+
1872+end:
1873+ if (archesStr) free(archesStr);
1874+ return (PyObject *) res;
1875+}
1876+
1877+static void dpkgsrcsn_dealloc(dpkgsrcsn *self) {
1878+ if (self->srcsn) free_sources_note(self->srcsn);
1879+ self->srcsn = NULL;
1880+ Py_XDECREF(self->refs);
1881+ self->refs = NULL;
1882+
1883+ PyObject_DEL(self);
1884+}
1885+
1886+static PyObject *dpkgsrcsn_removesource(dpkgsrcsn *self, PyObject *args) {
1887+ char *name;
1888+ if (!PyArg_ParseTuple(args, "s", &name)) return NULL;
1889+ remove_source(self->srcsn, name);
1890+ return Py_BuildValue("");
1891+}
1892+static PyObject *dpkgsrcsn_upgradesource(dpkgsrcsn *self, PyObject *args) {
1893+ char *name;
1894+ dpkgsources *srcs;
1895+ dpkg_source *src;
1896+ if (!PyArg_ParseTuple(args, "O!s", &Sources_Type, &srcs, &name))
1897+ return NULL;
1898+ src = lookup_sourcetbl(srcs->srcs->sources, name);
1899+ if (!src) {
1900+ PyErr_SetString(PyExc_ValueError, "Source does not exist");
1901+ return NULL;
1902+ }
1903+ if (!PySequence_In(self->refs, (PyObject *)srcs))
1904+ PyList_Append(self->refs, (PyObject *)srcs);
1905+ upgrade_source(self->srcsn, src);
1906+ return Py_BuildValue("");
1907+}
1908+static PyObject *dpkgsrcsn_upgradearch(dpkgsrcsn *self, PyObject *args) {
1909+ char *name, *arch;
1910+ dpkgsources *srcs;
1911+ dpkg_source *src;
1912+ if (!PyArg_ParseTuple(args, "O!ss", &Sources_Type, &srcs, &name, &arch))
1913+ return NULL;
1914+ src = lookup_sourcetbl(srcs->srcs->sources, name);
1915+ if (!src) {
1916+ PyErr_SetString(PyExc_ValueError, "Source does not exist");
1917+ return NULL;
1918+ }
1919+ if (!PySequence_In(self->refs, (PyObject *)srcs))
1920+ PyList_Append(self->refs, (PyObject *)srcs);
1921+ upgrade_arch(self->srcsn, src, arch);
1922+ return Py_BuildValue("");
1923+}
1924+
1925+static PyObject *dpkgsrcsn_undochange(dpkgsrcsn *self, PyObject *args) {
1926+ if (!PyArg_ParseTuple(args, "")) return NULL;
1927+ undo_change(self->srcsn);
1928+ return Py_BuildValue("");
1929+}
1930+
1931+static PyObject *dpkgsrcsn_commitchanges(dpkgsrcsn *self, PyObject *args) {
1932+ if (!PyArg_ParseTuple(args, "")) return NULL;
1933+ commit_changes(self->srcsn);
1934+ return Py_BuildValue("");
1935+}
1936+
1937+static PyObject *dpkgsrcsn_writenotes(dpkgsrcsn *self, PyObject *args) {
1938+ char *dir;
1939+ if (!PyArg_ParseTuple(args, "s", &dir)) return NULL;
1940+ write_notes(dir, self->srcsn);
1941+ return Py_BuildValue("");
1942+}
1943+
1944+static PyObject *dpkgsrcsn_packages(dpkgsrcsn *self, PyObject *args) {
1945+ char *arch;
1946+ int archnum;
1947+ if (!PyArg_ParseTuple(args, "s", &arch)) return NULL;
1948+ for (archnum = 0; archnum < self->srcsn->n_arches; archnum++) {
1949+ if (strcmp(arch, self->srcsn->archname[archnum]) == 0) break;
1950+ }
1951+ if (archnum == self->srcsn->n_arches) {
1952+ PyErr_SetString(PyExc_ValueError, "Not a valid architecture");
1953+ return NULL;
1954+ }
1955+ return dpkgpackages_new(self->srcsn->pkgs[archnum], DONTFREE,
1956+ (PyObject *) self);
1957+}
1958+
1959+static PyObject *dpkgsrcsn_getversion(dpkgsrcsn *self, PyObject *args) {
1960+ char *srcname;
1961+ dpkg_source_note *srcn;
1962+
1963+ if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
1964+ srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname);
1965+ if (srcn) return Py_BuildValue("s", srcn->source->version);
1966+ else return Py_BuildValue("");
1967+}
1968+static PyObject *dpkgsrcsn_getfield(dpkgsrcsn *self, PyObject *args) {
1969+ char *srcname, *field;
1970+ dpkg_source_note *srcn;
1971+ int i;
1972+ dpkg_paragraph *para;
1973+
1974+ if (!PyArg_ParseTuple(args, "ss", &srcname, &field)) return NULL;
1975+ srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname);
1976+ if (!srcn) {
1977+ PyErr_SetString(PyExc_ValueError, "Not a valid source package");
1978+ return NULL;
1979+ }
1980+ para = srcn->source->details;
1981+ if (para) {
1982+ for (i = 0; i < para->n_entries; i++) {
1983+ if (strcasecmp(para->entry[i].name, field) == 0) {
1984+ return Py_BuildValue("s", para->entry[i].value);
1985+ }
1986+ }
1987+ }
1988+ return Py_BuildValue("");
1989+}
1990+static PyObject *dpkgsrcsn_ispresent(dpkgsrcsn *self, PyObject *args) {
1991+ char *srcname;
1992+ if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
1993+ if (lookup_sourcenotetbl(self->srcsn->sources, srcname)) {
1994+ return Py_BuildValue("i", 1);
1995+ } else {
1996+ return Py_BuildValue("i", 0);
1997+ }
1998+}
1999+
2000+static PyObject *dpkgsrcsn_isfake(dpkgsrcsn *self, PyObject *args) {
2001+ char *srcname;
2002+ dpkg_source_note *srcn;
2003+
2004+ if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
2005+ srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname);
2006+ if (srcn) return Py_BuildValue("i", srcn->source->fake);
2007+ else return Py_BuildValue("");
2008+}
2009+
2010+static PyObject *dpkgsrcsn_binaries(dpkgsrcsn *self, PyObject *args) {
2011+ char *srcname, *arch;
2012+ int archnum;
2013+ dpkg_source_note *srcn;
2014+ PyObject *res;
2015+ packagelist *p;
2016+
2017+ if (!PyArg_ParseTuple(args, "ss", &srcname, &arch)) return NULL;
2018+
2019+ for (archnum = 0; archnum < self->srcsn->n_arches; archnum++) {
2020+ if (strcmp(arch, self->srcsn->archname[archnum]) == 0) break;
2021+ }
2022+ if (archnum == self->srcsn->n_arches) {
2023+ PyErr_SetString(PyExc_ValueError, "Not a valid architecture");
2024+ return NULL;
2025+ }
2026+
2027+ srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname);
2028+ if (srcn == NULL) {
2029+ PyErr_SetString(PyExc_ValueError, "Not a valid source package");
2030+ return NULL;
2031+ }
2032+
2033+ MAKE_PY_LIST(res, p = srcn->binaries[archnum], p, p = p->next,
2034+ ("s", p->value->package)
2035+ );
2036+ return res;
2037+}
2038+
2039+static PyObject *dpkgsrcsn_getattr(dpkgsrcsn *self, char *name) {
2040+ static struct PyMethodDef dpkgsrcsn_methods[] = {
2041+ { "remove_source", (binaryfunc) dpkgsrcsn_removesource,
2042+ METH_VARARGS, NULL },
2043+ { "upgrade_source", (binaryfunc) dpkgsrcsn_upgradesource,
2044+ METH_VARARGS, NULL },
2045+ { "upgrade_arch", (binaryfunc) dpkgsrcsn_upgradearch,
2046+ METH_VARARGS, NULL },
2047+
2048+ { "undo_change", (binaryfunc) dpkgsrcsn_undochange,
2049+ METH_VARARGS, NULL },
2050+ { "commit_changes", (binaryfunc) dpkgsrcsn_commitchanges,
2051+ METH_VARARGS, NULL },
2052+
2053+ { "write_notes", (binaryfunc) dpkgsrcsn_writenotes,
2054+ METH_VARARGS, NULL },
2055+
2056+ { "Packages", (binaryfunc) dpkgsrcsn_packages,
2057+ METH_VARARGS, NULL },
2058+
2059+ { "get_version", (binaryfunc) dpkgsrcsn_getversion,
2060+ METH_VARARGS, NULL },
2061+ { "get_field", (binaryfunc) dpkgsrcsn_getfield,
2062+ METH_VARARGS, NULL },
2063+ { "is_present", (binaryfunc) dpkgsrcsn_ispresent,
2064+ METH_VARARGS, NULL },
2065+ { "is_fake", (binaryfunc) dpkgsrcsn_isfake,
2066+ METH_VARARGS, NULL },
2067+ { "binaries", (binaryfunc) dpkgsrcsn_binaries,
2068+ METH_VARARGS, NULL },
2069+ { NULL, NULL, 0, NULL }
2070+ };
2071+
2072+ if (strcmp(name, "arches") == 0) {
2073+ PyObject *arches;
2074+ int i;
2075+ MAKE_PY_LIST(arches, i = 0, i < self->srcsn->n_arches, i++,
2076+ ("s", self->srcsn->archname[i])
2077+ );
2078+ return arches;
2079+ } else if (strcmp(name, "sources") == 0) {
2080+ PyObject *sources;
2081+ sourcenotetbl_iter it;
2082+ MAKE_PY_LIST(sources,
2083+ it = first_sourcenotetbl(self->srcsn->sources),
2084+ !done_sourcenotetbl(it),
2085+ it = next_sourcenotetbl(it),
2086+ ("s", it.k)
2087+ );
2088+ return sources;
2089+ } else if (strcmp(name, "can_undo") == 0) {
2090+ if (can_undo(self->srcsn)) {
2091+ return Py_BuildValue("i", 1);
2092+ } else {
2093+ return Py_BuildValue("");
2094+ }
2095+ }
2096+
2097+ return Py_FindMethod(dpkgsrcsn_methods, (PyObject *)self, name);
2098+}
2099+
2100+static PyTypeObject SourcesNote_Type = {
2101+ PyObject_HEAD_INIT(&PyType_Type)
2102+
2103+ 0, /* ob_size (0) */
2104+ "SourcesNote", /* type name */
2105+ sizeof(dpkgsrcsn), /* basicsize */
2106+ 0, /* itemsize (0) */
2107+
2108+ (destructor) dpkgsrcsn_dealloc,
2109+ (printfunc) 0,
2110+ (getattrfunc) dpkgsrcsn_getattr,
2111+ (setattrfunc) 0,
2112+ (cmpfunc) 0,
2113+ (reprfunc) 0,
2114+
2115+ 0, /* number methods */
2116+ 0, /* sequence methods */
2117+ 0, /* mapping methods */
2118+
2119+ (hashfunc) 0, /* dict[x] ?? */
2120+ (ternaryfunc) 0, /* x() */
2121+ (reprfunc) 0 /* str(x) */
2122+};
2123+
2124+/**************************************************************************
2125+ * britney.versioncmp() -- apt version compare function
2126+ ******************************************************/
2127+
2128+static PyObject *apt_versioncmp(PyObject *self, PyObject *args) {
2129+ char *l, *r;
2130+ int res;
2131+
2132+ (void)self; /* unused */
2133+
2134+ if (!PyArg_ParseTuple(args, "ss", &l, &r)) {
2135+ return NULL;
2136+ }
2137+
2138+ res = versioncmp(l,r);
2139+ return Py_BuildValue("i", res);
2140+}
2141+
2142+/**************************************************************************
2143+ * module initialisation
2144+ ***********************/
2145+
2146+static PyMethodDef britneymethods[] = {
2147+ { "Sources", dpkgsources_new, METH_VARARGS, NULL },
2148+ { "SourcesNote", dpkgsrcsn_new, METH_VARARGS, NULL },
2149+
2150+ { "versioncmp", apt_versioncmp, METH_VARARGS, NULL },
2151+
2152+ { NULL, NULL, 0, NULL }
2153+};
2154+
2155+void initbritney(void) {
2156+ Py_InitModule("britney", britneymethods);
2157+}
2158+
2159
2160=== added file 'update_out/checklib.c'
2161--- update_out/checklib.c 1970-01-01 00:00:00 +0000
2162+++ update_out/checklib.c 2015-02-19 13:49:56 +0000
2163@@ -0,0 +1,185 @@
2164+#include <stdlib.h>
2165+#include <unistd.h>
2166+
2167+#include <assert.h>
2168+
2169+#include "dpkg.h"
2170+
2171+#if 0
2172+static void checknewsrc(sourcetbl *srcstbl, dpkg_source *cur, void *data) {
2173+ dpkg_sources *oldsrc = data;
2174+ dpkg_source *old;
2175+ old = lookup_sourcetbl(oldsrc->sources, cur->package);
2176+ if (old == NULL) {
2177+ printf("New: %s (%s)\n", cur->package, cur->version );
2178+ } else if (strcmp(old->version, cur->version) != 0) {
2179+ printf("Updated: %s (%s, was %s)\n",
2180+ cur->package, cur->version, old->version );
2181+ } else {
2182+ dpkg_source *src2;
2183+ src2 = remove_sourcetbl(srcstbl, cur->package);
2184+ assert(cur == src2);
2185+ free_source(cur);
2186+ }
2187+}
2188+
2189+static void checkoldsrc(sourcetbl *oldsrctbl, dpkg_source *old, void *data) {
2190+ dpkg_sources *src = data;
2191+ dpkg_source *cur;
2192+ (void)oldsrctbl;
2193+ cur = lookup_sourcetbl(src->sources, old->package);
2194+ if (cur == NULL) {
2195+ printf("Removed: %s (was %s)\n", old->package, old->version );
2196+ }
2197+}
2198+
2199+static void checkuptodate(sourcetbl *srctbl, dpkg_source *src, void *data) {
2200+ int i;
2201+ int remove;
2202+ ownedpackagelist **p;
2203+ dpkg_sources *srcs = data;
2204+
2205+ (void)srctbl;
2206+
2207+ remove = 0;
2208+ for (i = 0; i < srcs->n_arches; i++) {
2209+ p = &src->packages[i];
2210+ while(*p != NULL) {
2211+ if (strcmp((*p)->value->source_ver, src->version) != 0) {
2212+ if (cmpversions((*p)->value->source_ver, GT, src->version)) {
2213+ printf("ALERT: old source: ");
2214+ } else {
2215+ printf("WARN: out of date: ");
2216+ }
2217+ printf("%s %s: %s binary: %s %s from %s\n",
2218+ src->package, src->version, srcs->archname[i],
2219+ (*p)->value->package, (*p)->value->version,
2220+ (*p)->value->source_ver);
2221+ delete_ownedpackagelist(p);
2222+ } else {
2223+ p = &(*p)->next;
2224+ }
2225+ }
2226+ if (src->packages[i] == NULL) {
2227+ printf("%s missing uptodate binaries for %s\n",
2228+ src->package, srcs->archname[i]);
2229+ remove = 1;
2230+ }
2231+ }
2232+ if (remove) {
2233+ dpkg_source *src2;
2234+ src2 = remove_sourcetbl(srcs->sources, src->package);
2235+ assert(src == src2);
2236+ free_source(src);
2237+ }
2238+}
2239+#endif
2240+
2241+static void upgrade(sourcetbl *srctbl, dpkg_source *src, void *data) {
2242+ static int i = 0;
2243+ dpkg_sources_note *srcsn = data;
2244+ (void)srctbl;
2245+ i++; i %= 1000;
2246+ if (can_undo(srcsn)) {
2247+ if (i % 29 == 1 || i % 31 == 1 || i % 7 == 5)
2248+ undo_change(srcsn);
2249+ if (i % 33 == 0) commit_changes(srcsn);
2250+ }
2251+ upgrade_source(data, src);
2252+}
2253+
2254+static void checkpkgs(packagetbl *pkgtbl, dpkg_collected_package *cpkg,
2255+ void *data)
2256+{
2257+ dpkg_packages *pkgs = data;
2258+ assert(pkgs->packages == pkgtbl);
2259+ printf("Trying %s (%s, %s)\n", cpkg->pkg->package, cpkg->pkg->version, pkgs->arch);
2260+ if (!checkinstallable2(pkgs, cpkg->pkg->package)) {
2261+ printf("Package: %s (%s, %s) is uninstallable\n",
2262+ cpkg->pkg->package, cpkg->pkg->version, pkgs->arch);
2263+ }
2264+}
2265+
2266+void print_memblock_summary(void);
2267+
2268+int main(int argc, char **argv) {
2269+ dpkg_sources *src = NULL, *oldsrc = NULL;
2270+ dpkg_sources_note *srcsn;
2271+ dpkg_source *srcpkg;
2272+ dpkg_packages *pkgs[10];
2273+ int n_pkgs;
2274+ int i,j;
2275+ int reps;
2276+
2277+ if (argc < 3) {
2278+ printf("Usage: %s <reps> <arch>...\n", argv[0]);
2279+ exit(EXIT_FAILURE);
2280+ }
2281+
2282+ reps = atoi(argv[1]);
2283+ if (reps < 1) {
2284+ printf("reps must be >= 1\n");
2285+ exit(EXIT_FAILURE);
2286+ }
2287+
2288+ src = read_directory("cur", argc - 2, argv + 2);
2289+ oldsrc = read_directory("old", argc - 2, argv + 2);
2290+ srcsn = new_sources_note(argc - 2, argv + 2);
2291+
2292+ printf("FINISHED LOADING\n"); fflush(stdout); /* sleep(5); */
2293+
2294+#if 0
2295+ iterate_sourcetbl(oldsrc->sources, checkoldsrc, src);
2296+
2297+ printf("FIRST\n");
2298+ iterate_sourcetbl(src->sources, checkuptodate, src);
2299+ printf("SECOND\n");
2300+ iterate_sourcetbl(src->sources, checkuptodate, src);
2301+ printf("END\n");
2302+
2303+ iterate_sourcetbl(src->sources, checknewsrc, oldsrc);
2304+#endif
2305+
2306+ n_pkgs = 0;
2307+ for (i = argc - 1; i > 1; i--) {
2308+ pkgs[n_pkgs++] = get_architecture(oldsrc, argv[i]);
2309+ }
2310+ for (j = 0; j < reps; j++) {
2311+ printf("Round %d/%d starting...\n", j + 1, reps);
2312+ for (i = 0; i < n_pkgs; i++) {
2313+ iterate_packagetbl(pkgs[i]->packages, checkpkgs, pkgs[i]);
2314+ }
2315+ printf("Round %d ended.\n", j+1);
2316+ }
2317+ iterate_sourcetbl(src->sources, upgrade, srcsn);
2318+ iterate_sourcetbl(oldsrc->sources, upgrade, srcsn);
2319+
2320+ for (i = 0; i < n_pkgs; i++) {
2321+ free_packages(pkgs[i]);
2322+ }
2323+
2324+ srcpkg = lookup_sourcetbl(oldsrc->sources, "omirr");
2325+ if (srcpkg != NULL) {
2326+ printf("Adding old\n");
2327+ upgrade_source(srcsn, srcpkg);
2328+ }
2329+ srcpkg = lookup_sourcetbl(src->sources, "omirr");
2330+ if (srcpkg != NULL) {
2331+ printf("Adding cur\n");
2332+ upgrade_source(srcsn, srcpkg);
2333+ }
2334+
2335+ printf("FINISHED PROCESSING\n"); fflush(stdout); /* sleep(5); */
2336+
2337+ write_directory("out", oldsrc);
2338+
2339+ printf("FINISHED WRITING\n"); fflush(stdout); /* sleep(5); */
2340+
2341+ free_sources_note(srcsn);
2342+ free_sources(src);
2343+ free_sources(oldsrc);
2344+
2345+ DEBUG_ONLY( print_memblock_summary(); )
2346+
2347+ return 0;
2348+}
2349
2350=== added file 'update_out/dpkg-lib.cpp'
2351--- update_out/dpkg-lib.cpp 1970-01-01 00:00:00 +0000
2352+++ update_out/dpkg-lib.cpp 2015-02-19 13:49:56 +0000
2353@@ -0,0 +1,34 @@
2354+
2355+#include <apt-pkg/debversion.h>
2356+
2357+extern "C" {
2358+
2359+#include "dpkg.h"
2360+
2361+int versioncmp(char *left, char *right) {
2362+ return debVS.CmpVersion(left, right);
2363+}
2364+
2365+int cmpversions(char *left, int op, char *right) {
2366+ int i = debVS.CmpVersion(left, right);
2367+
2368+ switch(op) {
2369+ case dr_LT: return i < 0;
2370+ case dr_LTEQ: return i <= 0;
2371+ case dr_EQ: return i == 0;
2372+ case dr_GTEQ: return i >= 0;
2373+ case dr_GT: return i > 0;
2374+ }
2375+ return 0;
2376+}
2377+
2378+}
2379+
2380+#ifdef TESTBIN
2381+int main(int argc, char **argv) {
2382+ if (argc != 3) { printf("Usage: %s <ver> <ver>\n", argv[0]); exit(1); }
2383+
2384+ printf("%d\n", versioncmp(argv[1], argv[2]));
2385+ return 0;
2386+}
2387+#endif
2388
2389=== added file 'update_out/dpkg.c'
2390--- update_out/dpkg.c 1970-01-01 00:00:00 +0000
2391+++ update_out/dpkg.c 2015-02-19 13:49:56 +0000
2392@@ -0,0 +1,2013 @@
2393+#include <stdio.h>
2394+#include <stdlib.h>
2395+#include <string.h>
2396+#include <ctype.h>
2397+#include <errno.h>
2398+
2399+#include "dpkg.h"
2400+#include "memory.h"
2401+
2402+
2403+// enlarge this is britney has issues to parse packages
2404+#define SIZEOFHASHMAP 16
2405+
2406+#define insert_packagenamelist(x,y) insert_l_packagenamelist(x,y,__LINE__)
2407+
2408+static void free_dependency(dependency *dep);
2409+static void free_package(dpkg_package *pkg);
2410+static void free_collected_package(dpkg_collected_package *pkg);
2411+static dpkg_paragraph *read_paragraph( FILE *f );
2412+static dpkg_package *read_package( FILE *f );
2413+static collpackagelist **get_matching_low(collpackagelist **addto,
2414+ dpkg_packages *pkgs, dependency *dep, int line);
2415+static collpackagelist *get_matching(dpkg_packages *pkgs, deplist *depopts, int line);
2416+static deplist *read_dep_and(char *buf);
2417+static deplistlist *read_dep_andor(char *buf);
2418+static ownedpackagenamelist *read_packagenames(char *buf);
2419+static dpkg_sources *read_sources_file(char *filename, int n_arches);
2420+static dpkg_source *new_source(dpkg_sources *owner);
2421+static dpkg_source *read_source(FILE *f, dpkg_sources *owner);
2422+static deplist *read_deplist(char **buf, char sep, char end);
2423+static dependency *read_dependency(char **buf, char *end);
2424+static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package,
2425+ char *version, dpkg_collected_package *cpkg);
2426+static void remove_virtualpackage(virtualpkgtbl *vpkgs, char *pkgname,
2427+ dpkg_collected_package *cpkg);
2428+static char *read_packagename(char **buf, char *end);
2429+static char *read_until_char(char **buf, char *end);
2430+static void add_package(dpkg_packages *pkgs, dpkg_package *pkg);
2431+static void remove_package(dpkg_packages *pkgs, dpkg_collected_package *pkg);
2432+static dpkg_source_note *copy_source_note(dpkg_source_note *srcn);
2433+
2434+#if 0
2435+static inline void *bm(size_t s, int n) { void *res = block_malloc(s); fprintf(stderr, "ALLOCED: %d %p %lu\n", n, res, s); return res; }
2436+static inline void bf(void *p, size_t s, int n) { block_free(p,s); fprintf(stderr, "FREED: %d %p %lu\n", n, p, s); }
2437+
2438+#define block_malloc(s) bm(s,__LINE__)
2439+#define block_free(p,s) bf(p,s,__LINE__)
2440+#endif
2441+
2442+#define block_malloc(s) block_malloc2(s, __LINE__)
2443+
2444+static char *priorities[] = {
2445+ "required",
2446+ "important",
2447+ "standard",
2448+ "optional",
2449+ "extra",
2450+ NULL
2451+};
2452+
2453+static char *dependency_title[] = {
2454+ "Pre-Depends", "Depends", "Recommends", "Suggests", NULL
2455+};
2456+
2457+static int dependency_counts[] = { 1, 1, 0, 0 };
2458+
2459+char *dependency_relation_sym[] = {"*", "<<", "<=", "=", ">=", ">>"};
2460+
2461+#define SMB_SIZE (1<<22)
2462+struct stringmemblock {
2463+ struct stringmemblock *next;
2464+ size_t last;
2465+ char mem[SMB_SIZE];
2466+};
2467+static struct stringmemblock *stringmemory = NULL;
2468+static int stringmemorycount = 0;
2469+static const unsigned long stringmemblocksizekib = (unsigned long) sizeof(struct stringmemblock) / 1024;
2470+
2471+char *my_strdup(char *foo) {
2472+ struct stringmemblock *which;
2473+ size_t len;
2474+
2475+ if (!foo) return NULL;
2476+
2477+ len = strlen(foo) + 1;
2478+
2479+ if (len > SMB_SIZE) return strdup(foo);
2480+
2481+ for (which = stringmemory; which; which = which->next) {
2482+ if (SMB_SIZE - which->last > len + 1) {
2483+ break;
2484+ }
2485+ }
2486+ if (!which) {
2487+ which = malloc(sizeof(struct stringmemblock));
2488+ if (!which) return NULL;
2489+ MDEBUG1_ONLY(fprintf(stderr,
2490+ "ALLOC: string memblock %d (%lu KiB, %lu KiB total)\n",
2491+ stringmemorycount, stringmemblocksizekib,
2492+ (stringmemorycount+1) * stringmemblocksizekib));
2493+ memset(which->mem, 0, SMB_SIZE);
2494+ which->last = 0;
2495+ which->next = stringmemory;
2496+ stringmemory = which;
2497+ stringmemorycount++;
2498+ }
2499+ strcpy(&which->mem[which->last], foo);
2500+ foo = &which->mem[which->last];
2501+ which->last += len;
2502+ return foo;
2503+}
2504+
2505+char *my_rep_strdup(char *foo) {
2506+ static char *repeats[1000] = {0};
2507+ int i;
2508+
2509+ for (i = 0; i < 1000; i++) {
2510+ if (repeats[i] == NULL) {
2511+ DEBUG_ONLY(fprintf(stderr, "REPEAT NR %d\n", i+1); )
2512+ return repeats[i] = my_strdup(foo);
2513+ }
2514+ if (strcmp(repeats[i], foo) == 0) return repeats[i];
2515+ }
2516+
2517+ return my_strdup(foo);
2518+}
2519+
2520+/* DIE **/
2521+
2522+static void die(char *orig_msg) {
2523+ char *msg = my_strdup(orig_msg);
2524+ if (*msg && msg[strlen(msg)-1] == ':') {
2525+ msg[strlen(msg)-1] = '\0';
2526+ perror(msg);
2527+ } else {
2528+ printf("%s\n", msg);
2529+ }
2530+ abort();
2531+}
2532+
2533+/*************************************************************************
2534+ * Dpkg Control/Packages/etc Operations
2535+ */
2536+
2537+static dpkg_paragraph *read_paragraph( FILE *f ) {
2538+ dpkg_paragraph *result;
2539+ static int line_size = 0;
2540+ static char *line = NULL;
2541+ char *pch;
2542+
2543+ dpkg_entry *c_entry = NULL;
2544+ char *c_value = NULL;
2545+
2546+ if (line == NULL) {
2547+ line_size = 10;
2548+ line = malloc(line_size);
2549+ if (line == NULL) die("read_paragraph alloc 0:");
2550+ }
2551+
2552+ result = block_malloc( sizeof(dpkg_paragraph) );
2553+ if (result == NULL) die("read_paragraph alloc 1:");
2554+
2555+ result->n_entries = 0;
2556+ result->entry = NULL;
2557+ result->n_allocated = 0;
2558+
2559+ while(fgets(line, line_size, f)) {
2560+ while (!feof(f) && *line && line[strlen(line)-1] != '\n') {
2561+ line = realloc(line, line_size * 2);
2562+ if (!line) die("read_paragraph realloc:");
2563+ fgets(line + strlen(line), line_size, f);
2564+ line_size *= 2;
2565+ }
2566+
2567+ if (line[0] == '\n') break;
2568+
2569+ if (isspace(line[0])) {
2570+ if (c_value == NULL)
2571+ die("read_paragraph early spaces");
2572+
2573+ if (c_entry == NULL) {
2574+ /* no need to bother */
2575+ } else {
2576+ /* extend the line */
2577+ c_value = realloc(c_value, strlen(c_value) + strlen(line) + 1);
2578+ if (c_value == NULL)
2579+ die("read_paragraph realloc c_value:");
2580+
2581+ strcat(c_value, line);
2582+ }
2583+ } else {
2584+ if (c_entry) {
2585+ c_entry->value = my_strdup(c_value);
2586+ c_value[0] = '\0';
2587+ free(c_value);
2588+ c_value = NULL;
2589+ } else if (c_value) {
2590+ free(c_value);
2591+ c_value = NULL;
2592+ }
2593+ pch = strchr(line, ':');
2594+ if (pch == NULL) {
2595+ fprintf(stderr, "the line was: \"%s\"\n", line);
2596+ die("read_paragraph: no colon");
2597+ }
2598+
2599+ *pch = '\0';
2600+ while(isspace(*++pch));
2601+
2602+ if (strcmp(line, "Description") == 0) {
2603+ c_value = strdup(pch);
2604+ c_entry = NULL;
2605+ } else {
2606+ assert(result->n_entries <= result->n_allocated);
2607+ if (result->n_entries >= result->n_allocated) {
2608+ result->n_allocated += 10;
2609+ result->entry = realloc( result->entry,
2610+ sizeof(dpkg_entry)
2611+ * result->n_allocated);
2612+ if (result->entry == NULL)
2613+ die("read_paragraph realloc entry:");
2614+ }
2615+
2616+ c_entry = &result->entry[result->n_entries++];
2617+ c_entry->name = my_rep_strdup(line);
2618+ c_value = strdup(pch);
2619+ }
2620+ }
2621+ }
2622+
2623+ if (c_entry) {
2624+ c_entry->value = my_strdup(c_value);
2625+ c_value[0] = '\0';
2626+ free(c_value);
2627+ c_value = NULL;
2628+ }
2629+
2630+ if (result->n_entries == 0) {
2631+ if (result->entry) free(result->entry);
2632+ block_free(result, sizeof(dpkg_paragraph));
2633+ return NULL;
2634+ } else {
2635+ result->entry = realloc(result->entry,
2636+ sizeof(result->entry[0]) * result->n_entries);
2637+ result->n_allocated = result->n_entries;
2638+ }
2639+
2640+ return result;
2641+}
2642+
2643+static void write_paragraph(FILE *f, dpkg_paragraph *p) {
2644+ int i;
2645+
2646+ for (i = 0; i < p->n_entries; i++) {
2647+ fprintf(f, "%s: %s", p->entry[i].name, p->entry[i].value);
2648+ }
2649+ fprintf(f, "\n");
2650+}
2651+
2652+
2653+static void free_paragraph(dpkg_paragraph *p) {
2654+ int i;
2655+
2656+ if (p == NULL) return;
2657+
2658+ for (i = 0; i < p->n_entries; i++) {
2659+ /* block_free(p->entry[i].name); */
2660+ /* block_free(p->entry[i].value); */
2661+ }
2662+ free(p->entry);
2663+ block_free(p, sizeof(dpkg_paragraph));
2664+}
2665+
2666+/*************************************************************************
2667+ * Basic Package Operations
2668+ */
2669+
2670+static dpkg_package *new_package(void) {
2671+ dpkg_package *result;
2672+
2673+ result = block_malloc(sizeof(dpkg_package));
2674+ if (result == NULL) die("new_package alloc:");
2675+
2676+ result->package = NULL;
2677+ result->version = NULL;
2678+
2679+ result->priority = 0;
2680+ result->arch_all = 0;
2681+
2682+ result->source = NULL;
2683+ result->source_ver = NULL;
2684+
2685+ result->depends[0] = NULL;
2686+ result->depends[1] = NULL;
2687+ result->depends[2] = NULL;
2688+ result->depends[3] = NULL;
2689+
2690+ result->conflicts = NULL;
2691+
2692+ result->provides = NULL;
2693+ result->details = NULL;
2694+
2695+ return result;
2696+}
2697+
2698+static dpkg_collected_package *new_collected_package(dpkg_package *pkg) {
2699+ dpkg_collected_package *result;
2700+
2701+ result = block_malloc(sizeof(dpkg_collected_package));
2702+ if (result == NULL) die("new_collected_package alloc:");
2703+
2704+ result->pkg = pkg;
2705+
2706+ result->installed = 0;
2707+ result->conflicted = 0;
2708+
2709+ result->installable = UNKNOWN;
2710+ result->mayaffect = NULL;
2711+
2712+ return result;
2713+}
2714+
2715+static void free_collected_package(dpkg_collected_package *cpkg) {
2716+ if (cpkg == NULL) return;
2717+ cpkg->pkg = NULL;
2718+ free_packagenamelist(cpkg->mayaffect);
2719+ cpkg->mayaffect = NULL;
2720+ block_free(cpkg, sizeof(dpkg_collected_package));
2721+}
2722+
2723+static void free_package(dpkg_package *pkg) {
2724+ int i;
2725+ if (pkg == NULL) return;
2726+
2727+ /* block_free(pkg->package);
2728+ * block_free(pkg->version);
2729+ * block_free(pkg->source);
2730+ * block_free(pkg->source_ver); */
2731+
2732+ for (i = 0; i < 4; i++)
2733+ free_deplistlist(pkg->depends[i]);
2734+
2735+ free_deplist(pkg->conflicts);
2736+ free_ownedpackagenamelist(pkg->provides);
2737+
2738+ free_paragraph(pkg->details);
2739+
2740+ block_free(pkg, sizeof(dpkg_package));
2741+}
2742+
2743+static dpkg_package *read_package( FILE *f ) {
2744+ dpkg_package *result;
2745+ dpkg_paragraph *para;
2746+ dpkg_entry *e;
2747+ int i;
2748+
2749+ para = read_paragraph(f);
2750+ if (para == NULL) return NULL;
2751+
2752+ result = new_package();
2753+ result->details = para;
2754+
2755+ for (e = &para->entry[0]; e < &para->entry[para->n_entries]; e++) {
2756+ if (strcasecmp("Package", e->name) == 0) {
2757+ result->package = my_strdup(e->value);
2758+ if (result->package == NULL)
2759+ die("read_package my_strdup:");
2760+ result->package[strlen(result->package)-1] = '\0';
2761+ }
2762+
2763+ if (strcasecmp("Version", e->name) == 0) {
2764+ result->version = my_strdup(e->value);
2765+ if (result->version == NULL)
2766+ die("read_package my_strdup:");
2767+ result->version[strlen(result->version)-1] = '\0';
2768+ }
2769+
2770+ if (strcasecmp("Priority", e->name) == 0) {
2771+ int i;
2772+ for (i = 0; priorities[i] != NULL; i++) {
2773+ if (strcasecmp(priorities[i], e->value))
2774+ break;
2775+ }
2776+ result->priority = i;
2777+ if (priorities[i] == NULL) {
2778+ die("read_package: unknown priority");
2779+ }
2780+ }
2781+
2782+ if (strcasecmp("Architecture", e->name) == 0) {
2783+ if (strncasecmp(e->value, "all", 3) == 0) {
2784+ if (!e->value[3] || isspace(e->value[3])) {
2785+ result->arch_all = 1;
2786+ }
2787+ }
2788+ }
2789+
2790+ for (i = 0; dependency_title[i] != NULL; i++) {
2791+ if (strcasecmp(dependency_title[i], e->name) == 0) {
2792+ result->depends[i] = read_dep_andor(e->value);
2793+ }
2794+ }
2795+
2796+ /*
2797+ * Support Breaks by treating them as Conflicts.
2798+ */
2799+ if (strcasecmp("Conflicts", e->name) == 0
2800+ || strcasecmp("Breaks", e->name) == 0) {
2801+ deplist *pkgs = read_dep_and(e->value);
2802+ if (result->conflicts == NULL)
2803+ result->conflicts = pkgs;
2804+ else {
2805+ // TODO(dato): create extend_deplist() in templates.h?
2806+ deplist *end = result->conflicts;
2807+ while (end->next)
2808+ end = end->next;
2809+ end->next = pkgs;
2810+ }
2811+ }
2812+
2813+ if (strcasecmp("Provides", e->name) == 0)
2814+ result->provides = read_packagenames(e->value);
2815+
2816+ if (strcasecmp("source", e->name) == 0) {
2817+ char *pch = e->value;
2818+
2819+ assert(result->source == NULL);
2820+ assert(result->source_ver == NULL);
2821+
2822+ result->source = my_strdup(read_packagename(&pch, "("));
2823+ if (result->source == NULL)
2824+ die("read_package: bad source header");
2825+
2826+ while(isspace(*pch)) pch++;
2827+ if (*pch == '(') {
2828+ pch++;
2829+ result->source_ver = my_strdup(read_until_char(&pch, ")"));
2830+ if (result->source_ver == NULL)
2831+ die("read_package: bad source version");
2832+ while(isspace(*pch)) pch++;
2833+ if (*pch != ')')
2834+ die("read_package: unterminated ver");
2835+ }
2836+ }
2837+ }
2838+
2839+ if (result->source == NULL) {
2840+ assert(result->source_ver == NULL);
2841+ result->source = my_strdup(result->package);
2842+ }
2843+ if (result->source_ver == NULL) {
2844+ result->source_ver = my_strdup(result->version);
2845+ }
2846+
2847+ return result;
2848+}
2849+
2850+static void freesize(void *p, size_t s) { (void)s; free(p); }
2851+
2852+LIST_IMPL(deplist, dependency*, free_dependency, block_malloc, block_free);
2853+LIST_IMPL(deplistlist, deplist*, free_deplist, block_malloc, block_free);
2854+
2855+LIST_IMPLX(packagenamelist, char*, KEEP(char*));
2856+
2857+LIST_IMPL(ownedpackagenamelist, char*, KEEP(char*), block_malloc, block_free);
2858+ /* ownedpackagenamelist stores the packagename in the string store */
2859+
2860+static int packagecmp(dpkg_package *l, dpkg_package *r) {
2861+ if (l->priority < r->priority) return -1;
2862+ if (l->priority > r->priority) return +1;
2863+ return strcmp(l->package, r->package);
2864+}
2865+
2866+/* container for owned pkgs */
2867+LIST_IMPL(ownedpackagelist, dpkg_package *, free_package,
2868+ block_malloc, block_free);
2869+
2870+/* container for existing pkgs */
2871+LIST_IMPL(packagelist, dpkg_package *, KEEP(dpkg_package *), block_malloc, block_free);
2872+
2873+LIST_IMPLX(collpackagelist, dpkg_collected_package *,
2874+ KEEP(dpkg_collected_package *))
2875+#define insert_collpackagelist(x,y) insert_l_collpackagelist(x,y,__LINE__)
2876+
2877+/*************************************************************************
2878+ * Operations on distributions (collections of packages)
2879+ */
2880+
2881+dpkg_packages *new_packages(char *arch) {
2882+ dpkg_packages *result;
2883+
2884+ result = block_malloc(sizeof(dpkg_packages));
2885+ if (result == NULL) die("new_packages alloc:");
2886+
2887+ result->arch = my_strdup(arch);
2888+ result->packages = new_packagetbl();
2889+ result->virtualpkgs = new_virtualpkgtbl();
2890+
2891+ return result;
2892+}
2893+
2894+static void add_package(dpkg_packages *pkgs, dpkg_package *pkg)
2895+{
2896+ ownedpackagenamelist *v;
2897+ dpkg_collected_package *cpkg;
2898+
2899+ if (lookup_packagetbl(pkgs->packages, pkg->package) != NULL)
2900+ return;
2901+
2902+ cpkg = new_collected_package(pkg);
2903+
2904+ add_packagetbl(pkgs->packages, cpkg->pkg->package, cpkg);
2905+
2906+ add_virtualpackage(pkgs->virtualpkgs, cpkg->pkg->package,
2907+ cpkg->pkg->version, cpkg);
2908+ for (v = cpkg->pkg->provides; v != NULL; v = v->next) {
2909+ add_virtualpackage(pkgs->virtualpkgs, v->value, NULL, cpkg);
2910+ }
2911+}
2912+
2913+static void remove_package(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
2914+ ownedpackagenamelist *v;
2915+ packagenamelist *aff;
2916+ dpkg_collected_package *p;
2917+
2918+ for (aff = cpkg->mayaffect; aff != NULL; aff = aff->next) {
2919+ p = lookup_packagetbl(pkgs->packages, aff->value);
2920+ if (p == NULL) continue;
2921+ p->installable = UNKNOWN;
2922+ }
2923+
2924+ p = remove_packagetbl(pkgs->packages, cpkg->pkg->package);
2925+ if (p != cpkg) return;
2926+
2927+ remove_virtualpackage(pkgs->virtualpkgs, cpkg->pkg->package, cpkg);
2928+ for (v = cpkg->pkg->provides; v != NULL; v = v->next) {
2929+ remove_virtualpackage(pkgs->virtualpkgs, v->value, cpkg);
2930+ }
2931+
2932+ free_collected_package(cpkg);
2933+}
2934+
2935+dpkg_packages *get_architecture(dpkg_sources *srcs, char *arch) {
2936+ int i, arch_index;
2937+ dpkg_packages *result;
2938+ sourcetbl_iter srci;
2939+ ownedpackagelist *p;
2940+
2941+ arch_index = -1;
2942+ for (i = 0; i < srcs->n_arches; i++) {
2943+ if (strcmp(srcs->archname[i], arch) == 0) {
2944+ arch_index = i;
2945+ break;
2946+ }
2947+ }
2948+ if (arch_index == -1) die("get_architecture: unknown arch");
2949+
2950+ result = new_packages(arch);
2951+
2952+ for (srci = first_sourcetbl(srcs->sources);
2953+ !done_sourcetbl(srci);
2954+ srci = next_sourcetbl(srci))
2955+ {
2956+ for (p = srci.v->packages[arch_index]; p != NULL; p = p->next) {
2957+ add_package(result, p->value);
2958+ }
2959+ }
2960+
2961+ return result;
2962+}
2963+
2964+void free_packages(dpkg_packages *pkgs) {
2965+ if (pkgs == NULL) return;
2966+ /* block_free(pkgs->arch); */
2967+ free_packagetbl(pkgs->packages);
2968+ free_virtualpkgtbl(pkgs->virtualpkgs);
2969+ block_free(pkgs, sizeof(dpkg_packages));
2970+}
2971+
2972+
2973+HASH_IMPL(packagetbl, char *, dpkg_collected_package *, SIZEOFHASHMAP, strhash, strcmp,
2974+ KEEP(char*),free_collected_package);
2975+HASH_IMPL(virtualpkgtbl, char *, virtualpkg *, SIZEOFHASHMAP, strhash, strcmp,
2976+ KEEP(char*), free_virtualpkg);
2977+
2978+/* dpkg_provision refers to memory allocated elsewhere */
2979+LIST_IMPL(virtualpkg, dpkg_provision, KEEP(dpkg_provision), block_malloc, block_free);
2980+
2981+static void remove_virtualpackage(virtualpkgtbl *vpkgs, char *pkgname,
2982+ dpkg_collected_package *cpkg)
2983+{
2984+ virtualpkg *list;
2985+ virtualpkg **where;
2986+ list = lookup_virtualpkgtbl(vpkgs, pkgname);
2987+ assert(list != NULL);
2988+
2989+ where = &list;
2990+ while((*where)->value.pkg != cpkg) {
2991+ where = &(*where)->next;
2992+ assert(*where != NULL);
2993+ }
2994+
2995+ delete_virtualpkg(where);
2996+
2997+ if (list == NULL) {
2998+ remove_virtualpkgtbl(vpkgs, pkgname);
2999+ } else {
3000+ replace_virtualpkgtbl(vpkgs, pkgname, list);
3001+ }
3002+}
3003+
3004+static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package,
3005+ char *version, dpkg_collected_package *cpkg)
3006+{
3007+ dpkg_provision value;
3008+ virtualpkg *list, **addto;
3009+ int shouldreplace;
3010+
3011+ value.pkg = cpkg;
3012+ value.version = version;
3013+
3014+ list = lookup_virtualpkgtbl(vpkgs, package);
3015+ shouldreplace = (list != NULL);
3016+
3017+ addto = &list;
3018+ while (*addto != NULL
3019+ && packagecmp(cpkg->pkg, (*addto)->value.pkg->pkg) >= 0)
3020+ {
3021+ addto = &(*addto)->next;
3022+ }
3023+ insert_virtualpkg(addto, value);
3024+
3025+ if (shouldreplace) {
3026+ replace_virtualpkgtbl(vpkgs, package, list);
3027+ /* old list is included in new list, so we don't need to free */
3028+ } else {
3029+ add_virtualpkgtbl(vpkgs, package, list);
3030+ }
3031+}
3032+
3033+/*************************************************************************
3034+ * Parsing Helper Functions
3035+ */
3036+
3037+static ownedpackagenamelist *read_packagenames(char *buf) {
3038+ ownedpackagenamelist *result = NULL;
3039+ ownedpackagenamelist **addto = &result;
3040+
3041+ DEBUG_ONLY( char *strend = buf + strlen(buf); )
3042+
3043+ char *sub;
3044+
3045+ while ((sub = my_strdup(read_packagename(&buf, ",")))) {
3046+ insert_ownedpackagenamelist(addto, sub);
3047+ addto = &(*addto)->next;
3048+
3049+ while(isspace(*buf)) buf++;
3050+ if (*buf == ',') {
3051+ buf++;
3052+ continue;
3053+ }
3054+ if (*buf == '\0') {
3055+ break;
3056+ }
3057+
3058+ die("read_packagenames no/bad seperator");
3059+ }
3060+
3061+ DEBUG_ONLY( assert(buf <= strend); )
3062+
3063+ return result;
3064+}
3065+
3066+static char *read_until_char(char **buf, char *end) {
3067+ static char *result = NULL;
3068+ char *start;
3069+ DEBUG_ONLY( char *strend = *buf + strlen(*buf); )
3070+ int n;
3071+
3072+ while(isspace(**buf)) (*buf)++;
3073+
3074+ start = *buf;
3075+ while (**buf && !isspace(**buf) && strchr(end, **buf) == NULL) {
3076+ (*buf)++;
3077+ }
3078+
3079+ n = *buf - start;
3080+ if (n == 0) return NULL;
3081+
3082+ result = realloc(result, n + 1);
3083+ if (result == NULL) die("read_until_char alloc:");
3084+
3085+ strncpy(result, start, n);
3086+ result[n] = '\0';
3087+
3088+ while(isspace(**buf)) (*buf)++;
3089+
3090+ DEBUG_ONLY( assert(*buf <= strend); )
3091+
3092+ return result;
3093+}
3094+
3095+static char *read_packagename(char **buf, char *end) {
3096+ return read_until_char(buf, end);
3097+}
3098+
3099+static deplist *read_dep_and(char *buf) {
3100+ return read_deplist(&buf, ',', '\0');
3101+}
3102+
3103+static deplist *read_deplist(char **buf, char sep, char end) {
3104+ deplist *result = NULL;
3105+ deplist **addto = &result;
3106+
3107+ char separs[3] = { sep, end, '\0' };
3108+
3109+ DEBUG_ONLY( char *strend = *buf + strlen(*buf); )
3110+
3111+ dependency *sub;
3112+
3113+ while ((sub = read_dependency(buf, separs))) {
3114+ insert_deplist(addto, sub);
3115+ addto = &(*addto)->next;
3116+
3117+ while(isspace(**buf)) (*buf)++;
3118+ if (**buf == sep) {
3119+ (*buf)++;
3120+ continue;
3121+ }
3122+ if (**buf == '\0' || **buf == end) {
3123+ break;
3124+ }
3125+
3126+ die("read_deplist no/bad seperator");
3127+ }
3128+
3129+ DEBUG_ONLY( assert(*buf <= strend); )
3130+
3131+ return result;
3132+}
3133+
3134+static deplistlist *read_dep_andor(char *buf) {
3135+ deplistlist *result = NULL;
3136+ deplistlist **addto = &result;
3137+
3138+ deplist *sub;
3139+
3140+ DEBUG_ONLY( char *strend = buf + strlen(buf); )
3141+
3142+ while ((sub = read_deplist(&buf, '|', ','))) {
3143+ insert_deplistlist(addto, sub);
3144+ addto = &(*addto)->next;
3145+
3146+ if (*buf == ',') buf++;
3147+ }
3148+
3149+ DEBUG_ONLY( assert(buf <= strend); )
3150+
3151+ return result;
3152+}
3153+
3154+static dependency *read_dependency(char **buf, char *end) {
3155+ dependency *dep;
3156+ char *name;
3157+ char newend[10];
3158+ DEBUG_ONLY( char *strend = *buf + strlen(*buf); )
3159+
3160+ assert(strlen(end) <= 8);
3161+ newend[0] = '('; strcpy(newend + 1, end);
3162+
3163+ name = my_strdup(read_until_char(buf, newend));
3164+ if (name == NULL) return NULL;
3165+
3166+ dep = block_malloc(sizeof(dependency));
3167+ if (dep == NULL) die("read_dependency alloc 1:");
3168+
3169+ dep->package = name;
3170+
3171+ while(isspace(**buf)) (*buf)++;
3172+
3173+ if (**buf != '(') {
3174+ dep->op = dr_NOOP;
3175+ dep->version = NULL;
3176+ } else {
3177+ (*buf)++;
3178+ while(isspace(**buf)) (*buf)++;
3179+ /* << , <= , = , >= , >> */
3180+ if (**buf == '<') {
3181+ (*buf)++;
3182+ if (**buf == '<') {
3183+ dep->op = dr_LT;
3184+ (*buf)++;
3185+ } else if (**buf == '=') {
3186+ dep->op = dr_LTEQ;
3187+ (*buf)++;
3188+ } else {
3189+ /* The forms `<' and `>' were used to mean earlier/later or
3190+ * equal, rather than strictly earlier/later, so they should
3191+ * not appear in new packages (though `dpkg' still supports
3192+ * them).
3193+ */
3194+ dep->op = dr_LTEQ;
3195+ }
3196+ } else if (**buf == '>') {
3197+ (*buf)++;
3198+ if (**buf == '>') {
3199+ dep->op = dr_GT;
3200+ (*buf)++;
3201+ } else if (**buf == '=') {
3202+ dep->op = dr_GTEQ;
3203+ (*buf)++;
3204+ } else {
3205+ dep->op = dr_GTEQ;
3206+ }
3207+ } else if (**buf == '=') {
3208+ dep->op = dr_EQ;
3209+ (*buf)++;
3210+ if (**buf == '>') {
3211+ dep->op = dr_GTEQ;
3212+ (*buf)++;
3213+ } else if (**buf == '<') {
3214+ dep->op = dr_LTEQ;
3215+ (*buf)++;
3216+ }
3217+ } else {
3218+ /* treat it as an implicit = :( */
3219+ dep->op = dr_EQ;
3220+ /* would prefer to: die("read_dependency unknown version op"); */
3221+ }
3222+
3223+ while (isspace(**buf)) (*buf)++;
3224+ newend[0] = ')';
3225+ dep->version = my_strdup(read_until_char(buf, newend));
3226+ while (isspace(**buf)) (*buf)++;
3227+
3228+ if (dep->version == NULL) die("read_dependency: no version");
3229+ if (**buf != ')') die("read_dependency: unterminated version");
3230+ (*buf)++;
3231+ }
3232+
3233+ DEBUG_ONLY( assert(*buf <= strend); )
3234+
3235+ return dep;
3236+}
3237+
3238+static void free_dependency(dependency *dep) {
3239+ if (dep == NULL) return;
3240+ /* block_free(dep->package); */
3241+ /* if (dep->version) block_free(dep->version); */
3242+ block_free(dep, sizeof(dependency));
3243+}
3244+
3245+/*************************************************************************
3246+ * Installability Checking
3247+ */
3248+
3249+static collpackagelist **get_matching_low(collpackagelist **addto,
3250+ dpkg_packages *pkgs, dependency *dep, int line)
3251+{
3252+ virtualpkg *vpkg;
3253+ for (vpkg = lookup_virtualpkgtbl(pkgs->virtualpkgs, dep->package);
3254+ vpkg != NULL;
3255+ vpkg = vpkg->next)
3256+ {
3257+ int add;
3258+
3259+ add = 0;
3260+ if (dep->op == dr_NOOP) {
3261+ add = 1;
3262+ } else if (vpkg->value.version != NULL) {
3263+ if (cmpversions(vpkg->value.version, dep->op, dep->version)) {
3264+ add = 1;
3265+ }
3266+ }
3267+
3268+ if (add) {
3269+ insert_l_collpackagelist(addto, vpkg->value.pkg, line);
3270+ addto = &(*addto)->next;
3271+ }
3272+ }
3273+
3274+ return addto;
3275+}
3276+
3277+static collpackagelist *get_matching(dpkg_packages *pkgs, deplist *depopts, int line) {
3278+ collpackagelist *list = NULL;
3279+ collpackagelist **addto = &list;
3280+
3281+ for(; depopts != NULL; depopts = depopts->next) {
3282+ addto = get_matching_low(addto, pkgs, depopts->value, line);
3283+ }
3284+
3285+ return list;
3286+}
3287+
3288+typedef struct instonelist instonelist;
3289+struct instonelist {
3290+ collpackagelist *curX;
3291+ collpackagelist *instoneX;
3292+ int expandedX;
3293+ struct instonelist *nextX, *prevX, *cutoffX;
3294+};
3295+
3296+#define I1CUR(i1) ((i1)->curX)
3297+#define I1INSTONE(i1) ((i1)->instoneX)
3298+#define I1CUTOFF(i1) ((i1)->cutoffX)
3299+#define I1NEXT(i1) ((i1)->nextX) /* can be modified ! */
3300+#define I1PREV(i1) ((i1)->prevX)
3301+#define I1EXPANDED(i1) ((i1)->expandedX)
3302+
3303+static instonelist *insert_instonelist(instonelist *where, collpackagelist *instone);
3304+static void trim_instonelist_after(instonelist *first);
3305+static void free_instonelist(instonelist *l);
3306+
3307+static int max_instone_len = 0;
3308+static int cur_instone_len = 0;
3309+
3310+static instonelist *insert_instonelist(instonelist *old, collpackagelist *instone)
3311+{
3312+ instonelist *n = block_malloc(sizeof(instonelist));
3313+ if (n == NULL)
3314+ die("insert_instonelist alloc:");
3315+
3316+ n->curX = NULL;
3317+ n->instoneX = instone;
3318+ n->cutoffX = NULL;
3319+ n->nextX = (old ? old->nextX : NULL);
3320+ n->prevX = old;
3321+ n->expandedX = 0;
3322+
3323+ if (old) old->nextX = n;
3324+ if (n->nextX) n->nextX->prevX = n;
3325+
3326+ cur_instone_len++;
3327+ if (cur_instone_len > max_instone_len) max_instone_len = cur_instone_len;
3328+
3329+ return n;
3330+}
3331+
3332+static void trim_instonelist_after(instonelist *first) {
3333+ if (!first->nextX) return;
3334+ first->nextX->prevX = NULL;
3335+ free_instonelist(first->nextX);
3336+ first->nextX = NULL;
3337+}
3338+
3339+static void free_instonelist(instonelist *l) {
3340+ instonelist *p, *k;
3341+ if (!l) return;
3342+ for (p = l; p->nextX; p = p->nextX);
3343+ do {
3344+ k = p;
3345+ p = k->prevX;
3346+ free_collpackagelist(k->instoneX);
3347+ block_free(k, sizeof(instonelist));
3348+ cur_instone_len--;
3349+ } while (k != l);
3350+}
3351+
3352+static int caninstall(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
3353+ collpackagelist *conflicts;
3354+ collpackagelist *conf;
3355+ int okay;
3356+
3357+ if (cpkg->installed > 0) return 1;
3358+ if (cpkg->conflicted > 0) return 0;
3359+
3360+ conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__);
3361+
3362+ okay = 1;
3363+ for (conf = conflicts; conf != NULL; conf = conf->next) {
3364+ if (conf->value->installed > 0) {
3365+ okay = 0;
3366+ break;
3367+ }
3368+ }
3369+ free_collpackagelist(conflicts);
3370+ return okay;
3371+}
3372+
3373+static int cur_install =0;
3374+static int max_install = 0;
3375+static int cur_conflicted = 0;
3376+static int max_conflicted = 0;
3377+
3378+static void install(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
3379+ if (cpkg->installed == 0) {
3380+ collpackagelist *conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__);
3381+ collpackagelist *conf;
3382+ for (conf = conflicts; conf != NULL; conf = conf->next) {
3383+ if (conf->value == cpkg) continue;
3384+ assert(conf->value->installed == 0);
3385+ conf->value->conflicted++;
3386+ if (conf->value->conflicted == 1) {
3387+ cur_conflicted++;
3388+ if (max_conflicted < cur_conflicted)
3389+ max_conflicted = cur_conflicted;
3390+ }
3391+ }
3392+ free_collpackagelist(conflicts);
3393+ cur_install++;
3394+ if (max_install < cur_install) max_install = cur_install;
3395+ }
3396+ assert(cpkg->conflicted == 0);
3397+ cpkg->installed++;
3398+}
3399+
3400+static void uninstall(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
3401+ assert(cpkg->installed > 0);
3402+ assert(cpkg->conflicted == 0);
3403+ cpkg->installed--;
3404+ if (cpkg->installed == 0) {
3405+ collpackagelist *conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__);
3406+ collpackagelist *conf;
3407+ for (conf = conflicts; conf != NULL; conf = conf->next) {
3408+ if (conf->value == cpkg) continue;
3409+ assert(conf->value->installed == 0);
3410+ assert(conf->value->conflicted > 0);
3411+ conf->value->conflicted--;
3412+ if (conf->value->conflicted == 0) cur_conflicted--;
3413+ }
3414+ free_collpackagelist(conflicts);
3415+ cur_install--;
3416+ }
3417+}
3418+
3419+satisfieddep *new_satisfieddep(void) {
3420+ satisfieddep *sd = block_malloc(sizeof(satisfieddep));
3421+ if (!sd) die("new_satisfieddep alloc:");
3422+ return sd;
3423+}
3424+
3425+void free_satisfieddep(satisfieddep *sd) {
3426+ if (!sd) return;
3427+ free_packagelist(sd->pkgs);
3428+ block_free(sd, sizeof(satisfieddep));
3429+}
3430+
3431+LIST_IMPL(satisfieddeplist, satisfieddep *, free_satisfieddep, block_malloc, block_free);
3432+
3433+packagelist *collpkglist2pkglist(collpackagelist *l) {
3434+ packagelist *r = NULL;
3435+ packagelist **addto = &r;
3436+
3437+ for (; l != NULL; l = l->next) {
3438+ insert_packagelist(addto, l->value->pkg);
3439+ addto = &(*addto)->next;
3440+ }
3441+
3442+ return r;
3443+}
3444+
3445+satisfieddeplist *checkunsatisfiabledeps(dpkg_packages *pkgs,
3446+ deplistlist *deps) {
3447+ satisfieddeplist *unsatisfiable = NULL;
3448+ satisfieddeplist **addto = &unsatisfiable;
3449+ satisfieddep *sd;
3450+ collpackagelist *deppkgs;
3451+
3452+ for (; deps != NULL; deps = deps->next) {
3453+ /* deplist *dep; */
3454+ /* for (dep = deps->value; dep != NULL; dep = dep->next) { */
3455+ sd = new_satisfieddep();
3456+ /* sd->dep = dep->value; */
3457+ sd->depl = deps->value;
3458+
3459+ deppkgs = NULL;
3460+ /* get_matching_low(&deppkgs, pkgs, dep->value); */
3461+ deppkgs = get_matching(pkgs, deps->value, __LINE__);
3462+ sd->pkgs = collpkglist2pkglist(deppkgs);
3463+ free_collpackagelist(deppkgs);
3464+
3465+ insert_satisfieddeplist(addto, sd);
3466+ addto = &(*addto)->next;
3467+ /* } */
3468+ }
3469+
3470+ return unsatisfiable;
3471+}
3472+
3473+int checkinstallable2(dpkg_packages *pkgs, char *pkgname) {
3474+ dpkg_collected_package *cpkg = lookup_packagetbl(pkgs->packages, pkgname);
3475+ collpackagelist *cpl = NULL;
3476+
3477+ if (cpkg == NULL) return 0;
3478+
3479+ insert_collpackagelist(&cpl, cpkg);
3480+ /* cpl gets freed in checkinstallable :-/ */
3481+ return checkinstallable(pkgs, cpl);
3482+}
3483+
3484+static void debug_checkinstallable(FILE *out, instonelist *list,
3485+ instonelist *last, instonelist *pointer)
3486+{
3487+ instonelist *l;
3488+ fprintf(out, "Status:");
3489+
3490+ /* codes: | = multiple options here
3491+ * @ = no options can satisfy this dep
3492+ * + = dependencies that can be expanded have been
3493+ * * = nothing selected yet
3494+ * > = where pointer points
3495+ * ^ = the cut point for where we are
3496+ */
3497+
3498+ for (l = list; ; l = I1NEXT(l)) {
3499+ fprintf(out, " ");
3500+ if (l == pointer) fprintf(out, ">");
3501+ if (l == I1CUTOFF(pointer)) fprintf(out, "^");
3502+ if (I1INSTONE(l) == NULL) {
3503+ fprintf(out, "@");
3504+ } else {
3505+ if (I1INSTONE(l)->next != NULL) {
3506+ fprintf(out, "|");
3507+ }
3508+ if (I1EXPANDED(l)) {
3509+ fprintf(out, "+");
3510+ }
3511+ if (I1CUR(l) == NULL) {
3512+ fprintf(out, "*%s", I1INSTONE(l)->value->pkg->package);
3513+ } else {
3514+ fprintf(out, "%s", I1CUR(l)->value->pkg->package);
3515+ }
3516+ }
3517+ if (l == last) break;
3518+ }
3519+ fprintf(out, " ###\n");
3520+ fflush(out);
3521+}
3522+
3523+int checkinstallable(dpkg_packages *pkgs, collpackagelist *instoneof) {
3524+ /* We use pkg->installed, pkg->conflicted to note how many
3525+ * times we've used this pkg to satisfy a dependency or installed
3526+ * a package that conflicts with it.
3527+ * Thus: pkg->installed == 0, or pkg->conflicted == 0
3528+ *
3529+ * We assume these are okay initially, aren't being played with
3530+ * concurrently elsewhere, and make sure they're still okay when
3531+ * we return.
3532+ */
3533+
3534+ instonelist *list;
3535+ instonelist *last;
3536+
3537+ instonelist *pointer;
3538+
3539+ unsigned long counter = 500000000;
3540+
3541+ int last_max_inst = max_install;
3542+ int last_max_instone = max_instone_len;
3543+ int last_max_conflict = max_conflicted;
3544+
3545+ {
3546+ collpackagelist *cpkg;
3547+ for (cpkg = instoneof; cpkg; cpkg = cpkg->next) {
3548+ if (cpkg->value->installable == YES) {
3549+ free_collpackagelist(instoneof);
3550+ return 1;
3551+ }
3552+ }
3553+ }
3554+
3555+ list = insert_instonelist(NULL, instoneof);
3556+
3557+ last = list;
3558+ pointer = list;
3559+
3560+ while(--counter > 0 && pointer) {
3561+ deplistlist *dep;
3562+ dpkg_collected_package *instpkg; /* convenient alias */
3563+ int i;
3564+
3565+#ifndef NDEBUG
3566+ {
3567+ instonelist *p;
3568+ for (p = list; p != pointer; p = I1NEXT(p)) {
3569+ assert(p != NULL);
3570+ assert(I1CUR(p) != NULL);
3571+ assert(I1CUR(p)->value != NULL);
3572+ assert(I1CUR(p)->value->installed > 0);
3573+ assert(I1CUR(p)->value->conflicted == 0);
3574+ }
3575+ if (I1NEXT(pointer) == NULL) {
3576+ assert(pointer == last);
3577+ } else {
3578+ for (p = I1NEXT(pointer); p; p = I1NEXT(p)) {
3579+ if (I1NEXT(p) == NULL) {
3580+ assert(p == last);
3581+ }
3582+ assert(I1CUR(p) == NULL);
3583+ }
3584+ }
3585+ }
3586+#endif
3587+
3588+#ifdef DIAGNOSE
3589+ debug_checkinstallable(stdout, list, last, pointer);
3590+#endif
3591+
3592+ if (I1CUR(pointer) == NULL) {
3593+ I1CUR(pointer) = I1INSTONE(pointer);
3594+ /* try to choose an already installed package if there is one */
3595+ while (I1CUR(pointer) != NULL) {
3596+ if (I1CUR(pointer)->value->installed != 0) {
3597+ break;
3598+ }
3599+ I1CUR(pointer) = I1CUR(pointer)->next;
3600+ }
3601+ if (I1CUR(pointer) == NULL) {
3602+ I1CUR(pointer) = I1INSTONE(pointer);
3603+ }
3604+ assert(I1CUR(pointer) || !I1INSTONE(pointer));
3605+
3606+ I1CUTOFF(pointer) = last;
3607+ } else {
3608+ uninstall(pkgs, I1CUR(pointer)->value);
3609+ trim_instonelist_after(I1CUTOFF(pointer));
3610+ last = I1CUTOFF(pointer);
3611+
3612+ if (I1CUR(pointer)->value->installed > 0) {
3613+ /* this dependency isn't the issue -- even doing
3614+ * nothing to satisfy it (ie, using an already
3615+ * installed package) doesn't do any good. So give up.
3616+ */
3617+ I1CUR(pointer) = NULL;
3618+ } else {
3619+ I1CUR(pointer) = I1CUR(pointer)->next;
3620+ }
3621+ }
3622+
3623+ while(I1CUR(pointer) && !caninstall(pkgs, I1CUR(pointer)->value)) {
3624+ I1CUR(pointer) = I1CUR(pointer)->next;
3625+ }
3626+
3627+ if (I1CUR(pointer) == NULL) {
3628+ if (I1PREV(pointer) == NULL) break;
3629+ pointer = I1PREV(pointer);
3630+ continue;
3631+ }
3632+
3633+ instpkg = I1CUR(pointer)->value;
3634+
3635+ install(pkgs, instpkg);
3636+
3637+ assert(instpkg->installed > 0);
3638+ if (instpkg->installed == 1) {
3639+ /* if it's been installed exactly once, then this must've been
3640+ * the first time it was touched, so we need to look at the
3641+ * dependencies. If it's the second or later, then we don't care
3642+ * about them.
3643+ */
3644+
3645+ /* if any of the deps can't be satisfied, don't move on */
3646+ int bother = 1;
3647+
3648+ int expanded = I1EXPANDED(pointer);
3649+
3650+ for (i = 0; i < 4; i++) {
3651+ if (!dependency_counts[i]) continue;
3652+ for (dep = instpkg->pkg->depends[i];
3653+ dep != NULL; dep = dep->next)
3654+ {
3655+ collpackagelist *thisdep = get_matching(pkgs, dep->value, __LINE__);
3656+
3657+ if (thisdep == NULL) {
3658+ bother = 0;
3659+
3660+ } else if (thisdep != NULL && thisdep->next == NULL) {
3661+ collpackagelist *x;
3662+
3663+ /* if there's only one way of fulfilling this dep,
3664+ * do it "ASAP"
3665+ */
3666+
3667+ /* optimisation: if thisdep == foo, but the parent
3668+ * was foo|bar, then we already know "foo" is not going
3669+ * to work in this combination, and we can skip it.
3670+ *
3671+ * This deals with cases like X deps: Y|bar, bar deps: Y
3672+ * where bar is a virtual package; cf xlibs
3673+ */
3674+ for (x = I1INSTONE(pointer); x != I1CUR(pointer); x = x->next) {
3675+ if (x->value == thisdep->value) {
3676+ bother = 0;
3677+ break;
3678+ }
3679+ }
3680+
3681+ if (I1INSTONE(pointer)->next == NULL) {
3682+ /* the parent of this entry essentially depends
3683+ * on this too, so we'll get it out of the way
3684+ * ASAP, to reduce the degree of exponentiation
3685+ * in bad cases.
3686+ *
3687+ * _However_ we only want to do this _once_ for
3688+ * any particular node.
3689+ */
3690+ if (expanded) {
3691+ /* thisdep isn't used! */
3692+ free_collpackagelist(thisdep);
3693+ } else {
3694+ insert_instonelist(pointer, thisdep);
3695+ I1EXPANDED(pointer) = 1;
3696+ }
3697+ } else {
3698+ insert_instonelist(I1CUTOFF(pointer), thisdep);
3699+ }
3700+ if (I1NEXT(last)) last = I1NEXT(last);
3701+ assert(!I1NEXT(last));
3702+
3703+ } else {
3704+ /* otherwise it's a multi possibility dep, so do it
3705+ * at the end
3706+ */
3707+
3708+ last = insert_instonelist(last, thisdep);
3709+ }
3710+ }
3711+ }
3712+ if (!bother) {
3713+ /* stay where we are, and try the next possibility */
3714+ continue;
3715+ }
3716+ }
3717+
3718+ pointer = I1NEXT(pointer);
3719+ }
3720+
3721+ if (max_install>last_max_inst || max_instone_len>last_max_instone || max_conflicted >last_max_conflict) {
3722+ printf("MAX: i:%d / c:%d / i1:%d %s\n", max_install,max_conflicted,max_instone_len,instoneof->value->pkg->package);
3723+ }
3724+
3725+ if (counter == 0) {
3726+ fprintf(stderr, "AIEEE: counter overflow:");
3727+ assert(pointer != NULL);
3728+ if (I1CUR(pointer) == NULL || I1CUR(pointer)->value == NULL) {
3729+ /* we're not guaranteed that pointer will make sense here */
3730+ pointer = I1PREV(pointer);
3731+ }
3732+ for (; pointer != NULL; pointer = I1PREV(pointer)) {
3733+ if (I1CUR(pointer) == NULL) {
3734+ /* should only happen at pointer, so not here */
3735+ fprintf(stderr, " >> eep, no packages at pointer <<");
3736+ continue;
3737+ }
3738+ if (I1CUR(pointer)->value == NULL) {
3739+ /* should never happen */
3740+ fprintf(stderr, " >> eep, no package selected <<");
3741+ continue;
3742+ }
3743+ fprintf(stderr, " %s%s",
3744+ (I1INSTONE(pointer)->next == NULL ? "" : "|"),
3745+ I1CUR(pointer)->value->pkg->package);
3746+ uninstall(pkgs, I1CUR(pointer)->value);
3747+ }
3748+ fprintf(stderr, ".\n");
3749+ free_instonelist(list);
3750+ return 0;
3751+ }
3752+
3753+ if (pointer == NULL) {
3754+ dpkg_collected_package *cpkg = I1CUR(list)->value;
3755+ assert(cpkg->installable != YES);
3756+ cpkg->installable = YES;
3757+ for (pointer = last; pointer != NULL; pointer = I1PREV(pointer)) {
3758+ if (I1CUR(pointer)->value->installed == 1) {
3759+ packagenamelist **p = &I1CUR(pointer)->value->mayaffect;
3760+#if 0
3761+ while ( *p && (*p)->value < cpkg->pkg->package ) {
3762+ p = &(*p)->next;
3763+ }
3764+ if (*p == NULL || (*p)->value > cpkg->pkg->package)
3765+#endif
3766+ {
3767+ insert_packagenamelist(p, cpkg->pkg->package);
3768+ }
3769+ }
3770+ uninstall(pkgs, I1CUR(pointer)->value);
3771+ }
3772+ free_instonelist(list);
3773+ return 1;
3774+ } else {
3775+ assert(I1CUR(list) == NULL);
3776+ free_instonelist(list);
3777+ return 0;
3778+ }
3779+}
3780+
3781+/******************/
3782+
3783+HASH_IMPL(sourcetbl, char *, dpkg_source *, SIZEOFHASHMAP, strhash, strcmp,
3784+ KEEP(char*), free_source);
3785+
3786+static dpkg_sources *read_sources_file(char *filename, int n_arches) {
3787+ FILE *f;
3788+ dpkg_sources *result;
3789+ dpkg_source *src;
3790+ int i;
3791+
3792+ f = fopen(filename, "r");
3793+ if (f == NULL && errno != ENOENT) {
3794+ die("read_sources_file: couldn't open file:");
3795+ }
3796+
3797+ result = block_malloc(sizeof(dpkg_sources));
3798+ if (result == NULL) die("read_sources_file alloc 1:");
3799+
3800+ result->n_arches = n_arches;
3801+ result->archname = block_malloc(sizeof(char*) * n_arches);
3802+ if (result->archname == NULL) die("read_sources_file alloc 2:");
3803+ for (i = 0; i < n_arches; i++) result->archname[i] = NULL;
3804+ result->unclaimedpackages = block_malloc(sizeof(ownedpackagelist*)
3805+ * n_arches);
3806+ if (result->unclaimedpackages == NULL) die("read_sources_file alloc 3:");
3807+ for (i = 0; i < n_arches; i++) result->unclaimedpackages[i] = NULL;
3808+
3809+ result->sources = new_sourcetbl();
3810+
3811+ if (f != NULL) {
3812+ while ((src = read_source(f, result))) {
3813+ dpkg_source *old = lookup_sourcetbl(result->sources, src->package);
3814+ if (old == NULL) {
3815+ add_sourcetbl(result->sources, src->package, src);
3816+ } else {
3817+ if (versioncmp(old->version, src->version) || 1) {
3818+ int i;
3819+ old = replace_sourcetbl(result->sources, src->package, src);
3820+ for (i = 0; i < old->owner->n_arches; i++) {
3821+ assert(old->packages[i] == NULL);
3822+ }
3823+ free_source(old);
3824+ } else {
3825+ int i;
3826+ for (i = 0; i < src->owner->n_arches; i++) {
3827+ assert(src->packages[i] == NULL);
3828+ }
3829+ free_source(src);
3830+ }
3831+ }
3832+ }
3833+ fclose(f);
3834+ }
3835+
3836+ return result;
3837+}
3838+
3839+void free_sources(dpkg_sources *s) {
3840+ int i;
3841+ if (s == NULL) return;
3842+ free_sourcetbl(s->sources);
3843+ for (i = 0; i < s->n_arches; i++) {
3844+ /* block_free(s->archname[i]); */
3845+ free_ownedpackagelist(s->unclaimedpackages[i]);
3846+ }
3847+ block_free(s->archname, s->n_arches * sizeof(char*));
3848+ block_free(s->unclaimedpackages, s->n_arches * sizeof(ownedpackagelist*));
3849+ block_free(s, sizeof(dpkg_sources));
3850+}
3851+
3852+static dpkg_source *new_source(dpkg_sources *owner) {
3853+ dpkg_source *result;
3854+ int i;
3855+
3856+ result = block_malloc(sizeof(dpkg_source));
3857+ if (result == NULL) die("new_source alloc 1:");
3858+
3859+ result->package = NULL;
3860+ result->version = NULL;
3861+ result->details = NULL;
3862+ result->fake = 0;
3863+
3864+ result->owner = owner;
3865+ result->packages = block_malloc(sizeof(packagelist*) * owner->n_arches);
3866+ if (result->packages == NULL) die("new_source alloc 2:");
3867+ for (i = 0; i < owner->n_arches; i++) {
3868+ result->packages[i] = NULL;
3869+ }
3870+
3871+ return result;
3872+}
3873+
3874+static dpkg_source *read_source(FILE *f, dpkg_sources *owner) {
3875+ dpkg_source *result;
3876+ dpkg_paragraph *para;
3877+ dpkg_entry *e;
3878+
3879+ para = read_paragraph(f);
3880+ if (para == NULL) return NULL;
3881+
3882+ result = new_source(owner);
3883+ result->details = para;
3884+
3885+ for (e = &para->entry[0]; e < &para->entry[para->n_entries]; e++) {
3886+ if (strcmp("Package", e->name) == 0) {
3887+ result->package = my_strdup(e->value);
3888+ if (result->package == NULL)
3889+ die("read_source strdup:");
3890+ result->package[strlen(result->package)-1] = '\0';
3891+ }
3892+
3893+ if (strcmp("Version", e->name) == 0) {
3894+ result->version = my_strdup(e->value);
3895+ if (result->version == NULL)
3896+ die("read_source strdup:");
3897+ result->version[strlen(result->version)-1] = '\0';
3898+ }
3899+ }
3900+
3901+ return result;
3902+}
3903+
3904+void free_source(dpkg_source *s) {
3905+ int i;
3906+ if (s == NULL) return;
3907+ assert(s->owner != NULL); /* shouldn't have allocated it */
3908+ /* block_free(s->package); */
3909+ /* block_free(s->version); */
3910+ free_paragraph(s->details);
3911+ for (i = 0; i < s->owner->n_arches; i++) {
3912+ free_ownedpackagelist(s->packages[i]);
3913+ }
3914+ block_free(s->packages, s->owner->n_arches * sizeof(ownedpackagelist*));
3915+ block_free(s, sizeof(dpkg_source));
3916+}
3917+
3918+/******************************/
3919+
3920+dpkg_sources *read_directory(char *dir, int n_arches, char *archname[]) {
3921+ char buf[1000];
3922+ dpkg_sources *srcs;
3923+ int i;
3924+
3925+ snprintf(buf, 1000, "%s/Sources", dir);
3926+ srcs = read_sources_file(buf, n_arches);
3927+
3928+ for (i = 0; i < n_arches; i++) {
3929+ FILE *f;
3930+ dpkg_package *pkg;
3931+
3932+ srcs->archname[i] = my_strdup(archname[i]);
3933+
3934+ snprintf(buf, 1000, "%s/Packages_%s", dir, archname[i]);
3935+ f = fopen(buf, "r");
3936+ if (f == NULL && errno != ENOENT) die("load_dirctory fopen:");
3937+ if (f != NULL) {
3938+ while ((pkg = read_package(f))) {
3939+ dpkg_source *src = lookup_sourcetbl(srcs->sources, pkg->source);
3940+ if (src == NULL) {
3941+ src = new_source(srcs);
3942+ src->fake = 1;
3943+ src->package = my_strdup(pkg->source);
3944+ src->version = my_strdup(pkg->source_ver);
3945+ add_sourcetbl(srcs->sources, src->package, src);
3946+ }
3947+ insert_ownedpackagelist(&src->packages[i], pkg);
3948+ }
3949+ fclose(f);
3950+ }
3951+ }
3952+
3953+ return srcs;
3954+}
3955+
3956+void write_directory(char *dir, dpkg_sources *srcs) {
3957+ FILE *src;
3958+ FILE *archfile[100];
3959+ char buf[1000];
3960+ int i;
3961+ sourcetbl_iter srciter;
3962+
3963+ snprintf(buf, 1000, "%s/Sources", dir);
3964+ src = fopen(buf, "w");
3965+ if (!src) die("write_directory: Couldn't open Sources file for output");
3966+
3967+ for (i = 0; i < srcs->n_arches; i++) {
3968+ snprintf(buf, 1000, "%s/Packages_%s", dir, srcs->archname[i]);
3969+ archfile[i] = fopen(buf, "w");
3970+ }
3971+
3972+ for (srciter = first_sourcetbl(srcs->sources);
3973+ !done_sourcetbl(srciter);
3974+ srciter = next_sourcetbl(srciter))
3975+ {
3976+ ownedpackagelist *p;
3977+ int i;
3978+
3979+ if (!srciter.v->fake)
3980+ write_paragraph(src, srciter.v->details);
3981+
3982+ for (i = 0; i < srcs->n_arches; i++) {
3983+ for (p = srciter.v->packages[i]; p != NULL; p = p->next) {
3984+ write_paragraph(archfile[i], p->value->details);
3985+ }
3986+ }
3987+ }
3988+
3989+ fclose(src);
3990+ for (i = 0; i < srcs->n_arches; i++) {
3991+ fclose(archfile[i]);
3992+ }
3993+}
3994+
3995+/*********************/
3996+
3997+HASH_IMPL(sourcenotetbl, char *, dpkg_source_note *, SIZEOFHASHMAP, strhash, strcmp,
3998+ KEEP(char*), free_source_note);
3999+
4000+dpkg_source_note *new_source_note(dpkg_source *src, int n_arches) {
4001+ dpkg_source_note *result = block_malloc(sizeof(dpkg_source_note));
4002+ int i;
4003+
4004+ if (result == NULL) die("new_source_note alloc 1:");
4005+ result->source = src;
4006+ result->n_arches = n_arches;
4007+ result->binaries = block_malloc(n_arches * sizeof(packagelist*));
4008+ if (result->binaries == NULL) die("new_source_note alloc 2:");
4009+ for (i = 0; i < n_arches; i++) {
4010+ result->binaries[i] = NULL;
4011+ }
4012+ return result;
4013+}
4014+
4015+void free_source_note(dpkg_source_note *srcn) {
4016+ int i;
4017+
4018+ if (srcn == NULL) return;
4019+
4020+ if (srcn->binaries != NULL) {
4021+ for (i = 0; i < srcn->n_arches; i++) {
4022+ free_packagelist(srcn->binaries[i]);
4023+ }
4024+ block_free(srcn->binaries, sizeof(packagelist*) * srcn->n_arches);
4025+ }
4026+ block_free(srcn, sizeof(dpkg_source_note));
4027+}
4028+
4029+#ifdef DEBUG
4030+static int is_sources_note(dpkg_sources_note *srcsn) {
4031+ int i;
4032+
4033+ assert(srcsn != NULL);
4034+ assert(srcsn->magic == 0xa1eebabe);
4035+ assert(srcsn->pkgs != NULL);
4036+ for (i = 0; i < srcsn->n_arches; i++) {
4037+ assert(srcsn->pkgs[i] != NULL && srcsn->archname[i] != NULL);
4038+ assert(strcmp(srcsn->archname[i], srcsn->pkgs[i]->arch) == 0);
4039+ }
4040+
4041+ return 1;
4042+}
4043+#endif
4044+
4045+dpkg_sources_note *new_sources_note(int n_arches, char **archname) {
4046+ dpkg_sources_note *result = block_malloc(sizeof(dpkg_sources_note));
4047+ int i;
4048+
4049+ if (result == NULL) die("new_sources_note alloc 1:");
4050+ result->magic = 0xA1EEBABE;
4051+ result->sources = new_sourcenotetbl();
4052+ result->pkgs = block_malloc(n_arches * sizeof(dpkg_packages*));
4053+ if (result->pkgs == NULL) die("new_sources_note alloc 2:");
4054+ result->archname = block_malloc(n_arches * sizeof(char*));
4055+ if (result->archname == NULL) die("new_sources_note alloc 3:");
4056+
4057+ result->n_arches = n_arches;
4058+ for (i = 0; i < n_arches; i++) {
4059+ result->archname[i] = my_strdup(archname[i]);
4060+ result->pkgs[i] = new_packages(result->archname[i]);
4061+ }
4062+ result->undo = NULL;
4063+ return result;
4064+}
4065+
4066+void free_sources_note(dpkg_sources_note *srcsn) {
4067+ int i;
4068+ if (srcsn == NULL) return;
4069+ assert(is_sources_note(srcsn));
4070+ srcsn->magic = 0xBABEA1EE;
4071+ free_sourcenotetbl(srcsn->sources);
4072+ for (i = 0; i < srcsn->n_arches; i++) {
4073+ free_packages(srcsn->pkgs[i]);
4074+ /* block_free(srcsn->archname[i]); */
4075+ }
4076+ block_free(srcsn->pkgs, sizeof(dpkg_packages*) * srcsn->n_arches);
4077+ block_free(srcsn->archname, sizeof(char*) * srcsn->n_arches);
4078+ free_source_note_listlist(srcsn->undo);
4079+ block_free(srcsn, sizeof(dpkg_sources_note));
4080+}
4081+
4082+static void new_op(dpkg_sources_note *srcsn) {
4083+ assert(is_sources_note(srcsn));
4084+ insert_source_note_listlist(&srcsn->undo, NULL);
4085+}
4086+static void save_source_note(dpkg_sources_note *srcsn, dpkg_source_note *srcn) {
4087+ source_note_list **where;
4088+ assert(is_sources_note(srcsn));
4089+ assert(srcsn->undo != NULL);
4090+
4091+ for (where = &srcsn->undo->value;
4092+ *where != NULL;
4093+ where = &(*where)->next)
4094+ {
4095+ if ((*where)->value->source == srcn->source)
4096+ return; /* already saved */
4097+ }
4098+
4099+ insert_source_note_list(where, copy_source_note(srcn));
4100+}
4101+static void save_empty_source_note(dpkg_sources_note *srcsn, dpkg_source *src) {
4102+ dpkg_source_note *srcn;
4103+ source_note_list **where;
4104+
4105+ for (where = &srcsn->undo->value;
4106+ *where != NULL;
4107+ where = &(*where)->next)
4108+ {
4109+ if ((*where)->value->source == src)
4110+ return; /* already saved */
4111+ }
4112+
4113+ srcn = block_malloc(sizeof(dpkg_source_note));
4114+ if (srcn == NULL) die("save_empty_source_note alloc:");
4115+ assert(is_sources_note(srcsn));
4116+
4117+ srcn->source = src;
4118+ srcn->n_arches = 0;
4119+ srcn->binaries = NULL;
4120+
4121+ insert_source_note_list(where, srcn);
4122+}
4123+
4124+typedef enum { DO_ARCHALL = 0, SKIP_ARCHALL = 1 } do_this;
4125+static void remove_binaries_by_arch(dpkg_sources_note *srcsn,
4126+ dpkg_source_note *srcn, int archnum,
4127+ do_this arch_all)
4128+{
4129+ packagelist *p;
4130+ packagelist *leftovers = NULL, **addto = &leftovers;
4131+ assert(is_sources_note(srcsn));
4132+
4133+ assert(arch_all == SKIP_ARCHALL || NULL == lookup_sourcenotetbl(srcsn->sources,srcn->source->package));
4134+ /* if we're removing the entire binary, we should already have
4135+ * removed the source. if we're removing just the binaries on this
4136+ * arch (not arch:all) then we may be keeping the source
4137+ *
4138+ * really a logical XOR, I think. we don't rely on this assertion
4139+ * here
4140+ */
4141+
4142+ for (p = srcn->binaries[archnum]; p != NULL; p = p->next) {
4143+ dpkg_collected_package *cpkg;
4144+ if (arch_all == SKIP_ARCHALL && p->value->arch_all) {
4145+ insert_packagelist(addto, p->value);
4146+ addto = &(*addto)->next;
4147+ continue;
4148+ }
4149+ cpkg = lookup_packagetbl(srcsn->pkgs[archnum]->packages,
4150+ p->value->package);
4151+ remove_package(srcsn->pkgs[archnum], cpkg);
4152+ }
4153+ free_packagelist(srcn->binaries[archnum]);
4154+ srcn->binaries[archnum] = leftovers;
4155+}
4156+
4157+typedef enum { NOTUNDOABLE = 0, UNDOABLE = 1 } undoable;
4158+static void add_binaries_by_arch(dpkg_sources_note *srcsn,
4159+ dpkg_source_note *srcn, dpkg_source *src,
4160+ int archnum, undoable undoop, do_this arch_all)
4161+{
4162+ ownedpackagelist *p;
4163+ const char *archname = srcsn->archname[archnum];
4164+ int origarchnum = -1;
4165+ int i;
4166+
4167+ assert(is_sources_note(srcsn));
4168+ assert(srcn == lookup_sourcenotetbl(srcsn->sources,srcn->source->package));
4169+ for (i = 0; i < src->owner->n_arches; i++) {
4170+ if (strcmp(archname, src->owner->archname[i]) == 0) {
4171+ origarchnum = i;
4172+ break;
4173+ }
4174+ }
4175+ if (origarchnum == -1) return; /* nothing to add, no biggie */
4176+
4177+ for (p = src->packages[origarchnum]; p != NULL; p = p->next) {
4178+ dpkg_collected_package *cpkg;
4179+
4180+ if (arch_all == SKIP_ARCHALL && p->value->arch_all) continue;
4181+
4182+ if ((cpkg = lookup_packagetbl(srcsn->pkgs[archnum]->packages,
4183+ p->value->package)))
4184+ {
4185+ dpkg_source_note *srcnB;
4186+ packagelist **p;
4187+
4188+ if (!undoop) {
4189+ printf("conflict w/o undo: binary %s, owned by %s, replaced by %s\n", cpkg->pkg->package, cpkg->pkg->source, src->package);
4190+ fflush(stdout);
4191+ }
4192+ srcnB = lookup_sourcenotetbl(srcsn->sources, cpkg->pkg->source);
4193+ assert(srcnB != NULL);
4194+
4195+ for (p = &srcnB->binaries[archnum]; *p != NULL; p = &(*p)->next) {
4196+ if ((*p)->value == cpkg->pkg) break;
4197+ }
4198+ assert(*p != NULL); /* binary should be from source */
4199+
4200+ assert(undoop);
4201+ save_source_note(srcsn, srcnB);
4202+ remove_package(srcsn->pkgs[archnum], cpkg);
4203+ remove_packagelist(p);
4204+ }
4205+
4206+ add_package(srcsn->pkgs[archnum], p->value);
4207+ insert_packagelist(&srcn->binaries[archnum], p->value);
4208+ }
4209+}
4210+
4211+void upgrade_source(dpkg_sources_note *srcsn, dpkg_source *src) {
4212+ dpkg_source_note *srcn;
4213+ int i;
4214+
4215+ new_op(srcsn);
4216+
4217+ assert(is_sources_note(srcsn));
4218+ /* first, find the old source, if it exists */
4219+ srcn = remove_sourcenotetbl(srcsn->sources, src->package);
4220+ if (srcn != NULL) {
4221+ save_source_note(srcsn, srcn);
4222+ for (i = 0; i < srcn->n_arches; i++) {
4223+ remove_binaries_by_arch(srcsn, srcn, i, DO_ARCHALL);
4224+ }
4225+ free_source_note(srcn);
4226+ } else {
4227+ save_empty_source_note(srcsn, src);
4228+ }
4229+
4230+ /* then add the new one */
4231+ srcn = new_source_note(src, srcsn->n_arches);
4232+ add_sourcenotetbl(srcsn->sources, src->package, srcn);
4233+ for (i = 0; i < srcsn->n_arches; i++) {
4234+ add_binaries_by_arch(srcsn, srcn, src, i, UNDOABLE, DO_ARCHALL);
4235+ }
4236+ assert(is_sources_note(srcsn));
4237+}
4238+
4239+void upgrade_arch(dpkg_sources_note *srcsn, dpkg_source *src, char *arch) {
4240+ dpkg_source_note *srcn;
4241+ int archnum = -1;
4242+ int i;
4243+
4244+ assert(is_sources_note(srcsn));
4245+ /* first, find the old source */
4246+ srcn = lookup_sourcenotetbl(srcsn->sources, src->package);
4247+
4248+ assert(srcn != NULL);
4249+ new_op(srcsn);
4250+ save_source_note(srcsn, srcn);
4251+
4252+ /* then lookup the archnum */
4253+ for (i = 0; i < srcsn->n_arches; i++) {
4254+ if (strcmp(arch, srcsn->archname[i]) == 0) {
4255+ archnum = i;
4256+ break;
4257+ }
4258+ }
4259+ if (archnum == -1) die("upgrade_arch: unknown arch");
4260+
4261+ /* then remove the old stuff and add the new */
4262+ remove_binaries_by_arch(srcsn, srcn, archnum, SKIP_ARCHALL);
4263+ add_binaries_by_arch(srcsn, srcn, src, archnum, UNDOABLE, SKIP_ARCHALL);
4264+ assert(is_sources_note(srcsn));
4265+}
4266+
4267+void remove_source(dpkg_sources_note *srcsn, char *name) {
4268+ dpkg_source_note *srcn;
4269+ int i;
4270+
4271+ assert(is_sources_note(srcsn));
4272+ srcn = remove_sourcenotetbl(srcsn->sources, name);
4273+ assert(srcn != NULL);
4274+
4275+ new_op(srcsn);
4276+ save_source_note(srcsn, srcn);
4277+ for (i = 0; i < srcn->n_arches; i++) {
4278+ remove_binaries_by_arch(srcsn, srcn, i, DO_ARCHALL);
4279+ }
4280+ free_source_note(srcn);
4281+ assert(is_sources_note(srcsn));
4282+}
4283+
4284+int can_undo(dpkg_sources_note *srcsn) {
4285+ assert(is_sources_note(srcsn));
4286+ return srcsn->undo != NULL;
4287+}
4288+
4289+void undo_change(dpkg_sources_note *srcsn) {
4290+ dpkg_source_note *srcnO, *srcnC; /* old, current */
4291+ source_note_list *srcnl;
4292+ int i;
4293+
4294+ assert(is_sources_note(srcsn));
4295+ assert(can_undo(srcsn));
4296+
4297+ srcnl = remove_source_note_listlist(&srcsn->undo);
4298+
4299+ while(srcnl) {
4300+ srcnO = remove_source_note_list(&srcnl);
4301+ assert(srcnO != NULL); /* can_undo() implies this is true... */
4302+
4303+ srcnC = remove_sourcenotetbl(srcsn->sources, srcnO->source->package);
4304+ if (srcnC != NULL) {
4305+ for (i = 0; i < srcnC->n_arches; i++) {
4306+ remove_binaries_by_arch(srcsn, srcnC, i, DO_ARCHALL);
4307+ }
4308+ free_source_note(srcnC);
4309+ assert(!lookup_sourcenotetbl(srcsn->sources,
4310+ srcnO->source->package));
4311+ }
4312+
4313+ if (srcnO->binaries == NULL) {
4314+ /* no original source */
4315+ assert(srcnC != NULL); /* some sort of no-op? freaky. */
4316+ free_source_note(srcnO);
4317+ } else {
4318+ packagelist *p;
4319+ /* original source */
4320+ add_sourcenotetbl(srcsn->sources, srcnO->source->package, srcnO);
4321+ for (i = 0; i < srcsn->n_arches; i++) {
4322+ for (p = srcnO->binaries[i]; p != NULL; p = p->next) {
4323+ add_package(srcsn->pkgs[i], p->value);
4324+ }
4325+ }
4326+ }
4327+ }
4328+}
4329+
4330+LIST_IMPL(source_note_list, dpkg_source_note *, free_source_note,
4331+ block_malloc, block_free);
4332+LIST_IMPL(source_note_listlist, source_note_list *, free_source_note_list,
4333+ block_malloc, block_free);
4334+
4335+void commit_changes(dpkg_sources_note *srcsn) {
4336+ assert(is_sources_note(srcsn));
4337+ free_source_note_listlist(srcsn->undo);
4338+ srcsn->undo = NULL;
4339+}
4340+
4341+dpkg_source_note *copy_source_note(dpkg_source_note *srcn) {
4342+ dpkg_source_note *srcn2;
4343+ packagelist *src, **dest;
4344+ int i;
4345+
4346+ assert(srcn->binaries != NULL);
4347+
4348+ srcn2 = block_malloc(sizeof(dpkg_source_note));
4349+ if (srcn2 == NULL) die("copy_source_note alloc:");
4350+
4351+ srcn2->source = srcn->source;
4352+ srcn2->n_arches = srcn->n_arches;
4353+ srcn2->binaries = block_malloc(sizeof(packagenamelist*) * srcn2->n_arches);
4354+ if (srcn2->binaries == NULL) die("copy_source_note alloc:");
4355+
4356+ for (i = 0; i < srcn2->n_arches; i++) {
4357+ dest = &(srcn2->binaries[i]);
4358+ *dest = NULL;
4359+ for (src = srcn->binaries[i]; src; src = src->next) {
4360+ insert_packagelist(dest, src->value);
4361+ dest = &((*dest)->next);
4362+ }
4363+ }
4364+
4365+ return srcn2;
4366+}
4367+
4368+void write_notes(char *dir, dpkg_sources_note *srcsn) {
4369+ FILE *src;
4370+ FILE *archfile[100];
4371+ char buf[1000];
4372+ int i;
4373+ sourcenotetbl_iter srciter;
4374+
4375+ assert(is_sources_note(srcsn));
4376+ snprintf(buf, 1000, "%s/Sources", dir);
4377+ src = fopen(buf, "w");
4378+ for (i = 0; i < srcsn->n_arches; i++) {
4379+ snprintf(buf, 1000, "%s/Packages_%s", dir, srcsn->archname[i]);
4380+ archfile[i] = fopen(buf, "w");
4381+ }
4382+
4383+ for (srciter = first_sourcenotetbl(srcsn->sources);
4384+ !done_sourcenotetbl(srciter);
4385+ srciter = next_sourcenotetbl(srciter))
4386+ {
4387+ packagelist *p;
4388+ int i;
4389+
4390+ if (!srciter.v->source->fake)
4391+ write_paragraph(src, srciter.v->source->details);
4392+
4393+ for (i = 0; i < srcsn->n_arches; i++) {
4394+ for (p = srciter.v->binaries[i]; p != NULL; p = p->next) {
4395+ write_paragraph(archfile[i], p->value->details);
4396+ }
4397+ }
4398+ }
4399+
4400+ fclose(src);
4401+ for (i = 0; i < srcsn->n_arches; i++) {
4402+ fclose(archfile[i]);
4403+ }
4404+}
4405+
4406
4407=== added file 'update_out/dpkg.h'
4408--- update_out/dpkg.h 1970-01-01 00:00:00 +0000
4409+++ update_out/dpkg.h 2015-02-19 13:49:56 +0000
4410@@ -0,0 +1,207 @@
4411+#ifndef DPKG_H
4412+#define DPKG_H
4413+
4414+#include "templates.h"
4415+#include "memory.h"
4416+
4417+#include <stdio.h>
4418+
4419+/**************************************************************************
4420+ * Coping with an rfc822-esque field
4421+ */
4422+
4423+typedef struct dpkg_entry dpkg_entry;
4424+struct dpkg_entry {
4425+ char *name;
4426+ char *value;
4427+};
4428+
4429+typedef struct dpkg_paragraph dpkg_paragraph;
4430+struct dpkg_paragraph {
4431+ int n_entries;
4432+ int n_allocated;
4433+ dpkg_entry *entry;
4434+};
4435+
4436+/**************************************************************************
4437+ * Coping with a package (or many pkgs) as an abstract entity
4438+ */
4439+
4440+typedef enum {dr_NOOP,dr_LT,dr_LTEQ,dr_EQ,dr_GTEQ,dr_GT} dependency_relation;
4441+extern char *dependency_relation_sym[];
4442+
4443+typedef struct dependency dependency;
4444+struct dependency {
4445+ char *package;
4446+ dependency_relation op;
4447+ char *version;
4448+};
4449+
4450+LIST(deplist, dependency*);
4451+LIST(deplistlist, deplist*);
4452+
4453+LIST(packagenamelist, char*);
4454+LIST(ownedpackagenamelist, char*);
4455+
4456+typedef struct dpkg_package dpkg_package;
4457+
4458+struct dpkg_package {
4459+ char *package;
4460+ char *version;
4461+
4462+ char *source;
4463+ char *source_ver;
4464+
4465+ int priority;
4466+
4467+ int arch_all;
4468+
4469+ deplistlist *depends[4];
4470+ deplist *conflicts;
4471+ ownedpackagenamelist *provides;
4472+
4473+ dpkg_paragraph *details;
4474+};
4475+
4476+LIST(packagelist, dpkg_package *);
4477+LIST(ownedpackagelist, dpkg_package *);
4478+
4479+typedef struct satisfieddep satisfieddep;
4480+
4481+struct satisfieddep {
4482+ /* dependency *dep; */
4483+ deplist *depl;
4484+ packagelist *pkgs;
4485+};
4486+
4487+LIST(satisfieddeplist, satisfieddep *);
4488+
4489+/**************************************************************************
4490+ * Coping with a source package (and collections thereof) as an abstract
4491+ * entity, owning a bunch of binary packages
4492+ */
4493+
4494+typedef struct dpkg_source dpkg_source;
4495+struct dpkg_source {
4496+ char *package;
4497+ char *version;
4498+
4499+ int fake;
4500+
4501+ struct dpkg_sources *owner;
4502+ ownedpackagelist **packages; /* one for each architecture */
4503+
4504+ dpkg_paragraph *details;
4505+};
4506+
4507+HASH(sourcetbl,char *,dpkg_source *);
4508+
4509+typedef struct dpkg_sources dpkg_sources;
4510+struct dpkg_sources {
4511+ int n_arches;
4512+ char **archname;
4513+ sourcetbl *sources;
4514+ ownedpackagelist **unclaimedpackages; /* one for each arch */
4515+};
4516+
4517+/**************************************************************************
4518+ */
4519+
4520+typedef struct dpkg_collected_package dpkg_collected_package;
4521+struct dpkg_collected_package {
4522+ dpkg_package *pkg;
4523+
4524+ int installed, conflicted;
4525+
4526+ enum { UNKNOWN, YES } installable;
4527+ packagenamelist *mayaffect;
4528+
4529+ /* on update, the installability_checked of each /mayaffect/ed package
4530+ * is cleared, and the mayaffect list is cleared.
4531+ *
4532+ * note that installable = NO couldn't be maintained over adding a package
4533+ * to testing. installable = YES can be, thanks to the mayaffect list
4534+ * (once a package is removed, everything it mayaffect must be set back
4535+ * to unknown, but everything else is okay)
4536+ */
4537+};
4538+
4539+LIST(collpackagelist, dpkg_collected_package *);
4540+
4541+/**************************************************************************
4542+ */
4543+
4544+typedef struct dpkg_provision dpkg_provision;
4545+struct dpkg_provision {
4546+ char *version;
4547+ dpkg_collected_package *pkg;
4548+};
4549+
4550+LIST(virtualpkg, dpkg_provision);
4551+
4552+HASH(virtualpkgtbl,char *,virtualpkg *);
4553+HASH(packagetbl,char *,dpkg_collected_package *);
4554+
4555+typedef struct dpkg_packages dpkg_packages;
4556+struct dpkg_packages {
4557+ char *arch;
4558+ packagetbl *packages;
4559+ virtualpkgtbl *virtualpkgs;
4560+};
4561+
4562+typedef struct dpkg_source_note dpkg_source_note;
4563+struct dpkg_source_note {
4564+ dpkg_source *source; /* unowned */
4565+ int n_arches;
4566+ packagelist **binaries; /* one for each arch */
4567+};
4568+HASH(sourcenotetbl, char *, dpkg_source_note *);
4569+
4570+LIST(source_note_list, dpkg_source_note *);
4571+ /* contains a copy of the previous source_note */
4572+LIST(source_note_listlist, source_note_list *);
4573+ /* contains a copy of all the source_notes modified by the last op */
4574+
4575+typedef struct dpkg_sources_note dpkg_sources_note;
4576+struct dpkg_sources_note {
4577+ unsigned long magic;
4578+ sourcenotetbl *sources;
4579+ int n_arches;
4580+ dpkg_packages **pkgs;
4581+ char **archname;
4582+
4583+ source_note_listlist *undo;
4584+};
4585+
4586+void free_packages(dpkg_packages *pkgs);
4587+void free_sources(dpkg_sources *s);
4588+
4589+dpkg_packages *get_architecture(dpkg_sources *srcs, char *arch);
4590+
4591+/* parsing things */
4592+int checkinstallable(dpkg_packages *pkgs, collpackagelist *instoneof);
4593+int checkinstallable2(dpkg_packages *pkgs, char *pkgname);
4594+satisfieddeplist *checkunsatisfiabledeps(dpkg_packages *pkgs,
4595+ deplistlist *deps);
4596+
4597+dpkg_sources *read_directory(char *dir, int n_arches, char *archname[]);
4598+void write_directory(char *dir, dpkg_sources *srcs);
4599+
4600+void free_source(dpkg_source *s);
4601+
4602+/* adding and deleting and stuff */
4603+dpkg_sources_note *new_sources_note(int n_arches, char **archname);
4604+void remove_source(dpkg_sources_note *srcsn, char *name);
4605+void upgrade_source(dpkg_sources_note *srcsn, dpkg_source *src);
4606+void upgrade_arch(dpkg_sources_note *srcsn, dpkg_source *src, char *arch);
4607+void write_notes(char *dir, dpkg_sources_note *srcsn);
4608+void free_sources_note(dpkg_sources_note *srcsn);
4609+void free_source_note(dpkg_source_note *srcn);
4610+void undo_change(dpkg_sources_note *srcsn);
4611+int can_undo(dpkg_sources_note *srcsn);
4612+void commit_changes(dpkg_sources_note *srcsn);
4613+
4614+int versioncmp(char *left, char *right);
4615+int cmpversions(char *left, int op, char *right);
4616+
4617+#endif
4618
4619=== added file 'update_out/freelist.c'
4620--- update_out/freelist.c 1970-01-01 00:00:00 +0000
4621+++ update_out/freelist.c 2015-02-19 13:49:56 +0000
4622@@ -0,0 +1,188 @@
4623+#include <stdio.h>
4624+#include <stdlib.h>
4625+#include "templates.h"
4626+
4627+typedef unsigned long ul;
4628+
4629+#define SIZE (sizeof(ul) * 8)
4630+#define ROUND_DOWN(x) ((x) & ~(SIZE-1))
4631+#define ROUND_UP(x) ROUND_DOWN((x) + (SIZE-1))
4632+#define NEXT_UP(x) ROUND_DOWN((x) + SIZE)
4633+#define NEXT_DOWN(x) ROUND_DOWN((x) - 1)
4634+
4635+#define SETBIT(s,p) \
4636+ assert( (bits[(s)/SIZE] & (p)) == (setp ? 0 : (p)) ); \
4637+ if (setp) bits[(s)/SIZE] |= (p); \
4638+ else bits[(s)/SIZE] &= ~(p)
4639+
4640+#define GETBIT(s) (bits[ROUND_DOWN(s)/SIZE] & (1ul << (NEXT_UP(s) - s - 1)))
4641+
4642+size_t count_free_bits_back(ul *bits, size_t s) {
4643+ size_t cnt = 0;
4644+ ul w = ROUND_DOWN(s) / SIZE;
4645+ size_t add = s % SIZE;
4646+ ul off = (~0ul) << (SIZE - add);
4647+ ul H, d;
4648+
4649+ while ((bits[w] & off) == 0) {
4650+ cnt += add;
4651+ add = SIZE;
4652+ off = ~0ul;
4653+ if (w == 0)
4654+ return cnt;
4655+ w--;
4656+ }
4657+
4658+ H = add;
4659+ add = 0;
4660+ while ((d = (H - add) / 2) > 0) {
4661+ ul offM = (off >> d) & off;
4662+ if (bits[w] & offM) {
4663+ off = offM;
4664+ H = H - d;
4665+ } else {
4666+ add = H - d;
4667+ }
4668+ }
4669+ cnt += add;
4670+ return cnt;
4671+}
4672+
4673+size_t count_free_bits_after(ul *bits, size_t s, size_t end) {
4674+ size_t cnt = 0;
4675+ ul w = ROUND_DOWN(s) / SIZE;
4676+ size_t add = SIZE - s % SIZE;
4677+ ul off = (~0ul) >> (SIZE - add);
4678+ ul H, d;
4679+
4680+ end /= SIZE;
4681+
4682+ while ((bits[w] & off) == 0) {
4683+ cnt += add;
4684+ add = SIZE;
4685+ off = ~0ul;
4686+ w++;
4687+ if (w == end)
4688+ return cnt;
4689+ }
4690+
4691+ H = add;
4692+ add = 0;
4693+ while ((d = (H - add) / 2) > 0) {
4694+ ul offM = off << d;
4695+ if (bits[w] & offM) {
4696+ off = offM;
4697+ H = H - d;
4698+ } else {
4699+ add = H - d;
4700+ }
4701+ }
4702+ cnt += add;
4703+ return cnt;
4704+}
4705+
4706+void find_long_freebits(ul *bits, size_t s, ul *start, size_t *size) {
4707+ ul clen = 0;
4708+ ul bstart = 0, blen = 0;
4709+ ul i, k;
4710+
4711+ for (i = 0; i < s; i++) {
4712+ if (bits[i] == 0) {
4713+ clen++;
4714+ } else {
4715+ if (clen > blen) {
4716+ bstart = i - clen;
4717+ blen = clen;
4718+ }
4719+ clen = 0;
4720+ }
4721+ }
4722+
4723+ if (blen == 0) return;
4724+
4725+ bstart *= SIZE; blen *= SIZE;
4726+ k = count_free_bits_back(bits, bstart);
4727+ bstart -= k; blen += k;
4728+
4729+ blen += count_free_bits_after(bits, bstart + blen, s*SIZE);
4730+
4731+ *start = bstart; *size = blen;
4732+}
4733+
4734+void mark_bits(ul *bits, ul s, size_t size, int setp) {
4735+ ul e = s+size;
4736+
4737+ ul rds = ROUND_DOWN(s);
4738+ ul nus = rds + SIZE;
4739+ ul rue = ROUND_UP(e);
4740+
4741+ ul patl = (~0UL) >> (s % SIZE);
4742+ ul patr = (~0UL) << (rue - e);
4743+
4744+ assert(size > 0);
4745+
4746+ /* bits[s1..e1] get touched, but bits[s1], bits[e1] only partially
4747+ *
4748+ * if s1 == e1, then bits[s1] get touched from [s%SIZE, e%SIZE)
4749+ * else
4750+ * bits[s1] gets touched from [s%SIZE, SIZE)
4751+ * bits[s2..e1) get reset completely
4752+ * bits[e1] gets touched from [0, e%SIZE)
4753+ */
4754+
4755+ if (nus >= e) {
4756+ /* ROUND_DOWN(s) <= s < e <= NEXT_UP(s) */
4757+ SETBIT(rds, patl & patr);
4758+ } else {
4759+ /* ROUND_DOWN(s) <= s < NEXT_UP(s) <= NEXT_DOWN(e) < e */
4760+ ul rde = ROUND_DOWN(e);
4761+
4762+ SETBIT(rds, patl);
4763+ SETBIT(rde, patr);
4764+ while (nus < rde) {
4765+ SETBIT(nus, ~0UL);
4766+ nus += SIZE;
4767+ }
4768+ }
4769+}
4770+
4771+void print_bits(ul *bits, ul s) {
4772+ ul i;
4773+ putchar(' ');
4774+ for (i = 0; i < s * SIZE; i++) {
4775+ putchar( GETBIT(i) ? '1' : '0' );
4776+ }
4777+}
4778+
4779+#ifdef TESTBIN
4780+
4781+#define X 2
4782+int main(void) {
4783+ ul memory[X];
4784+ ul l, r;
4785+ ul k = 5;
4786+
4787+ memset(memory, 0, sizeof(memory));
4788+ for (l = 0; l < X*SIZE; l += k) {
4789+ for (r = 1; l+(r*r) < X*SIZE; r++) {
4790+
4791+ printf("%lu %lu (%lu %lu", l, r*r,
4792+ (unsigned long) count_free_bits_back(memory, X*SIZE), (unsigned long) X*SIZE);
4793+ mark_bits(memory, l, r*r, 1);
4794+ printf("; %lu %lu %lu; %lu %lu %lu;): ",
4795+ (unsigned long) count_free_bits_back(memory, X*SIZE) + l + r*r,
4796+ (unsigned long) count_free_bits_after(memory, l + r*r, X*SIZE) + l + r*r,
4797+ (unsigned long) X*SIZE,
4798+ (unsigned long) count_free_bits_back(memory, l),
4799+ (unsigned long) count_free_bits_after(memory, 0, X*SIZE),
4800+ l);
4801+ print_bits(memory, X);
4802+ printf("\n");
4803+
4804+ mark_bits(memory, l, r*r, 0);
4805+ }
4806+ }
4807+
4808+ return 0;
4809+}
4810+#endif
4811
4812=== added file 'update_out/freelist.h'
4813--- update_out/freelist.h 1970-01-01 00:00:00 +0000
4814+++ update_out/freelist.h 2015-02-19 13:49:56 +0000
4815@@ -0,0 +1,14 @@
4816+
4817+#ifndef FREELIST_H
4818+#define FREELIST_H
4819+
4820+#include <stdlib.h>
4821+
4822+typedef unsigned long flb_t;
4823+
4824+void mark_bits(flb_t *bits, flb_t s, size_t size, int setp);
4825+size_t count_free_bits_back(flb_t *bits, size_t s);
4826+size_t count_free_bits_after(flb_t *bits, size_t s, size_t end);
4827+void find_long_freebits(flb_t *bits, flb_t s, flb_t *start, size_t *size);
4828+
4829+#endif
4830
4831=== added file 'update_out/index.html'
4832--- update_out/index.html 1970-01-01 00:00:00 +0000
4833+++ update_out/index.html 2015-02-19 13:49:56 +0000
4834@@ -0,0 +1,18 @@
4835+<a href="README">README</a><br>
4836+<a href="Makefile">Makefile</a><br>
4837+<a href="assert.c">assert.c</a><br>
4838+<a href="britney-py.c">britney-py.c</a><br>
4839+<a href="checklib.c">checklib.c</a><br>
4840+<a href="dpkg.c">dpkg.c</a><br>
4841+<a href="freelist.c">freelist.c</a><br>
4842+<a href="memory.c">memory.c</a><br>
4843+<a href="memory2.c">memory2.c</a><br>
4844+<a href="memory3.c">memory3.c</a><br>
4845+<a href="dpkg-lib.cpp">dpkg-lib.cpp</a><br>
4846+<a href="dpkg.h">dpkg.h</a><br>
4847+<a href="freelist.h">freelist.h</a><br>
4848+<a href="memory.h">memory.h</a><br>
4849+<a href="templates.h">templates.h</a><br>
4850+<a href="check_out.py">check_out.py</a><br>
4851+<a href="check_uptodate.py">check_uptodate.py</a><br>
4852+<a href="update_out.py">update_out.py</a><br>
4853
4854=== added file 'update_out/memory.c'
4855--- update_out/memory.c 1970-01-01 00:00:00 +0000
4856+++ update_out/memory.c 2015-02-19 13:49:56 +0000
4857@@ -0,0 +1,389 @@
4858+#include <stdio.h>
4859+#include <stdlib.h>
4860+
4861+#include "memory.h"
4862+#include "templates.h"
4863+#include "freelist.h"
4864+
4865+/**** THEORY
4866+ *
4867+
4868+So, we have blocks with a freelist
4869+
4870+ XXX............XXXXXXX..XXXXX.....XXXXXX......
4871+
4872+Within a block, we work with segments. A segment is...
4873+
4874+ ^..........|
4875+
4876+Every now and then we make sure we've got a decent sized segment.
4877+
4878+We have multiple blocks. They're kept ordered by the size of their
4879+current segment.
4880+
4881+ **********************************************/
4882+
4883+#define ALIGN 4
4884+
4885+#define FLBT_BITS (sizeof(flb_t)*8)
4886+#define MEMBLOCKSIZE (1 << 22)
4887+#define ALIGNEDSIZE(s) (((s) + ALIGN - 1) / ALIGN * ALIGN)
4888+
4889+struct memblock {
4890+ struct memblock *next;
4891+
4892+ size_t n_bytes; /* index of free char */
4893+ size_t size; /* size of block after char */
4894+
4895+ unsigned n_used_chunks; /* number of unfreed blocks */
4896+ size_t n_used_bytes; /* number of bytes actually used */
4897+ size_t n_productive_bytes; /* number of bytes used usefully */
4898+
4899+ flb_t free[MEMBLOCKSIZE/ALIGN/FLBT_BITS + 1];
4900+ unsigned char mem[MEMBLOCKSIZE];
4901+};
4902+typedef struct memblock memblock;
4903+
4904+static memblock *base = NULL;
4905+
4906+#ifdef MDEBUG1
4907+static int valid_memblock_mdebug1(struct memblock *mb) {
4908+ size_t cnt, i;
4909+ static int rarity = 0;
4910+
4911+ assert(mb->n_bytes + mb->size <= sizeof(mb->mem));
4912+
4913+ if (mb->n_used_chunks == 0) assert(mb->n_bytes == 0);
4914+ assert(((unsigned long)mb->mem + mb->n_bytes) % ALIGN == 0);
4915+
4916+ assert(mb->n_productive_bytes <= mb->n_used_bytes);
4917+ assert(mb->n_used_bytes + mb->size <= sizeof(mb->mem));
4918+
4919+#define TWO(k) (1ul << (k))
4920+#define CYCL(k) (~0ul / (1 + TWO(TWO(k))))
4921+
4922+ rarity++; rarity %= 25000;
4923+ if (rarity != 0) {
4924+ cnt = mb->n_used_bytes;
4925+ } else {
4926+ cnt = 0;
4927+ for (i = 0; i < sizeof(mb->mem)/ALIGN/FLBT_BITS+1; i++) {
4928+ unsigned long x = mb->free[i];
4929+ size_t s;
4930+ x = (x & CYCL(0)) + ((x >> TWO(0)) & CYCL(0));
4931+ x = (x & CYCL(1)) + ((x >> TWO(1)) & CYCL(1));
4932+ for (s = 2; (2u << s) <= FLBT_BITS; s++) {
4933+ x += x >> TWO(s);
4934+ x &= CYCL(s);
4935+ }
4936+ cnt += x * ALIGN;
4937+ }
4938+ }
4939+#undef TWO
4940+#undef CYCL
4941+
4942+ assert(cnt == mb->n_used_bytes);
4943+
4944+ return 1;
4945+}
4946+#endif
4947+
4948+#if MDEBUG3
4949+static int valid_memblock_mdebug3(struct memblock *mb) {
4950+ size_t offset, step, used;
4951+ unsigned chunk = 0;
4952+
4953+ offset = 0;
4954+ used = 0;
4955+ if ((unsigned long)mb->mem % ALIGN != 0)
4956+ offset = ALIGN - ((unsigned long)mb->mem % ALIGN);
4957+
4958+ while(offset < mb->n_bytes) {
4959+ step = *(size_t*)(mb->mem + offset);
4960+ assert(step % ALIGN == 0 || step % ALIGN == 1);
4961+ if (step % ALIGN == 1) step--; /* freed */
4962+ else used += step;
4963+ assert(step > 0);
4964+ offset += step;
4965+ chunk++;
4966+ }
4967+
4968+ assert(used == mb->n_used_bytes);
4969+
4970+ return 1;
4971+}
4972+#endif
4973+
4974+inline static int valid_memblock(struct memblock *mb) {
4975+ (void)mb;
4976+
4977+ MDEBUG1_ONLY( if (!valid_memblock_mdebug1(mb)) return 0; )
4978+ MDEBUG3_ONLY( if (!valid_memblock_mdebug3(mb)) return 0; )
4979+
4980+ return 1;
4981+}
4982+
4983+void print_memblock_summary(void) {
4984+ struct memblock *mb;
4985+ unsigned long tused = 0, talloc = 0, tprod = 0, tavail = 0, nb = 0;
4986+
4987+ for (mb = base; mb != NULL; mb = mb->next) {
4988+ assert(valid_memblock(mb));
4989+
4990+ MDEBUG3_ONLY(
4991+ fprintf(stderr, "%p: [%d,%lu/%lu,%p,%p]\n", mb,
4992+ mb->n_used_chunks, (unsigned long)mb->n_used_bytes,
4993+ (unsigned long)mb->n_bytes, mb->next, mb->mem);
4994+ )
4995+
4996+ if (mb != base && mb->size * 50 < sizeof(mb->mem) - mb->n_used_bytes) {
4997+ flb_t k; size_t s;
4998+ k = mb->n_bytes / ALIGN;
4999+ s = mb->size / ALIGN;
5000+ find_long_freebits(mb->free,MEMBLOCKSIZE/ALIGN/FLBT_BITS+1,&k,&s);
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: