|
@@ -0,0 +1,1921 @@
|
|
|
+############################################################### mylog
|
|
|
+MY_LOG_FILE=/var/tmp/my_debootstrap.log
|
|
|
+:> ${MY_LOG_FILE}
|
|
|
+
|
|
|
+mylog() {
|
|
|
+ echo "---> $1" >> ${MY_LOG_FILE}
|
|
|
+ :
|
|
|
+}
|
|
|
+
|
|
|
+############################################################### smallutils
|
|
|
+
|
|
|
+smallyes() {
|
|
|
+ YES="${1-y}"
|
|
|
+ while echo "$YES" 2>/dev/null ; do : ; done
|
|
|
+}
|
|
|
+
|
|
|
+in_path () {
|
|
|
+ local OLD_IFS="$IFS"
|
|
|
+ IFS=":"
|
|
|
+ for dir in $PATH; do
|
|
|
+ if [ -x "$dir/$1" ]; then
|
|
|
+ IFS="$OLD_IFS"
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ IFS="$OLD_IFS"
|
|
|
+ return 1
|
|
|
+}
|
|
|
+
|
|
|
+############################################################### interaction
|
|
|
+
|
|
|
+error () {
|
|
|
+ # <error code> <name> <string> <args>
|
|
|
+ local err name fmt
|
|
|
+ err="$1"
|
|
|
+ name="$2"
|
|
|
+ fmt="$3"
|
|
|
+ shift; shift; shift
|
|
|
+ if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then
|
|
|
+ (echo "E: $name"
|
|
|
+ for x in "$@"; do echo "EA: $x"; done
|
|
|
+ echo "EF: $fmt") >&4
|
|
|
+ else
|
|
|
+ (printf "E: $fmt\n" "$@") >&4
|
|
|
+ fi
|
|
|
+ exit "$err"
|
|
|
+}
|
|
|
+
|
|
|
+warning () {
|
|
|
+ # <name> <string> <args>
|
|
|
+ local name fmt
|
|
|
+ name="$1"
|
|
|
+ fmt="$2"
|
|
|
+ shift; shift
|
|
|
+ if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then
|
|
|
+ (echo "W: $name"
|
|
|
+ for x in "$@"; do echo "WA: $x"; done
|
|
|
+ echo "WF: $fmt") >&4
|
|
|
+ else
|
|
|
+ printf "W: $fmt\n" "$@" >&4
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+info () {
|
|
|
+ # <name> <string> <args>
|
|
|
+ local name fmt
|
|
|
+ name="$1"
|
|
|
+ fmt="$2"
|
|
|
+ shift; shift
|
|
|
+ if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then
|
|
|
+ (echo "I: $name"
|
|
|
+ for x in "$@"; do echo "IA: $x"; done
|
|
|
+ echo "IF: $fmt") >&4
|
|
|
+ else
|
|
|
+ printf "I: $fmt\n" "$@" >&4
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+PROGRESS_NOW=0
|
|
|
+PROGRESS_END=0
|
|
|
+PROGRESS_NEXT=""
|
|
|
+PROGRESS_WHAT=""
|
|
|
+
|
|
|
+progress_next () {
|
|
|
+ PROGRESS_NEXT="$1"
|
|
|
+}
|
|
|
+
|
|
|
+wgetprogress () {
|
|
|
+ [ ! "$VERBOSE" ] && NVSWITCH="-nv"
|
|
|
+ local ret=0
|
|
|
+ if [ "$USE_DEBIANINSTALLER_INTERACTION" ] && [ "$PROGRESS_NEXT" ]; then
|
|
|
+ # The exit status of a pipeline is that of the last command in
|
|
|
+ # the pipeline, so wget's exit status must be saved in the
|
|
|
+ # pipeline's first command. Since commands in a pipeline run in
|
|
|
+ # subshells, we have to print the exit status (on a file
|
|
|
+ # descriptor other than standard output, which is used by the
|
|
|
+ # pipeline itself) and then assign it to $ret outside of the
|
|
|
+ # pipeline. The "||" is necessary due to "set -e"; otherwise, a
|
|
|
+ # non-zero exit status would cause the echo command to be
|
|
|
+ # skipped. If wget succeeds, $ret will be "", so it then has to
|
|
|
+ # be set to a default value of 0.
|
|
|
+ ret=$({ { wget $@ 2>&1 >/dev/null || echo $? >&2; } | "$PKGDETAILS" "WGET%" "$PROGRESS_NOW" "$PROGRESS_NEXT" "$PROGRESS_END" >&3; } 2>&1)
|
|
|
+ : ${ret:=0}
|
|
|
+ else
|
|
|
+ wget ${NVSWITCH:+"$NVSWITCH"} "$@"
|
|
|
+ ret=$?
|
|
|
+ fi
|
|
|
+ return $ret
|
|
|
+}
|
|
|
+
|
|
|
+progress () {
|
|
|
+ # <now> <end> <name> <string> <args>
|
|
|
+ local now end name fmt
|
|
|
+ now="$1"
|
|
|
+ end="$2"
|
|
|
+ name="$3"
|
|
|
+ fmt="$4"
|
|
|
+ shift; shift; shift; shift
|
|
|
+ if [ "$USE_DEBIANINSTALLER_INTERACTION" ]; then
|
|
|
+ PROGRESS_NOW="$now"
|
|
|
+ PROGRESS_END="$end"
|
|
|
+ PROGRESS_NEXT=""
|
|
|
+ (echo "P: $now $end $name"
|
|
|
+ for x in "$@"; do echo "PA: $x"; done
|
|
|
+ echo "PF: $fmt") >&3
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+dpkg_progress () {
|
|
|
+ # <now> <end> <name> <desc> UNPACKING|CONFIGURING
|
|
|
+ local now end name desc action expect
|
|
|
+ now="$1"
|
|
|
+ end="$2"
|
|
|
+ name="$3"
|
|
|
+ desc="$4"
|
|
|
+ action="$5"
|
|
|
+ expect=""
|
|
|
+
|
|
|
+ if [ "$action" = UNPACKING ]; then
|
|
|
+ expect=half-installed
|
|
|
+ elif [ "$action" = CONFIGURING ]; then
|
|
|
+ expect=half-configured
|
|
|
+ fi
|
|
|
+
|
|
|
+ dp () {
|
|
|
+ now=$(($now + ${1:-1}))
|
|
|
+ }
|
|
|
+
|
|
|
+ exitcode=0
|
|
|
+ while read status pkg qstate; do
|
|
|
+ if [ "$status" = "EXITCODE" ]; then
|
|
|
+ exitcode="$pkg"
|
|
|
+ continue
|
|
|
+ fi
|
|
|
+ [ "$qstate" = "$expect" ] || continue
|
|
|
+ case $qstate in
|
|
|
+ half-installed)
|
|
|
+ dp; progress "$now" "$end" "$name" "$desc"
|
|
|
+ info "$action" "Unpacking %s..." "${pkg%:}"
|
|
|
+ expect="unpacked"
|
|
|
+ ;;
|
|
|
+ unpacked)
|
|
|
+ expect="half-installed"
|
|
|
+ ;;
|
|
|
+ half-configured)
|
|
|
+ dp; progress "$now" "$end" "$name" "$desc"
|
|
|
+ info "$action" "Configuring %s..." "${pkg%:}"
|
|
|
+ expect="installed"
|
|
|
+ ;;
|
|
|
+ installed)
|
|
|
+ expect="half-configured"
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+ done
|
|
|
+ return "$exitcode"
|
|
|
+}
|
|
|
+
|
|
|
+############################################################# set variables
|
|
|
+
|
|
|
+default_mirror () {
|
|
|
+ DEF_MIRROR="$1"
|
|
|
+}
|
|
|
+
|
|
|
+FINDDEBS_NEEDS_INDICES="false"
|
|
|
+finddebs_style () {
|
|
|
+ case "$1" in
|
|
|
+ hardcoded)
|
|
|
+ ;;
|
|
|
+ from-indices)
|
|
|
+ FINDDEBS_NEEDS_INDICES="true"
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ error 1 BADFINDDEBS "unknown finddebs style"
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+mk_download_dirs () {
|
|
|
+ if [ "$DLDEST" = "apt_dest" ]; then
|
|
|
+ mkdir -p "$TARGET/$APTSTATE/lists/partial"
|
|
|
+ mkdir -p "$TARGET/var/cache/apt/archives/partial"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+download_style () {
|
|
|
+ case "$1" in
|
|
|
+ apt)
|
|
|
+ if [ "$2" = "var-state" ]; then
|
|
|
+ APTSTATE="var/state/apt"
|
|
|
+ else
|
|
|
+ APTSTATE="var/lib/apt"
|
|
|
+ fi
|
|
|
+ DLDEST="apt_dest"
|
|
|
+ export APTSTATE DLDEST DEBFOR
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ error 1 BADDLOAD "unknown download style"
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+keyring () {
|
|
|
+ # avoid unnecessary warning with --second-stage
|
|
|
+ if [ -z "$KEYRING" ] && [ "$SECOND_STAGE_ONLY" != true ]; then
|
|
|
+ if [ -e "$1" ]; then
|
|
|
+ KEYRING="$1"
|
|
|
+ elif [ -z "$DISABLE_KEYRING" ]; then
|
|
|
+ if [ -n "$DEF_HTTPS_MIRROR" ] && [ -z "$USER_MIRROR" ] && [ -z "$FORCE_KEYRING" ]; then
|
|
|
+ info KEYRING "Keyring file not available at %s; switching to https mirror %s" "$1" "$DEF_HTTPS_MIRROR"
|
|
|
+ USER_MIRROR="$DEF_HTTPS_MIRROR"
|
|
|
+ else
|
|
|
+ warning KEYRING "Cannot check Release signature; keyring file not available %s" "$1"
|
|
|
+ if [ -n "$FORCE_KEYRING" ]; then
|
|
|
+ error 1 KEYRING "Keyring-based check was requested; aborting accordingly"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+detect_container () {
|
|
|
+ if [ "$container" = lxc ]; then
|
|
|
+ CONTAINER="lxc"
|
|
|
+ elif grep -qs container=lxc-libvirt /proc/1/environ; then
|
|
|
+ CONTAINER="lxc-libvirt"
|
|
|
+ elif grep -qs ^systemd-nspawn$ /run/systemd/container || [ "$container" = "systemd-nspawn" ]; then
|
|
|
+ CONTAINER="systemd-nspawn"
|
|
|
+ elif grep -qs '[[:space:]]/docker/.*/sys/fs/cgroup' /proc/1/mountinfo; then
|
|
|
+ CONTAINER="docker"
|
|
|
+ else
|
|
|
+ CONTAINER=""
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+########################################################## variant handling
|
|
|
+
|
|
|
+doing_variant () {
|
|
|
+ if [ "$1" = "$VARIANT" ]; then return 0; fi
|
|
|
+ if [ "$1" = "-" ] && [ "$VARIANT" = "" ]; then return 0; fi
|
|
|
+ return 1
|
|
|
+}
|
|
|
+
|
|
|
+SUPPORTED_VARIANTS="-"
|
|
|
+variants () {
|
|
|
+ SUPPORTED_VARIANTS="$*"
|
|
|
+ for v in $*; do
|
|
|
+ if doing_variant "$v"; then return 0; fi
|
|
|
+ done
|
|
|
+ error 1 UNSUPPVARIANT "unsupported variant"
|
|
|
+}
|
|
|
+
|
|
|
+########################################################### option handling
|
|
|
+check_conflicting_option () {
|
|
|
+ if [ "$set_what_to_do" = --foreign ] && [ "${1%%=*}" = --unpack-tarball ] || \
|
|
|
+ [ "${set_what_to_do%%=*}" = "--unpack-tarball" ] && [ "$1" == --foreign ]; then
|
|
|
+ LOOSEN_CONFLICTING_RESTRICTION="true"
|
|
|
+ elif [ -n "$set_what_to_do" ]; then
|
|
|
+ error 1 ARG_CONFLICTING "$set_what_to_do is specified with $1, please use only one of those options."
|
|
|
+ fi
|
|
|
+ set_what_to_do="$1"
|
|
|
+}
|
|
|
+
|
|
|
+################################################# work out names for things
|
|
|
+
|
|
|
+mirror_style () {
|
|
|
+ case "$1" in
|
|
|
+ release)
|
|
|
+ DOWNLOAD_INDICES="download_release_indices"
|
|
|
+ DOWNLOAD_DEBS="download_release"
|
|
|
+ ;;
|
|
|
+ main)
|
|
|
+ DOWNLOAD_INDICES="download_main_indices"
|
|
|
+ DOWNLOAD_DEBS="download_main"
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ error 1 BADMIRROR "unknown mirror style"
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+ export DOWNLOAD_INDICES
|
|
|
+ export DOWNLOAD_DEBS
|
|
|
+}
|
|
|
+
|
|
|
+force_md5 () {
|
|
|
+ DEBOOTSTRAP_CHECKSUM_FIELD=MD5SUM
|
|
|
+ export DEBOOTSTRAP_CHECKSUM_FIELD
|
|
|
+}
|
|
|
+
|
|
|
+verify_checksum () {
|
|
|
+ # args: dest checksum size
|
|
|
+ local expchecksum="$2"
|
|
|
+ local expsize="$3"
|
|
|
+ if [ "$DEBOOTSTRAP_CHECKSUM_FIELD" = "MD5SUM" ]; then
|
|
|
+ if in_path md5sum; then
|
|
|
+ relchecksum=$(md5sum < "$1" | sed 's/ .*$//')
|
|
|
+ elif in_path md5; then
|
|
|
+ relchecksum=$(md5 < "$1")
|
|
|
+ else
|
|
|
+ error 1 SIGCHECK "Cannot check md5sum"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ if in_path "sha${SHA_SIZE}sum"; then
|
|
|
+ relchecksum="$(sha${SHA_SIZE}sum < "$1" | sed 's/ .*$//')"
|
|
|
+ elif in_path "sha${SHA_SIZE}"; then
|
|
|
+ relchecksum="$(sha${SHA_SIZE} < "$1")"
|
|
|
+ else
|
|
|
+ error 1 SIGCHECK "Cannot check sha${SHA_SIZE}sum"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ relsize="$(wc -c < "$1")"
|
|
|
+ if [ "$expsize" -ne "$relsize" ] || [ "$expchecksum" != "$relchecksum" ]; then
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+get () {
|
|
|
+ # args: from dest 'nocache'
|
|
|
+ # args: from dest [checksum size] [alt {checksum size type}]
|
|
|
+ # args: from dest 'byhash' [checksum size] [alt {checksum size type}]
|
|
|
+ local displayname
|
|
|
+ local versionname
|
|
|
+ local from_base
|
|
|
+ local dest_base
|
|
|
+ local nocache=""
|
|
|
+ local byhash=""
|
|
|
+ from_base="$1"; shift
|
|
|
+ dest_base="$1"; shift
|
|
|
+ if [ "$1" = "nocache" ]; then
|
|
|
+ nocache="true"; shift
|
|
|
+ elif [ "$1" = "byhash" ]; then
|
|
|
+ byhash="true"; shift
|
|
|
+ fi
|
|
|
+ if [ "${dest_base%.deb}" != "$dest_base" ]; then
|
|
|
+ displayname="$(echo "$dest_base" | sed 's,^.*/,,;s,_.*$,,')"
|
|
|
+ versionname="$(echo "$dest_base" | sed 's,^.*/,,' | cut -d_ -f2 | sed 's/%3a/:/')"
|
|
|
+ else
|
|
|
+ displayname="$(echo "$from_base" | sed 's,^.*/,,')"
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [ -e "$dest_base" ]; then
|
|
|
+ if [ -z "$1" ]; then
|
|
|
+ return 0
|
|
|
+ elif [ -n "$nocache" ]; then
|
|
|
+ rm -f "$dest_base"
|
|
|
+ else
|
|
|
+ info VALIDATING "Validating %s %s" "$displayname" "$versionname"
|
|
|
+ # mylog "1 $dest_base $displayname $versionname"
|
|
|
+ if verify_checksum "$dest_base" "$1" "$2"; then
|
|
|
+ return 0
|
|
|
+ else
|
|
|
+ rm -f "$dest_base"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [ "$#" -gt 3 ]; then
|
|
|
+ local st=1
|
|
|
+ if [ "$3" = "-" ]; then st=4; fi
|
|
|
+ local order="$(a=$st; while [ "$a" -le $# ]; do eval echo \"\${$(($a+1))}\" $a;
|
|
|
+ a=$(($a + 3)); done | sort -n | sed 's/.* //')"
|
|
|
+ else
|
|
|
+ local order=1
|
|
|
+ fi
|
|
|
+ for a in $order; do
|
|
|
+ local checksum siz typ from dest iters
|
|
|
+ checksum="$(eval echo \${$a})"
|
|
|
+ siz="$(eval echo \${$(( $a+1 ))})"
|
|
|
+ typ="$(eval echo \${$(( $a+2 ))})"
|
|
|
+ iters="0"
|
|
|
+
|
|
|
+ case "$typ" in
|
|
|
+ xz) from="$from_base.xz"; dest="$dest_base.xz" ;;
|
|
|
+ bz2) from="$from_base.bz2"; dest="$dest_base.bz2" ;;
|
|
|
+ gz) from="$from_base.gz"; dest="$dest_base.gz" ;;
|
|
|
+ *) from="$from_base"; dest="$dest_base" ;;
|
|
|
+ esac
|
|
|
+
|
|
|
+ if [ ! -z "$CACHE_DIR" ]; then
|
|
|
+ dest="${dest%%*/}"
|
|
|
+ elif [ "${dest#/}" = "$dest" ]; then
|
|
|
+ dest="./$dest"
|
|
|
+ fi
|
|
|
+ local dest2="$dest"
|
|
|
+ if [ -d "${dest2%/*}/partial" ]; then
|
|
|
+ dest2="${dest2%/*}/partial/${dest2##*/}"
|
|
|
+ fi
|
|
|
+
|
|
|
+ while [ "$iters" -lt 10 ]; do
|
|
|
+ local from2=""
|
|
|
+ info RETRIEVING "Retrieving %s %s" "$displayname" "$versionname"
|
|
|
+ if [ "$checksum" != "" ] && [ "$byhash" != "" ]; then
|
|
|
+ # assume we don't mix acquire-by-hash and md5
|
|
|
+ from2="$(dirname "$from")/by-hash/SHA${SHA_SIZE}/$checksum"
|
|
|
+ fi
|
|
|
+ if [ ! -e "$dest2" ]; then
|
|
|
+ if [ -z "$from2" ] || ! just_get "$from2" "$dest2"; then
|
|
|
+ if ! just_get "$from" "$dest2"; then continue 2; fi
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ if [ "$checksum" != "" ]; then
|
|
|
+ info VALIDATING "Validating %s %s" "$displayname" "$versionname"
|
|
|
+ # mylog "2 $dest_base $displayname $versionname"
|
|
|
+ if verify_checksum "$dest2" "$checksum" "$siz"; then
|
|
|
+ checksum=""
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ if [ -z "$checksum" ]; then
|
|
|
+ [ "$dest2" = "$dest" ] || mv "$dest2" "$dest"
|
|
|
+ case "$typ" in
|
|
|
+ gz) gunzip "$dest" ;;
|
|
|
+ bz2) bunzip2 "$dest" ;;
|
|
|
+ xz) unxz "$dest" ;;
|
|
|
+ esac
|
|
|
+ return 0
|
|
|
+ else
|
|
|
+ rm -f "$dest2"
|
|
|
+ warning RETRYING "Retrying failed download of %s" "$from"
|
|
|
+ iters=$(($iters + 1))
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ warning CORRUPTFILE "%s was corrupt" "$from"
|
|
|
+ done
|
|
|
+ return 1
|
|
|
+}
|
|
|
+
|
|
|
+just_get () {
|
|
|
+ # args: from dest
|
|
|
+ local from="$1"
|
|
|
+ local dest="$2"
|
|
|
+ mkdir -p "${dest%/*}"
|
|
|
+ if [ "${from#null:}" != "$from" ]; then
|
|
|
+ error 1 NOTPREDL "%s was not pre-downloaded" "${from#null:}"
|
|
|
+ elif [ "${from#http://}" != "$from" ] || [ "${from#https://}" != "$from" ] || [ "${from#ftp://}" != "$from" ]; then
|
|
|
+ # http/https/ftp mirror
|
|
|
+ if wgetprogress ${CHECKCERTIF:+"$CHECKCERTIF"} ${CERTIFICATE:+"$CERTIFICATE"} ${PRIVATEKEY:+"$PRIVATEKEY"} -O "$dest" "$from"; then
|
|
|
+ return 0
|
|
|
+ else
|
|
|
+ rm -f "$dest"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ elif [ "${from#file:}" != "$from" ]; then
|
|
|
+ local base="${from#file:}"
|
|
|
+ if [ "${base#//}" != "$base" ]; then
|
|
|
+ base="/${from#file://*/}"
|
|
|
+ fi
|
|
|
+ if [ -e "$base" ]; then
|
|
|
+ cp "$base" "$dest"
|
|
|
+ return 0
|
|
|
+ else
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ elif [ "${from#ssh:}" != "$from" ]; then
|
|
|
+ local ssh_dest="$(echo "$from" | sed -e 's#ssh://##' -e 's#/#:/#')"
|
|
|
+ if [ -n "$ssh_dest" ]; then
|
|
|
+ scp "$ssh_dest" "$dest"
|
|
|
+ return 0
|
|
|
+ else
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ error 1 UNKNOWNLOC "unknown location %s" "$from"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+download () {
|
|
|
+ mk_download_dirs
|
|
|
+ "$DOWNLOAD_DEBS" "$(echo "$@" | tr ' ' '\n' | sort)"
|
|
|
+}
|
|
|
+
|
|
|
+download_indices () {
|
|
|
+ mk_download_dirs
|
|
|
+ "$DOWNLOAD_INDICES" "$(echo "$@" | tr ' ' '\n' | sort)"
|
|
|
+}
|
|
|
+
|
|
|
+debfor () {
|
|
|
+ (while read pkg path; do
|
|
|
+ for p in "$@"; do
|
|
|
+ [ "$p" = "$pkg" ] || continue;
|
|
|
+ echo "$path"
|
|
|
+ # mylog "====== $path"
|
|
|
+ # mylog "====== $pkg"
|
|
|
+ done
|
|
|
+ done <"$TARGET/debootstrap/debpaths"
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+apt_dest () {
|
|
|
+ # args:
|
|
|
+ # deb package version arch mirror path
|
|
|
+ # pkg suite component arch mirror path
|
|
|
+ # rel suite mirror path
|
|
|
+ case "$1" in
|
|
|
+ deb)
|
|
|
+ echo "/var/cache/apt/archives/${2}_${3}_${4}.deb" | sed 's/:/%3a/'
|
|
|
+ ;;
|
|
|
+ pkg)
|
|
|
+ local m="$5"
|
|
|
+ printf "%s" "$APTSTATE/lists/"
|
|
|
+ echo "${m}_$6" | sed -e 's,^[^:]\+://,,' -e 's/\//_/g'
|
|
|
+ ;;
|
|
|
+ rel)
|
|
|
+ local m="$3"
|
|
|
+ printf "%s" "$APTSTATE/lists/"
|
|
|
+ echo "${m}_$4" | sed -e 's,^[^:]\+://,,' -e 's/\//_/g'
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+################################################################## download
|
|
|
+
|
|
|
+get_release_checksum () {
|
|
|
+ local reldest path
|
|
|
+ reldest="$1"
|
|
|
+ path="$2"
|
|
|
+
|
|
|
+ if [ "$DEBOOTSTRAP_CHECKSUM_FIELD" = MD5SUM ]; then
|
|
|
+ local match="^[Mm][Dd]5[Ss][Uu][Mm]"
|
|
|
+ else
|
|
|
+ local match="^[Ss][Hh][Aa]$SHA_SIZE:"
|
|
|
+ fi
|
|
|
+ # sed -n "/$match/,/^[^ ]/p" < "$reldest" | \
|
|
|
+ # while read a b c; do
|
|
|
+ # if [ "$c" = "$path" ]; then echo "$a $b"; fi
|
|
|
+ # done | head -n 1
|
|
|
+
|
|
|
+ ret=$(sed -n "/$match/,/^[^ ]/p" < "$reldest" | grep "${path}$" | awk '{print $1,$2}')
|
|
|
+ if [ "x" != "$ret"x ]; then
|
|
|
+ echo "${ret}"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+extract_release_components () {
|
|
|
+ local reldest="$1"; shift
|
|
|
+ TMPCOMPONENTS="$(sed -n 's/Components: *//p' "$reldest")"
|
|
|
+ for c in $TMPCOMPONENTS ; do
|
|
|
+ eval "
|
|
|
+ case \"\$c\" in
|
|
|
+ $USE_COMPONENTS)
|
|
|
+ COMPONENTS=\"\$COMPONENTS \$c\"
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+ "
|
|
|
+ done
|
|
|
+
|
|
|
+ if [ -z "$COMPONENTS" ]; then
|
|
|
+ mv "$reldest" "$reldest.malformed"
|
|
|
+ error 1 INVALIDREL "Invalid Release file, no valid components"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+CODENAME=""
|
|
|
+validate_suite () {
|
|
|
+ local reldest suite
|
|
|
+ reldest="$1"
|
|
|
+
|
|
|
+ CODENAME=$(sed -n "s/^Codename: *//p" "$reldest")
|
|
|
+ suite=$(sed -n "s/^Suite: *//p" "$reldest")
|
|
|
+
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ if [ "$s" = "$suite" ] || [ "$s" = "$CODENAME" ]; then
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ if [ "$EXTRA_SUITES" = "" ]; then
|
|
|
+ error 1 WRONGSUITE "Asked to install suite %s, but got %s (codename: %s) from mirror" "$SUITE" "$suite" "$CODENAME"
|
|
|
+ else
|
|
|
+ error 1 WRONGSUITE "Asked to install suites %s %s, but got %s (codename: %s) from mirror" "$SUITE" "$EXTRA_SUITES" "$suite" "$CODENAME"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+split_inline_sig () {
|
|
|
+ local inreldest reldest relsigdest
|
|
|
+ inreldest="$1"
|
|
|
+ reldest="$2"
|
|
|
+ relsigdest="$3"
|
|
|
+
|
|
|
+ # Note: InRelease files are fun since one needs to remove the
|
|
|
+ # last newline from the PGP SIGNED MESSAGE part, while keeping
|
|
|
+ # the PGP SIGNATURE part intact. This shell implementation
|
|
|
+ # should work on most if not all systems, instead of trying to
|
|
|
+ # sed/tr/head, etc.
|
|
|
+ rm -f "$reldest" "$relsigdest"
|
|
|
+
|
|
|
+ sed -n "/-----BEGIN PGP SIGNED MESSAGE-----/,/-----BEGIN PGP SIGNATURE-----/p" $inreldest | sed '$d' | sed -n "/^Origin:/,//p" > $reldest
|
|
|
+ sed -n "/-----BEGIN PGP SIGNATURE-----/,/-----END PGP SIGNATURE-----/p" $inreldest > $relsigdest
|
|
|
+
|
|
|
+ mylog "split_inline_sig $reldest"
|
|
|
+ # mylog "split_inline_sig $inreldest -> $relsigdest"
|
|
|
+
|
|
|
+ # nl=""
|
|
|
+ # state="pre-begin"
|
|
|
+ # while IFS= read -r line; do
|
|
|
+ # mylog "split_inline_sig ${line}"
|
|
|
+ # case "${state}" in
|
|
|
+ # pre-begin)
|
|
|
+ # if [ "x${line}" = "x-----BEGIN PGP SIGNED MESSAGE-----" ]; then
|
|
|
+ # state="begin"
|
|
|
+ # fi
|
|
|
+ # ;;
|
|
|
+ # begin)
|
|
|
+ # if [ "x${line}" = "x" ]; then
|
|
|
+ # state="data"
|
|
|
+ # fi
|
|
|
+ # ;;
|
|
|
+ # data)
|
|
|
+ # if [ "x${line}" = "x-----BEGIN PGP SIGNATURE-----" ]; then
|
|
|
+ # printf "%s\n" "${line}" > "$relsigdest"
|
|
|
+ # state="signature"
|
|
|
+ # else
|
|
|
+ # printf "${nl}%s" "${line}" >> "$reldest"
|
|
|
+ # nl="\n"
|
|
|
+ # fi
|
|
|
+ # ;;
|
|
|
+ # signature)
|
|
|
+ # printf "%s\n" "${line}" >> "$relsigdest"
|
|
|
+ # if [ "x${line}" = "x-----END PGP SIGNATURE-----" ]; then
|
|
|
+ # break
|
|
|
+ # fi
|
|
|
+ # esac
|
|
|
+ # done < "$inreldest"
|
|
|
+}
|
|
|
+
|
|
|
+download_release_sig () {
|
|
|
+ local m1 suite inreldest reldest relsigdest
|
|
|
+ m1="$1"
|
|
|
+ suite="$2"
|
|
|
+ inreldest="$3"
|
|
|
+ reldest="$4"
|
|
|
+ relsigdest="$5"
|
|
|
+
|
|
|
+ progress 0 100 DOWNREL "Downloading Release file"
|
|
|
+ progress_next 100
|
|
|
+ if get "$m1/dists/$suite/InRelease" "$inreldest" nocache; then
|
|
|
+ split_inline_sig "$inreldest" "$reldest" "$relsigdest"
|
|
|
+ progress 100 100 DOWNREL "Downloading Release file"
|
|
|
+ else
|
|
|
+ get "$m1/dists/$suite/Release" "$reldest" nocache ||
|
|
|
+ error 1 NOGETREL "Failed getting release file %s" "$m1/dists/$suite/Release"
|
|
|
+ progress 100 100 DOWNREL "Downloading Release file"
|
|
|
+ fi
|
|
|
+ if [ -n "$KEYRING" ] && [ -z "$DISABLE_KEYRING" ]; then
|
|
|
+ progress 0 100 DOWNRELSIG "Downloading Release file signature"
|
|
|
+ if ! [ -f "$relsigdest" ]; then
|
|
|
+ progress_next 50
|
|
|
+ get "$m1/dists/$suite/Release.gpg" "$relsigdest" nocache ||
|
|
|
+ error 1 NOGETRELSIG "Failed getting release signature file %s" \
|
|
|
+ "$m1/dists/$suite/Release.gpg"
|
|
|
+ progress 50 100 DOWNRELSIG "Downloading Release file signature"
|
|
|
+ fi
|
|
|
+
|
|
|
+ info RELEASESIG "Checking Release signature"
|
|
|
+ # Don't worry about the exit status from gpgv; parsing the output will
|
|
|
+ # take care of that.
|
|
|
+ (gpgv --status-fd 1 --keyring "$KEYRING" --ignore-time-conflict \
|
|
|
+ "$relsigdest" "$reldest" || true) | read_gpg_status
|
|
|
+ progress 100 100 DOWNRELSIG "Downloading Release file signature"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+download_release_indices () {
|
|
|
+ local m1 inreldest reldest relsigdest totalpkgs \
|
|
|
+ subpath xzi bz2i gzi normi i ext \
|
|
|
+ donepkgs pkgdest acquirebyhash
|
|
|
+ m1="${MIRRORS%% *}"
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ inreldest="$TARGET/$($DLDEST rel "$s" "$m1" "dists/$s/InRelease")"
|
|
|
+ reldest="$TARGET/$($DLDEST rel "$s" "$m1" "dists/$s/Release")"
|
|
|
+ relsigdest="$TARGET/$($DLDEST rel "$s" "$m1" "dists/$s/Release.gpg")"
|
|
|
+
|
|
|
+ download_release_sig "$m1" "$s" "$inreldest" "$reldest" "$relsigdest"
|
|
|
+
|
|
|
+ validate_suite "$reldest"
|
|
|
+
|
|
|
+ extract_release_components "$reldest"
|
|
|
+
|
|
|
+ acquirebyhash=$(grep "^Acquire-By-Hash: yes$" "$reldest" || true)
|
|
|
+ totalpkgs=0
|
|
|
+ for c in $COMPONENTS; do
|
|
|
+ subpath="$c/binary-$ARCH/Packages"
|
|
|
+ xzi="$(get_release_checksum "$reldest" "$subpath.xz")"
|
|
|
+ bz2i="$(get_release_checksum "$reldest" "$subpath.bz2")"
|
|
|
+ gzi="$(get_release_checksum "$reldest" "$subpath.gz")"
|
|
|
+ normi="$(get_release_checksum "$reldest" "$subpath")"
|
|
|
+
|
|
|
+ mylog "1 subpath=${subpath}"
|
|
|
+
|
|
|
+ if [ "$normi" != "" ]; then
|
|
|
+ i="$normi"
|
|
|
+ elif in_path bunzip2 && [ "$bz2i" != "" ]; then
|
|
|
+ i="$bz2i"
|
|
|
+ elif in_path unxz && [ "$xzi" != "" ]; then
|
|
|
+ i="$xzi"
|
|
|
+ elif in_path gunzip && [ "$gzi" != "" ]; then
|
|
|
+ i="$gzi"
|
|
|
+ fi
|
|
|
+ if [ "$i" != "" ]; then
|
|
|
+ totalpkgs=$(( $totalpkgs + ${i#* } ))
|
|
|
+ else
|
|
|
+ mv "$reldest" "$reldest.malformed"
|
|
|
+ error 1 MISSINGRELENTRY "Invalid Release file, no entry for %s" "$subpath"
|
|
|
+ fi
|
|
|
+ # mylog "download_release_indices xzi=${xzi} bz2i=${bz2i} gzi=${gzi} normi=${normi}, totalpkgs=${totalpkgs}"
|
|
|
+ done
|
|
|
+
|
|
|
+ donepkgs=0
|
|
|
+ progress 0 $totalpkgs DOWNPKGS "Downloading Packages files"
|
|
|
+ for c in $COMPONENTS; do
|
|
|
+ subpath="$c/binary-$ARCH/Packages"
|
|
|
+ path="dists/$s/$subpath"
|
|
|
+ xzi="$(get_release_checksum "$reldest" "$subpath.xz")"
|
|
|
+ bz2i="$(get_release_checksum "$reldest" "$subpath.bz2")"
|
|
|
+ gzi="$(get_release_checksum "$reldest" "$subpath.gz")"
|
|
|
+ normi="$(get_release_checksum "$reldest" "$subpath")"
|
|
|
+ ext=""
|
|
|
+ if [ "$acquirebyhash" != "" ]; then
|
|
|
+ ext="$ext byhash"
|
|
|
+ fi
|
|
|
+ if [ "$normi" != "" ]; then
|
|
|
+ ext="$ext $normi ."
|
|
|
+ i="$normi"
|
|
|
+ fi
|
|
|
+ if in_path unxz && [ "$xzi" != "" ]; then
|
|
|
+ ext="$ext $xzi xz"
|
|
|
+ i="${i:-$xzi}"
|
|
|
+ fi
|
|
|
+ if in_path bunzip2 && [ "$bz2i" != "" ]; then
|
|
|
+ ext="$ext $bz2i bz2"
|
|
|
+ i="${i:-$bz2i}"
|
|
|
+ fi
|
|
|
+ if in_path gunzip && [ "$gzi" != "" ]; then
|
|
|
+ ext="$ext $gzi gz"
|
|
|
+ i="${i:-$gzi}"
|
|
|
+ fi
|
|
|
+ progress_next $(($donepkgs + ${i#* }))
|
|
|
+ for m in $MIRRORS; do
|
|
|
+ pkgdest="$TARGET/$($DLDEST pkg "$s" "$c" "$ARCH" "$m" "$path")"
|
|
|
+ if get "$m/$path" "$pkgdest" $ext; then break; fi
|
|
|
+ done
|
|
|
+ if [ ! -f "$pkgdest" ]; then
|
|
|
+ warning 1 COULDNTDL "Couldn't download %s" "$m/$path"
|
|
|
+ fi
|
|
|
+ donepkgs=$(($donepkgs + ${i#* }))
|
|
|
+ progress $donepkgs $totalpkgs DOWNPKGS "Downloading Packages files"
|
|
|
+ done
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+get_package_sizes () {
|
|
|
+ # mirror pkgdest debs..
|
|
|
+ local m pkgdest
|
|
|
+ m="$1"; shift
|
|
|
+ pkgdest="$1"; shift
|
|
|
+ $PKGDETAILS PKGS "$m" "$pkgdest" "$@" | (
|
|
|
+ newleft=""
|
|
|
+ totaldebs=0
|
|
|
+ countdebs=0
|
|
|
+ while read p details; do
|
|
|
+ if [ "$details" = "-" ]; then
|
|
|
+ newleft="$newleft $p"
|
|
|
+ else
|
|
|
+ size="${details##* }";
|
|
|
+ totaldebs=$(($totaldebs + $size))
|
|
|
+ countdebs=$(($countdebs + 1))
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ echo "$countdebs $totaldebs$newleft"
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+# note, leftovers come back on fd5 !!
|
|
|
+download_debs () {
|
|
|
+ local m pkgdest debdest debcache
|
|
|
+ m="$1"
|
|
|
+ pkgdest="$2"
|
|
|
+ shift; shift
|
|
|
+
|
|
|
+ "$PKGDETAILS" PKGS "$m" "$pkgdest" "$@" | (
|
|
|
+ leftover=""
|
|
|
+ while read p ver arc mdup fil checksum size; do
|
|
|
+ if [ "$ver" = "-" ]; then
|
|
|
+ leftover="$leftover $p"
|
|
|
+ else
|
|
|
+ progress_next $(($dloaddebs + $size))
|
|
|
+ debdest="$($DLDEST deb "$p" "$ver" "$arc" "$m" "$fil")"
|
|
|
+ debcache="$(echo "$p"_"$ver"_"$arc".deb | sed 's/:/%3a/')"
|
|
|
+ if [ -z "$CACHE_DIR" ] && get "$m/$fil" "$TARGET/$debdest" "$checksum" "$size"; then
|
|
|
+ dloaddebs=$(($dloaddebs + $size))
|
|
|
+ echo >>"$TARGET/debootstrap/deburis" "$p $ver $m/$fil"
|
|
|
+ echo >>"$TARGET/debootstrap/debpaths" "$p $debdest"
|
|
|
+ elif [ -d "$CACHE_DIR" ] && get "$m/$fil" "$CACHE_DIR/$debcache" "$checksum" "$size"; then
|
|
|
+ dloaddebs=$(($dloaddebs + $size))
|
|
|
+ echo >>"$TARGET/debootstrap/deburis" "$p $ver $m/$fil"
|
|
|
+ echo >>"$TARGET/debootstrap/debpaths" "$p $debdest"
|
|
|
+ cp "$CACHE_DIR/$debcache" "$TARGET/$debdest"
|
|
|
+ else
|
|
|
+ warning COULDNTDL "Couldn't download package %s (ver %s arch %s) at %s" "$p" "$ver" "$arc" "$m/$fil"
|
|
|
+ leftover="$leftover $p"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ echo >&5 ${leftover# }
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+download_release () {
|
|
|
+ local m1 numdebs countdebs totaldebs leftoverdebs path pkgdest dloaddebs
|
|
|
+ m1="${MIRRORS%% *}"
|
|
|
+
|
|
|
+ numdebs="$#"
|
|
|
+
|
|
|
+ countdebs=0
|
|
|
+ progress "$countdebs" "$numdebs" SIZEDEBS "Finding package sizes"
|
|
|
+
|
|
|
+ totaldebs=0
|
|
|
+ leftoverdebs="$*"
|
|
|
+
|
|
|
+ # Fix possible duplicate package names, which would screw up counts:
|
|
|
+ leftoverdebs=$(printf "$leftoverdebs"|tr ' ' '\n'|sort -u|tr '\n' ' ')
|
|
|
+ numdebs=$(printf "$leftoverdebs"|wc -w)
|
|
|
+
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ for c in $COMPONENTS; do
|
|
|
+ if [ "$countdebs" -ge "$numdebs" ]; then break; fi
|
|
|
+
|
|
|
+ path="dists/$s/$c/binary-$ARCH/Packages"
|
|
|
+ pkgdest="$TARGET/$($DLDEST pkg "$s" "$c" "$ARCH" "$m1" "$path")"
|
|
|
+ if [ ! -e "$pkgdest" ]; then continue; fi
|
|
|
+
|
|
|
+ info CHECKINGSIZES "Checking component %s on %s..." "$c" "$m1"
|
|
|
+
|
|
|
+ leftoverdebs="$(get_package_sizes "$m1" "$pkgdest" $leftoverdebs)"
|
|
|
+
|
|
|
+ countdebs=$(($countdebs + ${leftoverdebs%% *}))
|
|
|
+ leftoverdebs=${leftoverdebs#* }
|
|
|
+
|
|
|
+ totaldebs=${leftoverdebs%% *}
|
|
|
+ leftoverdebs=${leftoverdebs#* }
|
|
|
+
|
|
|
+ progress "$countdebs" "$numdebs" SIZEDEBS "Finding package sizes"
|
|
|
+ done
|
|
|
+ done
|
|
|
+
|
|
|
+ if [ "$countdebs" -ne "$numdebs" ]; then
|
|
|
+ error 1 LEFTOVERDEBS "Couldn't find these debs: %s" "$leftoverdebs"
|
|
|
+ fi
|
|
|
+
|
|
|
+ dloaddebs=0
|
|
|
+
|
|
|
+ progress "$dloaddebs" "$totaldebs" DOWNDEBS "Downloading packages"
|
|
|
+ :>"$TARGET/debootstrap/debpaths"
|
|
|
+
|
|
|
+ pkgs_to_get="$*"
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ for c in $COMPONENTS; do
|
|
|
+ path="dists/$s/$c/binary-$ARCH/Packages"
|
|
|
+ for m in $MIRRORS; do
|
|
|
+ pkgdest="$TARGET/$($DLDEST pkg "$s" "$c" "$ARCH" "$m" "$path")"
|
|
|
+ if [ ! -e "$pkgdest" ]; then continue; fi
|
|
|
+ pkgs_to_get="$(download_debs "$m" "$pkgdest" $pkgs_to_get 5>&1 1>&6)"
|
|
|
+ if [ -z "$pkgs_to_get" ]; then break; fi
|
|
|
+ done 6>&1
|
|
|
+ if [ -z "$pkgs_to_get" ]; then break; fi
|
|
|
+ done
|
|
|
+ if [ -z "$pkgs_to_get" ]; then break; fi
|
|
|
+ done
|
|
|
+ progress "$dloaddebs" "$totaldebs" DOWNDEBS "Downloading packages"
|
|
|
+ if [ "$pkgs_to_get" != "" ]; then
|
|
|
+ error 1 COULDNTDLPKGS "Couldn't download packages: %s" "$pkgs_to_get"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+download_main_indices () {
|
|
|
+ local m1 comp path pkgdest
|
|
|
+ m1="${MIRRORS%% *}"
|
|
|
+ comp="${USE_COMPONENTS}"
|
|
|
+ progress 0 100 DOWNMAINPKGS "Downloading Packages file"
|
|
|
+ progress_next 100
|
|
|
+
|
|
|
+ if [ -z "$comp" ]; then comp=main; fi
|
|
|
+ COMPONENTS="$(echo $comp | tr '|' ' ')"
|
|
|
+
|
|
|
+ export COMPONENTS
|
|
|
+ for m in $MIRRORS; do
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ for c in $COMPONENTS; do
|
|
|
+ path="dists/$s/$c/binary-$ARCH/Packages"
|
|
|
+ pkgdest="$TARGET/$($DLDEST pkg "$s" "$c" "$ARCH" "$m" "$path")"
|
|
|
+ if in_path gunzip && get "$m/${path}.gz" "${pkgdest}.gz"; then
|
|
|
+ rm -f "$pkgdest"
|
|
|
+ gunzip "$pkgdest.gz"
|
|
|
+ elif get "$m/$path" "$pkgdest"; then
|
|
|
+ true
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ done
|
|
|
+ done
|
|
|
+ progress 100 100 DOWNMAINPKGS "Downloading Packages file"
|
|
|
+}
|
|
|
+
|
|
|
+download_main () {
|
|
|
+ local m1 path pkgdest debdest
|
|
|
+ m1="${MIRRORS%% *}"
|
|
|
+
|
|
|
+ :>"$TARGET/debootstrap/debpaths"
|
|
|
+ for p in "$@"; do
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ for c in $COMPONENTS; do
|
|
|
+ local details=""
|
|
|
+ for m in $MIRRORS; do
|
|
|
+ path="dists/$s/$c/binary-$ARCH/Packages"
|
|
|
+ pkgdest="$TARGET/$($DLDEST pkg "$s" "$c" "$ARCH" "$m" "$path")"
|
|
|
+ if [ ! -e "$pkgdest" ]; then continue; fi
|
|
|
+ details="$($PKGDETAILS PKGS "$m" "$pkgdest" "$p")"
|
|
|
+ if [ "$details" = "$p -" ]; then
|
|
|
+ details=""
|
|
|
+ continue
|
|
|
+ fi
|
|
|
+ size="${details##* }"; details="${details% *}"
|
|
|
+ checksum="${details##* }"; details="${details% *}"
|
|
|
+ debdest="$($DLDEST deb $details)"
|
|
|
+ if get "$m/${details##* }" "$TARGET/$debdest" "$checksum" "$size"; then
|
|
|
+ echo >>"$TARGET/debootstrap/debpaths" "$p $debdest"
|
|
|
+ details="done"
|
|
|
+ break
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ if [ "$details" != "" ]; then
|
|
|
+ break
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ if [ "$details" != "" ]; then
|
|
|
+ break
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ if [ "$details" != "done" ]; then
|
|
|
+ error 1 COULDNTDL "Couldn't download %s" "$p"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+###################################################### deb choosing support
|
|
|
+
|
|
|
+get_debs () {
|
|
|
+ local field m1 c path pkgdest
|
|
|
+ field="$1"
|
|
|
+ shift
|
|
|
+ for m1 in $MIRRORS; do
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ for c in $COMPONENTS; do
|
|
|
+ path="dists/$s/$c/binary-$ARCH/Packages"
|
|
|
+ pkgdest="$TARGET/$($DLDEST pkg "$s" "$c" "$ARCH" "$m1" "$path")"
|
|
|
+ ret_debs="$("$PKGDETAILS" FIELD "$field" "$m1" "$pkgdest" "$@" | sed 's/ .*//')"
|
|
|
+ echo "$ret_debs"
|
|
|
+ # mylog "$ret_debs"
|
|
|
+ done
|
|
|
+ done
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+################################################################ extraction
|
|
|
+
|
|
|
+EXTRACTORS_SUPPORTED="dpkg-deb ar"
|
|
|
+EXTRACT_DEB_TAR_OPTIONS=
|
|
|
+
|
|
|
+# Native dpkg-deb based extractors
|
|
|
+extract_dpkg_deb_field () {
|
|
|
+ local pkg field
|
|
|
+ pkg="$1"
|
|
|
+ field="$2"
|
|
|
+
|
|
|
+ dpkg-deb -f "$pkg" "$field"
|
|
|
+}
|
|
|
+
|
|
|
+extract_dpkg_deb_data () {
|
|
|
+ local pkg="$1"
|
|
|
+
|
|
|
+ dpkg-deb --fsys-tarfile "$pkg" | tar $EXTRACT_DEB_TAR_OPTIONS -xf - || warning 1 FILEEXIST "Tried to extract package, but file already exists. Exit..."
|
|
|
+}
|
|
|
+
|
|
|
+# Raw .deb extractors
|
|
|
+extract_ar_deb_field () {
|
|
|
+ local pkg field tarball
|
|
|
+ pkg="$1"
|
|
|
+ field="$2"
|
|
|
+ tarball=$(ar -t "$pkg" | grep "^control\.tar")
|
|
|
+
|
|
|
+ case "$tarball" in
|
|
|
+ control.tar.gz) cat_cmd=zcat ;;
|
|
|
+ control.tar.xz) cat_cmd=xzcat ;;
|
|
|
+ control.tar) cat_cmd=cat ;;
|
|
|
+ *) error 1 UNKNOWNCONTROLCOMP "Unknown compression type for %s in %s" "$tarball" "$pkg" ;;
|
|
|
+ esac
|
|
|
+
|
|
|
+ if in_path $cat_cmd; then
|
|
|
+ ar -p "$pkg" "$tarball" | $cat_cmd |
|
|
|
+ tar -O -xf - control ./control 2>/dev/null |
|
|
|
+ grep -i "^$field:" | sed -e 's/[^:]*: *//' | head -n 1
|
|
|
+ else
|
|
|
+ error 1 UNPACKCMDUNVL "Extracting %s requires the %s command, which is not available" "$pkg" "$cat_cmd"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+extract_ar_deb_data () {
|
|
|
+ local pkg tarball
|
|
|
+ pkg="$1"
|
|
|
+ tarball="$(ar -t "$pkg" | grep "^data.tar")"
|
|
|
+
|
|
|
+ case "$tarball" in
|
|
|
+ data.tar.gz) cat_cmd=zcat ;;
|
|
|
+ data.tar.bz2) cat_cmd=bzcat ;;
|
|
|
+ data.tar.xz) cat_cmd=xzcat ;;
|
|
|
+ data.tar) cat_cmd=cat ;;
|
|
|
+ *) error 1 UNKNOWNDATACOMP "Unknown compression type for %s in %s" "$tarball" "$pkg" ;;
|
|
|
+ esac
|
|
|
+
|
|
|
+ if in_path "$cat_cmd"; then
|
|
|
+ ar -p "$pkg" "$tarball" | "$cat_cmd" | tar $EXTRACT_DEB_TAR_OPTIONS -xf -
|
|
|
+ else
|
|
|
+ error 1 UNPACKCMDUNVL "Extracting %s requires the %s command, which is not available" "$pkg" "$cat_cmd"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+valid_extractor () {
|
|
|
+ local extractor="$1"
|
|
|
+
|
|
|
+ for E in $EXTRACTORS_SUPPORTED; do
|
|
|
+ if [ "$extractor" = "$E" ]; then
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ return 1
|
|
|
+}
|
|
|
+
|
|
|
+choose_extractor () {
|
|
|
+ local extractor
|
|
|
+
|
|
|
+ if [ -n "$EXTRACTOR_OVERRIDE" ]; then
|
|
|
+ extractor="$EXTRACTOR_OVERRIDE"
|
|
|
+ elif in_path dpkg-deb; then
|
|
|
+ extractor="dpkg-deb"
|
|
|
+ else
|
|
|
+ extractor="ar"
|
|
|
+ fi
|
|
|
+
|
|
|
+ info CHOSENEXTRACTOR "Chosen extractor for .deb packages: %s" "$extractor"
|
|
|
+ case "$extractor" in
|
|
|
+ dpkg-deb)
|
|
|
+ extract_deb_field () { extract_dpkg_deb_field "$@"; }
|
|
|
+ extract_deb_data () { extract_dpkg_deb_data "$@"; }
|
|
|
+ ;;
|
|
|
+ ar)
|
|
|
+ extract_deb_field () { extract_ar_deb_field "$@"; }
|
|
|
+ extract_deb_data () { extract_ar_deb_data "$@"; }
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+extract () { (
|
|
|
+ cd "$TARGET" || exit 1
|
|
|
+ local p cat_cmd
|
|
|
+ p=0
|
|
|
+ for pkg in $(debfor "$@"); do
|
|
|
+ p=$(($p + 1))
|
|
|
+ progress "$p" "$#" EXTRACTPKGS "Extracting packages"
|
|
|
+ packagename="$(echo "$pkg" | sed 's,^.*/,,;s,_.*$,,')"
|
|
|
+ # info EXTRACTING "Extracting %s..." "$packagename"
|
|
|
+ info EXTRACTING "Extracting %s..." "$pkg"
|
|
|
+ extract_deb_data "./$pkg"
|
|
|
+ done
|
|
|
+); }
|
|
|
+
|
|
|
+in_target_nofail () {
|
|
|
+ if ! PATH=/sbin:/usr/sbin:/bin:/usr/bin eval "$CHROOT_CMD \"\$@\"" 2>/dev/null; then
|
|
|
+ true
|
|
|
+ fi
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+in_target_failmsg () {
|
|
|
+ local code msg arg
|
|
|
+ code="$1"
|
|
|
+ msg="$2"
|
|
|
+ arg="$3"
|
|
|
+ shift; shift; shift
|
|
|
+ if ! PATH=/sbin:/usr/sbin:/bin:/usr/bin eval "$CHROOT_CMD \"\$@\""; then
|
|
|
+ warning "$code" "$msg" "$arg"
|
|
|
+ # Try to point user at actual failing package.
|
|
|
+ msg="See %s for details"
|
|
|
+ if [ -e "$TARGET/debootstrap/debootstrap.log" ]; then
|
|
|
+ arg="$TARGET/debootstrap/debootstrap.log"
|
|
|
+ local pkg="$(grep '^dpkg: error processing ' "$TARGET/debootstrap/debootstrap.log" | head -n 1 | sed 's/\(error processing \)\(package \|archive \)/\1/' | cut -d ' ' -f 4)"
|
|
|
+ if [ -n "$pkg" ]; then
|
|
|
+ msg="$msg (possibly the package $pkg is at fault)"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ arg="the log"
|
|
|
+ fi
|
|
|
+ warning "$code" "$msg" "$arg"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+in_target () {
|
|
|
+ in_target_failmsg IN_TARGET_FAIL "Failure trying to run: %s" "$CHROOT_CMD $*" "$@"
|
|
|
+}
|
|
|
+
|
|
|
+###################################################### standard setup stuff
|
|
|
+
|
|
|
+conditional_cp () {
|
|
|
+ if [ ! -e "$2/$1" ]; then
|
|
|
+ if [ -L "$1" ] && [ -e "$1" ]; then
|
|
|
+ cat "$1" >"$2/$1"
|
|
|
+ elif [ -e "$1" ]; then
|
|
|
+ cp "$1" "$2/$1"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+setup_apt_sources () {
|
|
|
+ mkdir -p "$TARGET/etc/apt"
|
|
|
+ for m in "$@"; do
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ local cs c path pkgdest
|
|
|
+ for c in ${COMPONENTS:-$USE_COMPONENTS}; do
|
|
|
+ path="dists/$s/$c/binary-$ARCH/Packages"
|
|
|
+ pkgdest="$TARGET/$($DLDEST pkg "$s" "$c" "$ARCH" "$m" "$path")"
|
|
|
+ if [ -e "$pkgdest" ]; then cs="$cs $c"; fi
|
|
|
+ done
|
|
|
+ if [ "$cs" != "" ]; then echo "deb $m $s$cs"; fi
|
|
|
+ done
|
|
|
+ done > "$TARGET/etc/apt/sources.list"
|
|
|
+}
|
|
|
+
|
|
|
+setup_etc () {
|
|
|
+ mkdir -p "$TARGET/etc"
|
|
|
+
|
|
|
+ conditional_cp /etc/resolv.conf "$TARGET"
|
|
|
+ conditional_cp /etc/hostname "$TARGET"
|
|
|
+}
|
|
|
+
|
|
|
+UMOUNT_DIRS=
|
|
|
+
|
|
|
+umount_exit_function () {
|
|
|
+ local realdir
|
|
|
+ for dir in $UMOUNT_DIRS; do
|
|
|
+ realdir="$(in_target_nofail readlink -f "$dir")"
|
|
|
+ [ "$realdir" ] || continue
|
|
|
+ ( cd / ; umount "$TARGET/${realdir#/}" ) || true
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+umount_on_exit () {
|
|
|
+ if [ "$UMOUNT_DIRS" ]; then
|
|
|
+ UMOUNT_DIRS="$1 $UMOUNT_DIRS"
|
|
|
+ else
|
|
|
+ UMOUNT_DIRS="$1"
|
|
|
+ on_exit umount_exit_function
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+clear_mtab () {
|
|
|
+ if [ -f "$TARGET/etc/mtab" ] && [ ! -h "$TARGET/etc/mtab" ]; then
|
|
|
+ rm -f "$TARGET/etc/mtab"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+setup_proc () {
|
|
|
+ case "$HOST_OS" in
|
|
|
+ *freebsd*)
|
|
|
+ umount_on_exit /dev
|
|
|
+ umount_on_exit /proc
|
|
|
+ umount "$TARGET/proc" 2>/dev/null || true
|
|
|
+ if [ "$HOST_OS" = kfreebsd ]; then
|
|
|
+ in_target mount -t linprocfs proc /proc
|
|
|
+ else
|
|
|
+ mount -t linprocfs proc "$TARGET/proc"
|
|
|
+ fi
|
|
|
+ ;;
|
|
|
+ hurd*)
|
|
|
+ # firmlink $TARGET/{dev,servers,proc} to the system ones.
|
|
|
+ settrans -a "$TARGET/dev" /hurd/firmlink /dev
|
|
|
+ settrans -a "$TARGET/servers" /hurd/firmlink /servers
|
|
|
+ settrans -a "$TARGET/proc" /hurd/firmlink /proc
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ umount_on_exit /dev/pts
|
|
|
+ umount_on_exit /dev/shm
|
|
|
+ umount_on_exit /proc
|
|
|
+ umount_on_exit /proc/bus/usb
|
|
|
+ if [ -L "$TARGET/proc" ];then
|
|
|
+ rm -f $TARGET/proc
|
|
|
+ mkdir $TARGET/proc
|
|
|
+ else
|
|
|
+ umount "$TARGET/proc" 2>/dev/null || true
|
|
|
+ fi
|
|
|
+
|
|
|
+ # some container environment are used at second-stage, it already treats /proc and so on
|
|
|
+ if [ -z "$(ls -A "$TARGET/proc")" ]; then
|
|
|
+ # second-stage in docker, we cannot detect it is inside docker... just ignore warning
|
|
|
+ in_target mount -t proc proc /proc || true
|
|
|
+ umount_on_exit /proc
|
|
|
+ fi
|
|
|
+ if [ -n "$(ls -A "$TARGET/sys")" ] && \
|
|
|
+ grep -qs '[[:space:]]sysfs' "$TARGET/proc/filesystems" || \
|
|
|
+ [ "$CONTAINER" = "docker" ]; then
|
|
|
+ umount_on_exit /sys
|
|
|
+ umount "$TARGET/sys" 2>/dev/null || true
|
|
|
+ else
|
|
|
+ # second-stage in docker, we cannot detect it is inside docker... just ignore warning
|
|
|
+ in_target mount -t sysfs sysfs /sys || true
|
|
|
+ umount_on_exit /sys
|
|
|
+ fi
|
|
|
+ on_exit clear_mtab
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+ umount_on_exit /lib/init/rw
|
|
|
+}
|
|
|
+
|
|
|
+setup_proc_symlink () {
|
|
|
+ rm -rf "$TARGET/proc"
|
|
|
+ ln -s /proc "$TARGET"
|
|
|
+}
|
|
|
+
|
|
|
+# create the static device nodes
|
|
|
+setup_devices () {
|
|
|
+ if doing_variant fakechroot; then
|
|
|
+ setup_devices_fakechroot
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+
|
|
|
+ case "$HOST_OS" in
|
|
|
+ kfreebsd*)
|
|
|
+ ;;
|
|
|
+ freebsd)
|
|
|
+ ;;
|
|
|
+ hurd*)
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ if [ "$CONTAINER" = "lxc" ] || [ "$CONTAINER" = "lxc-libvirt" ]; then
|
|
|
+ if ! setup_devices_simple; then
|
|
|
+ setup_devices_bind
|
|
|
+ fi
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+ setup_devices_simple
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+# enable the dynamic device nodes
|
|
|
+setup_dynamic_devices () {
|
|
|
+ if doing_variant fakechroot; then
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+
|
|
|
+ case "$HOST_OS" in
|
|
|
+ kfreebsd*)
|
|
|
+ in_target mount -t devfs devfs /dev ;;
|
|
|
+ freebsd)
|
|
|
+ mount -t devfs devfs "$TARGET/dev" ;;
|
|
|
+ hurd*)
|
|
|
+ # Use the setup-translators of the hurd package
|
|
|
+ in_target /usr/lib/hurd/setup-translators -k ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+# Create a device node if it does not exist. By default, the mode is 666.
|
|
|
+mknod_if_needed () {
|
|
|
+ local device type major minor mode
|
|
|
+ device="$1"
|
|
|
+ type="$2"
|
|
|
+ major="$3"
|
|
|
+ minor="$4"
|
|
|
+ mode="${5:-666}"
|
|
|
+
|
|
|
+ if [ ! -e "$device" ]; then
|
|
|
+ mknod -m "$mode" "$device" "$type" "$major" "$minor"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+setup_devices_simple () {
|
|
|
+ # The list of devices that can be created in a container comes from
|
|
|
+ # src/core/cgroup.c in the systemd source tree.
|
|
|
+ mknod_if_needed "$TARGET/dev/null" c 1 3
|
|
|
+ mknod_if_needed "$TARGET/dev/zero" c 1 5
|
|
|
+ mknod_if_needed "$TARGET/dev/full" c 1 7
|
|
|
+ mknod_if_needed "$TARGET/dev/random" c 1 8
|
|
|
+ mknod_if_needed "$TARGET/dev/urandom" c 1 9
|
|
|
+ mknod_if_needed "$TARGET/dev/tty" c 5 0
|
|
|
+ if [ ! "$CONTAINER" = "systemd-nspawn" ]; then
|
|
|
+ mknod_if_needed "$TARGET/dev/console" c 5 1
|
|
|
+ fi
|
|
|
+ # To avoid pre-exist directory causes error, specify "-p" option
|
|
|
+ mkdir -p "$TARGET/dev/pts/" "$TARGET/dev/shm/"
|
|
|
+ # Inside a container, we might not be allowed to create /dev/ptmx.
|
|
|
+ # If not, do the next best thing.
|
|
|
+ if ! mknod_if_needed "$TARGET/dev/ptmx" c 5 2; then
|
|
|
+ warning MKNOD "Could not create /dev/ptmx, falling back to symlink. This chroot will require /dev/pts mounted with ptmxmode=666"
|
|
|
+ ln -sf pts/ptmx "$TARGET/dev/ptmx"
|
|
|
+ fi
|
|
|
+ ln -sf /proc/self/fd "$TARGET/dev/fd"
|
|
|
+ ln -sf /proc/self/fd/0 "$TARGET/dev/stdin"
|
|
|
+ ln -sf /proc/self/fd/1 "$TARGET/dev/stdout"
|
|
|
+ ln -sf /proc/self/fd/2 "$TARGET/dev/stderr"
|
|
|
+}
|
|
|
+
|
|
|
+setup_devices_fakechroot () {
|
|
|
+ rm -rf "$TARGET/dev"
|
|
|
+ ln -s /dev "$TARGET"
|
|
|
+}
|
|
|
+
|
|
|
+setup_devices_bind () {
|
|
|
+ mount -t tmpfs nodev "$TARGET/dev"
|
|
|
+ umount_on_exit /dev
|
|
|
+ for device in null zero full random urandom tty pts shm ptmx; do
|
|
|
+ if [ -d "/dev/$device" ]; then
|
|
|
+ mkdir "$TARGET/dev/$device"
|
|
|
+ elif [ -c "/dev/$device" ]; then
|
|
|
+ touch "$TARGET/dev/$device"
|
|
|
+ else
|
|
|
+ continue
|
|
|
+ fi
|
|
|
+ mount -o bind "/dev/$device" "$TARGET/dev/$device"
|
|
|
+ umount_on_exit "/dev/$device"
|
|
|
+ done
|
|
|
+ ln -s /proc/self/fd "$TARGET/dev/fd"
|
|
|
+ ln -s /proc/self/fd/0 "$TARGET/dev/stdin"
|
|
|
+ ln -s /proc/self/fd/1 "$TARGET/dev/stdout"
|
|
|
+ ln -s /proc/self/fd/2 "$TARGET/dev/stderr"
|
|
|
+}
|
|
|
+
|
|
|
+setup_dselect_method () {
|
|
|
+ case "$1" in
|
|
|
+ apt)
|
|
|
+ mkdir -p "$TARGET/var/lib/dpkg"
|
|
|
+ echo "apt apt" > "$TARGET/var/lib/dpkg/cmethopt"
|
|
|
+ chmod 644 "$TARGET/var/lib/dpkg/cmethopt"
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ error 1 UNKNOWNDSELECT "unknown dselect method"
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+# Find out where the runtime dynamic linker and the shared libraries
|
|
|
+# can be installed on each architecture: native, multilib and multiarch.
|
|
|
+# This data can be verified by checking the files in the debian/sysdeps/
|
|
|
+# directory of the glibc package.
|
|
|
+#
|
|
|
+# This function must be updated to support any new architecture which
|
|
|
+# either installs the RTLD in a directory different from /lib or builds
|
|
|
+# multilib library packages.
|
|
|
+setup_merged_usr() {
|
|
|
+ if doing_variant buildd && [ -z "$MERGED_USR" ]; then
|
|
|
+ MERGED_USR="no"
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [ "$MERGED_USR" = "no" ]; then return 0; fi
|
|
|
+
|
|
|
+ local link_dir
|
|
|
+ case $ARCH in
|
|
|
+ hurd-*) return 0 ;;
|
|
|
+ amd64) link_dir="lib32 lib64 libx32" ;;
|
|
|
+ i386) link_dir="lib64 libx32" ;;
|
|
|
+ mips|mipsel)
|
|
|
+ link_dir="lib32 lib64" ;;
|
|
|
+ mips64*|mipsn32*)
|
|
|
+ link_dir="lib32 lib64 libo32" ;;
|
|
|
+ powerpc) link_dir="lib64" ;;
|
|
|
+ ppc64) link_dir="lib32 lib64" ;;
|
|
|
+ ppc64el) link_dir="lib64" ;;
|
|
|
+ s390x) link_dir="lib32" ;;
|
|
|
+ sparc) link_dir="lib64" ;;
|
|
|
+ sparc64) link_dir="lib32 lib64" ;;
|
|
|
+ x32) link_dir="lib32 lib64 libx32" ;;
|
|
|
+ esac
|
|
|
+ link_dir="bin sbin lib $link_dir"
|
|
|
+
|
|
|
+ local dir
|
|
|
+ for dir in $link_dir; do
|
|
|
+ ln -s usr/"$dir" "$TARGET/$dir"
|
|
|
+ mkdir -p "$TARGET/usr/$dir"
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+################################################################ pkgdetails
|
|
|
+
|
|
|
+# NOTE
|
|
|
+# For the debootstrap udeb, pkgdetails is provided by the bootstrap-base
|
|
|
+# udeb, so the pkgdetails API needs to be kept in sync with that.
|
|
|
+
|
|
|
+if in_path perl; then
|
|
|
+ PKGDETAILS=pkgdetails_perl
|
|
|
+
|
|
|
+ # test if grep supports --perl-regexp
|
|
|
+ set +e
|
|
|
+ echo x | grep --perl-regexp . >/dev/null 2>&1
|
|
|
+ if [ $? -eq 2 ]; then
|
|
|
+ gropt=-E
|
|
|
+ else
|
|
|
+ gropt=--perl-regexp
|
|
|
+ fi
|
|
|
+ set -e
|
|
|
+
|
|
|
+ pkgdetails_field () {
|
|
|
+ # uniq field mirror Packages values...
|
|
|
+ perl -le '
|
|
|
+$unique = shift @ARGV; $field = lc(shift @ARGV); $mirror = shift @ARGV;
|
|
|
+%fields = map { $_, 0 } @ARGV;
|
|
|
+$prevpkg = "";
|
|
|
+$chksumfield = lc($ENV{DEBOOTSTRAP_CHECKSUM_FIELD}).":";
|
|
|
+while (<STDIN>) {
|
|
|
+ if (/^([^:]*:)\s*(.*)$/) {
|
|
|
+ $f = lc($1); $v = $2;
|
|
|
+ if ($f eq "package:") {
|
|
|
+ $last = 0;
|
|
|
+ $pkg = $v;
|
|
|
+ if ($pkg ne $prevpkg) {
|
|
|
+ print $output if defined $output;
|
|
|
+ if ($unique && defined $output_val) {
|
|
|
+ delete $fields{$output_val};
|
|
|
+ $last = 1 unless keys %fields;
|
|
|
+ }
|
|
|
+ $prevpkg = $pkg;
|
|
|
+ }
|
|
|
+ undef $output;
|
|
|
+ undef $output_val;
|
|
|
+ last if $last;
|
|
|
+ }
|
|
|
+ $ver = $v if ($f eq "version:");
|
|
|
+ $arc = $v if ($f eq "architecture:");
|
|
|
+ $fil = $v if ($f eq "filename:");
|
|
|
+ $chk = $v if ($f eq $chksumfield);
|
|
|
+ $siz = $v if ($f eq "size:");
|
|
|
+ $val = $v if ($f eq $field);
|
|
|
+ } elsif (/^$/) {
|
|
|
+ if (defined $val && defined $fields{$val}) {
|
|
|
+ $output = sprintf "%s %s %s %s %s %s %s",
|
|
|
+ $pkg, $ver, $arc, $mirror, $fil, $chk, $siz;
|
|
|
+ $output_val = $val;
|
|
|
+ }
|
|
|
+ undef $val;
|
|
|
+ }
|
|
|
+}
|
|
|
+print $output if defined $output;
|
|
|
+delete $fields{$output_val} if $unique && defined $output_val;
|
|
|
+for $v (keys %fields) {
|
|
|
+ printf ("%s -\n", $v) if ($unique);
|
|
|
+}
|
|
|
+' "$@"
|
|
|
+ }
|
|
|
+
|
|
|
+ pkgdetails_perl () {
|
|
|
+ if [ "$1" = "WGET%" ]; then
|
|
|
+ shift;
|
|
|
+ perl -e '
|
|
|
+$v = 0;
|
|
|
+$allow_percentage = 0;
|
|
|
+while (read STDIN, $x, 1) {
|
|
|
+ if ($x =~ m/\s/) {
|
|
|
+ $allow_percentage = 1;
|
|
|
+ } elsif ($allow_percentage and $x =~ m/\d/) {
|
|
|
+ $v *= 10;
|
|
|
+ $v += $x;
|
|
|
+ } elsif ($allow_percentage and $x eq "%") {
|
|
|
+ printf "P: %d %d%s\n", int($v / 100.0 * ($ARGV[1] - $ARGV[0]) + $ARGV[0]), $ARGV[2], ($#ARGV == 3 ? " $ARGV[3]" : "");
|
|
|
+ $v = 0;
|
|
|
+ } else {
|
|
|
+ $v = 0;
|
|
|
+ $allow_percentage = 0;
|
|
|
+ }
|
|
|
+}' "$@"
|
|
|
+ elif [ "$1" = "GETDEPS" ]; then
|
|
|
+ local pkgdest="$2"; shift; shift
|
|
|
+LC_ALL=C grep "$gropt" '^$|^Package:|^Depends:|^Pre-Depends:' $pkgdest | perl -e '
|
|
|
+%seen = map { $_ => 1 } @ARGV;
|
|
|
+while (<STDIN>) {
|
|
|
+ if (/^Package: (.*)$/) {
|
|
|
+ $pkg = $1;
|
|
|
+ next;
|
|
|
+ } elsif (/^$/) {
|
|
|
+ $in = 0;
|
|
|
+ next;
|
|
|
+ }
|
|
|
+ $in = 1 if $seen{$pkg};
|
|
|
+ if ($in and (/^Depends: (.*)$/ or /^Pre-Depends: (.*)$/)) {
|
|
|
+ for $d (split /\s*,\s*/, $1) {
|
|
|
+ $d =~ s/\s*[|].*$//;
|
|
|
+ $d =~ s/\s*[(].*[)]\s*//;
|
|
|
+ $d =~ s/:.*//;
|
|
|
+ $depends{$d} = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+ foreach (sort keys %depends) {
|
|
|
+ print "$_\n";
|
|
|
+ }
|
|
|
+' "$@"
|
|
|
+ elif [ "$1" = "PKGS" ]; then
|
|
|
+ local m="$2"
|
|
|
+ local p="$3"
|
|
|
+ shift; shift; shift
|
|
|
+ LC_ALL=C grep "$gropt" '^$|^Architecture:|^Filename:|^MD5sum:|^Package:|^Priority:|^SHA256:|^Size:|^Version:|^Depends:|^Pre-Depends:' "$p" | pkgdetails_field 1 Package: "$m" "$@"
|
|
|
+ elif [ "$1" = "FIELD" ]; then
|
|
|
+ local f="$2"
|
|
|
+ local m="$3"
|
|
|
+ local p="$4"
|
|
|
+ shift; shift; shift; shift
|
|
|
+ LC_ALL=C grep "$gropt" '^$|^Package:|^Priority:' "$p" | pkgdetails_field 0 "$f" "$m" "$@"
|
|
|
+ elif [ "$1" = "STANZAS" ]; then
|
|
|
+ local pkgdest="$2"; shift; shift
|
|
|
+ perl -e '
|
|
|
+my $accum = "";
|
|
|
+%seen = map { $_ => 1 } @ARGV;
|
|
|
+while (<STDIN>) {
|
|
|
+ $accum .= $_;
|
|
|
+ $in = 1 if (/^Package: (.*)$/ && $seen{$1});
|
|
|
+ if ($in and /^$/) {
|
|
|
+ print $accum;
|
|
|
+ if (substr($accum, -1) != "\n") {
|
|
|
+ print "\n\n";
|
|
|
+ } elsif (substr($accum, -2, 1) != "\n") {
|
|
|
+ print "\n";
|
|
|
+ }
|
|
|
+ $in = 0;
|
|
|
+ }
|
|
|
+ $accum = "" if /^$/;
|
|
|
+}' <"$pkgdest" "$@"
|
|
|
+ fi
|
|
|
+ }
|
|
|
+elif [ -e "/usr/lib/debootstrap/pkgdetails" ]; then
|
|
|
+ PKGDETAILS="/usr/lib/debootstrap/pkgdetails"
|
|
|
+elif [ -e "$DEBOOTSTRAP_DIR/pkgdetails" ]; then
|
|
|
+ PKGDETAILS="$DEBOOTSTRAP_DIR/pkgdetails"
|
|
|
+else
|
|
|
+ PKGDETAILS=""
|
|
|
+fi
|
|
|
+
|
|
|
+##################################################### dependency resolution
|
|
|
+
|
|
|
+resolve_deps () {
|
|
|
+ local m1="${MIRRORS%% *}"
|
|
|
+
|
|
|
+ local PKGS="$*"
|
|
|
+ local ALLPKGS="$PKGS";
|
|
|
+ local ALLPKGS2="";
|
|
|
+ while [ "$PKGS" != "" ]; do
|
|
|
+ local NEWPKGS=""
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ for c in ${COMPONENTS:-$(echo ${USE_COMPONENTS} | tr '|' ' ')}; do
|
|
|
+ local path="dists/$s/$c/binary-$ARCH/Packages"
|
|
|
+ local pkgdest="$TARGET/$($DLDEST pkg "$s" "$c" "$ARCH" "$m1" "$path")"
|
|
|
+ NEWPKGS="$NEWPKGS $("$PKGDETAILS" GETDEPS "$pkgdest" $PKGS)"
|
|
|
+ done
|
|
|
+ done
|
|
|
+ PKGS=$(echo "$PKGS $NEWPKGS" | tr ' ' '\n' | sort | uniq)
|
|
|
+ local REALPKGS=""
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ for c in ${COMPONENTS:-$(echo ${USE_COMPONENTS} | tr '|' ' ')}; do
|
|
|
+ local path="dists/$s/$c/binary-$ARCH/Packages"
|
|
|
+ local pkgdest="$TARGET/$($DLDEST pkg "$s" "$c" "$ARCH" "$m1" "$path")"
|
|
|
+ REALPKGS="$REALPKGS $("$PKGDETAILS" PKGS REAL "$pkgdest" $PKGS | sed -n 's/ .*REAL.*$//p')"
|
|
|
+ done
|
|
|
+ done
|
|
|
+ PKGS="$REALPKGS"
|
|
|
+ ALLPKGS2=$(echo "$PKGS $ALLPKGS" | tr ' ' '\n' | sort | uniq)
|
|
|
+ PKGS=$(without "$ALLPKGS2" "$ALLPKGS")
|
|
|
+ ALLPKGS="$ALLPKGS2"
|
|
|
+ done
|
|
|
+ echo "$ALLPKGS"
|
|
|
+}
|
|
|
+
|
|
|
+setup_available () {
|
|
|
+ local m1 c path pkgdest pkg
|
|
|
+ m1="${MIRRORS%% *}"
|
|
|
+
|
|
|
+ for s in $SUITE $EXTRA_SUITES; do
|
|
|
+ for c in ${COMPONENTS:-$(echo ${USE_COMPONENTS} | tr '|' ' ')}; do
|
|
|
+ path="dists/$s/$c/binary-$ARCH/Packages"
|
|
|
+ pkgdest="$TARGET/$($DLDEST pkg "$s" "$c" "$ARCH" "$m1" "$path")"
|
|
|
+ # XXX: What if a package is in more than one component?
|
|
|
+ # -- cjwatson 2009-07-29
|
|
|
+ # XXX: ...or suite?
|
|
|
+ # -- jrtc27 2019-06-11
|
|
|
+ "$PKGDETAILS" STANZAS "$pkgdest" "$@"
|
|
|
+ done
|
|
|
+ done >"$TARGET/var/lib/dpkg/available"
|
|
|
+
|
|
|
+ for pkg; do
|
|
|
+ echo "$pkg install"
|
|
|
+ done | in_target dpkg --set-selections
|
|
|
+}
|
|
|
+
|
|
|
+get_next_predep () {
|
|
|
+ local stanza="$(in_target_nofail dpkg --predep-package)"
|
|
|
+ [ "$stanza" ] || return 1
|
|
|
+ echo "$stanza" | grep '^Package:' | sed 's/^Package://; s/^ *//'
|
|
|
+}
|
|
|
+
|
|
|
+################################################################### helpers
|
|
|
+
|
|
|
+# Return zero if it is possible to create devices and execute programs in
|
|
|
+# this directory. (Both may be forbidden by mount options, e.g. nodev and
|
|
|
+# noexec respectively.)
|
|
|
+check_sane_mount () {
|
|
|
+ mkdir -p "$1"
|
|
|
+
|
|
|
+ case "$HOST_OS" in
|
|
|
+ *freebsd*|hurd*)
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ if ! doing_variant fakechroot; then
|
|
|
+ case "$CONTAINER" in
|
|
|
+ lxc|lxc-libvirt)
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ mknod "$1/test-dev-null" c 1 3 || return 1
|
|
|
+ if ! echo test > "$1/test-dev-null"; then
|
|
|
+ rm -f "$1/test-dev-null"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ rm -f "$1/test-dev-null"
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+ fi
|
|
|
+ esac
|
|
|
+
|
|
|
+ SH="/bin/sh"
|
|
|
+ [ -x "$SH" ] || SH="$(which sh)"
|
|
|
+
|
|
|
+ cat > "$1/test-exec" <<EOF
|
|
|
+#! $SH
|
|
|
+:
|
|
|
+EOF
|
|
|
+ chmod +x "$1/test-exec"
|
|
|
+ if ! "$1/test-exec"; then
|
|
|
+ rm -f "$1/test-exec"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ rm -f "$1/test-exec"
|
|
|
+
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+read_gpg_status () {
|
|
|
+ local badsig unkkey validsig
|
|
|
+ while read prefix keyword keyid rest; do
|
|
|
+ [ "$prefix" = '[GNUPG:]' ] || continue
|
|
|
+ case $keyword in
|
|
|
+ BADSIG) badsig="$keyid" ;;
|
|
|
+ NO_PUBKEY) unkkey="$keyid" ;;
|
|
|
+ VALIDSIG) validsig="$keyid" ;;
|
|
|
+ esac
|
|
|
+ done
|
|
|
+ if [ "$validsig" ]; then
|
|
|
+ info VALIDRELSIG "Valid Release signature (key id %s)" "$validsig"
|
|
|
+ elif [ "$badsig" ]; then
|
|
|
+ error 1 BADRELSIG "Invalid Release signature (key id %s)" "$badsig"
|
|
|
+ elif [ "$unkkey" ]; then
|
|
|
+ error 1 UNKNOWNRELSIG "Release signed by unknown key (key id %s)\n The specified keyring $KEYRING may be incorrect or out of date.\n You can find the latest Debian release key at https://ftp-master.debian.org/keys.html" "$unkkey"
|
|
|
+ else
|
|
|
+ error 1 SIGCHECK "Error executing gpgv to check Release signature"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+without () {
|
|
|
+ # usage: without "a b c" "a d" -> "b" "c"
|
|
|
+ (echo "$1" | tr ' ' '\n' | sort | uniq;
|
|
|
+ echo "$2" "$2" | tr ' ' '\n') | sort | uniq -u | tr '\n' ' '
|
|
|
+ echo
|
|
|
+}
|
|
|
+
|
|
|
+# Formerly called 'repeat', but that's a reserved word in zsh.
|
|
|
+repeatn () {
|
|
|
+ local n="$1"
|
|
|
+ shift
|
|
|
+ while [ "$n" -gt 0 ]; do
|
|
|
+ if "$@"; then
|
|
|
+ break
|
|
|
+ else
|
|
|
+ n=$(( $n - 1 ))
|
|
|
+ sleep 1
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ if [ "$n" -eq 0 ]; then return 1; fi
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+N_EXIT_THINGS=0
|
|
|
+exit_function () {
|
|
|
+ local n=0
|
|
|
+ while [ "$n" -lt "$N_EXIT_THINGS" ]; do
|
|
|
+ (eval $(eval echo \${EXIT_THING_$n}) 2>/dev/null || true)
|
|
|
+ n=$(( $n + 1 ))
|
|
|
+ done
|
|
|
+ N_EXIT_THINGS=0
|
|
|
+}
|
|
|
+
|
|
|
+trap "exit_function" 0
|
|
|
+trap "exit 129" 1
|
|
|
+trap "error 130 INTERRUPTED \"Interrupt caught ... exiting\"" 2
|
|
|
+trap "exit 131" 3
|
|
|
+trap "exit 143" 15
|
|
|
+
|
|
|
+on_exit () {
|
|
|
+ eval "$(echo EXIT_THING_${N_EXIT_THINGS}=\"$1\")"
|
|
|
+ N_EXIT_THINGS=$(( $N_EXIT_THINGS + 1 ))
|
|
|
+}
|
|
|
+
|
|
|
+############################################################## fakechroot tools
|
|
|
+
|
|
|
+install_fakechroot_tools () {
|
|
|
+ if [ "$VARIANT" = "fakechroot" ]; then
|
|
|
+ export PATH=/usr/sbin:/sbin:$PATH
|
|
|
+ fi
|
|
|
+
|
|
|
+ mv "$TARGET/sbin/ldconfig" "$TARGET/sbin/ldconfig.REAL"
|
|
|
+ echo \
|
|
|
+"#!/bin/sh
|
|
|
+echo
|
|
|
+echo \"Warning: Fake ldconfig called, doing nothing\"" > "$TARGET/sbin/ldconfig"
|
|
|
+ chmod 755 "$TARGET/sbin/ldconfig"
|
|
|
+
|
|
|
+ echo \
|
|
|
+"/sbin/ldconfig
|
|
|
+/sbin/ldconfig.REAL
|
|
|
+fakechroot" >> "$TARGET/var/lib/dpkg/diversions"
|
|
|
+
|
|
|
+ mv "$TARGET/usr/bin/ldd" "$TARGET/usr/bin/ldd.REAL"
|
|
|
+ cat << 'END' > "$TARGET/usr/bin/ldd"
|
|
|
+#!/usr/bin/perl
|
|
|
+
|
|
|
+# fakeldd
|
|
|
+#
|
|
|
+# Replacement for ldd with usage of objdump
|
|
|
+#
|
|
|
+# (c) 2003-2005 Piotr Roszatycki <dexter@debian.org>, BSD
|
|
|
+
|
|
|
+
|
|
|
+my %libs = ();
|
|
|
+
|
|
|
+my $status = 0;
|
|
|
+my $dynamic = 0;
|
|
|
+my $biarch = 0;
|
|
|
+
|
|
|
+my $ldlinuxsodir = "/lib";
|
|
|
+my @ld_library_path = qw(/usr/lib /lib);
|
|
|
+
|
|
|
+
|
|
|
+sub ldso($) {
|
|
|
+ my ($lib) = @_;
|
|
|
+ my @files = ();
|
|
|
+
|
|
|
+ if ($lib =~ /^\//) {
|
|
|
+ $libs{$lib} = $lib;
|
|
|
+ push @files, $lib;
|
|
|
+ } else {
|
|
|
+ foreach my $ld_path (@ld_library_path) {
|
|
|
+ next unless -f "$ld_path/$lib";
|
|
|
+ my $badformat = 0;
|
|
|
+ open OBJDUMP, "objdump -p $ld_path/$lib 2>/dev/null |";
|
|
|
+ while (my $line = <OBJDUMP>) {
|
|
|
+ if ($line =~ /file format (\S*)$/) {
|
|
|
+ $badformat = 1 unless $format eq $1;
|
|
|
+ last;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ close OBJDUMP;
|
|
|
+ next if $badformat;
|
|
|
+ $libs{$lib} = "$ld_path/$lib";
|
|
|
+ push @files, "$ld_path/$lib";
|
|
|
+ }
|
|
|
+ objdump(@files);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+sub objdump(@) {
|
|
|
+ my (@files) = @_;
|
|
|
+ my @libs = ();
|
|
|
+
|
|
|
+ foreach my $file (@files) {
|
|
|
+ open OBJDUMP, "objdump -p $file 2>/dev/null |";
|
|
|
+ while (my $line = <OBJDUMP>) {
|
|
|
+ $line =~ s/^\s+//;
|
|
|
+ my @f = split (/\s+/, $line);
|
|
|
+ if ($line =~ /file format (\S*)$/) {
|
|
|
+ if (not $format) {
|
|
|
+ $format = $1;
|
|
|
+ if ($unamearch eq "x86_64" and $format eq "elf32-i386") {
|
|
|
+ my $link = readlink "/lib/ld-linux.so.2";
|
|
|
+ if ($link =~ /^\/emul\/ia32-linux\//) {
|
|
|
+ $ld_library_path[-2] = "/emul/ia32-linux/usr/lib";
|
|
|
+ $ld_library_path[-1] = "/emul/ia32-linux/lib";
|
|
|
+ }
|
|
|
+ } elsif ($unamearch =~ /^(sparc|sparc64)$/ and $format eq "elf64-sparc") {
|
|
|
+ $ldlinuxsodir = "/lib64";
|
|
|
+ $ld_library_path[-2] = "/usr/lib64";
|
|
|
+ $ld_library_path[-1] = "/lib64";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ next unless $format eq $1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (not $dynamic and $f[0] eq "Dynamic") {
|
|
|
+ $dynamic = 1;
|
|
|
+ }
|
|
|
+ next unless $f[0] eq "NEEDED";
|
|
|
+ if ($f[1] =~ /^ld-linux(\.|-)/) {
|
|
|
+ $f[1] = "$ldlinuxsodir/" . $f[1];
|
|
|
+ }
|
|
|
+ if (not defined $libs{$f[1]}) {
|
|
|
+ $libs{$f[1]} = undef;
|
|
|
+ push @libs, $f[1];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ close OBJDUMP;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach my $lib (@libs) {
|
|
|
+ ldso($lib);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if ($#ARGV < 0) {
|
|
|
+ print STDERR "fakeldd: missing file arguments\n";
|
|
|
+ exit 1;
|
|
|
+}
|
|
|
+
|
|
|
+while ($ARGV[0] =~ /^-/) {
|
|
|
+ my $arg = $ARGV[0];
|
|
|
+ shift @ARGV;
|
|
|
+ last if $arg eq "--";
|
|
|
+}
|
|
|
+
|
|
|
+open LD_SO_CONF, "/etc/ld.so.conf";
|
|
|
+while ($line = <LD_SO_CONF>) {
|
|
|
+ chomp $line;
|
|
|
+ unshift @ld_library_path, $line;
|
|
|
+}
|
|
|
+close LD_SO_CONF;
|
|
|
+
|
|
|
+unshift @ld_library_path, split(/:/, $ENV{LD_LIBRARY_PATH});
|
|
|
+
|
|
|
+$unamearch = "$(/bin/uname -m)";
|
|
|
+chomp $unamearch;
|
|
|
+
|
|
|
+foreach my $file (@ARGV) {
|
|
|
+ my $address;
|
|
|
+ %libs = ();
|
|
|
+ $dynamic = 0;
|
|
|
+
|
|
|
+ if ($#ARGV > 0) {
|
|
|
+ print "$file:\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (not -f $file) {
|
|
|
+ print STDERR "ldd: $file: No such file or directory\n";
|
|
|
+ $status = 1;
|
|
|
+ next;
|
|
|
+ }
|
|
|
+
|
|
|
+ objdump($file);
|
|
|
+
|
|
|
+ if ($dynamic == 0) {
|
|
|
+ print "\tnot a dynamic executable\n";
|
|
|
+ $status = 1;
|
|
|
+ } elsif (scalar %libs eq "0") {
|
|
|
+ print "\tstatically linked\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($format =~ /^elf64-/) {
|
|
|
+ $address = "0x0000000000000000";
|
|
|
+ } else {
|
|
|
+ $address = "0x00000000";
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach $lib (keys %libs) {
|
|
|
+ if ($libs{$lib}) {
|
|
|
+ printf "\t%s => %s (%s)\n", $lib, $libs{$lib}, $address;
|
|
|
+ } else {
|
|
|
+ printf "\t%s => not found\n", $lib;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+exit $status;
|
|
|
+END
|
|
|
+ chmod 755 "$TARGET/usr/bin/ldd"
|
|
|
+
|
|
|
+ echo \
|
|
|
+"/usr/bin/ldd
|
|
|
+/usr/bin/ldd.REAL
|
|
|
+fakechroot" >> "$TARGET/var/lib/dpkg/diversions"
|
|
|
+
|
|
|
+}
|