summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorP. 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)
commit2cd968e982bb9942e6d044270a42de88d8d01b67 (patch)
tree4751e5a9802ce2d0b319e5a988ce723db8611660
parent78a64f4f12a28be389fdc935cdf7dcfddf386c35 (diff)
parent27abaab4e6861d60f1316349395eeff57b65c964 (diff)
Merge branch 'feature/installer-integration'
-rw-r--r--Makefile.am7
-rw-r--r--installers/local.mk2
-rwxr-xr-xinstallers/pc.sh308
-rw-r--r--lib/cmd.sh3
-rw-r--r--lib/cmd/install.sh251
-rw-r--r--lib/cmd/installer-pc.sh101
-rw-r--r--lib/cmd/local.mk3
-rw-r--r--lib/getopt.sh18
-rw-r--r--lib/install.sh274
-rw-r--r--lib/local.mk3
-rw-r--r--locale/en_US.sh37
-rw-r--r--man/local.mk3
-rw-r--r--man/prokit-installer-pc.8in55
-rw-r--r--man/prokit.1in3
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 "${@}"
diff --git a/lib/cmd.sh b/lib/cmd.sh
index fb2dad4..208e2fa 100644
--- a/lib/cmd.sh
+++ b/lib/cmd.sh
@@ -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