diff options
author | P. J. McDermott <pj@pehjota.net> | 2015-05-26 18:07:14 (EDT) |
---|---|---|
committer | P. J. McDermott <pj@pehjota.net> | 2015-05-26 18:07:14 (EDT) |
commit | 2cd968e982bb9942e6d044270a42de88d8d01b67 (patch) | |
tree | 4751e5a9802ce2d0b319e5a988ce723db8611660 | |
parent | 78a64f4f12a28be389fdc935cdf7dcfddf386c35 (diff) | |
parent | 27abaab4e6861d60f1316349395eeff57b65c964 (diff) |
Merge branch 'feature/installer-integration'
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | installers/local.mk | 2 | ||||
-rwxr-xr-x | installers/pc.sh | 308 | ||||
-rw-r--r-- | lib/cmd.sh | 3 | ||||
-rw-r--r-- | lib/cmd/install.sh | 251 | ||||
-rw-r--r-- | lib/cmd/installer-pc.sh | 101 | ||||
-rw-r--r-- | lib/cmd/local.mk | 3 | ||||
-rw-r--r-- | lib/getopt.sh | 18 | ||||
-rw-r--r-- | lib/install.sh | 274 | ||||
-rw-r--r-- | lib/local.mk | 3 | ||||
-rw-r--r-- | locale/en_US.sh | 37 | ||||
-rw-r--r-- | man/local.mk | 3 | ||||
-rw-r--r-- | man/prokit-installer-pc.8in | 55 | ||||
-rw-r--r-- | man/prokit.1in | 3 |
14 files changed, 481 insertions, 587 deletions
diff --git a/Makefile.am b/Makefile.am index 4d1657b..83c0127 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,6 @@ include $(top_srcdir)/lib/package/local.mk include $(top_srcdir)/man/local.mk include $(top_srcdir)/locale/local.mk include $(top_srcdir)/tests/local.mk -include $(top_srcdir)/installers/local.mk MANUAL = ProteanOS Development Kit Manual @@ -38,8 +37,6 @@ pkgdatapackage_SCRIPTS = $(pkgdatapackage_sources:.sh=.sm) man1_MANS = $(man1_sources:.1in=.1) man8_MANS = $(man8_sources:.8in=.8) locale_MESSAGES = $(locale_sources:.sh=.ms) -installers = $(installers_sources:.sh=) -noinst_SCRIPTS = $(installers) noinst_DATA = $(locale_MESSAGES) .builddirstamp CLEANFILES = \ $(bin_SCRIPTS) \ @@ -50,7 +47,6 @@ CLEANFILES = \ $(man1_MANS) \ $(man8_MANS) \ $(locale_MESSAGES) \ - $(installers) \ .builddirstamp pkgdatacmddir = $(pkgdatadir)/cmd pkgdataprofiledir = $(pkgdatadir)/profile @@ -73,8 +69,7 @@ sources = \ $(locale_sources) \ $(TESTS) \ tests/common.sh \ - tests/parse_control.common.sh \ - $(installers_sources) + tests/parse_control.common.sh EXTRA_DIST = \ autogen.sh \ $(sources) \ diff --git a/installers/local.mk b/installers/local.mk deleted file mode 100644 index 0bccdce..0000000 --- a/installers/local.mk +++ /dev/null @@ -1,2 +0,0 @@ -installers_sources = \ - installers/pc.sh diff --git a/installers/pc.sh b/installers/pc.sh deleted file mode 100755 index d23292b..0000000 --- a/installers/pc.sh +++ /dev/null @@ -1,308 +0,0 @@ -#!@SH@ - -set -u - -# This should be maintained in order of compatibility, i.e. each arch can also -# run programs built for the arches before it. -ARCHES='i686 amd64' - -# Description CPU Plat -PLATS=' -Acer Aspire One AO751h i686 ao751h -Dell Dimension 2400 i686 dimension2400 -Lenovo ThinkPad X60/X60s/X60t i686 x60 -' - -main() -{ - local opt= - local mirror= - local install_arch= - local host_arch= - local host_plat= - local mountpoint= - local b4= - local b3= - local b2= - local b1= - - while getopts 'm:' opt; do - case ${opt} in - m) mirror="${OPTARG}";; - ?) - print_usage >&2 - exit 1 - ;; - esac - done - shift $(($OPTIND - 1)) - if [ ${#} -ne 0 ]; then - print_usage >&2 - exit 1 - fi - - install_arch="$(detect_arch)" - printf '\nSelect a platorm' - printf '\n================\n\n' - read host_arch host_plat <<-EOF - $(prompt_plat) - EOF - host_arch="${host_arch}-${install_arch#*-}" - check_arch_compat "${install_arch}" "${host_arch}" - - printf '\nSelect a block device' - printf '\n=====================\n\n' - dev="$(prompt_block_dev)" - - printf '\nMaking partition table and file system' - printf '\n======================================\n\n' - make_partition_and_fs "${dev}" - - printf '\nInstalling base system' - printf '\n======================\n\n' - - mountpoint="$(mount_fs "${dev}")" - - "${0%installers/pc}src/prokit" install \ - -a "${host_arch}" -p "${host_plat}" \ - ${mirror:+-m} ${mirror} 'dev/trunk' "${mountpoint}" - - printf '\nInstalling boot loader' - printf '\n======================\n\n' - - read b4 b3 b2 b1 <<-EOF - $(od -An -tx1 -v -j 440 -N 4 "/dev/${dev}") - EOF - # This ln command won't be needed once lilo 24.1-1 is uploaded. - ln "${mountpoint}/boot/vmlinuz" "${mountpoint}/boot/vmlinuz.old" - "${0%installers/pc}src/prokit" shell "${mountpoint}" \ - install-lilo "/dev/${dev}" "PARTUUID=${b1}${b2}${b3}${b4}-01" - - umount_fs "${mountpoint}" -} - -print_usage() -{ - printf 'Usage: %s [-m <mirror>]\n' "${0}" -} - -error() -{ - local status=${1} - local fmt="${2}" - shift 2 - - printf "Error: ${fmt}\n" "${@}" >&2 - - exit ${status} -} - -_select() -{ - # Field width of the prompt numbers. - select_width=$(expr ${#} : '.*') - - select_i= - - while :; do - case "${select_i}" in - '') - select_i=0 - for select_word in "${@}"; do - select_i=$(expr ${select_i} + 1) - printf "%${select_width}d) %s\\n" \ - ${select_i} "${select_word}" \ - >&2 - done - ;; - *[!0-9]*) - printf 'Please enter a number in range.\n' >&2 - ;; - *) - if [ ${select_i} -gt 0 ] && \ - [ ${select_i} -le ${#} ]; then - shift $(expr $select_i - 1) - select_result="${1}" - break - fi - printf 'Please enter a number in range.\n' >&2 - ;; - esac - - # Prompt and read input. - printf '%s' "${PS3-#? }" >&2 - read -r select_i || exit - done -} - -detect_arch() -{ - local uname_m= - local uname_s= - local arch= - - uname_m="$( (uname -m) 2>/dev/null)" || uname_m='?' - uname_s="$( (uname -s) 2>/dev/null)" || uname_s='?' - case "${uname_m}:${uname_s}" in - 'i686:Linux') arch='i686-linux-glibc';; - 'x86_64:Linux') arch='amd64-linux-glibc';; - '?:?') error 2 'Architecture unknown';; - *) error 2 'Architecture unsupported';; - esac - - printf '%s\n' "${arch}" -} - -prompt_plat() -{ - local desc= - local arch= - local plat= - - set -- - while IFS=' ' read -r desc arch plat; do - [ "x${desc}" = 'x' ] && continue - set -- "${@}" "${desc}" - done <<-EOF - ${PLATS} - EOF - - printf 'Select a platform:\n' >&2 - _select "${@}" - - while IFS=' ' read -r desc arch plat; do - if [ "x${desc}" = "x${select_result}" ]; then - printf '%s %s\n' "${arch}" "${plat}" - break - fi - done <<-EOF - ${PLATS} - EOF -} - -check_arch_compat() -{ - local install_arch="${1}" - local host_arch="${2}" - local arches= - local install_cpu= - local host_cpu= - - if [ "x${install_arch}" = "x${host_arch}" ]; then - return 0 - fi - - arches="$(printf ' %s ' ${ARCHES})" - install_cpu="${install_arch%%-*}" - host_cpu="${host_arch%%-*}" - if [ "x${arches#* ${host_cpu} * ${install_cpu} }" = "x${arches}" ] - then - error 2 'Cannot install a system of architecture %s on %s %s' \ - "${host_arch}" 'a system of architecture' \ - "${install_arch}" - fi -} - -pretty_print_size_dec() -{ - local size="${1}" - - awk -v size=${size} 'BEGIN { - split("B KB MB GB TB", units, " "); - i=1; - while (size >= 1000) { - size /= 1000; - ++i; - }; - printf("%.2f %s\n", size, units[i]); }' -} - -pretty_print_size_bin() -{ - local size="${1}" - - awk -v size=${size} 'BEGIN { - split("B KiB MiB GiB TiB", units, " "); - i=1; - while (size >= 1024) { - size /= 1024; - ++i; - }; - printf("%.2f %s\n", size, units[i]); }' -} - -prompt_block_dev() -{ - local dev= - local vendor= - local model= - local name= - local size= - local size_s= - local desc= - local devs= - - set -- - for dev in /sys/block/*; do - dev="${dev#/sys/block/}" - case "${dev}" in - loop*|sr*) continue;; - esac - if [ -e "/sys/block/${dev}/device/vendor" ]; then - vendor="$(cat "/sys/block/${dev}/device/vendor")" - model="$(cat "/sys/block/${dev}/device/model")" - name="${vendor} ${model}" - else - name="$(cat "/sys/block/${dev}/device/name")" - fi - size="$(cat "/sys/block/${dev}/size")" - size="$(expr ${size} \* 512)" - size_s="$(pretty_print_size_dec "${size}")" - size_s="${size_s} ($(pretty_print_size_bin "${size}"))" - desc="$(printf '%s (%s) - %s\n' "${name}" "${dev}" "${size_s}")" - set -- "${@}" "${desc}" - devs="$(printf '%s\n%s\t%s\n' "${devs}" "${desc}" "${dev}")" - done - - printf 'Select a block device:\n' >&2 - _select "${@}" - - while IFS=' ' read -r desc dev; do - if [ "x${desc}" = "x${select_result}" ]; then - printf '%s\n' "${dev}" - fi - done <<-EOF - ${devs} - EOF -} - -make_partition_and_fs() -{ - local dev="${1}" - - dd if=/dev/zero of="/dev/${dev}" bs=512 count=1 - printf 'n\np\n1\n\n\nt\n83\na\n1\nw\n' | fdisk "/dev/${dev}" - mke2fs -t ext4 "/dev/${dev}1" -} - -mount_fs() -{ - local dev="${1}" - local mountpoint= - - mountpoint="$(mktemp -d)" - mount "/dev/${dev}1" "${mountpoint}" - printf '%s\n' "${mountpoint}" -} - -umount_fs() -{ - local mountpoint="${1}" - - while ! umount "${mountpoint}"; do - sleep 1 - done - rmdir "${mountpoint}" -} - -main "${@}" @@ -27,6 +27,7 @@ use locale CMDS='@cmds@' running_cmd= +running_cmd_clean= load_cmds() { @@ -118,8 +119,10 @@ run_cmd() tr '[A-Z]' '[a-z]' | tr -C '[a-z0-9_]' '_')" if is_cmd "${cmd}"; then running_cmd="${cmd}" + running_cmd_clean="${cmd_clean}" "cmd_${cmd_clean}_main" "${@}" running_cmd='' + running_cmd_clean='' else error 1 "$(get_msg 'cmd_not_found')" "${cmd}" fi diff --git a/lib/cmd/install.sh b/lib/cmd/install.sh index e63059d..d983e28 100644 --- a/lib/cmd/install.sh +++ b/lib/cmd/install.sh @@ -22,25 +22,15 @@ use getopt use feed use profile use block -use dir -use fd -use pkg +use install cmd_install_optstring='a:p:m:F' -cmd_install_deps= -cmd_install_fnames= -cmd_install_md5sums= -cmd_install_sha256sums= -cmd_install_feed_url= cmd_install_main() { local suite= local chroot= - local arch= - local plat= local profile= - local mirror= local foreign= local dev= @@ -69,32 +59,6 @@ cmd_install_main() profile_set "${profile}" suite="$(profile_normalize_suite "${suite}")" - if [ "x${cmd_install_opt_a+set}" = 'xset' ]; then - arch="${cmd_install_opt_a}" - else - arch="$(profile_detect_arch)" - fi - if [ "x${cmd_install_opt_p+set}" = 'xset' ]; then - plat="${cmd_install_opt_p}" - else - plat="$(profile_default_plat)" - fi - if [ "x${cmd_install_opt_m+set}" = 'xset' ]; then - mirror="${cmd_install_opt_m}" - else - mirror="$(profile_select_mirror)" - fi - - if ! profile_validate_archplat "${mirror}" "${arch}" "${plat}" \ - "${suite}"; then - error 2 "$(get_msg 'cmd_install_bad_archplat')" \ - "${arch}" "${plat}" - fi - - info "$(get_msg 'cmd_install_selected_arch')" "${arch}" - info "$(get_msg 'cmd_install_selected_plat')" "${plat}" - info "$(get_msg 'cmd_install_selected_mirror')" "${mirror}" - if [ "x${cmd_install_opt_F+set}" = 'xset' ]; then foreign=true else @@ -107,218 +71,11 @@ cmd_install_main() chroot="$(block_mount "${dev}")" fi - info "$(get_msg 'cmd_install_setting_up_chroot')" - if [ -d "${chroot}" ] && ! dir_is_empty "${chroot}" 'lost+found'; then - error 2 "$(get_msg 'cmd_install_chroot_dir_exists')" "${chroot}" - fi - if ! mkdir -p "${chroot}/.prokit" "${chroot}/prokit"; then - error 2 "$(get_msg 'cmd_install_mkdir_chroot_fail')" "${chroot}" - fi - >"${chroot}/prokit/installing" - - info "$(get_msg 'cmd_install_find_pkgs')" - cmd_install_find_pkgs "${mirror}" "${suite}" "${arch}" "${plat}" \ - "${chroot}" - cmd_install_get_pkgs "${chroot}" - - info "$(get_msg 'cmd_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_system "${cmd_install_opt_m-}" "${suite}" \ + "${cmd_install_opt_a-}" "${cmd_install_opt_p-}" \ + "${chroot}" "${foreign}" if [ "x${dev}" != 'x' ]; then block_umount "${chroot}" fi } - -cmd_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} - - cmd_install_deps= - cmd_install_fnames= - cmd_install_md5sums= - cmd_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}" - cmd_install_feed_url="${feed%/*}" - feed_find_pkgs "${chroot}/var/lib/opkg/lists/${feed_idx}" \ - "$(profile_dep_fields)" profile_include_pkg \ - cmd_install_deps_cb cmd_install_fname_cb \ - cmd_install_md5sum_cb cmd_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")" \ - "${cmd_install_deps}" | xargs printf '%s\n' | sort -u)" - printf '%s\n' "${pkgs}" >"${chroot}/.prokit/packages" -} - -cmd_install_deps_cb() -{ - local pkg="${1}" - local deps="${2}" - - cmd_install_deps="${cmd_install_deps}${pkg}: ${deps}${LF}" -} - -cmd_install_fname_cb() -{ - local pkg="${1}" - local fname="${2}" - - cmd_install_fnames="$(printf '%s\n%s %s/%s' "${cmd_install_fnames}" \ - "${pkg}" "${cmd_install_feed_url}" "${fname}")" -} - -cmd_install_md5sum_cb() -{ - local pkg="${1}" - local md5sum="${2}" - - cmd_install_md5sums="$(printf '%s\n%s %s' "${cmd_install_md5sums}" \ - "${pkg}" "${md5sum}")" -} - -cmd_install_sha256sum_cb() -{ - local pkg="${1}" - local sha256sum="${2}" - - cmd_install_sha256sums="$(printf '%s\n%s %s' \ - "${cmd_install_sha256sums}" "${pkg}" "${sha256sum}")" -} - -cmd_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 'cmd_install_downloading_pkg')" "${pkg}" - fname="$(printf '%s\n' "${cmd_install_fnames}" | \ - sed -n "s/^${pkg} //p")" - md5sum="$(printf '%s\n' "${cmd_install_md5sums}" | \ - sed -n "s/^${pkg} //p")" - sha256sum="$(printf '%s\n' "${cmd_install_sha256sums}" | \ - sed -n "s/^${pkg} //p")" - wget -q -O "${chroot}/var/cache/opkg/archives/${fname##*/}" \ - "${fname}" || \ - error 2 "$(get_msg 'cmd_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 'cmd_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 'cmd_install_checksum_fail')" - fi - - info "$(get_msg 'cmd_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} -} diff --git a/lib/cmd/installer-pc.sh b/lib/cmd/installer-pc.sh new file mode 100644 index 0000000..69381d0 --- /dev/null +++ b/lib/cmd/installer-pc.sh @@ -0,0 +1,101 @@ +# "installer-pc" command +# +# Copyright (C) 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/>. + +use getopt +use profile +use block +use install +use session + +cmd_installer_pc_optstring='a:p:m:' + +cmd_installer_pc_main() +{ + local suite= + local dev= + local profile= + local root= + local b4= + local b3= + local b2= + local b1= + + if ! get_options "${@}"; then + print_cmd_usage 'installer-pc' >&2 + exit 1 + fi + shift $(($OPTIND - 1)) + + if [ "x${cmd_installer_pc_opt_a-}" = 'x' ]; then + print_cmd_usage 'installer-pc' >&2 + exit 1 + fi + if [ "x${cmd_installer_pc_opt_p-}" = 'x' ]; then + print_cmd_usage 'installer-pc' >&2 + exit 1 + fi + if [ ${#} -ne 2 ]; then + print_cmd_usage 'installer-pc' >&2 + exit 1 + fi + + suite="${1}" + dev="${2}" + check_block "${dev}" + + if [ "x${suite%%:*}" != "x${suite}" ]; then + profile="${suite%%:*}" + suite="${suite#*:}" + else + profile='proteanos' + fi + profile_set "${profile}" + suite="$(profile_normalize_suite "${suite}")" + + cmd_installer_pc_make_partition_and_fs "${dev}" + root="$(block_mount "${dev}1")" + + install_system "${cmd_installer_pc_opt_m-}" "${suite}" \ + "${cmd_installer_pc_opt_a-}" "${cmd_installer_pc_opt_p-}" \ + "${root}" false + + if [ -f "${root}/sbin/lilo" ]; then + read b4 b3 b2 b1 <<-EOF + $(od -An -tx1 -v -j 440 -N 4 "${dev}") + EOF + # This ln command won't be needed once lilo 24.1-1 is uploaded. + ln "${root}/boot/vmlinuz" "${root}/boot/vmlinuz.old" + session_begin "${root}" . : false + session_exec install-lilo \ + "${dev}" "PARTUUID=${b1}${b2}${b3}${b4}-01" + session_end + fi + + block_umount "${root}" +} + +cmd_installer_pc_make_partition_and_fs() +{ + local dev="${1}" + + dd if=/dev/zero of="${dev}" bs=512 count=1 + printf 'n\np\n1\n\n\nt\n83\na\n1\nw\n' | fdisk "${dev}" + mke2fs -t ext4 "${dev}1" +} diff --git a/lib/cmd/local.mk b/lib/cmd/local.mk index 8c56946..dc6e2ae 100644 --- a/lib/cmd/local.mk +++ b/lib/cmd/local.mk @@ -4,4 +4,5 @@ pkgdatacmd_sources = \ lib/cmd/install.sh \ lib/cmd/shell.sh \ lib/cmd/opkg.sh \ - lib/cmd/build.sh + lib/cmd/build.sh \ + lib/cmd/installer-pc.sh diff --git a/lib/getopt.sh b/lib/getopt.sh index 32fb57d..b8d90fb 100644 --- a/lib/getopt.sh +++ b/lib/getopt.sh @@ -27,21 +27,27 @@ get_options() local prefix= local opt= - if [ "x${running_cmd}" = 'x' ]; then + if [ "x${running_cmd_clean}" = 'x' ]; then optstring="${OPTSTRING}" prefix='opt_' else - eval "optstring=\"\${cmd_${running_cmd}_optstring}\"" - prefix="cmd_${running_cmd}_opt_" + eval "optstring=\"\${cmd_${running_cmd_clean}_optstring}\"" + prefix="cmd_${running_cmd_clean}_opt_" fi unset OPTARG while getopts "${optstring}" opt; do - if [ "x${opt}" != 'x?' ]; then - eval "${prefix}${opt}=\"\${OPTARG:-true}\"" - else + if [ "x${opt}" = 'x?' ]; then return 1 fi + case "${optstring}" in + *"${opt}:"*) + eval "${prefix}${opt}=\"\${OPTARG}\"" + ;; + *) + eval "${prefix}${opt}=true" + ;; + esac unset OPTARG done 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} +} diff --git a/lib/local.mk b/lib/local.mk index 53b2d91..a202aad 100644 --- a/lib/local.mk +++ b/lib/local.mk @@ -18,4 +18,5 @@ pkgdata_sources = \ lib/rand.sh \ lib/cmd.sh \ lib/profile.sh \ - lib/package.sh + lib/package.sh \ + lib/install.sh diff --git a/locale/en_US.sh b/locale/en_US.sh index efcc65b..8731c3d 100644 --- a/locale/en_US.sh +++ b/locale/en_US.sh @@ -81,21 +81,6 @@ There is NO WARRANTY, to the extent permitted by law.' msg_prokit_cmd_install_summary='install a system into a directory' msg_prokit_cmd_install_usage='[-a <arch>] [-p <plat>] [-m <mirror>] [-F] '\ '<suite> <root>' -msg_prokit_cmd_install_bad_archplat='Invalid combination of architecture "%s" '\ -'and platform "%s"' -msg_prokit_cmd_install_selected_arch='Using architecture %s' -msg_prokit_cmd_install_selected_plat='Using platform %s' -msg_prokit_cmd_install_selected_mirror='Using mirror %s' -msg_prokit_cmd_install_setting_up_chroot='Setting up root...' -msg_prokit_cmd_install_chroot_dir_exists='Directory "%s" exists' -msg_prokit_cmd_install_mkdir_chroot_fail='Failed to create directory "%s"' -msg_prokit_cmd_install_find_pkgs='Configuring opkg and retrieving Packages '\ -'files...' -msg_prokit_cmd_install_downloading_pkg='Downloading %s...' -msg_prokit_cmd_install_downloading_pkg_fail='Failed to download package' -msg_prokit_cmd_install_unpacking_pkg='Unpacking %s...' -msg_prokit_cmd_install_configuring='Configuring packages...' -msg_prokit_cmd_install_checksum_fail='Checksum of package file failed' # lib/cmd/shell.sh msg_prokit_cmd_shell_summary='run a shell in an isolated environment' @@ -112,8 +97,30 @@ msg_prokit_cmd_build_summary='build a package' msg_prokit_cmd_build_usage='<root> [<option> ...] <pkg-dir>' msg_prokit_cmd_build_not_a_dir='Not a directory: %s' +# lib/cmd/installer-pc.sh +msg_prokit_cmd_installer_pc_summary='install a PC system onto a block device' +msg_prokit_cmd_installer_pc_usage='-a <arch> -p <plat> [-m <mirror>] '\ +'<suite> <device>' + # lib/profile.sh msg_prokit_profile_not_found='Profile "%s" not found' # lib/package.sh msg_prokit_package_format_unknown='Unable to detect package format' + +# lib/install.sh +msg_prokit_install_bad_archplat='Invalid combination of architecture "%s" '\ +'and platform "%s"' +msg_prokit_install_selected_arch='Using architecture %s' +msg_prokit_install_selected_plat='Using platform %s' +msg_prokit_install_selected_mirror='Using mirror %s' +msg_prokit_install_setting_up_chroot='Setting up root...' +msg_prokit_install_chroot_dir_exists='Directory "%s" exists' +msg_prokit_install_mkdir_chroot_fail='Failed to create directory "%s"' +msg_prokit_install_find_pkgs='Configuring opkg and retrieving Packages '\ +'files...' +msg_prokit_install_downloading_pkg='Downloading %s...' +msg_prokit_install_downloading_pkg_fail='Failed to download package' +msg_prokit_install_unpacking_pkg='Unpacking %s...' +msg_prokit_install_configuring='Configuring packages...' +msg_prokit_install_checksum_fail='Checksum of package file failed' diff --git a/man/local.mk b/man/local.mk index fef3059..73e5828 100644 --- a/man/local.mk +++ b/man/local.mk @@ -7,4 +7,5 @@ man8_sources = \ man/prokit-install.8in \ man/prokit-shell.8in \ man/prokit-opkg.8in \ - man/prokit-build.8in + man/prokit-build.8in \ + man/prokit-installer-pc.8in diff --git a/man/prokit-installer-pc.8in b/man/prokit-installer-pc.8in new file mode 100644 index 0000000..c74c233 --- /dev/null +++ b/man/prokit-installer-pc.8in @@ -0,0 +1,55 @@ +.TH prokit-installer-pc 8 \ +"2015-05-26" "@PACKAGE_NAME@ @PACKAGE_VERSION@" "@MANUAL@" + +.SH NAME +prokit-installer-pc \- Install a PC system onto a block device + +.SH SYNOPSIS +\fBprokit installer-pc\fP \fB-a\fP \fIarch\fP \fB-p\fP \fIplat\fP +[\fB-m\fP \fImirror\fP] \fIsuite\fP \fIdevice\fP + +.SH DESCRIPTION +\fBprokit installer-pc\fP installs a basic PC system of \fIsuite\fP onto +\fIdevice\fP. +.P +\fIsuite\fP can be a distribution like \fItrunk\fP; a channel and distribution +like \fIdev/trunk\fP; a profile and distribution like \fIproteanos:trunk\fP; or +a profile, channel, and distribution like \fIproteanos:dev/trunk\fP. +.P +\fIdevice\fP must be a block device file representing a whole storage device, +not a partition. + +.SH OPTIONS +.TP +.BI \-a \ arch +Install packages built for the \fIarch\fP architecture. +.TP +.BI \-p \ plat +Install packages built for the \fIplat\fP platform. +.TP +.BI \-m \ mirror +Download packages from \fImirror\fP instead of automatically selecting one at +random. \fImirror\fP is a base URL like +\fIhttp://mirror.gnu.dk/pub/proteanos\fP. + +.SH EXAMPLES + +.IP \[bu] +# prokit installer-pc -a i686-linux-glibc -p x60 dev/trunk /dev/sdb + +.SH COPYRIGHT +Copyright (C) 2014, 2015 Patrick "P. J." McDermott +.P +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. +.P +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. +.P +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/>. diff --git a/man/prokit.1in b/man/prokit.1in index 8fe00fb..b7de221 100644 --- a/man/prokit.1in +++ b/man/prokit.1in @@ -40,6 +40,9 @@ Manage packages with opkg .TP .BR prokit-build (8) Build a package +.TP +.BR prokit-installer-pc (8) +Install a PC system onto a block device .SH COPYRIGHT Copyright (C) 2014 Patrick "P. J." McDermott |