# Functions for installing systems # # Copyright (C) 2013-2015 Patrick 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 # . _install_deps= _install_urls= _install_md5sums= _install_sha256sums= _install_feed_url= _usign_fingerprint() { local key_data="${1}" shift 1 local usign= if ${in_place} && ${USIGN_EMBEDDED}; then usign="${builddir}/3rdparty/usign/usign" else usign="${USIGN}" fi IFS="${LF}" if printf '%s\n' ${key_data} | "${usign}" -F -p -; then unset IFS return 0 else unset IFS return 1 fi } _install_deps_cb() { local pkg="${1}" local deps="${2}" shift 2 _install_deps="${_install_deps}${pkg}: ${deps}${LF}" return 0 } _install_fname_cb() { local pkg="${1}" local fname="${2}" shift 2 _install_urls="$(printf '%s\n%s %s/%s' "${_install_urls}" \ "${pkg}" "${_install_feed_url}" "${fname}")" return 0 } _install_md5sum_cb() { local pkg="${1}" local md5sum="${2}" shift 2 _install_md5sums="$(printf '%s\n%s %s' "${_install_md5sums}" \ "${pkg}" "${md5sum}")" return 0 } _install_sha256sum_cb() { local pkg="${1}" local sha256sum="${2}" shift 2 _install_sha256sums="$(printf '%s\n%s %s' \ "${_install_sha256sums}" "${pkg}" "${sha256sum}")" return 0 } _install_find_pkgs() { local arch="${1}" local plat="${2}" local root="${3}" shift 3 local opkg_conf_fd= local pkgs_fd= local type= local name= local base_url= local gzip= local cert_url= local root_key= local cert_fd= local dl_func= local pkgs= mkdir -p -- "${root}/etc/opkg" "${root}/$(profile_opkg_state_dir)/lists" if ! fopen "${root}/$(profile_opkg_conf_file)" 'w'; then return 1 fi opkg_conf_fd=${FD} _install_deps= _install_urls= _install_md5sums= _install_sha256sums= if ! fopen "${root}/.prokit/packages" 'w'; then return 1 fi pkgs_fd=${FD} if cert_url="$(profile_get_cert_url)"; then # This is a hack to generate a fake certificate with some valid # (but incorrect) key and the mirror-specific certificate URL to # make opkg-cert download and verify the actual certificate. mkdir -p -- "${root}/etc/opkg/keys/" "${root}/var/cache/opkg/" root_key="$(profile_get_root_key)" printf '%s\n' "${root_key}" \ >"${root}/etc/opkg/keys/$(_usign_fingerprint \ "${root_key}").root" if ! fopen "${root}/etc/opkg/keys/temp.cert" 'w'; then return 1 fi cert_fd=${FD} printf '%s\n---\n' "${cert_url}" >&${cert_fd} IFS="${LF}" printf 'K: %s\n' ${root_key} >&${cert_fd} unset IFS printf '%s' '---' >&${cert_fd} fclose ${cert_fd} printf 'option check_signature 1\n\n' >&${opkg_conf_fd} dl_func=feed_download_cert else dl_func=feed_download fi while read -r type name base_url; do case "${type}" in 'src') gzip=false;; 'src/gz') gzip=true;; *) continue;; esac printf '%s %s %s\n' "${type}" "${name}" \ "${base_url}" >&${opkg_conf_fd} if ! ${dl_func} "${base_url}" \ "${root}/$(profile_opkg_state_dir)/lists/${name}" \ ${gzip} "${root}"; then return 1 fi _install_feed_url="${base_url}" feed_find_pkgs \ "${root}/$(profile_opkg_state_dir)/lists/${name}" \ "$(profile_dep_fields)" profile_include_pkg \ _install_deps_cb _install_fname_cb \ _install_md5sum_cb _install_sha256sum_cb \ >&${pkgs_fd} done <<-EOF $(profile_feeds "${arch}" "${plat}") 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 -- "${root}/.prokit/packages")" \ "${_install_deps}" | xargs printf '%s\n' | sort -u)" printf '%s\n' "${pkgs}" >"${root}/.prokit/packages" return 0 } _install_get_pkgs() { local root="${1}" shift 1 local status_fd= local errors= local pkg= local url= local md5sum= local sha256sum= local fname= local file= local control= local field= local printed= mkdir -p -- "${root}/var/cache/opkg/archives" "${root}/tmp/opkg" \ "${root}/$(profile_opkg_state_dir)/info" if ! fopen "${root}/$(profile_opkg_state_dir)/status" 'w'; then return 1 fi status_fd=${FD} errors=false for pkg in $(cat -- "${root}/.prokit/packages"); do info "$(get_msg 'install_downloading_pkg')" "${pkg}" url="$(printf '%s\n' "${_install_urls}" | \ sed -n "s/^${pkg} //p")" # FIXME: Remove the next four lines after ProteanOS's gcc-8-dev # is fixed to not try to install non-existent liblsan.0 and # libtsan.0 packages on i686-linux-glibc. if [ x"${url}" = x'' ]; then error "$(get_msg 'install_downloading_pkg_fail')" continue fi md5sum="$(printf '%s\n' "${_install_md5sums}" | \ sed -n "s/^${pkg} //p")" sha256sum="$(printf '%s\n' "${_install_sha256sums}" | \ sed -n "s/^${pkg} //p")" fname="var/cache/opkg/archives/${url##*/}" if ! ${WGET} -q -O "${root}/${fname}" -- "${url}"; then error "$(get_msg 'install_downloading_pkg_fail')" errors=true continue fi if [ "x${md5sum}" != 'x' ]; then if ! printf '%s %s\n' \ "${md5sum}" "${root}/${fname}" | \ ${MD5SUM} -c >/dev/null 2>&1; then error "$(get_msg 'install_checksum_fail')" errors=true continue fi fi if [ "x${sha256sum}" != 'x' ]; then if ! printf '%s %s\n' \ "${sha256sum}" "${root}/${fname}" | \ ${SHA256SUM} -c >/dev/null 2>&1; then error "$(get_msg 'install_checksum_fail')" errors=true continue fi fi info "$(get_msg 'install_unpacking_pkg')" "${pkg}" mkdir -- "${root}/tmp/opkg/${pkg}" ( cd -- "${root}" 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 "${root}/tmp/opkg/${pkg}/data.tar.gz" | \ sed 's/^\.//' \ >"${root}/$(profile_opkg_state_dir)/info/${pkg}.list" rm -f -- "${root}/tmp/opkg/${pkg}/data.tar.gz" for file in "${root}/tmp/opkg/${pkg}/"*; do mv -- "${file}" \ "${root}/$(profile_opkg_state_dir \ )/info/${pkg}.${file##*/}" done rmdir -- "${root}/tmp/opkg/${pkg}" # Write status file. control="${root}/$(profile_opkg_state_dir)/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 "${root}/$(profile_opkg_state_dir \ )/info/${pkg}.conffiles" ]; then printed=false while read -r file; do ${printed} || printf 'Conffiles:\n' \ >&${status_fd} printf ' %s %s\n' "${file}" "$(md5sum \ "${root}/${file}" | cut -d' ' -f1)" \ >&${status_fd} printed=true done <"${root}/$(profile_opkg_state_dir \ )/info/${pkg}.conffiles" fi printf 'Installed-Time: %d\n\n' $(unixtime) >&${status_fd} rm -f -- "${root}/${fname}" done rm -f -- "${root}/.prokit/packages" rmdir -- "${root}/.prokit" fclose ${status_fd} if ! ${errors}; then return 0 else return 1 fi } install_system() { local arch="${1}" local plat="${2}" local root="${3}" local foreign="${4}" shift 4 info "$(get_msg 'install_setting_up_chroot')" if [ -d "${root}" ] && ! dir_is_empty "${root}" 'lost+found'; then error "$(get_msg 'install_chroot_dir_exists')" "${root}" return 1 fi if ! mkdir -p -- "${root}/.prokit" "${root}/prokit"; then error "$(get_msg 'install_mkdir_chroot_fail')" "${root}" return 1 fi >"${root}/prokit/installing" info "$(get_msg 'install_find_pkgs')" if ! _install_find_pkgs "${arch}" "${plat}" "${root}"; then return 1 fi if ! _install_get_pkgs "${root}"; then return 1 fi info "$(get_msg 'install_configuring')" if ! ${foreign}; then profile_configure_system_native "${root}" "${arch}" "${plat}" else profile_configure_system_foreign "${root}" "${arch}" "${plat}" fi rm -f -- "${root}/prokit/installing" rmdir -- "${root}/prokit" return 0 }