pi-bake 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/deb/functions ADDED
@@ -0,0 +1,1570 @@
1
+ ############################################################### smallutils
2
+
3
+ smallyes() {
4
+ YES="${1-y}"
5
+ while echo "$YES" 2>/dev/null ; do : ; done
6
+ }
7
+
8
+ in_path () {
9
+ local OLD_IFS="$IFS"
10
+ IFS=":"
11
+ for dir in $PATH; do
12
+ if [ -x "$dir/$1" ]; then
13
+ IFS="$OLD_IFS"
14
+ return 0
15
+ fi
16
+ done
17
+ IFS="$OLD_IFS"
18
+ return 1
19
+ }
20
+
21
+ ############################################################### interaction
22
+
23
+ error () {
24
+ # <error code> <name> <string> <args>
25
+ local err="$1"
26
+ local name="$2"
27
+ local fmt="$3"
28
+ shift; shift; shift
29
+ if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then
30
+ (echo "E: $name"
31
+ for x in "$@"; do echo "EA: $x"; done
32
+ echo "EF: $fmt") >&4
33
+ else
34
+ (printf "E: $fmt\n" "$@") >&4
35
+ fi
36
+ exit $err
37
+ }
38
+
39
+ warning () {
40
+ # <name> <string> <args>
41
+ local name="$1"
42
+ local fmt="$2"
43
+ shift; shift
44
+ if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then
45
+ (echo "W: $name"
46
+ for x in "$@"; do echo "WA: $x"; done
47
+ echo "WF: $fmt") >&4
48
+ else
49
+ printf "W: $fmt\n" "$@" >&4
50
+ fi
51
+ }
52
+
53
+ info () {
54
+ # <name> <string> <args>
55
+ local name="$1"
56
+ local fmt="$2"
57
+ shift; shift
58
+ if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then
59
+ (echo "I: $name"
60
+ for x in "$@"; do echo "IA: $x"; done
61
+ echo "IF: $fmt") >&4
62
+ else
63
+ printf "I: $fmt\n" "$@" >&4
64
+ fi
65
+ }
66
+
67
+ PROGRESS_NOW=0
68
+ PROGRESS_END=0
69
+ PROGRESS_NEXT=""
70
+ PROGRESS_WHAT=""
71
+
72
+ progress_next () {
73
+ PROGRESS_NEXT="$1"
74
+ }
75
+
76
+ wgetprogress () {
77
+ [ ! "$VERBOSE" ] && QSWITCH="-q"
78
+ local ret=0
79
+ if [ "$USE_DEBIANINSTALLER_INTERACTION" ] && [ "$PROGRESS_NEXT" ]; then
80
+ wget "$@" 2>&1 >/dev/null | $PKGDETAILS "WGET%" $PROGRESS_NOW $PROGRESS_NEXT $PROGRESS_END >&3
81
+ ret=$?
82
+ else
83
+ wget $QSWITCH "$@"
84
+ ret=$?
85
+ fi
86
+ return $ret
87
+ }
88
+
89
+ progress () {
90
+ # <now> <end> <name> <string> <args>
91
+ local now="$1"
92
+ local end="$2"
93
+ local name="$3"
94
+ local fmt="$4"
95
+ shift; shift; shift; shift
96
+ if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then
97
+ PROGRESS_NOW="$now"
98
+ PROGRESS_END="$end"
99
+ PROGRESS_NEXT=""
100
+ (echo "P: $now $end $name"
101
+ for x in "$@"; do echo "PA: $x"; done
102
+ echo "PF: $fmt") >&3
103
+ fi
104
+ }
105
+
106
+ dpkg_progress () {
107
+ # <now> <end> <name> <desc> UNPACKING|CONFIGURING
108
+ local now="$1"
109
+ local end="$2"
110
+ local name="$3"
111
+ local desc="$4"
112
+ local action="$5"
113
+ local expect=
114
+
115
+ if [ "$action" = UNPACKING ]; then
116
+ expect=half-installed
117
+ elif [ "$action" = CONFIGURING ]; then
118
+ expect=half-configured
119
+ fi
120
+
121
+ dp () {
122
+ now="$(($now + ${1:-1}))"
123
+ }
124
+
125
+ exitcode=0
126
+ while read status pkg qstate; do
127
+ if [ "$status" = "EXITCODE" ]; then
128
+ exitcode="$pkg"
129
+ continue
130
+ fi
131
+ [ "$qstate" = "$expect" ] || continue
132
+ case $qstate in
133
+ half-installed)
134
+ dp; progress "$now" "$end" "$name" "$desc"
135
+ info "$action" "Unpacking %s..." "${pkg%:}"
136
+ expect=unpacked
137
+ ;;
138
+ unpacked)
139
+ expect=half-installed
140
+ ;;
141
+ half-configured)
142
+ dp; progress "$now" "$end" "$name" "$desc"
143
+ info "$action" "Configuring %s..." "${pkg%:}"
144
+ expect=installed
145
+ ;;
146
+ installed)
147
+ expect=half-configured
148
+ ;;
149
+ esac
150
+ done
151
+ return $exitcode
152
+ }
153
+
154
+ ############################################################# set variables
155
+
156
+ default_mirror () {
157
+ DEF_MIRROR="$1"
158
+ }
159
+
160
+ FINDDEBS_NEEDS_INDICES=false
161
+ finddebs_style () {
162
+ case "$1" in
163
+ hardcoded)
164
+ ;;
165
+ from-indices)
166
+ FINDDEBS_NEEDS_INDICES=true
167
+ ;;
168
+ *)
169
+ error 1 BADFINDDEBS "unknown finddebs style"
170
+ ;;
171
+ esac
172
+ }
173
+
174
+ mk_download_dirs () {
175
+ if [ $DLDEST = "apt_dest" ]; then
176
+ mkdir -p "$TARGET/$APTSTATE/lists/partial"
177
+ mkdir -p "$TARGET/var/cache/apt/archives/partial"
178
+ fi
179
+ }
180
+
181
+ download_style () {
182
+ case "$1" in
183
+ apt)
184
+ if [ "$2" = "var-state" ]; then
185
+ APTSTATE=var/state/apt
186
+ else
187
+ APTSTATE=var/lib/apt
188
+ fi
189
+ DLDEST=apt_dest
190
+ export APTSTATE DLDEST DEBFOR
191
+ ;;
192
+ *)
193
+ error 1 BADDLOAD "unknown download style"
194
+ ;;
195
+ esac
196
+ }
197
+
198
+ keyring () {
199
+ KEYRING_WANTED="$1"
200
+ if [ -z "$KEYRING" ] && [ -e "$KEYRING_WANTED" ]; then
201
+ KEYRING="$KEYRING_WANTED"
202
+ fi
203
+ }
204
+
205
+ ########################################################## variant handling
206
+
207
+ doing_variant () {
208
+ if [ "$1" = "$VARIANT" ]; then return 0; fi
209
+ if [ "$1" = "-" ] && [ "$VARIANT" = "" ]; then return 0; fi
210
+ return 1
211
+ }
212
+
213
+ SUPPORTED_VARIANTS="-"
214
+ variants () {
215
+ SUPPORTED_VARIANTS="$*"
216
+ for v in $*; do
217
+ if doing_variant "$v"; then return 0; fi
218
+ done
219
+ error 1 UNSUPPVARIANT "unsupported variant"
220
+ }
221
+
222
+ ################################################# work out names for things
223
+
224
+ mirror_style () {
225
+ case "$1" in
226
+ release)
227
+ DOWNLOAD_INDICES=download_release_indices
228
+ DOWNLOAD_DEBS=download_release
229
+ ;;
230
+ main)
231
+ DOWNLOAD_INDICES=download_main_indices
232
+ DOWNLOAD_DEBS=download_main
233
+ ;;
234
+ *)
235
+ error 1 BADMIRROR "unknown mirror style"
236
+ ;;
237
+ esac
238
+ export DOWNLOAD_INDICES
239
+ export DOWNLOAD_DEBS
240
+ }
241
+
242
+ force_md5 () {
243
+ DEBOOTSTRAP_CHECKSUM_FIELD=MD5SUM
244
+ export DEBOOTSTRAP_CHECKSUM_FIELD
245
+ }
246
+
247
+ verify_checksum () {
248
+ # args: dest checksum size
249
+ local expchecksum="$2"
250
+ local expsize="$3"
251
+ if [ "$DEBOOTSTRAP_CHECKSUM_FIELD" = "MD5SUM" ]; then
252
+ if in_path md5sum; then
253
+ relchecksum=`md5sum < "$1" | sed 's/ .*$//'`
254
+ elif in_path md5; then
255
+ relchecksum=`md5 < "$1"`
256
+ else
257
+ error 1 SIGCHECK "Cannot check md5sum"
258
+ fi
259
+ else
260
+ if in_path "sha${SHA_SIZE}sum"; then
261
+ relchecksum=`sha${SHA_SIZE}sum < "$1" | sed 's/ .*$//'`
262
+ elif in_path "sha${SHA_SIZE}"; then
263
+ relchecksum=`sha${SHA_SIZE} < "$1"`
264
+ else
265
+ error 1 SIGCHECK "Cannot check sha${SHA_SIZE}sum"
266
+ fi
267
+ fi
268
+ relsize=`wc -c < "$1"`
269
+ if [ "$expsize" -ne "$relsize" ] || [ "$expchecksum" != "$relchecksum" ]; then
270
+ return 1
271
+ fi
272
+ return 0
273
+ }
274
+
275
+ get () {
276
+ # args: from dest 'nocache'
277
+ # args: from dest [checksum size] [alt {checksum size type}]
278
+ local displayname
279
+ if [ "${2%.deb}" != "$2" ]; then
280
+ displayname="$(echo "$2" | sed 's,^.*/,,;s,_.*$,,')"
281
+ else
282
+ displayname="$(echo "$1" | sed 's,^.*/,,')"
283
+ fi
284
+
285
+ if [ -e "$2" ]; then
286
+ if [ -z "$3" ]; then
287
+ return 0
288
+ elif [ "$3" = nocache ]; then
289
+ rm -f "$2"
290
+ else
291
+ info VALIDATING "Validating %s" "$displayname"
292
+ if verify_checksum "$2" "$3" "$4"; then
293
+ return 0
294
+ else
295
+ rm -f "$2"
296
+ fi
297
+ fi
298
+ fi
299
+ # Drop 'nocache' option
300
+ if [ "$3" = nocache ]; then
301
+ set "$1" "$2"
302
+ fi
303
+
304
+ if [ "$#" -gt 5 ]; then
305
+ local st=3
306
+ if [ "$5" = "-" ]; then st=6; fi
307
+ local order="$(a=$st; while [ "$a" -le $# ]; do eval echo \"\${$(($a+1))}\" $a;
308
+ a=$(($a + 3)); done | sort -n | sed 's/.* //')"
309
+ else
310
+ local order=3
311
+ fi
312
+ for a in $order; do
313
+ local checksum="$(eval echo \${$a})"
314
+ local siz="$(eval echo \${$(( $a+1 ))})"
315
+ local typ="$(eval echo \${$(( $a+2 ))})"
316
+ local from
317
+ local dest
318
+ local iters=0
319
+
320
+ case "$typ" in
321
+ bz2) from="$1.bz2"; dest="$2.bz2" ;;
322
+ gz) from="$1.gz"; dest="$2.gz" ;;
323
+ *) from="$1"; dest="$2" ;;
324
+ esac
325
+
326
+ if [ "${dest#/}" = "$dest" ]; then
327
+ dest="./$dest"
328
+ fi
329
+ local dest2="$dest"
330
+ if [ -d "${dest2%/*}/partial" ]; then
331
+ dest2="${dest2%/*}/partial/${dest2##*/}"
332
+ fi
333
+
334
+ while [ "$iters" -lt 10 ]; do
335
+ info RETRIEVING "Retrieving %s" "$displayname"
336
+ if ! just_get "$from" "$dest2"; then continue 2; fi
337
+ if [ "$checksum" != "" ]; then
338
+ info VALIDATING "Validating %s" "$displayname"
339
+ if verify_checksum "$dest2" "$checksum" "$siz"; then
340
+ checksum=""
341
+ fi
342
+ fi
343
+ if [ -z "$checksum" ]; then
344
+ [ "$dest2" = "$dest" ] || mv "$dest2" "$dest"
345
+ case "$typ" in
346
+ gz) gunzip "$dest" ;;
347
+ bz2) bunzip2 "$dest" ;;
348
+ esac
349
+ return 0
350
+ else
351
+ rm -f "$dest2"
352
+ warning RETRYING "Retrying failed download of %s" "$from"
353
+ iters="$(($iters + 1))"
354
+ fi
355
+ done
356
+ warning CORRUPTFILE "%s was corrupt" "$from"
357
+ done
358
+ return 1
359
+ }
360
+
361
+ just_get () {
362
+ # args: from dest
363
+ local from="$1"
364
+ local dest="$2"
365
+ mkdir -p "${dest%/*}"
366
+ if [ "${from#null:}" != "$from" ]; then
367
+ error 1 NOTPREDL "%s was not pre-downloaded" "${from#null:}"
368
+ elif [ "${from#http://}" != "$from" ] || [ "${from#ftp://}" != "$from" ]; then
369
+ # http/ftp mirror
370
+ if wgetprogress -O "$dest" "$from"; then
371
+ return 0
372
+ else
373
+ rm -f "$dest"
374
+ return 1
375
+ fi
376
+ elif [ "${from#https://}" != "$from" ] ; then
377
+ # http/ftp mirror
378
+ if wgetprogress $CHECKCERTIF $CERTIFICATE $PRIVATEKEY -O "$dest" "$from"; then
379
+ return 0
380
+ else
381
+ rm -f "$dest"
382
+ return 1
383
+ fi
384
+ elif [ "${from#file:}" != "$from" ]; then
385
+ local base="${from#file:}"
386
+ if [ "${base#//}" != "$base" ]; then
387
+ base="/${from#file://*/}"
388
+ fi
389
+ if [ -e "$base" ]; then
390
+ cp "$base" "$dest"
391
+ return 0
392
+ else
393
+ return 1
394
+ fi
395
+ elif [ "${from#ssh:}" != "$from" ]; then
396
+ local ssh_dest="$(echo $from | sed -e 's#ssh://##' -e 's#/#:/#')"
397
+ if [ -n "$ssh_dest" ]; then
398
+ scp "$ssh_dest" "$dest"
399
+ return 0
400
+ else
401
+ return 1
402
+ fi
403
+ else
404
+ error 1 UNKNOWNLOC "unknown location %s" "$from"
405
+ fi
406
+ }
407
+
408
+ download () {
409
+ mk_download_dirs
410
+ "$DOWNLOAD_DEBS" $(echo "$@" | tr ' ' '\n' | sort)
411
+ }
412
+
413
+ download_indices () {
414
+ mk_download_dirs
415
+ "$DOWNLOAD_INDICES" $(echo "$@" | tr ' ' '\n' | sort)
416
+ }
417
+
418
+ debfor () {
419
+ (while read pkg path; do
420
+ for p in "$@"; do
421
+ [ "$p" = "$pkg" ] || continue;
422
+ echo "$path"
423
+ done
424
+ done <"$TARGET/debootstrap/debpaths"
425
+ )
426
+ }
427
+
428
+ apt_dest () {
429
+ # args:
430
+ # deb package version arch mirror path
431
+ # pkg suite component arch mirror path
432
+ # rel suite mirror path
433
+ case "$1" in
434
+ deb)
435
+ echo "/var/cache/apt/archives/${2}_${3}_${4}.deb" | sed 's/:/%3a/'
436
+ ;;
437
+ pkg)
438
+ local m="$5"
439
+ m="debootstrap.invalid"
440
+ #if [ "${m#http://}" != "$m" ]; then
441
+ # m="${m#http://}"
442
+ #elif [ "${m#file://}" != "$m" ]; then
443
+ # m="file_localhost_${m#file://*/}"
444
+ #elif [ "${m#file:/}" != "$m" ]; then
445
+ # m="file_localhost_${m#file:/}"
446
+ #fi
447
+
448
+ printf "%s" "$APTSTATE/lists/"
449
+ echo "${m}_$6" | sed 's/\//_/g'
450
+ ;;
451
+ rel)
452
+ local m="$3"
453
+ m="debootstrap.invalid"
454
+ #if [ "${m#http://}" != "$m" ]; then
455
+ # m="${m#http://}"
456
+ #elif [ "${m#file://}" != "$m" ]; then
457
+ # m="file_localhost_${m#file://*/}"
458
+ #elif [ "${m#file:/}" != "$m" ]; then
459
+ # m="file_localhost_${m#file:/}"
460
+ #fi
461
+ printf "%s" "$APTSTATE/lists/"
462
+ echo "${m}_$4" | sed 's/\//_/g'
463
+ ;;
464
+ esac
465
+ }
466
+
467
+ ################################################################## download
468
+
469
+ get_release_checksum () {
470
+ local reldest="$1"
471
+ local path="$2"
472
+ if [ "$DEBOOTSTRAP_CHECKSUM_FIELD" = MD5SUM ]; then
473
+ local match="^[Mm][Dd]5[Ss][Uu][Mm]"
474
+ else
475
+ local match="^[Ss][Hh][Aa]$SHA_SIZE:"
476
+ fi
477
+ sed -n "/$match/,/^[^ ]/p" < "$reldest" | \
478
+ while read a b c; do
479
+ if [ "$c" = "$path" ]; then echo "$a $b"; fi
480
+ done | head -n 1
481
+ }
482
+
483
+ extract_release_components () {
484
+ local reldest="$1"; shift
485
+ TMPCOMPONENTS="$(sed -n 's/Components: *//p' "$reldest")"
486
+ for c in $TMPCOMPONENTS ; do
487
+ eval "
488
+ case \"\$c\" in
489
+ $USE_COMPONENTS)
490
+ COMPONENTS=\"\$COMPONENTS \$c\"
491
+ ;;
492
+ esac
493
+ "
494
+ done
495
+ COMPONENTS="$(echo $COMPONENTS)"
496
+ if [ -z "$COMPONENTS" ]; then
497
+ mv "$reldest" "$reldest.malformed"
498
+ error 1 INVALIDREL "Invalid Release file, no valid components"
499
+ fi
500
+ }
501
+
502
+ download_release_sig () {
503
+ local m1="$1"
504
+ local reldest="$2"
505
+ local relsigdest="$3"
506
+ local release_file_variant="$4"
507
+
508
+ if [ -n "$KEYRING" ] && [ -z "$DISABLE_KEYRING" ]; then
509
+ if [ "$release_file_variant" != "IN" ]; then
510
+ progress 0 100 DOWNRELSIG "Downloading Release file signature"
511
+ progress_next 50
512
+ get "$m1/dists/$SUITE/Release.gpg" "$relsigdest" nocache ||
513
+ error 1 NOGETRELSIG "Failed getting release signature file %s" \
514
+ "$m1/dists/$SUITE/Release.gpg"
515
+ progress 50 100 DOWNRELSIG "Downloading Release file signature"
516
+ fi
517
+
518
+ info RELEASESIG "Checking Release signature"
519
+ # Don't worry about the exit status from gpgv; parsing the output will
520
+ # take care of that.
521
+ if [ "$release_file_variant" = "IN" ]; then
522
+ (gpgv --status-fd 1 --keyring "$KEYRING" --ignore-time-conflict \
523
+ "$relsigdest" || true) | read_gpg_status
524
+ else
525
+ (gpgv --status-fd 1 --keyring "$KEYRING" --ignore-time-conflict \
526
+ "$relsigdest" "$reldest" || true) | read_gpg_status
527
+ fi
528
+ progress 100 100 DOWNRELSIG "Downloading Release file signature"
529
+ elif [ -z "$DISABLE_KEYRING" ] && [ -n "$KEYRING_WANTED" ]; then
530
+ warning KEYRING "Cannot check Release signature; keyring file not available %s" "$KEYRING_WANTED"
531
+ fi
532
+ if [ "$release_file_variant" = "IN" ]; then
533
+ mv "$relsigdest" "$reldest"
534
+ fi
535
+ }
536
+
537
+ download_release_indices () {
538
+ local m1="${MIRRORS%% *}"
539
+ local reldest="$TARGET/$($DLDEST rel "$SUITE" "$m1" "dists/$SUITE/Release")"
540
+ local inreldest="$TARGET/$($DLDEST rel "$SUITE" "$m1" "dists/$SUITE/InRelease")"
541
+ local relsigdest
542
+ local release_file_variant="IN"
543
+ progress 0 100 DOWNREL "Downloading Release file"
544
+ progress_next 100
545
+ if get "$m1/dists/$SUITE/InRelease" "$inreldest" nocache; then
546
+ extract_release_components $inreldest
547
+ relsigdest="$inreldest"
548
+ else
549
+ warning RETRIEVING "Failed to retrieve InRelease"
550
+ get "$m1/dists/$SUITE/Release" "$reldest" nocache ||
551
+ error 1 NOGETREL "Failed getting release file %s" "$m1/dists/$SUITE/Release"
552
+ release_file_variant="GPG"
553
+ relsigdest="$TARGET/$($DLDEST rel "$SUITE" "$m1" "dists/$SUITE/Release.gpg")"
554
+ extract_release_components $reldest
555
+ fi
556
+ progress 100 100 DOWNREL "Downloading Release file"
557
+
558
+ download_release_sig "$m1" "$reldest" "$relsigdest" "$release_file_variant"
559
+
560
+ local totalpkgs=0
561
+ for c in $COMPONENTS; do
562
+ local subpath="$c/binary-$ARCH/Packages"
563
+ local bz2i="`get_release_checksum "$reldest" "$subpath.bz2"`"
564
+ local gzi="`get_release_checksum "$reldest" "$subpath.gz"`"
565
+ local normi="`get_release_checksum "$reldest" "$subpath"`"
566
+ local i=
567
+ if [ "$normi" != "" ]; then
568
+ i="$normi"
569
+ elif in_path bunzip2 && [ "$bz2i" != "" ]; then
570
+ i="$bz2i"
571
+ elif in_path gunzip && [ "$gzi" != "" ]; then
572
+ i="$gzi"
573
+ fi
574
+ if [ "$i" != "" ]; then
575
+ totalpkgs="$(( $totalpkgs + ${i#* } ))"
576
+ else
577
+ mv "$reldest" "$reldest.malformed"
578
+ error 1 MISSINGRELENTRY "Invalid Release file, no entry for %s" "$subpath"
579
+ fi
580
+ done
581
+
582
+ local donepkgs=0
583
+ local pkgdest
584
+ progress 0 $totalpkgs DOWNPKGS "Downloading Packages files"
585
+ for c in $COMPONENTS; do
586
+ local subpath="$c/binary-$ARCH/Packages"
587
+ local path="dists/$SUITE/$subpath"
588
+ local bz2i="`get_release_checksum "$reldest" "$subpath.bz2"`"
589
+ local gzi="`get_release_checksum "$reldest" "$subpath.gz"`"
590
+ local normi="`get_release_checksum "$reldest" "$subpath"`"
591
+ local ext=
592
+ local i=
593
+ if [ "$normi" != "" ]; then
594
+ ext="$ext $normi ."
595
+ i="$normi"
596
+ fi
597
+ if in_path bunzip2 && [ "$bz2i" != "" ]; then
598
+ ext="$ext $bz2i bz2"
599
+ i="${i:-$bz2i}"
600
+ fi
601
+ if in_path gunzip && [ "$gzi" != "" ]; then
602
+ ext="$ext $gzi gz"
603
+ i="${i:-$gzi}"
604
+ fi
605
+ progress_next "$(($donepkgs + ${i#* }))"
606
+ for m in $MIRRORS; do
607
+ pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")"
608
+ if get "$m/$path" "$pkgdest" $ext; then break; fi
609
+ done
610
+ if [ ! -f "$pkgdest" ]; then
611
+ error 1 COULDNTDL "Couldn't download %s" "$path"
612
+ fi
613
+ donepkgs="$(($donepkgs + ${i#* }))"
614
+ progress $donepkgs $totalpkgs DOWNPKGS "Downloading Packages files"
615
+ done
616
+ }
617
+
618
+ get_package_sizes () {
619
+ # mirror pkgdest debs..
620
+ local m="$1"; shift
621
+ local pkgdest="$1"; shift
622
+ $PKGDETAILS PKGS "$m" "$pkgdest" "$@" | (
623
+ newleft=""
624
+ totaldebs=0
625
+ countdebs=0
626
+ while read p details; do
627
+ if [ "$details" = "-" ]; then
628
+ newleft="$newleft $p"
629
+ else
630
+ size="${details##* }";
631
+ totaldebs="$(($totaldebs + $size))"
632
+ countdebs="$(($countdebs + 1))"
633
+ fi
634
+ done
635
+ echo "$countdebs $totaldebs$newleft"
636
+ )
637
+ }
638
+
639
+ # note, leftovers come back on fd5 !!
640
+ download_debs () {
641
+ local m="$1"
642
+ local pkgdest="$2"
643
+ shift; shift
644
+
645
+ $PKGDETAILS PKGS "$m" "$pkgdest" "$@" | (
646
+ leftover=""
647
+ while read p ver arc mdup fil checksum size; do
648
+ if [ "$ver" = "-" ]; then
649
+ leftover="$leftover $p"
650
+ else
651
+ progress_next "$(($dloaddebs + $size))"
652
+ local debdest="$($DLDEST deb "$p" "$ver" "$arc" "$m" "$fil")"
653
+ if get "$m/$fil" "$TARGET/$debdest" "$checksum" "$size"; then
654
+ dloaddebs="$(($dloaddebs + $size))"
655
+ echo >>$TARGET/debootstrap/debpaths "$p $debdest"
656
+ else
657
+ warning COULDNTDL "Couldn't download package %s (ver %s arc %s)" "$p" "$ver" "$arc"
658
+ leftover="$leftover $p"
659
+ fi
660
+ fi
661
+ done
662
+ echo >&5 ${leftover# }
663
+ )
664
+ }
665
+
666
+ download_release () {
667
+ local m1="${MIRRORS%% *}"
668
+
669
+ local numdebs="$#"
670
+
671
+ local countdebs=0
672
+ progress $countdebs $numdebs SIZEDEBS "Finding package sizes"
673
+
674
+ local totaldebs=0
675
+ local leftoverdebs="$*"
676
+ for c in $COMPONENTS; do
677
+ if [ "$countdebs" -ge "$numdebs" ]; then break; fi
678
+
679
+ local path="dists/$SUITE/$c/binary-$ARCH/Packages"
680
+ local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")"
681
+ if [ ! -e "$pkgdest" ]; then continue; fi
682
+
683
+ info CHECKINGSIZES "Checking component %s on %s..." "$c" "$m1"
684
+
685
+ leftoverdebs="$(get_package_sizes "$m1" "$pkgdest" $leftoverdebs)"
686
+
687
+ countdebs=$(($countdebs + ${leftoverdebs%% *}))
688
+ leftoverdebs=${leftoverdebs#* }
689
+
690
+ totaldebs=${leftoverdebs%% *}
691
+ leftoverdebs=${leftoverdebs#* }
692
+
693
+ progress $countdebs $numdebs SIZEDEBS "Finding package sizes"
694
+ done
695
+
696
+ if [ "$countdebs" -ne "$numdebs" ]; then
697
+ error 1 LEFTOVERDEBS "Couldn't find these debs: %s" "$leftoverdebs"
698
+ fi
699
+
700
+ local dloaddebs=0
701
+
702
+ progress $dloaddebs $totaldebs DOWNDEBS "Downloading packages"
703
+ :>$TARGET/debootstrap/debpaths
704
+
705
+ pkgs_to_get="$*"
706
+ for c in $COMPONENTS; do
707
+ local path="dists/$SUITE/$c/binary-$ARCH/Packages"
708
+ for m in $MIRRORS; do
709
+ local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")"
710
+ if [ ! -e "$pkgdest" ]; then continue; fi
711
+ pkgs_to_get="$(download_debs "$m" "$pkgdest" $pkgs_to_get 5>&1 1>&6)"
712
+ if [ -z "$pkgs_to_get" ]; then break; fi
713
+ done 6>&1
714
+ if [ -z "$pkgs_to_get" ]; then break; fi
715
+ done
716
+ progress $dloaddebs $totaldebs DOWNDEBS "Downloading packages"
717
+ if [ "$pkgs_to_get" != "" ]; then
718
+ error 1 COULDNTDLPKGS "Couldn't download packages: %s" "$pkgs_to_get"
719
+ fi
720
+ }
721
+
722
+ download_main_indices () {
723
+ local m1="${MIRRORS%% *}"
724
+ local comp="${USE_COMPONENTS}"
725
+ progress 0 100 DOWNMAINPKGS "Downloading Packages file"
726
+ progress_next 100
727
+
728
+ if [ -z "$comp" ]; then comp=main; fi
729
+ COMPONENTS="$(echo $comp | tr '|' ' ')"
730
+
731
+ export COMPONENTS
732
+ for m in $MIRRORS; do
733
+ for c in $COMPONENTS; do
734
+ local path="dists/$SUITE/$c/binary-$ARCH/Packages"
735
+ local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")"
736
+ if in_path gunzip && get "$m/${path}.gz" "${pkgdest}.gz"; then
737
+ rm -f "$pkgdest"
738
+ gunzip "$pkgdest.gz"
739
+ elif get "$m/$path" "$pkgdest"; then
740
+ true
741
+ fi
742
+ done
743
+ done
744
+ progress 100 100 DOWNMAINPKGS "Downloading Packages file"
745
+ }
746
+
747
+ download_main () {
748
+ local m1="${MIRRORS%% *}"
749
+
750
+ :>$TARGET/debootstrap/debpaths
751
+ for p in "$@"; do
752
+ for c in $COMPONENTS; do
753
+ local details=""
754
+ for m in $MIRRORS; do
755
+ local path="dists/$SUITE/$c/binary-$ARCH/Packages"
756
+ local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")"
757
+ if [ ! -e "$pkgdest" ]; then continue; fi
758
+ details="$($PKGDETAILS PKGS "$m" "$pkgdest" "$p")"
759
+ if [ "$details" = "$p -" ]; then
760
+ details=""
761
+ continue
762
+ fi
763
+ size="${details##* }"; details="${details% *}"
764
+ checksum="${details##* }"; details="${details% *}"
765
+ local debdest="$($DLDEST deb $details)"
766
+ if get "$m/${details##* }" "$TARGET/$debdest" "$checksum" "$size"; then
767
+ echo >>$TARGET/debootstrap/debpaths "$p $debdest"
768
+ details="done"
769
+ break
770
+ fi
771
+ done
772
+ if [ "$details" != "" ]; then
773
+ break
774
+ fi
775
+ done
776
+ if [ "$details" != "done" ]; then
777
+ error 1 COULDNTDL "Couldn't download %s" "$p"
778
+ fi
779
+ done
780
+ }
781
+
782
+ ###################################################### deb choosing support
783
+
784
+ get_debs () {
785
+ local field="$1"
786
+ shift
787
+ local m1 c
788
+ for m1 in $MIRRORS; do
789
+ for c in $COMPONENTS; do
790
+ local path="dists/$SUITE/$c/binary-$ARCH/Packages"
791
+ local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")"
792
+ echo $("$PKGDETAILS" FIELD "$field" "$m1" "$pkgdest" "$@" | sed 's/ .*//')
793
+ done
794
+ done
795
+ }
796
+
797
+ ################################################################ extraction
798
+
799
+ EXTRACTORS_SUPPORTED="dpkg-deb ar"
800
+
801
+ # Native dpkg-deb based extractors
802
+ extract_dpkg_deb_field () {
803
+ local pkg="$1"
804
+ local field="$2"
805
+
806
+ dpkg-deb -f "$pkg" "$field"
807
+ }
808
+
809
+ extract_dpkg_deb_data () {
810
+ local pkg="$1"
811
+
812
+ dpkg-deb --fsys-tarfile "$pkg" | tar -xf -
813
+ }
814
+
815
+ # Raw .deb extractors
816
+ extract_ar_deb_field () {
817
+ local pkg="$1"
818
+ local field="$2"
819
+
820
+ ar -p "$pkg" control.tar.gz | zcat |
821
+ tar -O -xf - control ./control 2>/dev/null |
822
+ grep -i "^$field:" | sed -e 's/[^:]*: *//' | head -n 1
823
+ }
824
+
825
+ extract_ar_deb_data () {
826
+ local pkg="$1"
827
+ local tarball=$(ar -t "$pkg" | grep "^data.tar.[bgx]z")
828
+
829
+ case "$tarball" in
830
+ data.tar.gz) cat_cmd=zcat ;;
831
+ data.tar.bz2) cat_cmd=bzcat ;;
832
+ data.tar.xz) cat_cmd=xzcat ;;
833
+ *) error 1 UNKNOWNDATACOMP "Unknown compression type for %s in %s" "$tarball" "$pkg" ;;
834
+ esac
835
+
836
+ if type $cat_cmd >/dev/null 2>&1; then
837
+ ar -p "$pkg" "$tarball" | $cat_cmd | tar -xf -
838
+ else
839
+ error 1 UNPACKCMDUNVL "Extracting %s requires the %s command, which is not available" "$pkg" "$cat_cmd"
840
+ fi
841
+ }
842
+
843
+ valid_extractor () {
844
+ local extractor="$1"
845
+
846
+ for E in $EXTRACTORS_SUPPORTED; do
847
+ if [ "$extractor" = "$E" ]; then
848
+ return 0
849
+ fi
850
+ done
851
+
852
+ return 1
853
+ }
854
+
855
+ choose_extractor () {
856
+ local extractor
857
+
858
+ if [ -n "$EXTRACTOR_OVERRIDE" ]; then
859
+ extractor="$EXTRACTOR_OVERRIDE"
860
+ elif type dpkg-deb >/dev/null 2>&1; then
861
+ extractor="dpkg-deb"
862
+ else
863
+ extractor="ar"
864
+ fi
865
+
866
+ info CHOSENEXTRACTOR "Chosen extractor for .deb packages: %s" "$extractor"
867
+ case "$extractor" in
868
+ dpkg-deb)
869
+ extract_deb_field () { extract_dpkg_deb_field "$@"; }
870
+ extract_deb_data () { extract_dpkg_deb_data "$@"; }
871
+ ;;
872
+ ar)
873
+ extract_deb_field () { extract_ar_deb_field "$@"; }
874
+ extract_deb_data () { extract_ar_deb_data "$@"; }
875
+ ;;
876
+ esac
877
+ }
878
+
879
+ extract () { (
880
+ cd "$TARGET"
881
+ local p=0 cat_cmd
882
+ for pkg in $(debfor "$@"); do
883
+ p="$(($p + 1))"
884
+ progress "$p" "$#" EXTRACTPKGS "Extracting packages"
885
+ packagename="$(echo "$pkg" | sed 's,^.*/,,;s,_.*$,,')"
886
+ info EXTRACTING "Extracting %s..." "$packagename"
887
+ extract_deb_data "./$pkg"
888
+ done
889
+ ); }
890
+
891
+ in_target_nofail () {
892
+ if ! $CHROOT_CMD "$@" 2>/dev/null; then
893
+ true
894
+ fi
895
+ return 0
896
+ }
897
+
898
+ in_target_failmsg () {
899
+ local code="$1"
900
+ local msg="$2"
901
+ local arg="$3"
902
+ shift; shift; shift
903
+ if ! $CHROOT_CMD "$@"; then
904
+ warning "$code" "$msg" "$arg"
905
+ # Try to point user at actual failing package.
906
+ msg="See %s for details"
907
+ if [ -e "$TARGET/debootstrap/debootstrap.log" ]; then
908
+ arg="$TARGET/debootstrap/debootstrap.log"
909
+ local pkg="$(grep '^dpkg: error processing ' "$TARGET/debootstrap/debootstrap.log" | head -n 1 | cut -d ' ' -f 4)"
910
+ if [ -n "$pkg" ]; then
911
+ msg="$msg (possibly the package $pkg is at fault)"
912
+ fi
913
+ else
914
+ arg="the log"
915
+ fi
916
+ warning "$code" "$msg" "$arg"
917
+ return 1
918
+ fi
919
+ return 0
920
+ }
921
+
922
+ in_target () {
923
+ in_target_failmsg IN_TARGET_FAIL "Failure trying to run: %s" "$CHROOT_CMD $*" "$@"
924
+ }
925
+
926
+ ###################################################### standard setup stuff
927
+
928
+ conditional_cp () {
929
+ if [ ! -e "$2/$1" ]; then
930
+ if [ -L "$1" ] && [ -e "$1" ]; then
931
+ cat "$1" >"$2/$1"
932
+ elif [ -e "$1" ]; then
933
+ cp -a "$1" "$2/$1"
934
+ fi
935
+ fi
936
+ }
937
+
938
+ mv_invalid_to () {
939
+ local m="$1"
940
+ m="$(echo "${m#http://}" | tr '/' '_' | sed 's/_*//')"
941
+ (cd "$TARGET/$APTSTATE/lists"
942
+ for a in debootstrap.invalid_*; do
943
+ mv "$a" "${m}_${a#*_}"
944
+ done
945
+ )
946
+ }
947
+
948
+ setup_apt_sources () {
949
+ mkdir -p "$TARGET/etc/apt"
950
+ for m in "$@"; do
951
+ local cs=""
952
+ for c in $COMPONENTS; do
953
+ local path="dists/$SUITE/$c/binary-$ARCH/Packages"
954
+ local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")"
955
+ if [ -e "$pkgdest" ]; then cs="$cs $c"; fi
956
+ done
957
+ if [ "$cs" != "" ]; then echo "deb $m $SUITE$cs"; fi
958
+ done > "$TARGET/etc/apt/sources.list"
959
+ }
960
+
961
+ setup_etc () {
962
+ mkdir -p "$TARGET/etc"
963
+
964
+ conditional_cp /etc/resolv.conf "$TARGET"
965
+ conditional_cp /etc/hostname "$TARGET"
966
+
967
+ if [ "$DLDEST" = apt_dest ] && [ ! -e "$TARGET/etc/apt/sources.list" ]; then
968
+ setup_apt_sources "http://debootstrap.invalid/"
969
+ fi
970
+ }
971
+
972
+ UMOUNT_DIRS=
973
+
974
+ umount_exit_function () {
975
+ for dir in $UMOUNT_DIRS; do
976
+ ( cd / ; umount "$TARGET/${dir#/}" ) || true
977
+ done
978
+ }
979
+
980
+ umount_on_exit () {
981
+ if [ "$UMOUNT_DIRS" ]; then
982
+ UMOUNT_DIRS="$UMOUNT_DIRS $1"
983
+ else
984
+ UMOUNT_DIRS="$1"
985
+ on_exit umount_exit_function
986
+ fi
987
+ }
988
+
989
+ clear_mtab () {
990
+ if [ -f "$TARGET/etc/mtab" ] && [ ! -h "$TARGET/etc/mtab" ]; then
991
+ rm -f "$TARGET/etc/mtab"
992
+ fi
993
+ }
994
+
995
+ setup_proc () {
996
+ case "$HOST_OS" in
997
+ *freebsd*)
998
+ umount_on_exit /dev
999
+ umount_on_exit /proc
1000
+ umount "$TARGET/proc" 2>/dev/null || true
1001
+ if [ "$HOST_OS" = kfreebsd ]; then
1002
+ in_target mount -t linprocfs proc /proc
1003
+ else
1004
+ mount -t linprocfs proc $TARGET/proc
1005
+ fi
1006
+ ;;
1007
+ hurd*)
1008
+ ;;
1009
+ *)
1010
+ umount_on_exit /dev/pts
1011
+ umount_on_exit /dev/shm
1012
+ umount_on_exit /proc/bus/usb
1013
+ umount_on_exit /proc
1014
+ umount "$TARGET/proc" 2>/dev/null || true
1015
+ in_target mount -t proc proc /proc
1016
+ if [ -d "$TARGET/sys" ] && \
1017
+ grep -q '[[:space:]]sysfs' /proc/filesystems 2>/dev/null; then
1018
+ umount_on_exit /sys
1019
+ umount "$TARGET/sys" 2>/dev/null || true
1020
+ in_target mount -t sysfs sysfs /sys
1021
+ fi
1022
+ on_exit clear_mtab
1023
+ ;;
1024
+ esac
1025
+ umount_on_exit /lib/init/rw
1026
+ }
1027
+
1028
+ setup_proc_fakechroot () {
1029
+ rm -rf "$TARGET/proc"
1030
+ ln -s /proc "$TARGET"
1031
+ }
1032
+
1033
+ setup_devices () {
1034
+ if doing_variant fakechroot; then
1035
+ setup_devices_fakechroot
1036
+ return 0
1037
+ fi
1038
+
1039
+ case "$HOST_OS" in
1040
+ kfreebsd*)
1041
+ in_target mount -t devfs devfs /dev ;;
1042
+ freebsd)
1043
+ mount -t devfs devfs $TARGET/dev ;;
1044
+ hurd*)
1045
+ setup_devices_hurd ;;
1046
+ *)
1047
+ if [ -e "$DEVICES_TARGZ" ]; then
1048
+ zcat "$DEVICES_TARGZ" | (cd "$TARGET"; tar -xf -)
1049
+ else
1050
+ if [ -e /dev/.devfsd ] ; then
1051
+ in_target mount -t devfs devfs /dev
1052
+ else
1053
+ error 1 NODEVTGZ "no %s. cannot create devices" "$DEVICES_TARGZ"
1054
+ fi
1055
+ fi
1056
+ ;;
1057
+ esac
1058
+ }
1059
+
1060
+ setup_devices_hurd () {
1061
+ # Use the setup-translators of the hurd package, and firmlink
1062
+ # $TARGET/{dev,servers} to the system ones.
1063
+ in_target /usr/lib/hurd/setup-translators -k
1064
+ settrans -a $TARGET/dev /hurd/firmlink /dev
1065
+ settrans -a $TARGET/servers /hurd/firmlink /servers
1066
+ }
1067
+
1068
+ setup_devices_fakechroot () {
1069
+ rm -rf "$TARGET/dev"
1070
+ ln -s /dev "$TARGET"
1071
+ }
1072
+
1073
+ setup_dselect_method () {
1074
+ case "$1" in
1075
+ apt)
1076
+ mkdir -p "$TARGET/var/lib/dpkg"
1077
+ echo "apt apt" > "$TARGET/var/lib/dpkg/cmethopt"
1078
+ chmod 644 "$TARGET/var/lib/dpkg/cmethopt"
1079
+ ;;
1080
+ *)
1081
+ error 1 UNKNOWNDSELECT "unknown dselect method"
1082
+ ;;
1083
+ esac
1084
+ }
1085
+
1086
+ ################################################################ pkgdetails
1087
+
1088
+ # NOTE
1089
+ # For the debootstrap udeb, pkgdetails is provided by the bootstrap-base
1090
+ # udeb, so the pkgdetails API needs to be kept in sync with that.
1091
+
1092
+ if in_path perl; then
1093
+ PKGDETAILS=pkgdetails_perl
1094
+
1095
+ pkgdetails_field () {
1096
+ # uniq field mirror Packages values...
1097
+ perl -le '
1098
+ $unique = shift @ARGV; $field = lc(shift @ARGV); $mirror = shift @ARGV;
1099
+ %fields = map { $_, 0 } @ARGV;
1100
+ $prevpkg = "";
1101
+ while (<STDIN>) {
1102
+ chomp;
1103
+ next if (/^ /);
1104
+ if (/^([^:]*:)\s*(.*)$/) {
1105
+ $f = lc($1); $v = $2;
1106
+ if ($f eq "package:") {
1107
+ $last = 0;
1108
+ $pkg = $v;
1109
+ if ($pkg ne $prevpkg) {
1110
+ print $output if defined $output;
1111
+ if ($unique && defined $output_val) {
1112
+ delete $fields{$output_val};
1113
+ $last = 1 unless keys %fields;
1114
+ }
1115
+ $prevpkg = $pkg;
1116
+ }
1117
+ undef $output;
1118
+ undef $output_val;
1119
+ last if $last;
1120
+ }
1121
+ $ver = $v if ($f eq "version:");
1122
+ $arc = $v if ($f eq "architecture:");
1123
+ $fil = $v if ($f eq "filename:");
1124
+ $chk = $v if (lc $f eq lc($ENV{DEBOOTSTRAP_CHECKSUM_FIELD}).":");
1125
+ $siz = $v if ($f eq "size:");
1126
+ $val = $v if ($f eq $field);
1127
+ } elsif (/^$/) {
1128
+ if (defined $val && defined $fields{$val}) {
1129
+ $output = sprintf "%s %s %s %s %s %s %s",
1130
+ $pkg, $ver, $arc, $mirror, $fil, $chk, $siz;
1131
+ $output_val = $val;
1132
+ }
1133
+ undef $val;
1134
+ }
1135
+ }
1136
+ print $output if defined $output;
1137
+ delete $fields{$output_val} if $unique && defined $output_val;
1138
+ for $v (keys %fields) {
1139
+ printf ("%s -\n", $v) if ($unique);
1140
+ }
1141
+ ' "$@"
1142
+ }
1143
+
1144
+ pkgdetails_perl () {
1145
+ if [ "$1" = "WGET%" ]; then
1146
+ shift;
1147
+ perl -e '
1148
+ $v = 0;
1149
+ while (read STDIN, $x, 1) {
1150
+ if ($x =~ m/\d/) {
1151
+ $v *= 10;
1152
+ $v += $x;
1153
+ } elsif ($x eq "%") {
1154
+ printf "P: %d %d%s\n", int($v / 100.0 * ($ARGV[1] - $ARGV[0]) + $ARGV[0]), $ARGV[2], ($#ARGV == 3 ? " $ARGV[3]" : "");
1155
+ $v = 0;
1156
+ } else {
1157
+ $v = 0;
1158
+ }
1159
+ }' "$@"
1160
+ elif [ "$1" = "GETDEPS" ]; then
1161
+ local pkgdest="$2"; shift; shift
1162
+ perl -e '
1163
+ $prevpkg = "";
1164
+ @d = ();
1165
+ while (<STDIN>) {
1166
+ chomp;
1167
+ if (/^Package: (.*)$/) {
1168
+ $pkg = $1;
1169
+ if ($pkg ne $prevpkg) {
1170
+ for my $d (@d) {
1171
+ print "$d\n";
1172
+ }
1173
+ }
1174
+ $prevpkg = $1;
1175
+ @d = ();
1176
+ }
1177
+ $in = 1 if (grep {$_ eq $pkg} @ARGV);
1178
+ $in = 0 if (/^$/);
1179
+ if ($in and (/^Depends: (.*)$/ or /^Pre-Depends: (.*)$/)) {
1180
+ for $d (split /\s*,\s*/, $1) {
1181
+ $d =~ s/\s*[|].*$//;
1182
+ $d =~ s/\s*[(].*[)]\s*//;
1183
+ push @d, $d;
1184
+ }
1185
+ }
1186
+ }
1187
+ for my $d (@d) {
1188
+ print "$d\n";
1189
+ }' <"$pkgdest" "$@" | sort | uniq
1190
+ elif [ "$1" = "PKGS" ]; then
1191
+ local m="$2"
1192
+ local p="$3"
1193
+ shift; shift; shift
1194
+ pkgdetails_field 1 Package: "$m" "$@" < "$p"
1195
+ elif [ "$1" = "FIELD" ]; then
1196
+ local f="$2"
1197
+ local m="$3"
1198
+ local p="$4"
1199
+ shift; shift; shift; shift
1200
+ pkgdetails_field 0 "$f" "$m" "$@" < "$p"
1201
+ elif [ "$1" = "STANZAS" ]; then
1202
+ local pkgdest="$2"; shift; shift
1203
+ perl -e '
1204
+ my $accum = "";
1205
+ while (<STDIN>) {
1206
+ $accum .= $_;
1207
+ $in = 1 if (/^Package: (.*)$/ && grep {$_ eq $1} @ARGV);
1208
+ if ($in and /^$/) {
1209
+ print $accum;
1210
+ if (substr($accum, -1) != "\n") {
1211
+ print "\n\n";
1212
+ } elsif (substr($accum, -2, 1) != "\n") {
1213
+ print "\n";
1214
+ }
1215
+ $in = 0;
1216
+ }
1217
+ $accum = "" if /^$/;
1218
+ }' <"$pkgdest" "$@"
1219
+ fi
1220
+ }
1221
+ elif [ -e "/usr/lib/debootstrap/pkgdetails" ]; then
1222
+ PKGDETAILS="/usr/lib/debootstrap/pkgdetails"
1223
+ elif [ -e "$DEBOOTSTRAP_DIR/pkgdetails" ]; then
1224
+ PKGDETAILS="$DEBOOTSTRAP_DIR/pkgdetails"
1225
+ else
1226
+ PKGDETAILS=""
1227
+ fi
1228
+
1229
+ ##################################################### dependency resolution
1230
+
1231
+ resolve_deps () {
1232
+ local m1="${MIRRORS%% *}"
1233
+
1234
+ local PKGS="$*"
1235
+ local ALLPKGS="$PKGS";
1236
+ local ALLPKGS2="";
1237
+ while [ "$PKGS" != "" ]; do
1238
+ local NEWPKGS=""
1239
+ for c in $COMPONENTS; do
1240
+ local path="dists/$SUITE/$c/binary-$ARCH/Packages"
1241
+ local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")"
1242
+ NEWPKGS="$NEWPKGS $("$PKGDETAILS" GETDEPS "$pkgdest" $PKGS)"
1243
+ done
1244
+ PKGS=$(echo "$PKGS $NEWPKGS" | tr ' ' '\n' | sort | uniq)
1245
+ local REALPKGS=""
1246
+ for c in $COMPONENTS; do
1247
+ local path="dists/$SUITE/$c/binary-$ARCH/Packages"
1248
+ local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")"
1249
+ REALPKGS="$REALPKGS $("$PKGDETAILS" PKGS REAL "$pkgdest" $PKGS | sed -n 's/ .*REAL.*$//p')"
1250
+ done
1251
+ PKGS="$REALPKGS"
1252
+ ALLPKGS2=$(echo "$PKGS $ALLPKGS" | tr ' ' '\n' | sort | uniq)
1253
+ PKGS=$(without "$ALLPKGS2" "$ALLPKGS")
1254
+ ALLPKGS="$ALLPKGS2"
1255
+ done
1256
+ echo $ALLPKGS
1257
+ }
1258
+
1259
+ setup_available () {
1260
+ local m1="${MIRRORS%% *}"
1261
+
1262
+ for c in $COMPONENTS; do
1263
+ local path="dists/$SUITE/$c/binary-$ARCH/Packages"
1264
+ local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")"
1265
+ # XXX: What if a package is in more than one component?
1266
+ # -- cjwatson 2009-07-29
1267
+ "$PKGDETAILS" STANZAS "$pkgdest" "$@"
1268
+ done >"$TARGET/var/lib/dpkg/available"
1269
+
1270
+ for pkg; do
1271
+ echo "$pkg install"
1272
+ done | in_target dpkg --set-selections
1273
+ }
1274
+
1275
+ get_next_predep () {
1276
+ local stanza="$(in_target_nofail dpkg --predep-package)"
1277
+ [ "$stanza" ] || return 1
1278
+ echo "$stanza" | grep '^Package:' | sed 's/^Package://; s/^ *//'
1279
+ }
1280
+
1281
+ ################################################################### helpers
1282
+
1283
+ # Return zero if it is possible to create devices and execute programs in
1284
+ # this directory. (Both may be forbidden by mount options, e.g. nodev and
1285
+ # noexec respectively.)
1286
+ check_sane_mount () {
1287
+ mkdir -p "$1"
1288
+
1289
+ case "$HOST_OS" in
1290
+ *freebsd*|hurd*)
1291
+ ;;
1292
+ *)
1293
+ mknod "$1/test-dev-null" c 1 3 || return 1
1294
+ if ! echo test > "$1/test-dev-null"; then
1295
+ rm -f "$1/test-dev-null"
1296
+ return 1
1297
+ fi
1298
+ rm -f "$1/test-dev-null"
1299
+ ;;
1300
+ esac
1301
+
1302
+ cat > "$1/test-exec" <<EOF
1303
+ #! /bin/sh
1304
+ :
1305
+ EOF
1306
+ chmod +x "$1/test-exec"
1307
+ if ! "$1/test-exec"; then
1308
+ rm -f "$1/test-exec"
1309
+ return 1
1310
+ fi
1311
+ rm -f "$1/test-exec"
1312
+
1313
+ return 0
1314
+ }
1315
+
1316
+ read_gpg_status () {
1317
+ badsig=
1318
+ unkkey=
1319
+ validsig=
1320
+ while read prefix keyword keyid rest; do
1321
+ [ "$prefix" = '[GNUPG:]' ] || continue
1322
+ case $keyword in
1323
+ BADSIG) badsig="$keyid" ;;
1324
+ NO_PUBKEY) unkkey="$keyid" ;;
1325
+ VALIDSIG) validsig="$keyid" ;;
1326
+ esac
1327
+ done
1328
+ if [ "$validsig" ]; then
1329
+ info VALIDRELSIG "Valid Release signature (key id %s)" "$validsig"
1330
+ elif [ "$badsig" ]; then
1331
+ error 1 BADRELSIG "Invalid Release signature (key id %s)" "$badsig"
1332
+ elif [ "$unkkey" ]; then
1333
+ error 1 UNKNOWNRELSIG "Release signed by unknown key (key id %s)" "$unkkey"
1334
+ else
1335
+ error 1 SIGCHECK "Error executing gpgv to check Release signature"
1336
+ fi
1337
+ }
1338
+
1339
+ without () {
1340
+ # usage: without "a b c" "a d" -> "b" "c"
1341
+ (echo $1 | tr ' ' '\n' | sort | uniq;
1342
+ echo $2 $2 | tr ' ' '\n') | sort | uniq -u | tr '\n' ' '
1343
+ echo
1344
+ }
1345
+
1346
+ # Formerly called 'repeat', but that's a reserved word in zsh.
1347
+ repeatn () {
1348
+ local n="$1"
1349
+ shift
1350
+ while [ "$n" -gt 0 ]; do
1351
+ if "$@"; then
1352
+ break
1353
+ else
1354
+ n="$(( $n - 1 ))"
1355
+ sleep 1
1356
+ fi
1357
+ done
1358
+ if [ "$n" -eq 0 ]; then return 1; fi
1359
+ return 0
1360
+ }
1361
+
1362
+ N_EXIT_THINGS=0
1363
+ exit_function () {
1364
+ local n=0
1365
+ while [ "$n" -lt "$N_EXIT_THINGS" ]; do
1366
+ (eval $(eval echo \${EXIT_THING_$n}) 2>/dev/null || true)
1367
+ n="$(( $n + 1 ))"
1368
+ done
1369
+ N_EXIT_THINGS=0
1370
+ }
1371
+
1372
+ trap "exit_function" 0
1373
+ trap "exit 129" 1
1374
+ trap "error 130 INTERRUPTED \"Interrupt caught ... exiting\"" 2
1375
+ trap "exit 131" 3
1376
+ trap "exit 143" 15
1377
+
1378
+ on_exit () {
1379
+ eval `echo EXIT_THING_${N_EXIT_THINGS}=\"$1\"`
1380
+ N_EXIT_THINGS="$(( $N_EXIT_THINGS + 1 ))"
1381
+ }
1382
+
1383
+ ############################################################## fakechroot tools
1384
+
1385
+ install_fakechroot_tools () {
1386
+ if [ "$VARIANT" = "fakechroot" ]; then
1387
+ export PATH=/usr/sbin:/sbin:$PATH
1388
+ fi
1389
+
1390
+ mv "$TARGET/sbin/ldconfig" "$TARGET/sbin/ldconfig.REAL"
1391
+ echo \
1392
+ "#!/bin/sh
1393
+ echo
1394
+ echo \"Warning: Fake ldconfig called, doing nothing\"" > "$TARGET/sbin/ldconfig"
1395
+ chmod 755 "$TARGET/sbin/ldconfig"
1396
+
1397
+ echo \
1398
+ "/sbin/ldconfig
1399
+ /sbin/ldconfig.REAL
1400
+ fakechroot" >> "$TARGET/var/lib/dpkg/diversions"
1401
+
1402
+ mv "$TARGET/usr/bin/ldd" "$TARGET/usr/bin/ldd.REAL"
1403
+ cat << 'END' > "$TARGET/usr/bin/ldd"
1404
+ #!/usr/bin/perl
1405
+
1406
+ # fakeldd
1407
+ #
1408
+ # Replacement for ldd with usage of objdump
1409
+ #
1410
+ # (c) 2003-2005 Piotr Roszatycki <dexter@debian.org>, BSD
1411
+
1412
+
1413
+ my %libs = ();
1414
+
1415
+ my $status = 0;
1416
+ my $dynamic = 0;
1417
+ my $biarch = 0;
1418
+
1419
+ my $ldlinuxsodir = "/lib";
1420
+ my @ld_library_path = qw(/usr/lib /lib);
1421
+
1422
+
1423
+ sub ldso($) {
1424
+ my ($lib) = @_;
1425
+ my @files = ();
1426
+
1427
+ if ($lib =~ /^\//) {
1428
+ $libs{$lib} = $lib;
1429
+ push @files, $lib;
1430
+ } else {
1431
+ foreach my $ld_path (@ld_library_path) {
1432
+ next unless -f "$ld_path/$lib";
1433
+ my $badformat = 0;
1434
+ open OBJDUMP, "objdump -p $ld_path/$lib 2>/dev/null |";
1435
+ while (my $line = <OBJDUMP>) {
1436
+ if ($line =~ /file format (\S*)$/) {
1437
+ $badformat = 1 unless $format eq $1;
1438
+ last;
1439
+ }
1440
+ }
1441
+ close OBJDUMP;
1442
+ next if $badformat;
1443
+ $libs{$lib} = "$ld_path/$lib";
1444
+ push @files, "$ld_path/$lib";
1445
+ }
1446
+ objdump(@files);
1447
+ }
1448
+ }
1449
+
1450
+
1451
+ sub objdump(@) {
1452
+ my (@files) = @_;
1453
+ my @libs = ();
1454
+
1455
+ foreach my $file (@files) {
1456
+ open OBJDUMP, "objdump -p $file 2>/dev/null |";
1457
+ while (my $line = <OBJDUMP>) {
1458
+ $line =~ s/^\s+//;
1459
+ my @f = split (/\s+/, $line);
1460
+ if ($line =~ /file format (\S*)$/) {
1461
+ if (not $format) {
1462
+ $format = $1;
1463
+ if ($unamearch eq "x86_64" and $format eq "elf32-i386") {
1464
+ my $link = readlink "/lib/ld-linux.so.2";
1465
+ if ($link =~ /^\/emul\/ia32-linux\//) {
1466
+ $ld_library_path[-2] = "/emul/ia32-linux/usr/lib";
1467
+ $ld_library_path[-1] = "/emul/ia32-linux/lib";
1468
+ }
1469
+ } elsif ($unamearch =~ /^(sparc|sparc64)$/ and $format eq "elf64-sparc") {
1470
+ $ldlinuxsodir = "/lib64";
1471
+ $ld_library_path[-2] = "/usr/lib64";
1472
+ $ld_library_path[-1] = "/lib64";
1473
+ }
1474
+ } else {
1475
+ next unless $format eq $1;
1476
+ }
1477
+ }
1478
+ if (not $dynamic and $f[0] eq "Dynamic") {
1479
+ $dynamic = 1;
1480
+ }
1481
+ next unless $f[0] eq "NEEDED";
1482
+ if ($f[1] =~ /^ld-linux(\.|-)/) {
1483
+ $f[1] = "$ldlinuxsodir/" . $f[1];
1484
+ }
1485
+ if (not defined $libs{$f[1]}) {
1486
+ $libs{$f[1]} = undef;
1487
+ push @libs, $f[1];
1488
+ }
1489
+ }
1490
+ close OBJDUMP;
1491
+ }
1492
+
1493
+ foreach my $lib (@libs) {
1494
+ ldso($lib);
1495
+ }
1496
+ }
1497
+
1498
+
1499
+ if ($#ARGV < 0) {
1500
+ print STDERR "fakeldd: missing file arguments\n";
1501
+ exit 1;
1502
+ }
1503
+
1504
+ while ($ARGV[0] =~ /^-/) {
1505
+ my $arg = $ARGV[0];
1506
+ shift @ARGV;
1507
+ last if $arg eq "--";
1508
+ }
1509
+
1510
+ open LD_SO_CONF, "/etc/ld.so.conf";
1511
+ while ($line = <LD_SO_CONF>) {
1512
+ chomp $line;
1513
+ unshift @ld_library_path, $line;
1514
+ }
1515
+ close LD_SO_CONF;
1516
+
1517
+ unshift @ld_library_path, split(/:/, $ENV{LD_LIBRARY_PATH});
1518
+
1519
+ $unamearch = `/bin/uname -m`;
1520
+ chomp $unamearch;
1521
+
1522
+ foreach my $file (@ARGV) {
1523
+ my $address;
1524
+ %libs = ();
1525
+ $dynamic = 0;
1526
+
1527
+ if ($#ARGV > 0) {
1528
+ print "$file:\n";
1529
+ }
1530
+
1531
+ if (not -f $file) {
1532
+ print STDERR "ldd: $file: No such file or directory\n";
1533
+ $status = 1;
1534
+ next;
1535
+ }
1536
+
1537
+ objdump($file);
1538
+
1539
+ if ($dynamic == 0) {
1540
+ print "\tnot a dynamic executable\n";
1541
+ $status = 1;
1542
+ } elsif (scalar %libs eq "0") {
1543
+ print "\tstatically linked\n";
1544
+ }
1545
+
1546
+ if ($format =~ /^elf64-/) {
1547
+ $address = "0x0000000000000000";
1548
+ } else {
1549
+ $address = "0x00000000";
1550
+ }
1551
+
1552
+ foreach $lib (keys %libs) {
1553
+ if ($libs{$lib}) {
1554
+ printf "\t%s => %s (%s)\n", $lib, $libs{$lib}, $address;
1555
+ } else {
1556
+ printf "\t%s => not found\n", $lib;
1557
+ }
1558
+ }
1559
+ }
1560
+
1561
+ exit $status;
1562
+ END
1563
+ chmod 755 "$TARGET/usr/bin/ldd"
1564
+
1565
+ echo \
1566
+ "/usr/bin/ldd
1567
+ /usr/bin/ldd.REAL
1568
+ fakechroot" >> "$TARGET/var/lib/dpkg/diversions"
1569
+
1570
+ }