diff options
Diffstat (limited to 'contrib/debootstrap/debootstrap')
-rwxr-xr-x | contrib/debootstrap/debootstrap | 621 |
1 files changed, 621 insertions, 0 deletions
diff --git a/contrib/debootstrap/debootstrap b/contrib/debootstrap/debootstrap new file mode 100755 index 0000000..171a5ef --- /dev/null +++ b/contrib/debootstrap/debootstrap @@ -0,0 +1,621 @@ +#!/bin/sh -e + +VERSION='@VERSION@' + +unset TMP TEMP TMPDIR || true + +# might not be exported if we're running from init=/bin/sh or similar +export PATH + +########################################################################### + +if [ -z "$DEBOOTSTRAP_DIR" ]; then + if [ -x /debootstrap/debootstrap ]; then + DEBOOTSTRAP_DIR=/debootstrap + else + DEBOOTSTRAP_DIR=/usr/share/debootstrap + fi +fi + +DEVICES_TARGZ=$DEBOOTSTRAP_DIR/devices.tar.gz + +. $DEBOOTSTRAP_DIR/functions +exec 4>&1 + +LANG=C +USE_COMPONENTS=main +KEYRING="" +VARIANT="" + +DEF_MIRROR="http://ftp.us.debian.org/debian" + +export LANG USE_COMPONENTS +umask 022 + +########################################################################### + +## phases: +## finddebs dldebs printdebs first_stage second_stage + +RESOLVE_DEPS=true + +WHAT_TO_DO="finddebs dldebs first_stage second_stage" +am_doing_phase () { + # usage: if am_doing_phase finddebs; then ...; fi + local x; + for x in "$@"; do + if echo " $WHAT_TO_DO " | grep -q " $x "; then return 0; fi + done + return 1 +} + +########################################################################### + +usage_err() +{ + info USAGE1 "usage: [OPTION]... <suite> <target> [<mirror> [<script>]]" + info USAGE2 "Try \`${0##*/} --help' for more information." + error "$@" +} + +usage() +{ + echo "Usage: ${0##*/} [OPTION]... <suite> <target> [<mirror> [<script>]]" + echo "Bootstrap Debian base system." + echo + cat <<EOF + --help display this help and exit + --version display version information and exit + --verbose don't turn off the output of wget + + --download-only download packages, but don't perform installation + --print-debs print the packages to be installed, and exit + + --arch=A set the target architecture (use if no dpkg) + [ --arch=powerpc ] + + --include=A,B,C adds specified names to the list of base packages + --exclude=A,B,C removes specified packages from the list + --components=A,B,C use packages from the listed components of the + archive + --variant=X use variant X of the bootstrap scripts + (currently supported variants: buildd, fakechroot, + scratchbox) + --keyring=K check Release files against keyring K + --no-resolve-deps don't try to resolve dependencies automatically + + --unpack-tarball=T acquire .debs from a tarball instead of http + --make-tarball=T download .debs and create a tarball (tgz format) + --second-stage-target=DIR + Run second stage in a subdirectory instead of root + (can be used to create a foreign chroot) + (requires --second-stage) + --extractor=TYPE override automatic .deb extractor selection + (supported: $EXTRACTORS_SUPPORTED) + --boot-floppies used for internal purposes by boot-floppies + --debian-installer used for internal purposes by debian-installer +EOF +} + +########################################################################### + +if [ -z "$PKGDETAILS" ]; then + error 1 NO_PKGDETAILS "No pkgdetails available; either install perl, or build pkgdetails.c from source" +fi + +########################################################################### + +if [ $# != 0 ] ; then + while true ; do + case "$1" in + --help) + usage + exit 0 + ;; + --version) + echo "debootstrap $VERSION" + exit 0 + ;; + --boot-floppies) + if [ -n "$USE_DEBIANINSTALLER_INTERACTION" ] ; then + error 1 ARG_BFDI "Can only use one of --boot-floppies and --debian-installer" + fi + if ! (echo -n "" >&3) 2>/dev/null; then + error 1 ARG_BFBYHAND "If running debootstrap by hand, don't use --boot-floppies" + fi + USE_BOOTFLOPPIES_INTERACTION=yes + shift + ;; + --debian-installer) + if [ -n "$USE_BOOTFLOPPIES_INTERACTION" ] ; then + error 1 ARG_BFDI "Can only use one of --boot-floppies and --debian-installer" + fi + if ! (echo -n "" >&3) 2>/dev/null; then + error 1 ARG_DIBYHAND "If running debootstrap by hand, don't use --debian-installer" + fi + USE_DEBIANINSTALLER_INTERACTION=yes + shift + ;; + --foreign) + WHAT_TO_DO="finddebs dldebs first_stage" + shift + ;; + --second-stage) + WHAT_TO_DO="second_stage" + SECOND_STAGE_ONLY=true + shift + ;; + --second-stage-target|--second-stage-target=?*) + if [ "$SECOND_STAGE_ONLY" != "true" ] ; then + error 1 STAGE2ONLY "option %s only applies in the second stage" "$1" + fi + if [ "$1" = "--second-stage-target" -a -n "$2" ] ; then + CHROOTDIR="$2" + shift 2 + elif [ "$1" != "${1#--second-stage-target=}" ]; then + CHROOTDIR="${1#--second-stage-target=}" + shift + else + error 1 NEEDARG "option requires an argument: %s" "$1" + fi + ;; + --print-debs) + WHAT_TO_DO="finddebs printdebs kill_target" + shift + ;; + --download-only) + WHAT_TO_DO="finddebs dldebs" + shift + ;; + --make-tarball|--make-tarball=?*) + WHAT_TO_DO="finddebs dldebs maketarball kill_target" + if [ "$1" = "--make-tarball" -a -n "$2" ] ; then + MAKE_TARBALL="$2" + shift 2 + elif [ "$1" != "${1#--make-tarball=}" ]; then + MAKE_TARBALL="${1#--make-tarball=}" + shift + else + error 1 NEEDARG "option requires an argument %s" "$1" + fi + ;; + --resolve-deps) + # redundant, but avoids breaking compatability + RESOLVE_DEPS=true + shift + ;; + --no-resolve-deps) + RESOLVE_DEPS=false + shift + ;; + --keep-debootstrap-dir) + KEEP_DEBOOTSTRAP_DIR=true + shift + ;; + --arch|--arch=?*) + if [ "$1" = "--arch" -a -n "$2" ] ; then + ARCH="$2" + shift 2 + elif [ "$1" != "${1#--arch=}" ]; then + ARCH="${1#--arch=}" + shift + else + error 1 NEEDARG "option requires an argument %s" "$1" + fi + ;; + --extractor|--extractor=?*) + if [ "$1" = "--extractor" -a -n "$2" ] ; then + EXTRACTOR_OVERRIDE="$2" + shift 2 + elif [ "$1" != "${1#--extractor=}" ]; then + EXTRACTOR_OVERRIDE="${1#--extractor=}" + shift + else + error 1 NEEDARG "option requires an argument %s" "$1" + fi + if valid_extractor "$EXTRACTOR_OVERRIDE"; then + if ! type "$EXTRACTOR_OVERRIDE" >/dev/null 2>&1; then + error 1 MISSINGEXTRACTOR "The selected extractor cannot be found: %s" "$EXTRACTOR_OVERRIDE" + fi + else + error 1 BADEXTRACTOR "%s: unknown extractor" "$EXTRACTOR_OVERRIDE" + fi + ;; + --unpack-tarball|--unpack-tarball=?*) + if [ "$1" = "--unpack-tarball" -a -n "$2" ] ; then + UNPACK_TARBALL="$2" + shift 2 + elif [ "$1" != "${1#--unpack-tarball=}" ]; then + UNPACK_TARBALL="${1#--unpack-tarball=}" + shift + else + error 1 NEEDARG "option requires an argument %s" "$1" + fi + if [ ! -f "$UNPACK_TARBALL" ] ; then + error 1 NOTARBALL "%s: No such file or directory" "$UNPACK_TARBALL" + fi + ;; + --include|--include=?*) + if [ "$1" = "--include" -a -n "$2" ]; then + additional="$2" + shift 2 + elif [ "$1" != "${1#--include=}" ]; then + additional="${1#--include=}" + shift 1 + else + error 1 NEEDARG "option requires an argument %s" "$1" + fi + additional="$(echo "$additional" | tr , " ")" + ;; + --exclude|--exclude=?*) + if [ "$1" = "--exclude" -a -n "$2" ]; then + exclude="$2" + shift 2 + elif [ "$1" != "${1#--exclude=}" ]; then + exclude="${1#--exclude=}" + shift 1 + else + error 1 NEEDARG "option requires an argument %s" "$1" + fi + exclude="$(echo "$exclude" | tr , " ")" + ;; + --verbose) + verbose=true + export verbose + shift 1 + ;; + --components|--components=?*) + if [ "$1" = "--components" -a -n "$2" ]; then + USE_COMPONENTS="$2" + shift 2 + elif [ "$1" != "${1#--components=}" ]; then + USE_COMPONENTS="${1#--components=}" + shift 1 + else + error 1 NEEDARG "option requires an argument %s" "$1" + fi + USE_COMPONENTS="$(echo "$USE_COMPONENTS" | tr , "|")" + ;; + --variant|--variant=?*) + if [ "$1" = "--variant" -a -n "$2" ]; then + VARIANT="$2" + shift 2 + elif [ "$1" != "${1#--variant=}" ]; then + VARIANT="${1#--variant=}" + shift 1 + else + error 1 NEEDARG "option requires an argument %s" "$1" + fi + ;; + --keyring|--keyring=?*) + if ! gpgv --version >/dev/null 2>&1; then + error 1 NEEDGPGV "gpgv not installed, but required for Release verification" + fi + if [ "$1" = "--keyring" -a -n "$2" ]; then + KEYRING="$2" + shift 2 + elif [ "$1" != "${1#--keyring=}" ]; then + KEYRING="${1#--keyring=}" + shift 1 + else + error 1 NEEDARG "option requires an argument %s" "$1" + fi + ;; + --*) + error 1 BADARG "unrecognized or invalid option %s" "$1" + ;; + *) + break + ;; + esac + done +fi + +########################################################################### + +if [ "$SECOND_STAGE_ONLY" = "true" ]; then + SUITE=$(cat $DEBOOTSTRAP_DIR/suite) + ARCH=$(cat $DEBOOTSTRAP_DIR/arch) + if [ -e $DEBOOTSTRAP_DIR/variant ]; then + VARIANT=$(cat $DEBOOTSTRAP_DIR/variant) + SUPPORTED_VARIANTS="$VARIANT" + fi + if [ -z "$CHROOTDIR" ]; then + TARGET=/ + else + TARGET=$CHROOTDIR + fi + SCRIPT=$DEBOOTSTRAP_DIR/suite-script +else + if [ -z "$1" ] || [ -z "$2" ]; then + usage_err 1 NEEDSUITETARGET "You must specify a suite and a target." + fi + SUITE="$1" + TARGET="$2" + TARGET="${TARGET%/}" + if [ "${TARGET#/}" = "${TARGET}" ]; then + if [ "${TARGET%/*}" = "$TARGET" ] ; then + TARGET="$(echo "`pwd`/$TARGET")" + else + TARGET="$(cd "${TARGET%/*}"; echo "`pwd`/${TARGET##*/}")" + fi + fi + + SCRIPT="$DEBOOTSTRAP_DIR/scripts/$1" + if [ -n "$VARIANT" ] && [ -e "${SCRIPT}.${VARIANT}" ]; then + SCRIPT="${SCRIPT}.${VARIANT}" + SUPPORTED_VARIANTS="$VARIANT" + fi + if [ "$4" != "" ]; then + SCRIPT="$4" + fi +fi + +########################################################################### + +if [ "$ARCH" != "" ]; then + true +elif [ -x /usr/bin/dpkg ] && \ + /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then + ARCH=`/usr/bin/dpkg --print-architecture` +elif type udpkg >/dev/null 2>&1 && \ + udpkg --print-architecture >/dev/null 2>&1; then + ARCH=`/usr/bin/udpkg --print-architecture` +elif [ -e $DEBOOTSTRAP_DIR/arch ]; then + ARCH=`cat $DEBOOTSTRAP_DIR/arch` +else + error 1 WHATARCH "Couldn't work out current architecture" +fi + +if [ "$TARGET" = "/" ]; then + CHROOT_CMD="" +elif doing_variant scratchbox; then + for config in ~/.scratchbox2/*/sb2.config; + do + export `grep ^SBOX_TARGET_ROOT= $config` + if [ "x$SBOX_TARGET_ROOT" = "x$TARGET" ]; then + SB2_TARGET=$(basename $(dirname $config)) + fi + done + [ "x$SB2_TARGET" != "x" ] || error 1 SBOXTARGETREQ "No scratchbox target configured for $TARGET" + CHROOT_CMD="sb2 -eR -t $SB2_TARGET" +else + CHROOT_CMD="chroot $TARGET" +fi + +export ARCH SUITE TARGET CHROOT_CMD + +if am_doing_phase first_stage second_stage; then + if [ -x /usr/bin/id ] && [ `id -u` -ne 0 ]; then + error 1 NEEDROOT "debootstrap can only run as root" + fi + # Ensure that we can create working devices and executables on the target. + if ! check_sane_mount "$TARGET"; then + error 1 NOEXEC "Cannot install into target '$TARGET' mounted with noexec or nodev" + fi +fi + +if [ ! -e "$SCRIPT" ]; then + error 1 NOSCRIPT "No such script: %s" "$SCRIPT" +fi + +########################################################################### + +if [ "$TARGET" != "" ]; then + mkdir -p "$TARGET/debootstrap" +fi + +########################################################################### + +# Use of fd's by functions/scripts: +# +# stdin/stdout/stderr: used normally +# fd 4: I:/W:/etc information +# fd 5,6: spare for functions +# fd 7,8: spare for scripts + +if [ "$USE_DEBIANINSTALLER_INTERACTION" = yes ]; then + # stdout=stderr: full log of debootstrap run + # fd 3: I:/W:/etc information + exec 4>&3 +elif [ "$USE_BOOTFLOPPIES_INTERACTION" = yes ]; then + # stdout=stderr: full log of debootstrap run + # fd 3: I:/W:/etc information + exec 4>&3 +elif am_doing_phase printdebs; then + # stderr: I:/W:/etc information + # stdout: debs needed + exec 4>&2 +else + # stderr: used in exceptional circumstances only + # stdout: I:/W:/etc information + # $TARGET/debootstrap/debootstrap.log: full log of debootstrap run + exec 4>&1 + exec >>"$TARGET/debootstrap/debootstrap.log" + exec 2>&1 +fi + +########################################################################### + +if [ "$UNPACK_TARBALL" ]; then + if [ "${UNPACK_TARBALL#/}" = "$UNPACK_TARBALL" ]; then + error 1 TARPATH "Tarball must be given a complete path" + fi + if [ "${UNPACK_TARBALL%.tar}" != "$UNPACK_TARBALL" ]; then + (cd "$TARGET" && tar -xf "$UNPACK_TARBALL") + elif [ "${UNPACK_TARBALL%.tgz}" != "$UNPACK_TARBALL" ]; then + (cd "$TARGET" && zcat "$UNPACK_TARBALL" | tar -xf -) + else + error 1 NOTTAR "Unknown tarball: must be either .tar or .tgz" + fi +fi + +########################################################################### + +. "$SCRIPT" + +if [ "$SECOND_STAGE_ONLY" = "true" ]; then + MIRRORS=null: +else + MIRRORS="$DEF_MIRROR" + if [ "$3" != "" ]; then + MIRRORS="$3" + MIRRORS="${MIRRORS%/}" + fi +fi + +export MIRRORS + +ok=false +for v in $SUPPORTED_VARIANTS; do + if doing_variant $v; then ok=true; fi +done +if ! $ok; then + error 1 UNSUPPVARIANT "unsupported variant" +fi + +########################################################################### + +if am_doing_phase finddebs; then + if [ "$FINDDEBS_NEEDS_INDICES" = "true" ] || \ + [ "$RESOLVE_DEPS" = "true" ]; then + download_indices + GOT_INDICES=true + fi + + work_out_debs + + base=$(without "$base $additional" "$exclude") + + if [ "$RESOLVE_DEPS" = true ]; then + requiredX=$(echo $(echo $required | tr ' ' '\n' | sort | uniq)) + baseX=$(echo $(echo $base | tr ' ' '\n' | sort | uniq)) + + baseN=$(without "$baseX" "$requiredX") + baseU=$(without "$baseX" "$baseN") + + if [ "$baseU" != "" ]; then + info REDUNDANTBASE "Found packages in base already in required: %s" "$baseU" + sleep 5 + fi + + info RESOLVEREQ "Resolving dependencies of required packages..." + required=$(resolve_deps $requiredX) + info RESOLVEBASE "Resolving dependencies of base packages..." + base=$(resolve_deps $baseX) + base=$(without "$base" "$required") + + requiredX=$(without "$required" "$requiredX") + baseX=$(without "$base" "$baseX") + if [ "$requiredX" != "" ]; then + info NEWREQUIRED "Found additional required dependencies: %s" "$requiredX" + sleep 5 + fi + if [ "$baseX" != "" ]; then + info NEWBASE "Found additional base dependencies: %s" "$baseX" + sleep 5 + fi + fi + + all_debs="$required $base" +fi + +if am_doing_phase printdebs; then + echo "$all_debs" +fi + +if am_doing_phase dldebs; then + if [ "$GOT_INDICES" != "true" ]; then + download_indices + fi + download $all_debs +fi + +if am_doing_phase maketarball; then + (cd $TARGET; + tar czf - var/lib/apt var/cache/apt) >$MAKE_TARBALL +fi + +if am_doing_phase first_stage; then + choose_extractor + + # first stage sets up the chroot -- no calls should be made to + # "chroot $TARGET" here; but they should be possible by the time it's + # finished + first_stage_install + + if ! am_doing_phase second_stage; then + cp "$0" "$TARGET/debootstrap/debootstrap" + cp $DEBOOTSTRAP_DIR/functions "$TARGET/debootstrap/functions" + cp $SCRIPT "$TARGET/debootstrap/suite-script" + echo "$ARCH" >"$TARGET/debootstrap/arch" + echo "$SUITE" >"$TARGET/debootstrap/suite" + [ "" = "$VARIANT" ] || + echo "$VARIANT" >"$TARGET/debootstrap/variant" + echo "$required" >"$TARGET/debootstrap/required" + echo "$base" >"$TARGET/debootstrap/base" + + chmod 755 "$TARGET/debootstrap/debootstrap" + fi +fi + +if am_doing_phase second_stage; then + if [ "$SECOND_STAGE_ONLY" = true ]; then + required="$(cat $DEBOOTSTRAP_DIR/required)" + base="$(cat $DEBOOTSTRAP_DIR/base)" + all_debs="$required $base" + fi + + # second stage uses the chroot to clean itself up -- has to be able to + # work from entirely within the chroot (in case we've booted into it, + # possibly over NFS eg) + + second_stage_install + + # create sources.list + # first, kill debootstrap.invalid sources.list + if [ -e "$TARGET/etc/apt/sources.list" ]; then + rm -f "$TARGET/etc/apt/sources.list" + fi + if [ "${MIRRORS#http://}" != "$MIRRORS" ]; then + setup_apt_sources "${MIRRORS%% *}" + mv_invalid_to "${MIRRORS%% *}" + else + setup_apt_sources "$DEF_MIRROR" + mv_invalid_to "$DEF_MIRROR" + fi + + if [ -e "$TARGET/debootstrap/debootstrap.log" ]; then + if [ "$KEEP_DEBOOTSTRAP_DIR" = true ]; then + cp "$TARGET/debootstrap/debootstrap.log" "$TARGET/var/log/bootstrap.log" + else + # debootstrap.log is still open as stdout/stderr and needs + # to remain so, but after unlinking it some NFS servers + # implement this by a temporary file in the same directory, + # which makes it impossible to rmdir that directory. + # Moving it instead works around the problem. + mv "$TARGET/debootstrap/debootstrap.log" "$TARGET/var/log/bootstrap.log" + fi + fi + sync + + if [ "$KEEP_DEBOOTSTRAP_DIR" = true ]; then + if [ -x "$TARGET/debootstrap/debootstrap" ]; then + chmod 644 "$TARGET/debootstrap/debootstrap" + fi + else + rm -rf "$TARGET/debootstrap" + fi +fi + +if am_doing_phase kill_target; then + if [ "$KEEP_DEBOOTSTRAP_DIR" != true ]; then + info KILLTARGET "Deleting target directory" + rm -rf "$TARGET" + fi +fi + +if [ -n "$USE_BOOTFLOPPIES_INTERACTION" ] ; then + echo "I: debootstrap: Successfully completed" # goes to /dev/tty4 + sleep 1 || true # give the user a second to see the success notice. +fi |