Merge remote-tracking branch 'remotes/origin/pr/97'
[grml-debootstrap.git] / chroot-script
index 3a8dca9..7d8c6d2 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 # Filename:      /etc/debootstrap/chroot-script
 # Purpose:       script executed in chroot when installing Debian via grml-debootstrap
 # Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
@@ -9,10 +9,19 @@
 # this script as /bin/chroot-script on your new installed system
 ################################################################################
 
+# error_handler {{{
+if [ "$REPORT_TRAP_ERR" = "yes" ] || [ "$FAIL_TRAP_ERR" = "yes" ]; then
+   set -E
+   set -o pipefail
+   trap "error_handler" ERR
+fi
+# }}}
+
 . /etc/debootstrap/config    || exit 1
 . /etc/debootstrap/variables || exit 1
 
 [ -r /proc/1 ] || mount -t proc none /proc
+[ -r /sys/kernel ] || mount -t sysfs none /sys
 
 # variable checks {{{
 
@@ -28,9 +37,9 @@ if [ -x /usr/bin/aptitude ] ; then
       APTUPGRADE="aptitude -y safe-upgrade $DPKG_OPTIONS"
    fi
 else
-   APTINSTALL="apt-get --force-yes -y --no-install-recommends install $DPKG_OPTIONS"
+   APTINSTALL="apt-get -y --no-install-recommends install $DPKG_OPTIONS"
    APTUPDATE="apt-get update $DPKG_OPTIONS"
-   APTUPGRADE="apt-get --force-yes -y upgrade $DPKG_OPTIONS"
+   APTUPGRADE="apt-get -y upgrade $DPKG_OPTIONS"
 fi
 
 if [ -z "$STAGES" ] ; then
@@ -44,7 +53,7 @@ stage() {
   if [ -n "$2" ] ; then
      echo "$2" > "$STAGES/$1"
      return 0
-  elif grep -q done "$STAGES/$1" 2>/dev/null ; then
+  elif grep -q 'done' "$STAGES/$1" 2>/dev/null ; then
      echo "   [*] Notice: stage $1 has been executed already, skipping execution therefore.">&2
      return 1
   fi
@@ -70,15 +79,18 @@ chrootmirror() {
   fi
 
   if [ -z "$COMPONENTS" ] ; then
-    COMPONENTS='main contrib non-free'
+    COMPONENTS='main'
   fi
   echo "Using repository components $COMPONENTS"
 
   if [ -n "$ISO" ] ; then
     echo "Adjusting sources.list for ISO (${ISO})."
     echo "deb $ISO $RELEASE $COMPONENTS" > /etc/apt/sources.list
-    echo "Adding mirror entry (${MIRROR}) to sources.list."
-    [ -n "$MIRROR" ] && echo "deb $MIRROR $RELEASE $COMPONENTS" >> /etc/apt/sources.list || true
+
+    if [ -n "$MIRROR" ] ; then
+      echo "Adding mirror entry (${MIRROR}) to sources.list."
+      echo "deb $MIRROR $RELEASE $COMPONENTS" >> /etc/apt/sources.list
+    fi
   else
     if [ -n "$MIRROR" ] ; then
       echo "Adjusting sources.list for mirror (${MIRROR})."
@@ -86,6 +98,16 @@ chrootmirror() {
     fi
   fi
 
+  # LTS support
+  case "$RELEASE" in
+    squeeze)
+      if [ -n "$MIRROR" ] ; then
+        echo "Release matching $RELEASE - enabling LTS support in sources.list"
+        echo "deb $MIRROR ${RELEASE}-lts $COMPONENTS" >> /etc/apt/sources.list
+      fi
+      ;;
+  esac
+
   # add security.debian.org:
   case "$RELEASE" in
     unstable|sid|lenny) ;;  # no security pool available
@@ -109,7 +131,7 @@ remove_chrootmirror() {
     TMP_ISO=$(echo "$ISO" |sed 's#/#\\/#g')
     sed -i "/deb $TMP_ISO $RELEASE $COMPONENTS/ D" /etc/apt/sources.list
   else
-    if [ -n "$MIRROR" -a -n "$(echo $MIRROR|grep file:)" ] ; then
+    if [ -n "$MIRROR" ] && echo "$MIRROR" | grep -q 'file:' ; then
       echo "Removing local mirror (${MIRROR}) from sources.list."
       TMP_MIRROR=$(echo "$MIRROR" |sed 's#/#\\/#g')
       sed -i "/deb $TMP_MIRROR $RELEASE $COMPONENTS/ D" /etc/apt/sources.list
@@ -141,8 +163,8 @@ EOF
        apt-get update $DPKG_OPTIONS
      else
        # make sure we have the keys available for aptitude
-       gpg --keyserver subkeys.pgp.net --recv-keys F61E2E7CECDEA787
-       gpg --export F61E2E7CECDEA787 | apt-key add - || true # not yet sure
+       gpg --keyserver subkeys.pgp.net --recv-keys 709BCE51568573EBC160E590F61E2E7CECDEA787
+       gpg --export 709BCE51568573EBC160E590F61E2E7CECDEA787 | apt-key add - || true # not yet sure
        # why it's necessary, sometimes we get an error even though it works [mika]
      fi
 
@@ -167,14 +189,14 @@ EOF
 
 # check available backports release version {{{
 checkbackports() {
-  wget -q -O/dev/null http://backports.debian.org/debian-backports/dists/${1}-backports/Release
+  wget -q -O/dev/null "http://backports.debian.org/debian-backports/dists/${1}-backports/Release"
 }
 # }}}
 
 # feature to provide Debian backports repos {{{
 backportrepos() {
     if [ -n "$BACKPORTREPOS" ] ; then
-        if ! checkbackports $RELEASE ; then
+        if ! checkbackports "$RELEASE" ; then
             echo "Backports for ${RELEASE} are not available." >&2
             exit 1
         else
@@ -247,7 +269,7 @@ packages() {
   # as seen to prevent debconf from asking the question interactively.
   [ -f /etc/debootstrap/debconf-selections ] && {
     echo "Preseeding the debconf database, some lines might be skipped..."
-    cat /etc/debootstrap/debconf-selections | debconf-set-selections
+    debconf-set-selections < /etc/debootstrap/debconf-selections
   }
 
   if [ "$PACKAGES" = 'yes' ] ; then
@@ -291,9 +313,19 @@ get_kernel_version() {
     return 0
   fi
 
-  case $ARCH in
-    i386)   KARCH=686   ;;
-    amd64)  KARCH=amd64 ;;
+  local KARCH
+
+  case "$ARCH" in
+    i386)
+      case "$RELEASE" in
+        lenny|squeeze|wheezy) KARCH='686' ;;
+        # since jessie the linux-image-686 image doesn't exist any longer
+        *) KARCH='686-pae' ;;
+      esac
+      ;;
+    amd64)
+      KARCH='amd64'
+      ;;
     *)
       echo "Only i386 and amd64 are currently supported" >&2
       return 1
@@ -320,7 +352,11 @@ kernel() {
   KVER=$(get_kernel_version)
   if [ -n "$KVER" ] ; then
      # note: install busybox to be able to debug initramfs
-     KERNELPACKAGES="linux-image-$KVER linux-headers-$KVER busybox firmware-linux-free firmware-linux"
+     KERNELPACKAGES="linux-image-$KVER linux-headers-$KVER busybox firmware-linux-free"
+     # only add firmware-linux if we have non-free as a component
+     if expr "$COMPONENTS" : '.*non-free' >/dev/null ; then
+       KERNELPACKAGES="$KERNELPACKAGES firmware-linux"
+     fi
      DEBIAN_FRONTEND=$DEBIAN_FRONTEND $APTINSTALL $KERNELPACKAGES
   else
      echo "Warning: Could not find a kernel for your system. Your system won't be able to boot itself!"
@@ -365,12 +401,12 @@ passwords()
     b='2'
      echo "Setting password for user root:"
      while [ "$a" != "$b" ] ; do
-       echo -n "Enter new UNIX password for user root: "
+       printf "Enter new UNIX password for user root: "
        askpass
        a="$resp"
        unset resp
        echo
-       echo -n "Retype new UNIX password for user root: "
+       printf "Retype new UNIX password for user root: "
        askpass
        b="$resp"
        unset resp
@@ -391,24 +427,12 @@ passwords()
 
 # set up /etc/hosts {{{
 hosts() {
-  if [ -f /etc/hosts ] ; then
-     sed -i "s#127.0.0.1 .*#127.0.0.1       localhost  $HOSTNAME#" /etc/hosts
-     [ -n "$HOSTNAME" ] && sed -i "s/grml/$HOSTNAME/g" /etc/hosts
-  else
+  if ! [ -f /etc/hosts ] ; then
      cat > /etc/hosts << EOF
-127.0.0.1       localhost $HOSTNAME
-
-#127.0.0.1       localhost
-#127.0.1.1       $HOSTNAME.example.org $HOSTNAME
-
-# The following lines are desirable for IPv6 capable hosts
-#::1     ip6-localhost ip6-loopback $HOSTNAME
-::1     ip6-localhost ip6-loopback
-fe00::0 ip6-localnet
-ff00::0 ip6-mcastprefix
-ff02::1 ip6-allnodes
-ff02::2 ip6-allrouters
-ff02::3 ip6-allhosts
+127.0.0.1       localhost
+::1             localhost ip6-localhost ip6-loopback
+ff02::1         ip6-allnodes
+ff02::2         ip6-allrouters
 EOF
   fi
 }
@@ -432,18 +456,22 @@ default_locales() {
 timezone() {
   if [ -n "$TIMEZONE" ] ; then
      echo "Adjusting /etc/localtime"
-     ln -sf /usr/share/zoneinfo/$TIMEZONE /etc/localtime
+     ln -sf "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime
   fi
 }
 # }}}
 
 # helper function for fstab() {{{
 createfstab(){
-     echo "Setting up /etc/fstab"
-if [ -n "$TARGET_UUID" ] ; then
-   echo "/dev/disk/by-uuid/${TARGET_UUID} /  auto    defaults,errors=remount-ro 0   1" > /etc/fstab
-else
-   echo "${TARGET} /  auto    defaults,errors=remount-ro 0   1" > /etc/fstab
+  echo "Setting up /etc/fstab"
+  if [ -n "$TARGET_UUID" ] ; then
+    echo "/dev/disk/by-uuid/${TARGET_UUID} /  auto    defaults,errors=remount-ro 0   1" > /etc/fstab
+  else
+    echo "Warning: couldn't identify target UUID for rootfs, your /etc/fstab might be incomplete."
+  fi
+
+if [ -n "$EFI" ] ; then
+  echo "UUID=$(blkid -o value -s UUID $EFI)  /boot/efi       vfat    umask=0077      0       1" >> /etc/fstab
 fi
 
 cat >> /etc/fstab << EOF
@@ -489,6 +517,20 @@ hostname() {
         sed -i "s/^inet_interfaces = .*/inet_interfaces = loopback-only/" /etc/postfix/main.cf
         grep -q inet_interfaces /etc/postfix/main.cf || echo 'inet_interfaces = loopback-only' >> /etc/postfix/main.cf
      fi
+     if [ -r /etc/mailname ] ; then
+        # adjust /etc/mailname
+        local etc_mail_domain=$(/bin/dnsdomainname 2>/dev/null || echo localdomain)
+        case "$HOSTNAME" in
+          *.*)
+            local mailname="$HOSTNAME"
+            ;;
+          *)
+            local mailname="${HOSTNAME}.${etc_mail_domain}"
+            ;;
+        esac
+        echo "Setting mailname to ${mailname}"
+        echo "$mailname" > /etc/mailname
+     fi
   fi
 }
 # }}}
@@ -507,11 +549,29 @@ initrd() {
   # generate initrd
   if [ -n "$INITRD" ] ; then
      echo "Generating initrd."
-     update-initramfs -c -t -k $KERNELVER
+     update-initramfs -c -t -k "$KERNELVER"
   fi
 }
 # }}}
 
+efi_setup() {
+  if [ -z "$EFI" ] ; then
+    return 0
+  fi
+
+  if ! dpkg --list efibootmgr 2>/dev/null | grep -q '^ii' ; then
+    echo "Notice: efi option set but no efibootmgr package, installing it therefore."
+    DEBIAN_FRONTEND=$DEBIAN_FRONTEND $APTINSTALL efibootmgr
+  fi
+
+  mkdir -p /boot/efi
+  echo "Mounting $EFI on /boot/efi"
+  mount "$EFI" /boot/efi || return 1
+
+  echo "Invoking efibootmgr"
+  efibootmgr || return 1
+}
+
 # grub configuration/installation {{{
 grub_install() {
 
@@ -520,9 +580,22 @@ grub_install() {
     return 0
   fi
 
-  if ! dpkg --list grub-pc 2>/dev/null | grep -q '^ii' ; then
-    echo "Notice: grub option set but no grub-pc package, installing it therefore."
-    DEBIAN_FRONTEND=$DEBIAN_FRONTEND $APTINSTALL grub-pc
+  efi_setup || return 1
+
+  if [ -n "$EFI" ] ; then
+    GRUB_PACKAGE=grub-efi-amd64
+  else
+    GRUB_PACKAGE=grub-pc
+  fi
+
+  # make sure this is pre-defined so we have sane settings for automated
+  # upgrades, see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=711019
+  echo "Setting ${GRUB_PACKAGE} debconf configuration for install device to $GRUB"
+  echo "${GRUB_PACKAGE} ${GRUB_PACKAGE}/install_devices multiselect $GRUB" | debconf-set-selections
+
+  if ! dpkg --list ${GRUB_PACKAGE} 2>/dev/null | grep -q '^ii' ; then
+    echo "Notice: grub option set but no ${GRUB_PACKAGE} package, installing it therefore."
+    DEBIAN_FRONTEND=$DEBIAN_FRONTEND $APTINSTALL ${GRUB_PACKAGE}
   fi
 
   if ! [ -x "$(which grub-install)" ] ; then
@@ -536,9 +609,20 @@ grub_install() {
         echo "Installing grub on ${GRUB}:"
         grub-install --no-floppy "$GRUB"
      done
+     rm -f /boot/grub/device.map
   else
      echo "Installing grub on ${GRUB}:"
-     grub-install --no-floppy "$GRUB"
+     case "$RELEASE" in
+       lenny|squeeze|wheezy)
+         grub-install --no-floppy "$(readlink -f "${GRUB}")"
+         rm -f /boot/grub/device.map
+         ;;
+       *)
+         echo "(hd0) ${GRUB}" > /boot/grub/device.map
+         grub-install "(hd0)"
+         rm /boot/grub/device.map
+         ;;
+     esac
   fi
 
   echo "Adjusting grub configuration for use on ${GRUB}."
@@ -553,6 +637,8 @@ grub_install() {
     return 1
   fi
 
+  mountpoint /boot/efi >/dev/null && umount /boot/efi
+
   $UPDATEGRUB
 }
 # }}}
@@ -585,6 +671,7 @@ finalize() {
 
   [ -n "$POLICYRCD" ] && rm -f /usr/sbin/policy-rc.d
 
+  umount /sys >/dev/null 2>/dev/null || true
   umount /proc >/dev/null 2>/dev/null || true
 }
 # }}}
@@ -612,7 +699,7 @@ trap signal_handler HUP INT QUIT TERM
      custom_scripts upgrade_system remove_apt_cache services \
      remove_chrootmirror; do
      if stage $i ; then
-       $i && stage $i done || exit 1
+       $i && stage $i 'done' || exit 1
      fi
   done
   # always execute the finalize stage: