diff options
Diffstat (limited to 'inst')
-rwxr-xr-x | inst | 465 |
1 files changed, 465 insertions, 0 deletions
@@ -0,0 +1,465 @@ +#!/bin/sh + +set -u + +host= +dev= +target= + +err() +{ + local fmt="${1}" + shift 1 + + printf "Error: ${fmt}\n" "${@}" 1>&3 +} + +info() +{ + local fmt="${1}" + shift 1 + + printf "${fmt}\n" "${@}" 1>&3 +} + +in_target() +{ + chroot "${target}" "${@}" || return 1 + + return 0 +} + +do_() +{ + step="${1}" + shift 1 + + do_${step} 1>&4 2>&4 +} + +do_fdisk() +{ + local script= + local line= + + info 'Making partition table' + + script= + while read line; do + script="$(printf '%s\n' "${script}" "${line}")" + done <<-EOF + ${part_script} + EOF + printf '%s\n' "${script}" | sfdisk "${dev}" + + return 0 +} + +do_mkfs() +{ + local fs= + local mp= + local type= + local options= + local dump= + local pass= + + info 'Making file systems' + + while read fs mp type options dump pass; do + case "${type}" in ''|'swap') continue;; esac + case "${fs}" in + '@DEV'*'@') + fs="${fs%@}" + fs="${fs#@DEV}" + fs="${dev}${fs}" + ;; + *) + continue + ;; + esac + mkfs -t "${type}" "${fs}" || return 1 + done <<-EOF + ${fstab} + EOF + + return 0 +} + +do_mount() +{ + local fs= + local mp= + local type= + local options= + local dump= + local pass= + + info 'Mounting file systems' + + target="$(mktemp -d)" + + while read fs mp type options dump pass; do + case "${type}" in ''|'swap') continue;; esac + case "${fs}" in + '@DEV'*'@') + fs="${fs%@}" + fs="${fs#@DEV}" + fs="${dev}${fs}" + ;; + *) + continue + ;; + esac + mkdir -p "${target}${mp}" || return 1 + mount -t "${type}" ${options:+-o "${options}"} \ + "${fs}" "${target}${mp}" || return 1 + done <<-EOF + ${fstab} + EOF + + return 0 +} + +do_check_target() +{ + if [ -e "${target}/bin/sh" ]; then + err 'Unclean target' + return 1 + fi + + return 0 +} + +do_debootstrap() +{ + local include= + + info 'Installing base system' + + case "${extra_pkgs}" in ?*) + include="--include=$(printf '%s,' ${extra_pkgs})" + include="${include%,}" + ;; esac + + debootstrap --arch="${arch}" "${include}" \ + "${suite}" "${target}" "${mirror}" || return 1 + + return 0 +} + +do_chroot_setup() +{ + info 'Setting up system' + + case "$(uname -s)" in + 'Linux') + mount -t proc proc "${target}/proc" || return 1 + mount -t sysfs sysfs "${target}/sys" || return 1 + mount --bind /dev "${target}/dev" || return 1 + mkdir -p "${target}/dev/pts" || return 1 + mount -t devpts -o noexec,nosuid,gid=5,mode=620 \ + devpts "${target}/dev/pts" || return 1 + mount --bind /run "${target}/run" || return 1 + ;; + esac + + cat >"${target}/usr/sbin/policy-rc.d" <<-EOF + #!/bin/sh + exit 101 + EOF + chmod a+rx "${target}/usr/sbin/policy-rc.d" || return 1 + + if [ -e "${target}/sbin/start-stop-daemon" ]; then + in_target dpkg-divert --quiet --add \ + --divert '/sbin/start-stop-daemon.REAL' \ + --rename '/sbin/start-stop-daemon' || return 1 + fi + cat >"${target}/sbin/start-stop-daemon" <<-EOF + #!/bin/sh + exit 0 + EOF + chmod a+rx "${target}/sbin/start-stop-daemon" || return 1 + + for file in /etc/network/interfaces /etc/networks /etc/hostname \ + /etc/resolv.conf /etc/hosts; do + if ! [ -f "${file}" ]; then + continue + fi + if [ -f "${target}${file}" ]; then + mv "${target}${file}" "${target}${file}.REAL" + fi + mkdir -p "${target}${file%/*}" + cp "${file}" "${target}${file}" + done + + export LANG="${locale}" + export PERL_BADLANG=0 + export DEBCONF_ADMIN_EMAIL='' + export IT_LANG_OVERRIDE='C' + export APT_LISTCHANGES_FRONTEND='none' + export SUDO_FORCE_REMOVE='yes' + + return 0 +} + +do_fstab_setup() +{ + local fs= + local mp= + local type= + local options= + local dump= + local pass= + + info 'Making file system table' + + case "$(uname -s)" in + 'Linux') + printf '%-15s %-15s %-7s %-15s %-7s %s\n' \ + 'proc' '/proc' 'proc' 'defaults' '0' '0' \ + >"${target}/etc/fstab" + ;; + esac + while read fs mp type options dump pass; do + case "${fs}" in '@DEV'*'@') + fs="${fs%@}" + fs="${fs#@DEV}" + fs="${dev}${fs}" + fs="UUID=$(blkid -o value -s UUID "${fs}")" + ;; esac + printf '%-15s %-15s %-7s %-15s %-7s %s\n' \ + "${fs}" "${mp}" "${type}" "${options}" \ + "${dump}" "${pass}" >>"${target}/etc/fstab" + done <<-EOF + ${fstab} + EOF +} + +do_apt_update() +{ + info 'Downloading package lists' + + in_target apt-get update || return 1 + + return 0 +} + +do_locale_setup() +{ + local l= + local gen= + + info 'Setting locale' + + if ! [ "x${locale}" = 'xC' ] || ! [ "x${supported_locales}" = 'x' ] + then + in_target apt-get -q -y install locales + + gen=false + for l in $(printf '%s\n' "${locale}" ${supported_locales} | \ + sort -u); do + if ! LANG=C in_target validlocale "${l}" \ + >>"${target}/etc/locale.gen" 2>/dev/null + then + gen=true + fi + done + if ${gen}; then + in_target locale-gen --keep-existing >/dev/null || \ + return 1 + fi + fi + + printf 'LANG=%s\n' "${locale}" >"${target}/etc/default/locale" +} + +do_tz_setup() +{ + info 'Setting time zone' + + if [ "x${time_zone}" = 'x' ] || ! [ -e \ + "${target}/usr/share/zoneinfo/${time_zone}" ]; then + err '%s: Invalid time zone' "${time_zone}" + return 1 + fi + + printf '%s\n' "${time_zone}" >"${target}/etc/timezone" + cp -f "${target}/usr/share/zoneinfo/${time_zone}" \ + "${target}/etc/localtime" +} + +do_user_setup() +{ + local group= + local f= + + info 'Setting users and passwords' + + in_target shadowconfig "${passwd_shadow}" || return 1 + + case "${root_passwd_crypted}" in ?*) + in_target usermod --password="${root_passwd_crypted}" 'root' \ + || return 1 + ;; esac + + if ${user_make}; then + in_target adduser --disabled-password \ + --gecos "${user_full_name}" \ + "${user_name}" || return 1 + in_target usermod --password="${user_passwd_crypted}" \ + "${user_name}" || return 1 + in_target chown "${user_name}:${user_name}" \ + "/home/${user_name}" || return 1 + if ! ${root_login}; then + in_target apt-get -q -y install sudo || return 1 + case " ${user_groups} " in + *' sudo '*);; + *) + user_groups="${user_groups} sudo" + ;; + esac + if in_target update-alternatives \ + --display libgksu-gconf-defaults \ + 1>/dev/null 2>&1; then + f='/usr/share/libgksu/debian' + f="${f}/gconf-defaults.libgksu-sudo" + in_target update-alternatives \ + --set libgksu-gconf-defaults "${f}" || \ + return 1 + in_target update-gconf-defaults + fi + printf 'Aptitude::Get-Root-Command "%s";' \ + 'sudo:/usr/bin/sudo' \ + >"${target}/etc/apt/apt.conf.d/00aptitude" + fi + for group in ${user_groups}; do + in_target adduser "${user_name}" "${group}" || return 1 + done + fi +} + +do_install_extra() +{ + info 'Installing extra packages' + + in_target apt-get -q -y install ${postinst_pkgs} || return 1 + + return 0 +} + +do_chroot_cleanup() +{ + local mp= + + info 'Cleaning up system' + + for file in /etc/network/interfaces /etc/networks /etc/hostname \ + /etc/resolv.conf /etc/hosts; do + if [ -f "${target}${file}.REAL" ]; then + mv "${target}${file}.REAL" "${target}${file}" + fi + done + + rm -f "${target}/usr/sbin/policy-rc.d" + rm -f "${target}/sbin/start-stop-daemon" + in_target dpkg-divert --quiet --remove \ + --rename '/sbin/start-stop-daemon' || return 1 + + case "$(uname -s)" in + 'Linux') + for mp in 'run' 'dev/pts' 'dev' 'sys' 'proc'; do + while ! umount "${target}/${mp}"; do + sleep 1 + done + done + ;; + esac + + return 0 +} + +do_umount() +{ + local fs= + local mp= + local type= + local options= + local dump= + local pass= + + info 'Unmounting file systems' + + while read fs mp type options dump pass; do + case "${type}" in ''|'swap') continue;; esac + case "${fs}" in + '@DEV'*'@') + ;; + *) + continue + ;; + esac + while ! umount "${target}${mp}"; do + sleep 1 + done + rmdir "${target}${mp}" + done <<-EOF + ${fstab} + EOF + + return 0 +} + +usage() +{ + printf 'Usage: %s host device\n' "${0}" +} + +main() +{ + local host_file= + local log= + + exec 3>&1 + + if [ ${#} -ne 2 ]; then + usage >&2 + return 1 + fi + host="${1}" + host_file="$(dirname "${0}")/hosts/${host}" + if ! [ -r "${host_file}" ]; then + err '%s: Unknown host' "${host}" + return 1 + fi + dev="${2}" + + . "${host_file}" + + log="$(mktemp)" + exec 4>"${log}" + do_ fdisk || return 1 + do_ mkfs || return 1 + do_ mount || return 1 + do_ check_target || { do_ umount; return 1; } + do_ debootstrap || { do_ umount; return 1; } + do_ chroot_setup || { do_ umount; return 1; } + do_ fstab_setup || { do_ chroot_cleanup; do_ umount; return 1; } + do_ apt_update || { do_ chroot_cleanup; do_ umount; return 1; } + do_ locale_setup || { do_ chroot_cleanup; do_ umount; return 1; } + do_ tz_setup || { do_ chroot_cleanup; do_ umount; return 1; } + do_ user_setup || { do_ chroot_cleanup; do_ umount; return 1; } + do_ install_extra || { do_ chroot_cleanup; do_ umount; return 1; } + postinst || { do_ chroot_cleanup; do_ umount; return 1; } + do_ chroot_cleanup || { do_ umount; return 1; } + exec 4>&- + mkdir -p "${target}/var/log/installer" + mv "${log}" "${target}/var/log/installer/log" + do_umount || return 1 + + exec 3>&- + + return 0 +} + +main "${@}" |