diff options
Diffstat (limited to 'lib/install.sh')
-rw-r--r-- | lib/install.sh | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/lib/install.sh b/lib/install.sh new file mode 100644 index 0000000..b7ca485 --- /dev/null +++ b/lib/install.sh @@ -0,0 +1,274 @@ +# Functions for installing systems +# +# Copyright (C) 2013, 2014 Patrick "P. J." McDermott +# +# This file is part of the ProteanOS Development Kit. +# +# The ProteanOS Development Kit is free software: you can redistribute +# it and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# The ProteanOS Development Kit is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the ProteanOS Development Kit. If not, see +# <http://www.gnu.org/licenses/>. + +[ "x${_INSTALL_SM+set}" = 'xset' ] && return 0 +_INSTALL_SM=1 + +use profile +use dir +use fd +use pkg + +install_deps= +install_fnames= +install_md5sums= +install_sha256sums= +install_feed_url= + +install_system() +{ + local mirror="${1}" + local suite="${2}" + local arch="${3}" + local plat="${4}" + local chroot="${5}" + local foreign="${6}" + + if [ "x${arch}" = 'x' ]; then + arch="$(profile_detect_arch)" + fi + if [ "x${plat}" = 'x' ]; then + plat="$(profile_default_plat)" + fi + if [ "x${mirror}" = 'x' ]; then + mirror="$(profile_select_mirror)" + fi + + if ! profile_validate_archplat "${mirror}" "${arch}" "${plat}" \ + "${suite}"; then + error 2 "$(get_msg 'install_bad_archplat')" \ + "${arch}" "${plat}" + fi + + info "$(get_msg 'install_selected_arch')" "${arch}" + info "$(get_msg 'install_selected_plat')" "${plat}" + info "$(get_msg 'install_selected_mirror')" "${mirror}" + + info "$(get_msg 'install_setting_up_chroot')" + if [ -d "${chroot}" ] && ! dir_is_empty "${chroot}" 'lost+found'; then + error 2 "$(get_msg 'install_chroot_dir_exists')" "${chroot}" + fi + if ! mkdir -p "${chroot}/.prokit" "${chroot}/prokit"; then + error 2 "$(get_msg 'install_mkdir_chroot_fail')" "${chroot}" + fi + >"${chroot}/prokit/installing" + + info "$(get_msg 'install_find_pkgs')" + install_find_pkgs "${mirror}" "${suite}" "${arch}" "${plat}" \ + "${chroot}" + install_get_pkgs "${chroot}" + + info "$(get_msg 'install_configuring')" + if ! ${foreign}; then + profile_configure_system_native "${chroot}" "${arch}" "${plat}" + else + profile_configure_system_foreign "${chroot}" "${arch}" "${plat}" + fi + + rm "${chroot}/prokit/installing" +} + +install_find_pkgs() +{ + local mirror="${1}" + local suite="${2}" + local arch="${3}" + local plat="${4}" + local chroot="${5}" + local opkg_conf_fd= + local pkgs_fd= + local opt= + local feed_idx= + local feed= + local gzip= + local pkgs= + + mkdir -p "${chroot}/etc/opkg" "${chroot}/var/lib/opkg/lists" + fopen "${chroot}/etc/opkg/opkg.conf" 'w' + opkg_conf_fd=${FD} + + install_deps= + install_fnames= + install_md5sums= + install_sha256sums= + + fopen "${chroot}/.prokit/packages" 'w' + pkgs_fd=${FD} + + while read -r opt feed_idx feed; do + case "${opt}" in + 'src') gzip=false;; + 'src/gz') gzip=true;; + *) continue;; + esac + printf '%s %s %s\n' "${opt}" "${feed_idx}" \ + "${feed%/Packages*}" >&${opkg_conf_fd} + feed_download "${feed}" ${gzip} \ + >"${chroot}/var/lib/opkg/lists/${feed_idx}" + install_feed_url="${feed%/*}" + feed_find_pkgs "${chroot}/var/lib/opkg/lists/${feed_idx}" \ + "$(profile_dep_fields)" profile_include_pkg \ + install_deps_cb install_fname_cb \ + install_md5sum_cb install_sha256sum_cb \ + >&${pkgs_fd} + done <<-EOF + $(profile_feeds "${mirror}" "${arch}" "${plat}" "${suite}") + EOF + + printf '\ndest root /\n' >&${opkg_conf_fd} + printf 'arch %s 1\n' 'all' "${arch}" 'src' >&${opkg_conf_fd} + fclose ${opkg_conf_fd} + fclose ${pkgs_fd} + + pkgs="$(resolve_deps "$(cat "${chroot}/.prokit/packages")" \ + "${install_deps}" | xargs printf '%s\n' | sort -u)" + printf '%s\n' "${pkgs}" >"${chroot}/.prokit/packages" +} + +install_deps_cb() +{ + local pkg="${1}" + local deps="${2}" + + install_deps="${install_deps}${pkg}: ${deps}${LF}" +} + +install_fname_cb() +{ + local pkg="${1}" + local fname="${2}" + + install_fnames="$(printf '%s\n%s %s/%s' "${install_fnames}" \ + "${pkg}" "${install_feed_url}" "${fname}")" +} + +install_md5sum_cb() +{ + local pkg="${1}" + local md5sum="${2}" + + install_md5sums="$(printf '%s\n%s %s' "${install_md5sums}" \ + "${pkg}" "${md5sum}")" +} + +install_sha256sum_cb() +{ + local pkg="${1}" + local sha256sum="${2}" + + install_sha256sums="$(printf '%s\n%s %s' \ + "${install_sha256sums}" "${pkg}" "${sha256sum}")" +} + +install_get_pkgs() +{ + local chroot="${1}" + local status_fd= + local pkg= + local fname= + local md5sum= + local sha256sum= + local file= + local control= + local field= + local printed= + + mkdir -p "${chroot}/var/cache/opkg/archives" "${chroot}/tmp/opkg" \ + "${chroot}/var/lib/opkg/info" + + fopen "${chroot}/var/lib/opkg/status" 'w' + status_fd=${FD} + + for pkg in $(cat "${chroot}/.prokit/packages"); do + info "$(get_msg 'install_downloading_pkg')" "${pkg}" + fname="$(printf '%s\n' "${install_fnames}" | \ + sed -n "s/^${pkg} //p")" + md5sum="$(printf '%s\n' "${install_md5sums}" | \ + sed -n "s/^${pkg} //p")" + sha256sum="$(printf '%s\n' "${install_sha256sums}" | \ + sed -n "s/^${pkg} //p")" + wget -q -O "${chroot}/var/cache/opkg/archives/${fname##*/}" \ + "${fname}" || \ + error 2 "$(get_msg 'install_downloading_pkg_fail')" + fname="var/cache/opkg/archives/${fname##*/}" + if [ "x${md5sum}" != 'x' ]; then + printf '%s %s\n' \ + "${md5sum}" "${chroot}/${fname}" | \ + md5sum -c >/dev/null 2>&1 || \ + error 2 "$(get_msg 'install_checksum_fail')" + fi + if [ "x${sha256sum}" != 'x' ]; then + printf '%s %s\n' \ + "${sha256sum}" "${chroot}/${fname}" | \ + sha256sum -c >/dev/null 2>&1 || \ + error 2 "$(get_msg 'install_checksum_fail')" + fi + + info "$(get_msg 'install_unpacking_pkg')" "${pkg}" + mkdir "${chroot}/tmp/opkg/${pkg}" + ( + cd "${chroot}" + tar -xzOf "${fname}" data.tar.gz \ + >"tmp/opkg/${pkg}/data.tar.gz" + tar -xzf "tmp/opkg/${pkg}/data.tar.gz" + cd "tmp/opkg/${pkg}" + tar -xzOf "../../../${fname}" control.tar.gz | \ + tar -xz + ) + tar -tzf "${chroot}/tmp/opkg/${pkg}/data.tar.gz" | \ + sed 's/^\.//' >"${chroot}/var/lib/opkg/info/${pkg}.list" + rm -f "${chroot}/tmp/opkg/${pkg}/data.tar.gz" + for file in "${chroot}/tmp/opkg/${pkg}/"*; do + mv "${file}" \ + "${chroot}/var/lib/opkg/info/${pkg}.${file##*/}" + done + rmdir "${chroot}/tmp/opkg/${pkg}" + + # Write status file. + control="${chroot}/var/lib/opkg/info/${pkg}.control" + for field in Package Version Depends Recommends Suggests \ + Provides Replaces Conflicts; do + grep "^${field}: " "${control}" >&${status_fd} + done + printf 'Status: install ok unpacked\n' >&${status_fd} + for field in Essential Architecture; do + grep "^${field}: " "${control}" >&${status_fd} + done + if [ -r "${chroot}/var/lib/opkg/info/${pkg}.conffiles" ]; then + printed=false + while read -r file; do + ${printed} || printf 'Conffiles:\n' \ + >&${status_fd} + printf ' %s %s\n' "${file}" "$(md5sum \ + "${chroot}/${file}" | cut -d' ' -f1)" \ + >&${status_fd} + printed=true + done <"${chroot}/var/lib/opkg/info/${pkg}.conffiles" + fi + printf 'Installed-Time: %s\n\n' "$(date '+%s')" >&${status_fd} + + rm -f "${chroot}/${fname}" + done + + rm "${chroot}/.prokit/packages" + rmdir "${chroot}/.prokit" + + fclose ${status_fd} +} |