| 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 | if [ -z "$KEYRING" ]; then
|
| 200 | if [ -e "$1" ]; then
|
| 201 | KEYRING="$1"
|
| 202 | elif [ -z "$DISABLE_KEYRING" ]; then
|
| 203 | if [ -n "$DEF_HTTPS_MIRROR" ] && [ -z "$USER_MIRROR" ] && [ -z "$FORCE_KEYRING" ]; then
|
| 204 | info KEYRING "Keyring file not available at %s; switching to https mirror %s" "$1" "$DEF_HTTPS_MIRROR"
|
| 205 | USER_MIRROR="$DEF_HTTPS_MIRROR"
|
| 206 | else
|
| 207 | warning KEYRING "Cannot check Release signature; keyring file not available %s" "$1"
|
| 208 | if [ -n "$FORCE_KEYRING" ]; then
|
| 209 | error 1 KEYRING "Keyring-based check was requested; aborting accordingly"
|
| 210 | fi
|
| 211 | fi
|
| 212 | fi
|
| 213 | fi
|
| 214 | }
|
| 215 |
|
| 216 | ########################################################## variant handling
|
| 217 |
|
| 218 | doing_variant () {
|
| 219 | if [ "$1" = "$VARIANT" ]; then return 0; fi
|
| 220 | if [ "$1" = "-" ] && [ "$VARIANT" = "" ]; then return 0; fi
|
| 221 | return 1
|
| 222 | }
|
| 223 |
|
| 224 | SUPPORTED_VARIANTS="-"
|
| 225 | variants () {
|
| 226 | SUPPORTED_VARIANTS="$*"
|
| 227 | for v in $*; do
|
| 228 | if doing_variant "$v"; then return 0; fi
|
| 229 | done
|
| 230 | error 1 UNSUPPVARIANT "unsupported variant"
|
| 231 | }
|
| 232 |
|
| 233 | ################################################# work out names for things
|
| 234 |
|
| 235 | mirror_style () {
|
| 236 | case "$1" in
|
| 237 | release)
|
| 238 | DOWNLOAD_INDICES=download_release_indices
|
| 239 | DOWNLOAD_DEBS=download_release
|
| 240 | ;;
|
| 241 | main)
|
| 242 | DOWNLOAD_INDICES=download_main_indices
|
| 243 | DOWNLOAD_DEBS=download_main
|
| 244 | ;;
|
| 245 | *)
|
| 246 | error 1 BADMIRROR "unknown mirror style"
|
| 247 | ;;
|
| 248 | esac
|
| 249 | export DOWNLOAD_INDICES
|
| 250 | export DOWNLOAD_DEBS
|
| 251 | }
|
| 252 |
|
| 253 | force_md5 () {
|
| 254 | DEBOOTSTRAP_CHECKSUM_FIELD=MD5SUM
|
| 255 | export DEBOOTSTRAP_CHECKSUM_FIELD
|
| 256 | }
|
| 257 |
|
| 258 | verify_checksum () {
|
| 259 | # args: dest checksum size
|
| 260 | local expchecksum="$2"
|
| 261 | local expsize="$3"
|
| 262 | if [ "$DEBOOTSTRAP_CHECKSUM_FIELD" = "MD5SUM" ]; then
|
| 263 | if in_path md5sum; then
|
| 264 | relchecksum=`md5sum < "$1" | sed 's/ .*$//'`
|
| 265 | elif in_path md5; then
|
| 266 | relchecksum=`md5 < "$1"`
|
| 267 | else
|
| 268 | error 1 SIGCHECK "Cannot check md5sum"
|
| 269 | fi
|
| 270 | else
|
| 271 | if in_path "sha${SHA_SIZE}sum"; then
|
| 272 | relchecksum=`sha${SHA_SIZE}sum < "$1" | sed 's/ .*$//'`
|
| 273 | elif in_path "sha${SHA_SIZE}"; then
|
| 274 | relchecksum=`sha${SHA_SIZE} < "$1"`
|
| 275 | else
|
| 276 | error 1 SIGCHECK "Cannot check sha${SHA_SIZE}sum"
|
| 277 | fi
|
| 278 | fi
|
| 279 | relsize=`wc -c < "$1"`
|
| 280 | if [ "$expsize" -ne "$relsize" ] || [ "$expchecksum" != "$relchecksum" ]; then
|
| 281 | return 1
|
| 282 | fi
|
| 283 | return 0
|
| 284 | }
|
| 285 |
|
| 286 | get () {
|
| 287 | # args: from dest 'nocache'
|
| 288 | # args: from dest [checksum size] [alt {checksum size type}]
|
| 289 | local displayname
|
| 290 | local versionname
|
| 291 | if [ "${2%.deb}" != "$2" ]; then
|
| 292 | displayname="$(echo "$2" | sed 's,^.*/,,;s,_.*$,,')"
|
| 293 | versionname="$(echo "$2" | sed 's,^.*/,,' | cut -d_ -f2 | sed 's/%3a/:/')"
|
| 294 | else
|
| 295 | displayname="$(echo "$1" | sed 's,^.*/,,')"
|
| 296 | fi
|
| 297 |
|
| 298 | if [ -e "$2" ]; then
|
| 299 | if [ -z "$3" ]; then
|
| 300 | return 0
|
| 301 | elif [ "$3" = nocache ]; then
|
| 302 | rm -f "$2"
|
| 303 | else
|
| 304 | info VALIDATING "Validating %s %s" "$displayname" "$versionname"
|
| 305 | if verify_checksum "$2" "$3" "$4"; then
|
| 306 | return 0
|
| 307 | else
|
| 308 | rm -f "$2"
|
| 309 | fi
|
| 310 | fi
|
| 311 | fi
|
| 312 | # Drop 'nocache' option
|
| 313 | if [ "$3" = nocache ]; then
|
| 314 | set "$1" "$2"
|
| 315 | fi
|
| 316 |
|
| 317 | if [ "$#" -gt 5 ]; then
|
| 318 | local st=3
|
| 319 | if [ "$5" = "-" ]; then st=6; fi
|
| 320 | local order="$(a=$st; while [ "$a" -le $# ]; do eval echo \"\${$(($a+1))}\" $a;
|
| 321 | a=$(($a + 3)); done | sort -n | sed 's/.* //')"
|
| 322 | else
|
| 323 | local order=3
|
| 324 | fi
|
| 325 | for a in $order; do
|
| 326 | local checksum="$(eval echo \${$a})"
|
| 327 | local siz="$(eval echo \${$(( $a+1 ))})"
|
| 328 | local typ="$(eval echo \${$(( $a+2 ))})"
|
| 329 | local from
|
| 330 | local dest
|
| 331 | local iters=0
|
| 332 |
|
| 333 | case "$typ" in
|
| 334 | xz) from="$1.xz"; dest="$2.xz" ;;
|
| 335 | bz2) from="$1.bz2"; dest="$2.bz2" ;;
|
| 336 | gz) from="$1.gz"; dest="$2.gz" ;;
|
| 337 | *) from="$1"; dest="$2" ;;
|
| 338 | esac
|
| 339 |
|
| 340 | if [ "${dest#/}" = "$dest" ]; then
|
| 341 | dest="./$dest"
|
| 342 | fi
|
| 343 | local dest2="$dest"
|
| 344 | if [ -d "${dest2%/*}/partial" ]; then
|
| 345 | dest2="${dest2%/*}/partial/${dest2##*/}"
|
| 346 | fi
|
| 347 |
|
| 348 | while [ "$iters" -lt 10 ]; do
|
| 349 | info RETRIEVING "Retrieving %s %s" "$displayname" "$versionname"
|
| 350 | if ! just_get "$from" "$dest2"; then continue 2; fi
|
| 351 | if [ "$checksum" != "" ]; then
|
| 352 | info VALIDATING "Validating %s %s" "$displayname" "$versionname"
|
| 353 | if verify_checksum "$dest2" "$checksum" "$siz"; then
|
| 354 | checksum=""
|
| 355 | fi
|
| 356 | fi
|
| 357 | if [ -z "$checksum" ]; then
|
| 358 | [ "$dest2" = "$dest" ] || mv "$dest2" "$dest"
|
| 359 | case "$typ" in
|
| 360 | gz) gunzip "$dest" ;;
|
| 361 | bz2) bunzip2 "$dest" ;;
|
| 362 | xz) unxz "$dest" ;;
|
| 363 | esac
|
| 364 | return 0
|
| 365 | else
|
| 366 | rm -f "$dest2"
|
| 367 | warning RETRYING "Retrying failed download of %s" "$from"
|
| 368 | iters="$(($iters + 1))"
|
| 369 | fi
|
| 370 | done
|
| 371 | warning CORRUPTFILE "%s was corrupt" "$from"
|
| 372 | done
|
| 373 | return 1
|
| 374 | }
|
| 375 |
|
| 376 | just_get () {
|
| 377 | # args: from dest
|
| 378 | local from="$1"
|
| 379 | local dest="$2"
|
| 380 | mkdir -p "${dest%/*}"
|
| 381 | if [ "${from#null:}" != "$from" ]; then
|
| 382 | error 1 NOTPREDL "%s was not pre-downloaded" "${from#null:}"
|
| 383 | elif [ "${from#http://}" != "$from" ] || [ "${from#ftp://}" != "$from" ]; then
|
| 384 | # http/ftp mirror
|
| 385 | if wgetprogress -O "$dest" "$from"; then
|
| 386 | return 0
|
| 387 | else
|
| 388 | rm -f "$dest"
|
| 389 | return 1
|
| 390 | fi
|
| 391 | elif [ "${from#https://}" != "$from" ] ; then
|
| 392 | # http/ftp mirror
|
| 393 | if wgetprogress $CHECKCERTIF $CERTIFICATE $PRIVATEKEY -O "$dest" "$from"; then
|
| 394 | return 0
|
| 395 | else
|
| 396 | rm -f "$dest"
|
| 397 | return 1
|
| 398 | fi
|
| 399 | elif [ "${from#file:}" != "$from" ]; then
|
| 400 | local base="${from#file:}"
|
| 401 | if [ "${base#//}" != "$base" ]; then
|
| 402 | base="/${from#file://*/}"
|
| 403 | fi
|
| 404 | if [ -e "$base" ]; then
|
| 405 | cp "$base" "$dest"
|
| 406 | return 0
|
| 407 | else
|
| 408 | return 1
|
| 409 | fi
|
| 410 | elif [ "${from#ssh:}" != "$from" ]; then
|
| 411 | local ssh_dest="$(echo $from | sed -e 's#ssh://##' -e 's#/#:/#')"
|
| 412 | if [ -n "$ssh_dest" ]; then
|
| 413 | scp "$ssh_dest" "$dest"
|
| 414 | return 0
|
| 415 | else
|
| 416 | return 1
|
| 417 | fi
|
| 418 | else
|
| 419 | error 1 UNKNOWNLOC "unknown location %s" "$from"
|
| 420 | fi
|
| 421 | }
|
| 422 |
|
| 423 | download () {
|
| 424 | mk_download_dirs
|
| 425 | "$DOWNLOAD_DEBS" $(echo "$@" | tr ' ' '\n' | sort)
|
| 426 | }
|
| 427 |
|
| 428 | download_indices () {
|
| 429 | mk_download_dirs
|
| 430 | "$DOWNLOAD_INDICES" $(echo "$@" | tr ' ' '\n' | sort)
|
| 431 | }
|
| 432 |
|
| 433 | debfor () {
|
| 434 | (while read pkg path; do
|
| 435 | for p in "$@"; do
|
| 436 | [ "$p" = "$pkg" ] || continue;
|
| 437 | echo "$path"
|
| 438 | done
|
| 439 | done <"$TARGET/debootstrap/debpaths"
|
| 440 | )
|
| 441 | }
|
| 442 |
|
| 443 | apt_dest () {
|
| 444 | # args:
|
| 445 | # deb package version arch mirror path
|
| 446 | # pkg suite component arch mirror path
|
| 447 | # rel suite mirror path
|
| 448 | case "$1" in
|
| 449 | deb)
|
| 450 | echo "/var/cache/apt/archives/${2}_${3}_${4}.deb" | sed 's/:/%3a/'
|
| 451 | ;;
|
| 452 | pkg)
|
| 453 | local m="$5"
|
| 454 | m="debootstrap.invalid"
|
| 455 | #if [ "${m#http://}" != "$m" ]; then
|
| 456 | # m="${m#http://}"
|
| 457 | #elif [ "${m#file://}" != "$m" ]; then
|
| 458 | # m="file_localhost_${m#file://*/}"
|
| 459 | #elif [ "${m#file:/}" != "$m" ]; then
|
| 460 | # m="file_localhost_${m#file:/}"
|
| 461 | #fi
|
| 462 |
|
| 463 | printf "%s" "$APTSTATE/lists/"
|
| 464 | echo "${m}_$6" | sed 's/\//_/g'
|
| 465 | ;;
|
| 466 | rel)
|
| 467 | local m="$3"
|
| 468 | m="debootstrap.invalid"
|
| 469 | #if [ "${m#http://}" != "$m" ]; then
|
| 470 | # m="${m#http://}"
|
| 471 | #elif [ "${m#file://}" != "$m" ]; then
|
| 472 | # m="file_localhost_${m#file://*/}"
|
| 473 | #elif [ "${m#file:/}" != "$m" ]; then
|
| 474 | # m="file_localhost_${m#file:/}"
|
| 475 | #fi
|
| 476 | printf "%s" "$APTSTATE/lists/"
|
| 477 | echo "${m}_$4" | sed 's/\//_/g'
|
| 478 | ;;
|
| 479 | esac
|
| 480 | }
|
| 481 |
|
| 482 | ################################################################## download
|
| 483 |
|
| 484 | get_release_checksum () {
|
| 485 | local reldest="$1"
|
| 486 | local path="$2"
|
| 487 | if [ "$DEBOOTSTRAP_CHECKSUM_FIELD" = MD5SUM ]; then
|
| 488 | local match="^[Mm][Dd]5[Ss][Uu][Mm]"
|
| 489 | else
|
| 490 | local match="^[Ss][Hh][Aa]$SHA_SIZE:"
|
| 491 | fi
|
| 492 | sed -n "/$match/,/^[^ ]/p" < "$reldest" | \
|
| 493 | while read a b c; do
|
| 494 | if [ "$c" = "$path" ]; then echo "$a $b"; fi
|
| 495 | done | head -n 1
|
| 496 | }
|
| 497 |
|
| 498 | extract_release_components () {
|
| 499 | local reldest="$1"; shift
|
| 500 | TMPCOMPONENTS="$(sed -n 's/Components: *//p' "$reldest")"
|
| 501 | for c in $TMPCOMPONENTS ; do
|
| 502 | eval "
|
| 503 | case \"\$c\" in
|
| 504 | $USE_COMPONENTS)
|
| 505 | COMPONENTS=\"\$COMPONENTS \$c\"
|
| 506 | ;;
|
| 507 | esac
|
| 508 | "
|
| 509 | done
|
| 510 | COMPONENTS="$(echo $COMPONENTS)"
|
| 511 | if [ -z "$COMPONENTS" ]; then
|
| 512 | mv "$reldest" "$reldest.malformed"
|
| 513 | error 1 INVALIDREL "Invalid Release file, no valid components"
|
| 514 | fi
|
| 515 | }
|
| 516 |
|
| 517 | CODENAME=""
|
| 518 | validate_suite () {
|
| 519 | local reldest="$1"
|
| 520 |
|
| 521 | CODENAME=$(sed -n "s/^Codename: *//p" "$reldest")
|
| 522 | local suite=$(sed -n "s/^Suite: *//p" "$reldest")
|
| 523 |
|
| 524 | if [ "$SUITE" != "$suite" ] && [ "$SUITE" != "$CODENAME" ]; then
|
| 525 | error 1 WRONGSUITE "Asked to install suite %s, but got %s (codename: %s) from mirror" "$SUITE" "$suite" "$CODENAME"
|
| 526 | fi
|
| 527 | }
|
| 528 |
|
| 529 | split_inline_sig () {
|
| 530 | local inreldest="$1"
|
| 531 | local reldest="$2"
|
| 532 | local relsigdest="$3"
|
| 533 |
|
| 534 | # Note: InRelease files are fun since one needs to remove the
|
| 535 | # last newline from the PGP SIGNED MESSAGE part, while keeping
|
| 536 | # the PGP SIGNATURE part intact. This shell implementation
|
| 537 | # should work on most if not all systems, instead of trying to
|
| 538 | # sed/tr/head, etc.
|
| 539 | rm -f "$reldest" "$relsigdest"
|
| 540 | nl=""
|
| 541 | state=pre-begin
|
| 542 | while IFS= read -r line; do
|
| 543 | case "${state}" in
|
| 544 | pre-begin)
|
| 545 | if [ "x${line}" = "x-----BEGIN PGP SIGNED MESSAGE-----" ]; then
|
| 546 | state=begin
|
| 547 | fi
|
| 548 | ;;
|
| 549 | begin)
|
| 550 | if [ "x${line}" = "x" ]; then
|
| 551 | state=data
|
| 552 | fi
|
| 553 | ;;
|
| 554 | data)
|
| 555 | if [ "x${line}" = "x-----BEGIN PGP SIGNATURE-----" ]; then
|
| 556 | printf "%s\n" "${line}" > "$relsigdest"
|
| 557 | state=signature
|
| 558 | else
|
| 559 | printf "${nl}%s" "${line}" >> "$reldest"
|
| 560 | nl="\n"
|
| 561 | fi
|
| 562 | ;;
|
| 563 | signature)
|
| 564 | printf "%s\n" "${line}" >> "$relsigdest"
|
| 565 | if [ "x${line}" = "x-----END PGP SIGNATURE-----" ]; then
|
| 566 | break
|
| 567 | fi
|
| 568 | esac
|
| 569 | done < "$inreldest"
|
| 570 | }
|
| 571 |
|
| 572 | download_release_sig () {
|
| 573 | local m1="$1"
|
| 574 | local inreldest="$2"
|
| 575 | local reldest="$3"
|
| 576 | local relsigdest="$4"
|
| 577 |
|
| 578 | progress 0 100 DOWNREL "Downloading Release file"
|
| 579 | progress_next 100
|
| 580 | if get "$m1/dists/$SUITE/InRelease" "$inreldest" nocache; then
|
| 581 | split_inline_sig "$inreldest" "$reldest" "$relsigdest"
|
| 582 | progress 100 100 DOWNREL "Downloading Release file"
|
| 583 | else
|
| 584 | get "$m1/dists/$SUITE/Release" "$reldest" nocache ||
|
| 585 | error 1 NOGETREL "Failed getting release file %s" "$m1/dists/$SUITE/Release"
|
| 586 | progress 100 100 DOWNREL "Downloading Release file"
|
| 587 | fi
|
| 588 | if [ -n "$KEYRING" ] && [ -z "$DISABLE_KEYRING" ]; then
|
| 589 | progress 0 100 DOWNRELSIG "Downloading Release file signature"
|
| 590 | if ! [ -f "$relsigdest" ]; then
|
| 591 | progress_next 50
|
| 592 | get "$m1/dists/$SUITE/Release.gpg" "$relsigdest" nocache ||
|
| 593 | error 1 NOGETRELSIG "Failed getting release signature file %s" \
|
| 594 | "$m1/dists/$SUITE/Release.gpg"
|
| 595 | progress 50 100 DOWNRELSIG "Downloading Release file signature"
|
| 596 | fi
|
| 597 |
|
| 598 | info RELEASESIG "Checking Release signature"
|
| 599 | # Don't worry about the exit status from gpgv; parsing the output will
|
| 600 | # take care of that.
|
| 601 | (gpgv --status-fd 1 --keyring "$KEYRING" --ignore-time-conflict \
|
| 602 | "$relsigdest" "$reldest" || true) | read_gpg_status
|
| 603 | progress 100 100 DOWNRELSIG "Downloading Release file signature"
|
| 604 | fi
|
| 605 | }
|
| 606 |
|
| 607 | download_release_indices () {
|
| 608 | local m1="${MIRRORS%% *}"
|
| 609 | local inreldest="$TARGET/$($DLDEST rel "$SUITE" "$m1" "dists/$SUITE/InRelease")"
|
| 610 | local reldest="$TARGET/$($DLDEST rel "$SUITE" "$m1" "dists/$SUITE/Release")"
|
| 611 | local relsigdest="$TARGET/$($DLDEST rel "$SUITE" "$m1" "dists/$SUITE/Release.gpg")"
|
| 612 |
|
| 613 | download_release_sig "$m1" "$inreldest" "$reldest" "$relsigdest"
|
| 614 |
|
| 615 | validate_suite "$reldest"
|
| 616 |
|
| 617 | extract_release_components $reldest
|
| 618 |
|
| 619 | local totalpkgs=0
|
| 620 | for c in $COMPONENTS; do
|
| 621 | local subpath="$c/binary-$ARCH/Packages"
|
| 622 | local xzi="`get_release_checksum "$reldest" "$subpath.xz"`"
|
| 623 | local bz2i="`get_release_checksum "$reldest" "$subpath.bz2"`"
|
| 624 | local gzi="`get_release_checksum "$reldest" "$subpath.gz"`"
|
| 625 | local normi="`get_release_checksum "$reldest" "$subpath"`"
|
| 626 | local i=
|
| 627 | if [ "$normi" != "" ]; then
|
| 628 | i="$normi"
|
| 629 | elif in_path bunzip2 && [ "$bz2i" != "" ]; then
|
| 630 | i="$bz2i"
|
| 631 | elif in_path unxz && [ "$xzi" != "" ]; then
|
| 632 | i="$xzi"
|
| 633 | elif in_path gunzip && [ "$gzi" != "" ]; then
|
| 634 | i="$gzi"
|
| 635 | fi
|
| 636 | if [ "$i" != "" ]; then
|
| 637 | totalpkgs="$(( $totalpkgs + ${i#* } ))"
|
| 638 | else
|
| 639 | mv "$reldest" "$reldest.malformed"
|
| 640 | error 1 MISSINGRELENTRY "Invalid Release file, no entry for %s" "$subpath"
|
| 641 | fi
|
| 642 | done
|
| 643 |
|
| 644 | local donepkgs=0
|
| 645 | local pkgdest
|
| 646 | progress 0 $totalpkgs DOWNPKGS "Downloading Packages files"
|
| 647 | for c in $COMPONENTS; do
|
| 648 | local subpath="$c/binary-$ARCH/Packages"
|
| 649 | local path="dists/$SUITE/$subpath"
|
| 650 | local xzi="`get_release_checksum "$reldest" "$subpath.xz"`"
|
| 651 | local bz2i="`get_release_checksum "$reldest" "$subpath.bz2"`"
|
| 652 | local gzi="`get_release_checksum "$reldest" "$subpath.gz"`"
|
| 653 | local normi="`get_release_checksum "$reldest" "$subpath"`"
|
| 654 | local ext=
|
| 655 | local i=
|
| 656 | if [ "$normi" != "" ]; then
|
| 657 | ext="$ext $normi ."
|
| 658 | i="$normi"
|
| 659 | fi
|
| 660 | if in_path unxz && [ "$xzi" != "" ]; then
|
| 661 | ext="$ext $xzi xz"
|
| 662 | i="${i:-$xzi}"
|
| 663 | fi
|
| 664 | if in_path bunzip2 && [ "$bz2i" != "" ]; then
|
| 665 | ext="$ext $bz2i bz2"
|
| 666 | i="${i:-$bz2i}"
|
| 667 | fi
|
| 668 | if in_path gunzip && [ "$gzi" != "" ]; then
|
| 669 | ext="$ext $gzi gz"
|
| 670 | i="${i:-$gzi}"
|
| 671 | fi
|
| 672 | progress_next "$(($donepkgs + ${i#* }))"
|
| 673 | for m in $MIRRORS; do
|
| 674 | pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")"
|
| 675 | if get "$m/$path" "$pkgdest" $ext; then break; fi
|
| 676 | done
|
| 677 | if [ ! -f "$pkgdest" ]; then
|
| 678 | error 1 COULDNTDL "Couldn't download %s" "$path"
|
| 679 | fi
|
| 680 | donepkgs="$(($donepkgs + ${i#* }))"
|
| 681 | progress $donepkgs $totalpkgs DOWNPKGS "Downloading Packages files"
|
| 682 | done
|
| 683 | }
|
| 684 |
|
| 685 | get_package_sizes () {
|
| 686 | # mirror pkgdest debs..
|
| 687 | local m="$1"; shift
|
| 688 | local pkgdest="$1"; shift
|
| 689 | $PKGDETAILS PKGS "$m" "$pkgdest" "$@" | (
|
| 690 | newleft=""
|
| 691 | totaldebs=0
|
| 692 | countdebs=0
|
| 693 | while read p details; do
|
| 694 | if [ "$details" = "-" ]; then
|
| 695 | newleft="$newleft $p"
|
| 696 | else
|
| 697 | size="${details##* }";
|
| 698 | totaldebs="$(($totaldebs + $size))"
|
| 699 | countdebs="$(($countdebs + 1))"
|
| 700 | fi
|
| 701 | done
|
| 702 | echo "$countdebs $totaldebs$newleft"
|
| 703 | )
|
| 704 | }
|
| 705 |
|
| 706 | # note, leftovers come back on fd5 !!
|
| 707 | download_debs () {
|
| 708 | local m="$1"
|
| 709 | local pkgdest="$2"
|
| 710 | shift; shift
|
| 711 |
|
| 712 | $PKGDETAILS PKGS "$m" "$pkgdest" "$@" | (
|
| 713 | leftover=""
|
| 714 | while read p ver arc mdup fil checksum size; do
|
| 715 | if [ "$ver" = "-" ]; then
|
| 716 | leftover="$leftover $p"
|
| 717 | else
|
| 718 | progress_next "$(($dloaddebs + $size))"
|
| 719 | local debdest="$($DLDEST deb "$p" "$ver" "$arc" "$m" "$fil")"
|
| 720 | if get "$m/$fil" "$TARGET/$debdest" "$checksum" "$size"; then
|
| 721 | dloaddebs="$(($dloaddebs + $size))"
|
| 722 | echo >>$TARGET/debootstrap/deburis "$p $ver $m/$fil"
|
| 723 | echo >>$TARGET/debootstrap/debpaths "$p $debdest"
|
| 724 | else
|
| 725 | warning COULDNTDL "Couldn't download package %s (ver %s arch %s)" "$p" "$ver" "$arc"
|
| 726 | leftover="$leftover $p"
|
| 727 | fi
|
| 728 | fi
|
| 729 | done
|
| 730 | echo >&5 ${leftover# }
|
| 731 | )
|
| 732 | }
|
| 733 |
|
| 734 | download_release () {
|
| 735 | local m1="${MIRRORS%% *}"
|
| 736 |
|
| 737 | local numdebs="$#"
|
| 738 |
|
| 739 | local countdebs=0
|
| 740 | progress $countdebs $numdebs SIZEDEBS "Finding package sizes"
|
| 741 |
|
| 742 | local totaldebs=0
|
| 743 | local leftoverdebs="$*"
|
| 744 |
|
| 745 | # Fix possible duplicate package names, which would screw up counts:
|
| 746 | leftoverdebs=$(printf "$leftoverdebs"|tr ' ' '\n'|sort -u|tr '\n' ' ')
|
| 747 | numdebs=$(printf "$leftoverdebs"|wc -w)
|
| 748 |
|
| 749 | for c in $COMPONENTS; do
|
| 750 | if [ "$countdebs" -ge "$numdebs" ]; then break; fi
|
| 751 |
|
| 752 | local path="dists/$SUITE/$c/binary-$ARCH/Packages"
|
| 753 | local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")"
|
| 754 | if [ ! -e "$pkgdest" ]; then continue; fi
|
| 755 |
|
| 756 | info CHECKINGSIZES "Checking component %s on %s..." "$c" "$m1"
|
| 757 |
|
| 758 | leftoverdebs="$(get_package_sizes "$m1" "$pkgdest" $leftoverdebs)"
|
| 759 |
|
| 760 | countdebs=$(($countdebs + ${leftoverdebs%% *}))
|
| 761 | leftoverdebs=${leftoverdebs#* }
|
| 762 |
|
| 763 | totaldebs=${leftoverdebs%% *}
|
| 764 | leftoverdebs=${leftoverdebs#* }
|
| 765 |
|
| 766 | progress $countdebs $numdebs SIZEDEBS "Finding package sizes"
|
| 767 | done
|
| 768 |
|
| 769 | if [ "$countdebs" -ne "$numdebs" ]; then
|
| 770 | error 1 LEFTOVERDEBS "Couldn't find these debs: %s" "$leftoverdebs"
|
| 771 | fi
|
| 772 |
|
| 773 | local dloaddebs=0
|
| 774 |
|
| 775 | progress $dloaddebs $totaldebs DOWNDEBS "Downloading packages"
|
| 776 | :>$TARGET/debootstrap/debpaths
|
| 777 |
|
| 778 | pkgs_to_get="$*"
|
| 779 | for c in $COMPONENTS; do
|
| 780 | local path="dists/$SUITE/$c/binary-$ARCH/Packages"
|
| 781 | for m in $MIRRORS; do
|
| 782 | local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")"
|
| 783 | if [ ! -e "$pkgdest" ]; then continue; fi
|
| 784 | pkgs_to_get="$(download_debs "$m" "$pkgdest" $pkgs_to_get 5>&1 1>&6)"
|
| 785 | if [ -z "$pkgs_to_get" ]; then break; fi
|
| 786 | done 6>&1
|
| 787 | if [ -z "$pkgs_to_get" ]; then break; fi
|
| 788 | done
|
| 789 | progress $dloaddebs $totaldebs DOWNDEBS "Downloading packages"
|
| 790 | if [ "$pkgs_to_get" != "" ]; then
|
| 791 | error 1 COULDNTDLPKGS "Couldn't download packages: %s" "$pkgs_to_get"
|
| 792 | fi
|
| 793 | }
|
| 794 |
|
| 795 | download_main_indices () {
|
| 796 | local m1="${MIRRORS%% *}"
|
| 797 | local comp="${USE_COMPONENTS}"
|
| 798 | progress 0 100 DOWNMAINPKGS "Downloading Packages file"
|
| 799 | progress_next 100
|
| 800 |
|
| 801 | if [ -z "$comp" ]; then comp=main; fi
|
| 802 | COMPONENTS="$(echo $comp | tr '|' ' ')"
|
| 803 |
|
| 804 | export COMPONENTS
|
| 805 | for m in $MIRRORS; do
|
| 806 | for c in $COMPONENTS; do
|
| 807 | local path="dists/$SUITE/$c/binary-$ARCH/Packages"
|
| 808 | local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")"
|
| 809 | if in_path gunzip && get "$m/${path}.gz" "${pkgdest}.gz"; then
|
| 810 | rm -f "$pkgdest"
|
| 811 | gunzip "$pkgdest.gz"
|
| 812 | elif get "$m/$path" "$pkgdest"; then
|
| 813 | true
|
| 814 | fi
|
| 815 | done
|
| 816 | done
|
| 817 | progress 100 100 DOWNMAINPKGS "Downloading Packages file"
|
| 818 | }
|
| 819 |
|
| 820 | download_main () {
|
| 821 | local m1="${MIRRORS%% *}"
|
| 822 |
|
| 823 | :>$TARGET/debootstrap/debpaths
|
| 824 | for p in "$@"; do
|
| 825 | for c in $COMPONENTS; do
|
| 826 | local details=""
|
| 827 | for m in $MIRRORS; do
|
| 828 | local path="dists/$SUITE/$c/binary-$ARCH/Packages"
|
| 829 | local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")"
|
| 830 | if [ ! -e "$pkgdest" ]; then continue; fi
|
| 831 | details="$($PKGDETAILS PKGS "$m" "$pkgdest" "$p")"
|
| 832 | if [ "$details" = "$p -" ]; then
|
| 833 | details=""
|
| 834 | continue
|
| 835 | fi
|
| 836 | size="${details##* }"; details="${details% *}"
|
| 837 | checksum="${details##* }"; details="${details% *}"
|
| 838 | local debdest="$($DLDEST deb $details)"
|
| 839 | if get "$m/${details##* }" "$TARGET/$debdest" "$checksum" "$size"; then
|
| 840 | echo >>$TARGET/debootstrap/debpaths "$p $debdest"
|
| 841 | details="done"
|
| 842 | break
|
| 843 | fi
|
| 844 | done
|
| 845 | if [ "$details" != "" ]; then
|
| 846 | break
|
| 847 | fi
|
| 848 | done
|
| 849 | if [ "$details" != "done" ]; then
|
| 850 | error 1 COULDNTDL "Couldn't download %s" "$p"
|
| 851 | fi
|
| 852 | done
|
| 853 | }
|
| 854 |
|
| 855 | ###################################################### deb choosing support
|
| 856 |
|
| 857 | get_debs () {
|
| 858 | local field="$1"
|
| 859 | shift
|
| 860 | local m1 c
|
| 861 | for m1 in $MIRRORS; do
|
| 862 | for c in $COMPONENTS; do
|
| 863 | local path="dists/$SUITE/$c/binary-$ARCH/Packages"
|
| 864 | local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")"
|
| 865 | echo $("$PKGDETAILS" FIELD "$field" "$m1" "$pkgdest" "$@" | sed 's/ .*//')
|
| 866 | done
|
| 867 | done
|
| 868 | }
|
| 869 |
|
| 870 | ################################################################ extraction
|
| 871 |
|
| 872 | EXTRACTORS_SUPPORTED="dpkg-deb ar"
|
| 873 | EXTRACT_DEB_TAR_OPTIONS=
|
| 874 |
|
| 875 | # Native dpkg-deb based extractors
|
| 876 | extract_dpkg_deb_field () {
|
| 877 | local pkg="$1"
|
| 878 | local field="$2"
|
| 879 |
|
| 880 | dpkg-deb -f "$pkg" "$field"
|
| 881 | }
|
| 882 |
|
| 883 | extract_dpkg_deb_data () {
|
| 884 | local pkg="$1"
|
| 885 |
|
| 886 | dpkg-deb --fsys-tarfile "$pkg" | tar $EXTRACT_DEB_TAR_OPTIONS -xf -
|
| 887 | }
|
| 888 |
|
| 889 | # Raw .deb extractors
|
| 890 | extract_ar_deb_field () {
|
| 891 | local pkg="$1"
|
| 892 | local field="$2"
|
| 893 | local tarball=$(ar -t "$pkg" | grep "^control\.tar")
|
| 894 |
|
| 895 | case "$tarball" in
|
| 896 | control.tar.gz) cat_cmd=zcat ;;
|
| 897 | control.tar.xz) cat_cmd=xzcat ;;
|
| 898 | control.tar) cat_cmd=cat ;;
|
| 899 | *) error 1 UNKNOWNCONTROLCOMP "Unknown compression type for %s in %s" "$tarball" "$pkg" ;;
|
| 900 | esac
|
| 901 |
|
| 902 | if type $cat_cmd >/dev/null 2>&1; then
|
| 903 | ar -p "$pkg" "$tarball" | $cat_cmd |
|
| 904 | tar -O -xf - control ./control 2>/dev/null |
|
| 905 | grep -i "^$field:" | sed -e 's/[^:]*: *//' | head -n 1
|
| 906 | else
|
| 907 | error 1 UNPACKCMDUNVL "Extracting %s requires the %s command, which is not available" "$pkg" "$cat_cmd"
|
| 908 | fi
|
| 909 | }
|
| 910 |
|
| 911 | extract_ar_deb_data () {
|
| 912 | local pkg="$1"
|
| 913 | local tarball=$(ar -t "$pkg" | grep "^data.tar")
|
| 914 |
|
| 915 | case "$tarball" in
|
| 916 | data.tar.gz) cat_cmd=zcat ;;
|
| 917 | data.tar.bz2) cat_cmd=bzcat ;;
|
| 918 | data.tar.xz) cat_cmd=xzcat ;;
|
| 919 | data.tar) cat_cmd=cat ;;
|
| 920 | *) error 1 UNKNOWNDATACOMP "Unknown compression type for %s in %s" "$tarball" "$pkg" ;;
|
| 921 | esac
|
| 922 |
|
| 923 | if type $cat_cmd >/dev/null 2>&1; then
|
| 924 | ar -p "$pkg" "$tarball" | $cat_cmd | tar $EXTRACT_DEB_TAR_OPTIONS -xf -
|
| 925 | else
|
| 926 | error 1 UNPACKCMDUNVL "Extracting %s requires the %s command, which is not available" "$pkg" "$cat_cmd"
|
| 927 | fi
|
| 928 | }
|
| 929 |
|
| 930 | valid_extractor () {
|
| 931 | local extractor="$1"
|
| 932 |
|
| 933 | for E in $EXTRACTORS_SUPPORTED; do
|
| 934 | if [ "$extractor" = "$E" ]; then
|
| 935 | return 0
|
| 936 | fi
|
| 937 | done
|
| 938 |
|
| 939 | return 1
|
| 940 | }
|
| 941 |
|
| 942 | choose_extractor () {
|
| 943 | local extractor
|
| 944 |
|
| 945 | if [ -n "$EXTRACTOR_OVERRIDE" ]; then
|
| 946 | extractor="$EXTRACTOR_OVERRIDE"
|
| 947 | elif type dpkg-deb >/dev/null 2>&1; then
|
| 948 | extractor="dpkg-deb"
|
| 949 | else
|
| 950 | extractor="ar"
|
| 951 | fi
|
| 952 |
|
| 953 | info CHOSENEXTRACTOR "Chosen extractor for .deb packages: %s" "$extractor"
|
| 954 | case "$extractor" in
|
| 955 | dpkg-deb)
|
| 956 | extract_deb_field () { extract_dpkg_deb_field "$@"; }
|
| 957 | extract_deb_data () { extract_dpkg_deb_data "$@"; }
|
| 958 | ;;
|
| 959 | ar)
|
| 960 | extract_deb_field () { extract_ar_deb_field "$@"; }
|
| 961 | extract_deb_data () { extract_ar_deb_data "$@"; }
|
| 962 | ;;
|
| 963 | esac
|
| 964 | }
|
| 965 |
|
| 966 | extract () { (
|
| 967 | cd "$TARGET"
|
| 968 | local p=0 cat_cmd
|
| 969 | for pkg in $(debfor "$@"); do
|
| 970 | p="$(($p + 1))"
|
| 971 | progress "$p" "$#" EXTRACTPKGS "Extracting packages"
|
| 972 | packagename="$(echo "$pkg" | sed 's,^.*/,,;s,_.*$,,')"
|
| 973 | info EXTRACTING "Extracting %s..." "$packagename"
|
| 974 | extract_deb_data "./$pkg"
|
| 975 | done
|
| 976 | ); }
|
| 977 |
|
| 978 | in_target_nofail () {
|
| 979 | if ! $CHROOT_CMD "$@" 2>/dev/null; then
|
| 980 | true
|
| 981 | fi
|
| 982 | return 0
|
| 983 | }
|
| 984 |
|
| 985 | in_target_failmsg () {
|
| 986 | local code="$1"
|
| 987 | local msg="$2"
|
| 988 | local arg="$3"
|
| 989 | shift; shift; shift
|
| 990 | if ! $CHROOT_CMD "$@"; then
|
| 991 | warning "$code" "$msg" "$arg"
|
| 992 | # Try to point user at actual failing package.
|
| 993 | msg="See %s for details"
|
| 994 | if [ -e "$TARGET/debootstrap/debootstrap.log" ]; then
|
| 995 | arg="$TARGET/debootstrap/debootstrap.log"
|
| 996 | local pkg="$(grep '^dpkg: error processing ' "$TARGET/debootstrap/debootstrap.log" | head -n 1 | sed 's/\(error processing \)\(package \|archive \)/\1/' | cut -d ' ' -f 4)"
|
| 997 | if [ -n "$pkg" ]; then
|
| 998 | msg="$msg (possibly the package $pkg is at fault)"
|
| 999 | fi
|
| 1000 | else
|
| 1001 | arg="the log"
|
| 1002 | fi
|
| 1003 | warning "$code" "$msg" "$arg"
|
| 1004 | return 1
|
| 1005 | fi
|
| 1006 | return 0
|
| 1007 | }
|
| 1008 |
|
| 1009 | in_target () {
|
| 1010 | in_target_failmsg IN_TARGET_FAIL "Failure trying to run: %s" "$CHROOT_CMD $*" "$@"
|
| 1011 | }
|
| 1012 |
|
| 1013 | ###################################################### standard setup stuff
|
| 1014 |
|
| 1015 | conditional_cp () {
|
| 1016 | if [ ! -e "$2/$1" ]; then
|
| 1017 | if [ -L "$1" ] && [ -e "$1" ]; then
|
| 1018 | cat "$1" >"$2/$1"
|
| 1019 | elif [ -e "$1" ]; then
|
| 1020 | cp -a "$1" "$2/$1"
|
| 1021 | fi
|
| 1022 | fi
|
| 1023 | }
|
| 1024 |
|
| 1025 | mv_invalid_to () {
|
| 1026 | local m="$1"
|
| 1027 | m="$(echo "${m#http://}" | tr '/' '_' | sed 's/_*//')"
|
| 1028 | (cd "$TARGET/$APTSTATE/lists"
|
| 1029 | for a in debootstrap.invalid_*; do
|
| 1030 | mv "$a" "${m}_${a#*_}"
|
| 1031 | done
|
| 1032 | )
|
| 1033 | }
|
| 1034 |
|
| 1035 | setup_apt_sources () {
|
| 1036 | mkdir -p "$TARGET/etc/apt"
|
| 1037 | for m in "$@"; do
|
| 1038 | local cs=""
|
| 1039 | for c in ${COMPONENTS:-$USE_COMPONENTS}; do
|
| 1040 | local path="dists/$SUITE/$c/binary-$ARCH/Packages"
|
| 1041 | local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m" "$path")"
|
| 1042 | if [ -e "$pkgdest" ]; then cs="$cs $c"; fi
|
| 1043 | done
|
| 1044 | if [ "$cs" != "" ]; then echo "deb $m $SUITE$cs"; fi
|
| 1045 | done > "$TARGET/etc/apt/sources.list"
|
| 1046 | }
|
| 1047 |
|
| 1048 | setup_etc () {
|
| 1049 | mkdir -p "$TARGET/etc"
|
| 1050 |
|
| 1051 | conditional_cp /etc/resolv.conf "$TARGET"
|
| 1052 | conditional_cp /etc/hostname "$TARGET"
|
| 1053 |
|
| 1054 | if [ "$DLDEST" = apt_dest ] && [ ! -e "$TARGET/etc/apt/sources.list" ]; then
|
| 1055 | setup_apt_sources "http://debootstrap.invalid/"
|
| 1056 | fi
|
| 1057 | }
|
| 1058 |
|
| 1059 | UMOUNT_DIRS=
|
| 1060 |
|
| 1061 | umount_exit_function () {
|
| 1062 | local realdir
|
| 1063 | for dir in $UMOUNT_DIRS; do
|
| 1064 | realdir="$(in_target_nofail readlink -f "$dir")"
|
| 1065 | [ "$realdir" ] || continue
|
| 1066 | ( cd / ; umount "$TARGET/${realdir#/}" ) || true
|
| 1067 | done
|
| 1068 | }
|
| 1069 |
|
| 1070 | umount_on_exit () {
|
| 1071 | if [ "$UMOUNT_DIRS" ]; then
|
| 1072 | UMOUNT_DIRS="$UMOUNT_DIRS $1"
|
| 1073 | else
|
| 1074 | UMOUNT_DIRS="$1"
|
| 1075 | on_exit umount_exit_function
|
| 1076 | fi
|
| 1077 | }
|
| 1078 |
|
| 1079 | clear_mtab () {
|
| 1080 | if [ -f "$TARGET/etc/mtab" ] && [ ! -h "$TARGET/etc/mtab" ]; then
|
| 1081 | rm -f "$TARGET/etc/mtab"
|
| 1082 | fi
|
| 1083 | }
|
| 1084 |
|
| 1085 | setup_proc () {
|
| 1086 | case "$HOST_OS" in
|
| 1087 | *freebsd*)
|
| 1088 | umount_on_exit /dev
|
| 1089 | umount_on_exit /proc
|
| 1090 | umount "$TARGET/proc" 2>/dev/null || true
|
| 1091 | if [ "$HOST_OS" = kfreebsd ]; then
|
| 1092 | in_target mount -t linprocfs proc /proc
|
| 1093 | else
|
| 1094 | mount -t linprocfs proc $TARGET/proc
|
| 1095 | fi
|
| 1096 | ;;
|
| 1097 | hurd*)
|
| 1098 | # firmlink $TARGET/{dev,servers,proc} to the system ones.
|
| 1099 | settrans -a "$TARGET/dev" /hurd/firmlink /dev
|
| 1100 | settrans -a "$TARGET/servers" /hurd/firmlink /servers
|
| 1101 | settrans -a "$TARGET/proc" /hurd/firmlink /proc
|
| 1102 | ;;
|
| 1103 | *)
|
| 1104 | umount_on_exit /dev/pts
|
| 1105 | umount_on_exit /dev/shm
|
| 1106 | umount_on_exit /proc/bus/usb
|
| 1107 | umount_on_exit /proc
|
| 1108 | umount "$TARGET/proc" 2>/dev/null || true
|
| 1109 | in_target mount -t proc proc /proc
|
| 1110 | if [ -d "$TARGET/sys" ] && \
|
| 1111 | grep -q '[[:space:]]sysfs' /proc/filesystems 2>/dev/null; then
|
| 1112 | umount_on_exit /sys
|
| 1113 | umount "$TARGET/sys" 2>/dev/null || true
|
| 1114 | in_target mount -t sysfs sysfs /sys
|
| 1115 | fi
|
| 1116 | on_exit clear_mtab
|
| 1117 | ;;
|
| 1118 | esac
|
| 1119 | umount_on_exit /lib/init/rw
|
| 1120 | }
|
| 1121 |
|
| 1122 | setup_proc_fakechroot () {
|
| 1123 | rm -rf "$TARGET/proc"
|
| 1124 | ln -s /proc "$TARGET"
|
| 1125 | }
|
| 1126 |
|
| 1127 | # create the static device nodes
|
| 1128 | setup_devices () {
|
| 1129 | if doing_variant fakechroot; then
|
| 1130 | setup_devices_fakechroot
|
| 1131 | return 0
|
| 1132 | fi
|
| 1133 |
|
| 1134 | case "$HOST_OS" in
|
| 1135 | kfreebsd*)
|
| 1136 | ;;
|
| 1137 | freebsd)
|
| 1138 | ;;
|
| 1139 | hurd*)
|
| 1140 | ;;
|
| 1141 | *)
|
| 1142 | setup_devices_simple
|
| 1143 | ;;
|
| 1144 | esac
|
| 1145 | }
|
| 1146 |
|
| 1147 | # enable the dynamic device nodes
|
| 1148 | setup_dynamic_devices () {
|
| 1149 | if doing_variant fakechroot; then
|
| 1150 | return 0
|
| 1151 | fi
|
| 1152 |
|
| 1153 | case "$HOST_OS" in
|
| 1154 | kfreebsd*)
|
| 1155 | in_target mount -t devfs devfs /dev ;;
|
| 1156 | freebsd)
|
| 1157 | mount -t devfs devfs $TARGET/dev ;;
|
| 1158 | hurd*)
|
| 1159 | # Use the setup-translators of the hurd package
|
| 1160 | in_target /usr/lib/hurd/setup-translators -k ;;
|
| 1161 | esac
|
| 1162 | }
|
| 1163 |
|
| 1164 | setup_devices_simple () {
|
| 1165 | # The list of devices that can be created in a container comes from
|
| 1166 | # src/core/cgroup.c in the systemd source tree.
|
| 1167 | mknod -m 666 $TARGET/dev/null c 1 3
|
| 1168 | mknod -m 666 $TARGET/dev/zero c 1 5
|
| 1169 | mknod -m 666 $TARGET/dev/full c 1 7
|
| 1170 | mknod -m 666 $TARGET/dev/random c 1 8
|
| 1171 | mknod -m 666 $TARGET/dev/urandom c 1 9
|
| 1172 | mknod -m 666 $TARGET/dev/tty c 5 0
|
| 1173 | mkdir $TARGET/dev/pts/ $TARGET/dev/shm/
|
| 1174 | # Inside a container, we might not be allowed to create /dev/ptmx.
|
| 1175 | # If not, do the next best thing.
|
| 1176 | if ! mknod -m 666 $TARGET/dev/ptmx c 5 2; then
|
| 1177 | warning MKNOD "Could not create /dev/ptmx, falling back to symlink. This chroot will require /dev/pts mounted with ptmxmode=666"
|
| 1178 | ln -s pts/ptmx $TARGET/dev/ptmx
|
| 1179 | fi
|
| 1180 | ln -s /proc/self/fd $TARGET/dev/fd
|
| 1181 | ln -s /proc/self/fd/0 $TARGET/dev/stdin
|
| 1182 | ln -s /proc/self/fd/1 $TARGET/dev/stdout
|
| 1183 | ln -s /proc/self/fd/2 $TARGET/dev/stderr
|
| 1184 | }
|
| 1185 |
|
| 1186 | setup_devices_fakechroot () {
|
| 1187 | rm -rf "$TARGET/dev"
|
| 1188 | ln -s /dev "$TARGET"
|
| 1189 | }
|
| 1190 |
|
| 1191 | setup_dselect_method () {
|
| 1192 | case "$1" in
|
| 1193 | apt)
|
| 1194 | mkdir -p "$TARGET/var/lib/dpkg"
|
| 1195 | echo "apt apt" > "$TARGET/var/lib/dpkg/cmethopt"
|
| 1196 | chmod 644 "$TARGET/var/lib/dpkg/cmethopt"
|
| 1197 | ;;
|
| 1198 | *)
|
| 1199 | error 1 UNKNOWNDSELECT "unknown dselect method"
|
| 1200 | ;;
|
| 1201 | esac
|
| 1202 | }
|
| 1203 |
|
| 1204 | # Find out where the runtime dynamic linker and the shared libraries
|
| 1205 | # can be installed on each architecture: native, multilib and multiarch.
|
| 1206 | # This data can be verified by checking the files in the debian/sysdeps/
|
| 1207 | # directory of the glibc package.
|
| 1208 | #
|
| 1209 | # This function must be updated to support any new architecture which
|
| 1210 | # either installs the RTLD in a directory different from /lib or builds
|
| 1211 | # multilib library packages.
|
| 1212 | setup_merged_usr() {
|
| 1213 | if [ "$MERGED_USR" = "no" ]; then return 0; fi
|
| 1214 |
|
| 1215 | local link_dir
|
| 1216 | case $ARCH in
|
| 1217 | hurd-*) return 0 ;;
|
| 1218 | amd64) link_dir="lib32 lib64 libx32" ;;
|
| 1219 | i386) link_dir="lib64 libx32" ;;
|
| 1220 | mips|mipsel)
|
| 1221 | link_dir="lib32 lib64" ;;
|
| 1222 | mips64*|mipsn32*)
|
| 1223 | link_dir="lib32 lib64 libo32" ;;
|
| 1224 | powerpc) link_dir="lib64" ;;
|
| 1225 | ppc64) link_dir="lib32 lib64" ;;
|
| 1226 | ppc64el) link_dir="lib64" ;;
|
| 1227 | s390x) link_dir="lib32" ;;
|
| 1228 | sparc) link_dir="lib64" ;;
|
| 1229 | sparc64) link_dir="lib32 lib64" ;;
|
| 1230 | x32) link_dir="lib32 lib64 libx32" ;;
|
| 1231 | esac
|
| 1232 | link_dir="bin sbin lib $link_dir"
|
| 1233 |
|
| 1234 | local dir
|
| 1235 | for dir in $link_dir; do
|
| 1236 | ln -s usr/$dir $TARGET/$dir
|
| 1237 | mkdir -p $TARGET/usr/$dir
|
| 1238 | done
|
| 1239 | }
|
| 1240 |
|
| 1241 | ################################################################ pkgdetails
|
| 1242 |
|
| 1243 | # NOTE
|
| 1244 | # For the debootstrap udeb, pkgdetails is provided by the bootstrap-base
|
| 1245 | # udeb, so the pkgdetails API needs to be kept in sync with that.
|
| 1246 |
|
| 1247 | if in_path perl; then
|
| 1248 | PKGDETAILS=pkgdetails_perl
|
| 1249 |
|
| 1250 | pkgdetails_field () {
|
| 1251 | # uniq field mirror Packages values...
|
| 1252 | perl -le '
|
| 1253 | $unique = shift @ARGV; $field = lc(shift @ARGV); $mirror = shift @ARGV;
|
| 1254 | %fields = map { $_, 0 } @ARGV;
|
| 1255 | $prevpkg = "";
|
| 1256 | while (<STDIN>) {
|
| 1257 | chomp;
|
| 1258 | next if (/^ /);
|
| 1259 | if (/^([^:]*:)\s*(.*)$/) {
|
| 1260 | $f = lc($1); $v = $2;
|
| 1261 | if ($f eq "package:") {
|
| 1262 | $last = 0;
|
| 1263 | $pkg = $v;
|
| 1264 | if ($pkg ne $prevpkg) {
|
| 1265 | print $output if defined $output;
|
| 1266 | if ($unique && defined $output_val) {
|
| 1267 | delete $fields{$output_val};
|
| 1268 | $last = 1 unless keys %fields;
|
| 1269 | }
|
| 1270 | $prevpkg = $pkg;
|
| 1271 | }
|
| 1272 | undef $output;
|
| 1273 | undef $output_val;
|
| 1274 | last if $last;
|
| 1275 | }
|
| 1276 | $ver = $v if ($f eq "version:");
|
| 1277 | $arc = $v if ($f eq "architecture:");
|
| 1278 | $fil = $v if ($f eq "filename:");
|
| 1279 | $chk = $v if (lc $f eq lc($ENV{DEBOOTSTRAP_CHECKSUM_FIELD}).":");
|
| 1280 | $siz = $v if ($f eq "size:");
|
| 1281 | $val = $v if ($f eq $field);
|
| 1282 | } elsif (/^$/) {
|
| 1283 | if (defined $val && defined $fields{$val}) {
|
| 1284 | $output = sprintf "%s %s %s %s %s %s %s",
|
| 1285 | $pkg, $ver, $arc, $mirror, $fil, $chk, $siz;
|
| 1286 | $output_val = $val;
|
| 1287 | }
|
| 1288 | undef $val;
|
| 1289 | }
|
| 1290 | }
|
| 1291 | print $output if defined $output;
|
| 1292 | delete $fields{$output_val} if $unique && defined $output_val;
|
| 1293 | for $v (keys %fields) {
|
| 1294 | printf ("%s -\n", $v) if ($unique);
|
| 1295 | }
|
| 1296 | ' "$@"
|
| 1297 | }
|
| 1298 |
|
| 1299 | pkgdetails_perl () {
|
| 1300 | if [ "$1" = "WGET%" ]; then
|
| 1301 | shift;
|
| 1302 | perl -e '
|
| 1303 | $v = 0;
|
| 1304 | $allow_percentage = 0;
|
| 1305 | while (read STDIN, $x, 1) {
|
| 1306 | if ($x =~ m/\s/) {
|
| 1307 | $allow_percentage = 1;
|
| 1308 | } elsif ($allow_percentage and $x =~ m/\d/) {
|
| 1309 | $v *= 10;
|
| 1310 | $v += $x;
|
| 1311 | } elsif ($allow_percentage and $x eq "%") {
|
| 1312 | printf "P: %d %d%s\n", int($v / 100.0 * ($ARGV[1] - $ARGV[0]) + $ARGV[0]), $ARGV[2], ($#ARGV == 3 ? " $ARGV[3]" : "");
|
| 1313 | $v = 0;
|
| 1314 | } else {
|
| 1315 | $v = 0;
|
| 1316 | $allow_percentage = 0;
|
| 1317 | }
|
| 1318 | }' "$@"
|
| 1319 | elif [ "$1" = "GETDEPS" ]; then
|
| 1320 | local pkgdest="$2"; shift; shift
|
| 1321 | perl -e '
|
| 1322 | $prevpkg = "";
|
| 1323 | @d = ();
|
| 1324 | while (<STDIN>) {
|
| 1325 | chomp;
|
| 1326 | if (/^Package: (.*)$/) {
|
| 1327 | $pkg = $1;
|
| 1328 | if ($pkg ne $prevpkg) {
|
| 1329 | for my $d (@d) {
|
| 1330 | print "$d\n";
|
| 1331 | }
|
| 1332 | }
|
| 1333 | $prevpkg = $1;
|
| 1334 | @d = ();
|
| 1335 | }
|
| 1336 | $in = 1 if (grep {$_ eq $pkg} @ARGV);
|
| 1337 | $in = 0 if (/^$/);
|
| 1338 | if ($in and (/^Depends: (.*)$/ or /^Pre-Depends: (.*)$/)) {
|
| 1339 | for $d (split /\s*,\s*/, $1) {
|
| 1340 | $d =~ s/\s*[|].*$//;
|
| 1341 | $d =~ s/\s*[(].*[)]\s*//;
|
| 1342 | $d =~ s/:.*//;
|
| 1343 | push @d, $d;
|
| 1344 | }
|
| 1345 | }
|
| 1346 | }
|
| 1347 | for my $d (@d) {
|
| 1348 | print "$d\n";
|
| 1349 | }' <"$pkgdest" "$@" | sort | uniq
|
| 1350 | elif [ "$1" = "PKGS" ]; then
|
| 1351 | local m="$2"
|
| 1352 | local p="$3"
|
| 1353 | shift; shift; shift
|
| 1354 | pkgdetails_field 1 Package: "$m" "$@" < "$p"
|
| 1355 | elif [ "$1" = "FIELD" ]; then
|
| 1356 | local f="$2"
|
| 1357 | local m="$3"
|
| 1358 | local p="$4"
|
| 1359 | shift; shift; shift; shift
|
| 1360 | pkgdetails_field 0 "$f" "$m" "$@" < "$p"
|
| 1361 | elif [ "$1" = "STANZAS" ]; then
|
| 1362 | local pkgdest="$2"; shift; shift
|
| 1363 | perl -e '
|
| 1364 | my $accum = "";
|
| 1365 | while (<STDIN>) {
|
| 1366 | $accum .= $_;
|
| 1367 | $in = 1 if (/^Package: (.*)$/ && grep {$_ eq $1} @ARGV);
|
| 1368 | if ($in and /^$/) {
|
| 1369 | print $accum;
|
| 1370 | if (substr($accum, -1) != "\n") {
|
| 1371 | print "\n\n";
|
| 1372 | } elsif (substr($accum, -2, 1) != "\n") {
|
| 1373 | print "\n";
|
| 1374 | }
|
| 1375 | $in = 0;
|
| 1376 | }
|
| 1377 | $accum = "" if /^$/;
|
| 1378 | }' <"$pkgdest" "$@"
|
| 1379 | fi
|
| 1380 | }
|
| 1381 | elif [ -e "/usr/lib/debootstrap/pkgdetails" ]; then
|
| 1382 | PKGDETAILS="/usr/lib/debootstrap/pkgdetails"
|
| 1383 | elif [ -e "$DEBOOTSTRAP_DIR/pkgdetails" ]; then
|
| 1384 | PKGDETAILS="$DEBOOTSTRAP_DIR/pkgdetails"
|
| 1385 | else
|
| 1386 | PKGDETAILS=""
|
| 1387 | fi
|
| 1388 |
|
| 1389 | ##################################################### dependency resolution
|
| 1390 |
|
| 1391 | resolve_deps () {
|
| 1392 | local m1="${MIRRORS%% *}"
|
| 1393 |
|
| 1394 | local PKGS="$*"
|
| 1395 | local ALLPKGS="$PKGS";
|
| 1396 | local ALLPKGS2="";
|
| 1397 | while [ "$PKGS" != "" ]; do
|
| 1398 | local NEWPKGS=""
|
| 1399 | for c in ${COMPONENTS:-$USE_COMPONENTS}; do
|
| 1400 | local path="dists/$SUITE/$c/binary-$ARCH/Packages"
|
| 1401 | local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")"
|
| 1402 | NEWPKGS="$NEWPKGS $("$PKGDETAILS" GETDEPS "$pkgdest" $PKGS)"
|
| 1403 | done
|
| 1404 | PKGS=$(echo "$PKGS $NEWPKGS" | tr ' ' '\n' | sort | uniq)
|
| 1405 | local REALPKGS=""
|
| 1406 | for c in ${COMPONENTS:-$USE_COMPONENTS}; do
|
| 1407 | local path="dists/$SUITE/$c/binary-$ARCH/Packages"
|
| 1408 | local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")"
|
| 1409 | REALPKGS="$REALPKGS $("$PKGDETAILS" PKGS REAL "$pkgdest" $PKGS | sed -n 's/ .*REAL.*$//p')"
|
| 1410 | done
|
| 1411 | PKGS="$REALPKGS"
|
| 1412 | ALLPKGS2=$(echo "$PKGS $ALLPKGS" | tr ' ' '\n' | sort | uniq)
|
| 1413 | PKGS=$(without "$ALLPKGS2" "$ALLPKGS")
|
| 1414 | ALLPKGS="$ALLPKGS2"
|
| 1415 | done
|
| 1416 | echo $ALLPKGS
|
| 1417 | }
|
| 1418 |
|
| 1419 | setup_available () {
|
| 1420 | local m1="${MIRRORS%% *}"
|
| 1421 |
|
| 1422 | for c in ${COMPONENTS:-$USE_COMPONENTS}; do
|
| 1423 | local path="dists/$SUITE/$c/binary-$ARCH/Packages"
|
| 1424 | local pkgdest="$TARGET/$($DLDEST pkg "$SUITE" "$c" "$ARCH" "$m1" "$path")"
|
| 1425 | # XXX: What if a package is in more than one component?
|
| 1426 | # -- cjwatson 2009-07-29
|
| 1427 | "$PKGDETAILS" STANZAS "$pkgdest" "$@"
|
| 1428 | done >"$TARGET/var/lib/dpkg/available"
|
| 1429 |
|
| 1430 | for pkg; do
|
| 1431 | echo "$pkg install"
|
| 1432 | done | in_target dpkg --set-selections
|
| 1433 | }
|
| 1434 |
|
| 1435 | get_next_predep () {
|
| 1436 | local stanza="$(in_target_nofail dpkg --predep-package)"
|
| 1437 | [ "$stanza" ] || return 1
|
| 1438 | echo "$stanza" | grep '^Package:' | sed 's/^Package://; s/^ *//'
|
| 1439 | }
|
| 1440 |
|
| 1441 | ################################################################### helpers
|
| 1442 |
|
| 1443 | # Return zero if it is possible to create devices and execute programs in
|
| 1444 | # this directory. (Both may be forbidden by mount options, e.g. nodev and
|
| 1445 | # noexec respectively.)
|
| 1446 | check_sane_mount () {
|
| 1447 | mkdir -p "$1"
|
| 1448 |
|
| 1449 | case "$HOST_OS" in
|
| 1450 | *freebsd*|hurd*)
|
| 1451 | ;;
|
| 1452 | *)
|
| 1453 | mknod "$1/test-dev-null" c 1 3 || return 1
|
| 1454 | if ! echo test > "$1/test-dev-null"; then
|
| 1455 | rm -f "$1/test-dev-null"
|
| 1456 | return 1
|
| 1457 | fi
|
| 1458 | rm -f "$1/test-dev-null"
|
| 1459 | ;;
|
| 1460 | esac
|
| 1461 |
|
| 1462 | SH=/bin/sh
|
| 1463 | [ -x $SH ] || SH=`which sh`
|
| 1464 |
|
| 1465 | cat > "$1/test-exec" <<EOF
|
| 1466 | #! $SH
|
| 1467 | :
|
| 1468 | EOF
|
| 1469 | chmod +x "$1/test-exec"
|
| 1470 | if ! "$1/test-exec"; then
|
| 1471 | rm -f "$1/test-exec"
|
| 1472 | return 1
|
| 1473 | fi
|
| 1474 | rm -f "$1/test-exec"
|
| 1475 |
|
| 1476 | return 0
|
| 1477 | }
|
| 1478 |
|
| 1479 | read_gpg_status () {
|
| 1480 | badsig=
|
| 1481 | unkkey=
|
| 1482 | validsig=
|
| 1483 | while read prefix keyword keyid rest; do
|
| 1484 | [ "$prefix" = '[GNUPG:]' ] || continue
|
| 1485 | case $keyword in
|
| 1486 | BADSIG) badsig="$keyid" ;;
|
| 1487 | NO_PUBKEY) unkkey="$keyid" ;;
|
| 1488 | VALIDSIG) validsig="$keyid" ;;
|
| 1489 | esac
|
| 1490 | done
|
| 1491 | if [ "$validsig" ]; then
|
| 1492 | info VALIDRELSIG "Valid Release signature (key id %s)" "$validsig"
|
| 1493 | elif [ "$badsig" ]; then
|
| 1494 | error 1 BADRELSIG "Invalid Release signature (key id %s)" "$badsig"
|
| 1495 | elif [ "$unkkey" ]; then
|
| 1496 | error 1 UNKNOWNRELSIG "Release signed by unknown key (key id %s)" "$unkkey"
|
| 1497 | else
|
| 1498 | error 1 SIGCHECK "Error executing gpgv to check Release signature"
|
| 1499 | fi
|
| 1500 | }
|
| 1501 |
|
| 1502 | without () {
|
| 1503 | # usage: without "a b c" "a d" -> "b" "c"
|
| 1504 | (echo $1 | tr ' ' '\n' | sort | uniq;
|
| 1505 | echo $2 $2 | tr ' ' '\n') | sort | uniq -u | tr '\n' ' '
|
| 1506 | echo
|
| 1507 | }
|
| 1508 |
|
| 1509 | # Formerly called 'repeat', but that's a reserved word in zsh.
|
| 1510 | repeatn () {
|
| 1511 | local n="$1"
|
| 1512 | shift
|
| 1513 | while [ "$n" -gt 0 ]; do
|
| 1514 | if "$@"; then
|
| 1515 | break
|
| 1516 | else
|
| 1517 | n="$(( $n - 1 ))"
|
| 1518 | sleep 1
|
| 1519 | fi
|
| 1520 | done
|
| 1521 | if [ "$n" -eq 0 ]; then return 1; fi
|
| 1522 | return 0
|
| 1523 | }
|
| 1524 |
|
| 1525 | N_EXIT_THINGS=0
|
| 1526 | exit_function () {
|
| 1527 | local n=0
|
| 1528 | while [ "$n" -lt "$N_EXIT_THINGS" ]; do
|
| 1529 | (eval $(eval echo \${EXIT_THING_$n}) 2>/dev/null || true)
|
| 1530 | n="$(( $n + 1 ))"
|
| 1531 | done
|
| 1532 | N_EXIT_THINGS=0
|
| 1533 | }
|
| 1534 |
|
| 1535 | trap "exit_function" 0
|
| 1536 | trap "exit 129" 1
|
| 1537 | trap "error 130 INTERRUPTED \"Interrupt caught ... exiting\"" 2
|
| 1538 | trap "exit 131" 3
|
| 1539 | trap "exit 143" 15
|
| 1540 |
|
| 1541 | on_exit () {
|
| 1542 | eval `echo EXIT_THING_${N_EXIT_THINGS}=\"$1\"`
|
| 1543 | N_EXIT_THINGS="$(( $N_EXIT_THINGS + 1 ))"
|
| 1544 | }
|
| 1545 |
|
| 1546 | ############################################################## fakechroot tools
|
| 1547 |
|
| 1548 | install_fakechroot_tools () {
|
| 1549 | if [ "$VARIANT" = "fakechroot" ]; then
|
| 1550 | export PATH=/usr/sbin:/sbin:$PATH
|
| 1551 | fi
|
| 1552 |
|
| 1553 | mv "$TARGET/sbin/ldconfig" "$TARGET/sbin/ldconfig.REAL"
|
| 1554 | echo \
|
| 1555 | "#!/bin/sh
|
| 1556 | echo
|
| 1557 | echo \"Warning: Fake ldconfig called, doing nothing\"" > "$TARGET/sbin/ldconfig"
|
| 1558 | chmod 755 "$TARGET/sbin/ldconfig"
|
| 1559 |
|
| 1560 | echo \
|
| 1561 | "/sbin/ldconfig
|
| 1562 | /sbin/ldconfig.REAL
|
| 1563 | fakechroot" >> "$TARGET/var/lib/dpkg/diversions"
|
| 1564 |
|
| 1565 | mv "$TARGET/usr/bin/ldd" "$TARGET/usr/bin/ldd.REAL"
|
| 1566 | cat << 'END' > "$TARGET/usr/bin/ldd"
|
| 1567 | #!/usr/bin/perl
|
| 1568 |
|
| 1569 | # fakeldd
|
| 1570 | #
|
| 1571 | # Replacement for ldd with usage of objdump
|
| 1572 | #
|
| 1573 | # (c) 2003-2005 Piotr Roszatycki <dexter@debian.org>, BSD
|
| 1574 |
|
| 1575 |
|
| 1576 | my %libs = ();
|
| 1577 |
|
| 1578 | my $status = 0;
|
| 1579 | my $dynamic = 0;
|
| 1580 | my $biarch = 0;
|
| 1581 |
|
| 1582 | my $ldlinuxsodir = "/lib";
|
| 1583 | my @ld_library_path = qw(/usr/lib /lib);
|
| 1584 |
|
| 1585 |
|
| 1586 | sub ldso($) {
|
| 1587 | my ($lib) = @_;
|
| 1588 | my @files = ();
|
| 1589 |
|
| 1590 | if ($lib =~ /^\//) {
|
| 1591 | $libs{$lib} = $lib;
|
| 1592 | push @files, $lib;
|
| 1593 | } else {
|
| 1594 | foreach my $ld_path (@ld_library_path) {
|
| 1595 | next unless -f "$ld_path/$lib";
|
| 1596 | my $badformat = 0;
|
| 1597 | open OBJDUMP, "objdump -p $ld_path/$lib 2>/dev/null |";
|
| 1598 | while (my $line = <OBJDUMP>) {
|
| 1599 | if ($line =~ /file format (\S*)$/) {
|
| 1600 | $badformat = 1 unless $format eq $1;
|
| 1601 | last;
|
| 1602 | }
|
| 1603 | }
|
| 1604 | close OBJDUMP;
|
| 1605 | next if $badformat;
|
| 1606 | $libs{$lib} = "$ld_path/$lib";
|
| 1607 | push @files, "$ld_path/$lib";
|
| 1608 | }
|
| 1609 | objdump(@files);
|
| 1610 | }
|
| 1611 | }
|
| 1612 |
|
| 1613 |
|
| 1614 | sub objdump(@) {
|
| 1615 | my (@files) = @_;
|
| 1616 | my @libs = ();
|
| 1617 |
|
| 1618 | foreach my $file (@files) {
|
| 1619 | open OBJDUMP, "objdump -p $file 2>/dev/null |";
|
| 1620 | while (my $line = <OBJDUMP>) {
|
| 1621 | $line =~ s/^\s+//;
|
| 1622 | my @f = split (/\s+/, $line);
|
| 1623 | if ($line =~ /file format (\S*)$/) {
|
| 1624 | if (not $format) {
|
| 1625 | $format = $1;
|
| 1626 | if ($unamearch eq "x86_64" and $format eq "elf32-i386") {
|
| 1627 | my $link = readlink "/lib/ld-linux.so.2";
|
| 1628 | if ($link =~ /^\/emul\/ia32-linux\//) {
|
| 1629 | $ld_library_path[-2] = "/emul/ia32-linux/usr/lib";
|
| 1630 | $ld_library_path[-1] = "/emul/ia32-linux/lib";
|
| 1631 | }
|
| 1632 | } elsif ($unamearch =~ /^(sparc|sparc64)$/ and $format eq "elf64-sparc") {
|
| 1633 | $ldlinuxsodir = "/lib64";
|
| 1634 | $ld_library_path[-2] = "/usr/lib64";
|
| 1635 | $ld_library_path[-1] = "/lib64";
|
| 1636 | }
|
| 1637 | } else {
|
| 1638 | next unless $format eq $1;
|
| 1639 | }
|
| 1640 | }
|
| 1641 | if (not $dynamic and $f[0] eq "Dynamic") {
|
| 1642 | $dynamic = 1;
|
| 1643 | }
|
| 1644 | next unless $f[0] eq "NEEDED";
|
| 1645 | if ($f[1] =~ /^ld-linux(\.|-)/) {
|
| 1646 | $f[1] = "$ldlinuxsodir/" . $f[1];
|
| 1647 | }
|
| 1648 | if (not defined $libs{$f[1]}) {
|
| 1649 | $libs{$f[1]} = undef;
|
| 1650 | push @libs, $f[1];
|
| 1651 | }
|
| 1652 | }
|
| 1653 | close OBJDUMP;
|
| 1654 | }
|
| 1655 |
|
| 1656 | foreach my $lib (@libs) {
|
| 1657 | ldso($lib);
|
| 1658 | }
|
| 1659 | }
|
| 1660 |
|
| 1661 |
|
| 1662 | if ($#ARGV < 0) {
|
| 1663 | print STDERR "fakeldd: missing file arguments\n";
|
| 1664 | exit 1;
|
| 1665 | }
|
| 1666 |
|
| 1667 | while ($ARGV[0] =~ /^-/) {
|
| 1668 | my $arg = $ARGV[0];
|
| 1669 | shift @ARGV;
|
| 1670 | last if $arg eq "--";
|
| 1671 | }
|
| 1672 |
|
| 1673 | open LD_SO_CONF, "/etc/ld.so.conf";
|
| 1674 | while ($line = <LD_SO_CONF>) {
|
| 1675 | chomp $line;
|
| 1676 | unshift @ld_library_path, $line;
|
| 1677 | }
|
| 1678 | close LD_SO_CONF;
|
| 1679 |
|
| 1680 | unshift @ld_library_path, split(/:/, $ENV{LD_LIBRARY_PATH});
|
| 1681 |
|
| 1682 | $unamearch = `/bin/uname -m`;
|
| 1683 | chomp $unamearch;
|
| 1684 |
|
| 1685 | foreach my $file (@ARGV) {
|
| 1686 | my $address;
|
| 1687 | %libs = ();
|
| 1688 | $dynamic = 0;
|
| 1689 |
|
| 1690 | if ($#ARGV > 0) {
|
| 1691 | print "$file:\n";
|
| 1692 | }
|
| 1693 |
|
| 1694 | if (not -f $file) {
|
| 1695 | print STDERR "ldd: $file: No such file or directory\n";
|
| 1696 | $status = 1;
|
| 1697 | next;
|
| 1698 | }
|
| 1699 |
|
| 1700 | objdump($file);
|
| 1701 |
|
| 1702 | if ($dynamic == 0) {
|
| 1703 | print "\tnot a dynamic executable\n";
|
| 1704 | $status = 1;
|
| 1705 | } elsif (scalar %libs eq "0") {
|
| 1706 | print "\tstatically linked\n";
|
| 1707 | }
|
| 1708 |
|
| 1709 | if ($format =~ /^elf64-/) {
|
| 1710 | $address = "0x0000000000000000";
|
| 1711 | } else {
|
| 1712 | $address = "0x00000000";
|
| 1713 | }
|
| 1714 |
|
| 1715 | foreach $lib (keys %libs) {
|
| 1716 | if ($libs{$lib}) {
|
| 1717 | printf "\t%s => %s (%s)\n", $lib, $libs{$lib}, $address;
|
| 1718 | } else {
|
| 1719 | printf "\t%s => not found\n", $lib;
|
| 1720 | }
|
| 1721 | }
|
| 1722 | }
|
| 1723 |
|
| 1724 | exit $status;
|
| 1725 | END
|
| 1726 | chmod 755 "$TARGET/usr/bin/ldd"
|
| 1727 |
|
| 1728 | echo \
|
| 1729 | "/usr/bin/ldd
|
| 1730 | /usr/bin/ldd.REAL
|
| 1731 | fakechroot" >> "$TARGET/var/lib/dpkg/diversions"
|
| 1732 |
|
| 1733 | }
|