tOverhaul the entire library. - libdevuansdk - common library for devuan's simple distro kits
 (HTM) git clone https://git.parazyd.org/libdevuansdk
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit aedf124832b7643ab3f215395cb6083a9cf2db7f
 (DIR) parent 881efdf1ba1b4ed09ec42258403281a95b9cf2b3
 (HTM) Author: parazyd <parazyd@dyne.org>
       Date:   Fri, 13 Nov 2020 10:04:52 +0100
       
       Overhaul the entire library.
       
       This commit is a "complete" overhaul of libdevuansdk and is a likely
       breaking change for all the sdks. They will be updated accordingly.
       
       Notable changes:
           * Bootstrap tarballs are now cpio archives.
           * Error handling is improved a lot.
           * rsync is avoided and cpio is used where necessary.
           * debootstrap submodule is removed and system-wide debootstrap is
             used instead.
           * VMs aren't being built inside an nbd device anymore. They are now
             built normally on the filesystem, and copied into a raw image
             which is then converted to requested formats (qcow and/or vdi).
           * Vagrant build support is completely dropped.
           * apt-cache functionality is completely dropped.
           * The full-build helper functions are renamed and and separated into
             more internal functions/steps.
           * Obsolete and unused code is removed.
       
       Diffstat:
         M config                              |      18 +++++-------------
         M libdevuansdk                        |      29 +++++++++++++----------------
         M zlibs/bootstrap                     |     306 ++++++++++++++++---------------
         D zlibs/cache                         |      83 -------------------------------
         M zlibs/helpers                       |     452 ++++++++++++-------------------
         M zlibs/imaging                       |     487 +++++++++++++++++--------------
         M zlibs/iso                           |     119 ++++++++++++++++---------------
         D zlibs/kernel                        |      40 -------------------------------
         D zlibs/rsync                         |      44 -------------------------------
         M zlibs/sysconf                       |      14 +++-----------
         M zlibs/vm                            |     238 +++++++------------------------
       
       11 files changed, 719 insertions(+), 1111 deletions(-)
       ---
 (DIR) diff --git a/config b/config
       t@@ -1,4 +1,5 @@
        #!/usr/bin/env zsh
       +# shellcheck shell=bash
        # Copyright (c) 2016-2020 Dyne.org Foundation
        # libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
        #
       t@@ -17,21 +18,13 @@
        # You should have received a copy of the GNU General Public License
        # along with this source code. If not, see <http://www.gnu.org/licenses/>.
        
       -## libdevuansdk configuration
       -
        vars+=(release version mirror section blend_name image_name vm_name)
        vars+=(arch earch)
       -vars+=(aptcachedir APT_CACHE aptcachegpg)
        vars+=(usercredentials rootcredentials)
       -vars+=(nocompressimage)
       +vars+=(COMPRESS_IMAGE CPIO_STAGE4 MKEFI)
        
        arrs+=(core_packages base_packages purge_packages blend_packages)
       -
       -## enable local apt cache
       -APT_CACHE=${APT_CACHE:-0}
       -aptcachedir="$LIBPATH/apt-cache"
       -## key used to sign the cache's Release
       -aptcachegpg="0xdeadbeefdeadbeef"
       +arrs+=(core_packages_option base_packages_option purge_packages_option blend_packages_option)
        
        os="devuan"
        release="beowulf"
       t@@ -43,11 +36,10 @@ image_name="${os}_${release}_${version}_${arch}"
        [[ -n "$blend_name"  ]] && image_name="${image_name}_${blend_name}"
        [[ -n "$device_name" ]] && image_name="${image_name}_${device_name}"
        
       -vm_name="${os}_${release}_${version}_${arch}_vagrant"
       -[[ -n $blend_name  ]] && vm_name="${image_name}_${blend_name}"
       +vm_name="${os}_${release}_${version}_${arch}_virtual"
       +[[ -n "$blend_name" ]] && vm_name="${vm_name}_${blend_name}"
        
        rootcredentials="root:toor"
       -usercredentials="devuan:devuan"
        
        core_packages_option=()
        core_packages=(
 (DIR) diff --git a/libdevuansdk b/libdevuansdk
       t@@ -1,6 +1,7 @@
        #!/usr/bin/env zsh
       -# Copyright (c) 2016-2017 Dyne.org Foundation
       -# libdevuansdk maintained by Ivan J. <parazyd@dyne.org>
       +# shellcheck shell=bash
       +# Copyright (c) 2016-2020 Dyne.org Foundation
       +# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
        #
        # This file is part of libdevuansdk
        #
       t@@ -17,22 +18,18 @@
        # You should have received a copy of the GNU General Public License
        # along with this source code. If not, see <http://www.gnu.org/licenses/>.
        
       -libdevuansdk_version="1.0"
       -LIBPATH=${LIBPATH:-$(dirname $0)}
       +vars+=(libdevuansdk_version LIBPATH)
        
       -source $LIBPATH/config
       -source $LIBPATH/zlibs/bootstrap
       -source $LIBPATH/zlibs/cache
       -source $LIBPATH/zlibs/helpers
       -source $LIBPATH/zlibs/imaging
       -source $LIBPATH/zlibs/iso
       -source $LIBPATH/zlibs/kernel
       -source $LIBPATH/zlibs/rsync
       -source $LIBPATH/zlibs/sysconf
       -source $LIBPATH/zlibs/vm
       +libdevuansdk_version="2.0"
       +LIBPATH="${LIBPATH:-$(dirname $0)}"
        
       -vars+=(libdevuansdk_version)
       -vars+=(LIBPATH)
       +source "$LIBPATH/config"
       +source "$LIBPATH/zlibs/bootstrap"
       +source "$LIBPATH/zlibs/helpers"
       +source "$LIBPATH/zlibs/imaging"
       +source "$LIBPATH/zlibs/iso"
       +source "$LIBPATH/zlibs/vm"
       +source "$LIBPATH/zlibs/sysconf"
        
        setopt pushdsilent
        
 (DIR) diff --git a/zlibs/bootstrap b/zlibs/bootstrap
       t@@ -1,6 +1,7 @@
        #!/usr/bin/env zsh
       +# shellcheck shell=bash
        # Copyright (c) 2016-2020 Dyne.org Foundation
       -# libdevuansdk maintained by Ivan J. <parazyd@dyne.org>
       +# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
        #
        # This file is part of libdevuansdk
        #
       t@@ -17,222 +18,227 @@
        # You should have received a copy of the GNU General Public License
        # along with this source code. If not, see <http://www.gnu.org/licenses/>.
        
       -vars+=(bootstrap_tgz_stage3 bootstrap_tgz_stage4 TAR_STAGE4)
       -arrs+=(base_packages_option core_packages_option extra_packages_option)
       -arrs+=(purge_packages_option)
       +vars+=(bootstrap_cpio_stage3 bootstrap_cpio_stage4 CPIO_STAGE4)
        
       -bootstrap_complete_base() {
       -        fn bootstrap_complete_base "$@"
       -        req=(arch)
       +bootstrap_complete_base()
       +{
       +        fn bootstrap_complete_base "$*"
       +        req=(R os arch strapdir LIBPATH release mirror)
                ckreq || return 1
        
       -        notice "bootstrapping $os $arch base"
       +        notice "Bootstrapping: ${os}:${arch} base"
        
                export LANG=C
                export LC_ALL=C
                export DEBIAN_FRONTEND=noninteractive
        
       -        bootstrap_tgz_stage3="$R/tmp/bootstrap-${os}-${arch}-stage3.tgz"
       -        bootstrap_tgz_stage4="$R/tmp/bootstrap-${os}-${arch}-stage4.tgz"
       +        bootstrap_cpio_stage3="$R/tmp/bootstrap-${os}-${arch}-stage3.cpio.gz"
       +        bootstrap_cpio_stage4="$R/tmp/bootstrap-${os}-${arch}-stage4.cpio.gz"
        
       -        if [[ -n "$TAR_STAGE4" && -f "$bootstrap_tgz_stage4" ]]; then
       -                notice "using the existing stage4 bootstrap tarball found in $R/tmp"
       -                bootstrap_tar_unpack "$bootstrap_tgz_stage4" "$strapdir" || {
       -                        die "failed to extract tarball"
       -                        zerr
       +        if [[ -n "$CPIO_STAGE4" && -f "$bootstrap_cpio_stage4" ]]; then
       +                act "Using the existing stage4 bootstrap cpio archive..."
       +                bootstrap_cpio_unpack "$bootstrap_cpio_stage4" "$strapdir" || {
       +                        die "Failed to extract cpio archive"
       +                        return 1
                        }
                        return
       -        elif [[ -f "$bootstrap_tgz_stage3" ]]; then
       -                notice "using the existing stage3 bootstrap tarball found in $R/tmp"
       -                bootstrap_tar_unpack "$bootstrap_tgz_stage3" "$strapdir" || {
       -                        die "failed to extract tarball"
       -                        zerr
       +        elif [[ -f "$bootstrap_cpio_stage3" ]]; then
       +                act "Using the existing stage3 bootstrap cpio archive..."
       +                bootstrap_cpio_unpack "$bootstrap_cpio_stage3" "$strapdir" || {
       +                        die "Failed to extract cpio archive"
       +                        return 1
                        }
       +                bootstrap_stage4 || { zerr; return 1; }
       +                if [[ -n "$CPIO_STAGE4" ]]; then
       +                        bootstrap_cpio_pack "$bootstrap_cpio_stage4" || { zerr; return 1; }
       +                fi
                        return
                fi
        
       -        notice "running debootstrap stage 1"
       +        notice "Running stage1 debootstrap"
        
       -        sudo DEBOOTSTRAP_DIR="$LIBPATH/extra/debootstrap" "$LIBPATH/extra/debootstrap/debootstrap" \
       +        sudo debootstrap \
                        --keyring="$LIBPATH/extra/devuan-keyring/keyrings/devuan-archive-keyring.gpg" \
       -                --include=wget,ca-certificates \
       +                --include=devuan-keyring,wget,ca-certificates \
                        --foreign \
       -                --arch $arch $release $strapdir $mirror || zerr
       +                --arch "$arch" "$release" "$strapdir" "$mirror" || { zerr; return 1; }
        
       -        [[ $arch =~ "^arm.." ]] && { qemu_install_user || zerr }
       -
       -        sudo mkdir -p $strapdir/tmp
       -        sudo chmod 1777 $strapdir/tmp
       -
       -        ## debootstrap stage 2
       -        notice "running debootstrap stage 2"
       -        sudo chroot $strapdir \
       -                /debootstrap/debootstrap --second-stage || zerr
       -
       -        blend_bootstrap_setup || zerr
       -
       -        ## write all system configuration
       -        notice "writing system configuration"
       -        conf_print_debconf     | sudo tee $strapdir/debconf.set              >/dev/null
       -        conf_print_fstab       | sudo tee $strapdir/etc/fstab                >/dev/null
       -        conf_print_hostname    | sudo tee $strapdir/etc/hostname             >/dev/null
       -        conf_print_hosts       | sudo tee $strapdir/etc/hosts                >/dev/null
       -        conf_print_netifaces   | sudo tee $strapdir/etc/network/interfaces   >/dev/null
       -        conf_print_resolvconf  | sudo tee $strapdir/etc/resolv.conf          >/dev/null
       -        conf_print_sourceslist | sudo tee $strapdir/etc/apt/sources.list     >/dev/null
       -        #conf_print_locales     | sudo tee $strapdir/etc/profile.d/locales.sh >/dev/null
       +        if [[ "$arch" =~ "^arm.." ]]; then
       +                qemu_install_user "$strapdir" || { zerr; return 1; }
       +        fi
        
       -        ## write third-stage for chroot
       -        bootstrap_config_thirdstage | sudo tee $strapdir/thirdstage >/dev/null
       +        notice "Running stage2 debootstrap"
        
       -        ## chroot into it and configure further
       -        ## debootstrap stage 3
       -        notice "running debootstrap stage 3"
       +        sudo chroot "$strapdir" /debootstrap/debootstrap --second-stage || { zerr; return 1; }
        
       +        # TODO: sys config as function
       +        conf_print_fstab       | sudo tee "$strapdir/etc/fstab" >/dev/null
       +        conf_print_hostname    | sudo tee "$strapdir/etc/hostname" >/dev/null
       +        conf_print_hosts       | sudo tee "$strapdir/etc/hosts" >/dev/null
       +        conf_print_netifaces   | sudo tee "$strapdir/etc/network/interfaces" >/dev/null
       +        conf_print_resolvconf  | sudo tee "$strapdir/etc/resolv.conf" >/dev/null
       +        conf_print_sourceslist | sudo tee "$strapdir/etc/apt/sources.list" >/dev/null
        
       -        chroot-script -d thirdstage || zerr
       +        blend_bootstrap_setup || { zerr; return 1; }
        
       -        [[ $APT_CACHE = 1 ]] && {
       -                notice "adding apt cache gpg pubkey"
       -                cat <<EOF | sudo tee ${strapdir}/addcachepubkey >/dev/null
       -#!/bin/sh
       -gpgkey="$(gpg --export -a $aptcachegpg)"
       -printf "%s" "\$gpgkey" | apt-key add -
       -EOF
       -                chroot-script addcachepubkey || zerr
       -        }
       +        bootstrap_stage3 || { zerr; return 1; }
       +        bootstrap_cpio_pack "$bootstrap_cpio_stage3" || { zerr; return 1; }
        
       -        if [[ -n "$TAR_STAGE4" ]]; then
       -                bootstrap_tar_pack   "$bootstrap_tgz_stage3"             || zerr
       -                bootstrap_tar_unpack "$bootstrap_tgz_stage4" "$strapdir" || zerr
       -        else
       -                bootstrap_tar_pack   "$bootstrap_tgz_stage3"             || zerr
       -                bootstrap_tar_unpack "$bootstrap_tgz_stage3" "$strapdir" || zerr
       +        bootstrap_stage4 || { zerr; return 1; }
       +        if [[ -n "$CPIO_STAGE4" ]]; then
       +                bootstrap_cpio_pack "$bootstrap_cpio_stage4" || { zerr; return 1; }
                fi
       +
       +        return
        }
        
       -bootstrap_config_thirdstage() {
       -        fn bootstrap_config_thirdstage
       -        req=(core_packages base_packages)
       +bootstrap_stage3()
       +{
       +        fn bootstrap_stage3
       +        req=(core_packages base_packages rootcredentials)
                ckreq || return 1
        
       -        cat << EOF
       +        cat <<EOF | sudo tee "$strapdir/thirdstage" >/dev/null
        #!/bin/sh
        apt-get update
       -debconf-set-selections /debconf.set
       -
       -echo "${rootcredentials}" | chpasswd
       -sed -i -e 's/KERNEL\!=\"eth\*|/KERNEL\!=\"/' \
       -        /lib/udev/rules.d/75-persistent-net-generator.rules
       -rm -f /etc/udev/rules.d/70-persistent-net.rules
       -export DEBIAN_FRONTEND=noninteractive
       -
       -apt-get --yes --force-yes install ${core_packages_option} ${core_packages}
       -apt-get --yes --force-yes install ${base_packages_option} ${base_packages}
       -apt-get --yes --force-yes purge  ${purge_packages_option} ${purge_packages}
       -apt-get --yes --force-yes autoremove
       -
       +apt-get --yes --force-yes install ${core_packages_option} ${core_packages} || exit 1
       +apt-get --yes --force-yes install ${base_packages_option} ${base_packages} || exit 1
       +apt-get --yes --force-yes purge ${purge_packages_option} ${purge_packages} || exit 1
       +apt-get --yes --force-yes --purge autoremove || exit 1
        apt-get clean
        
       -sed -e 's/# en_US.UTF-8/en_US.UTF-8/' -i /etc/locale.gen
       -locale-gen
       +echo "${rootcredentials}" | chpasswd
        
       -rm -f /debconf.set
        rm -f /etc/ssh/ssh_host_*
        rm -f /root/.bash_history
       -#echo "1" > .keep
        EOF
       -}
        
       -bootstrap_tar_pack() {
       -        fn bootstrap_tar_pack
       -        req=(bootstrap_tgz)
       -        bootstrap_tgz="$1"
       -        ckreq || return 1
       -
       -        local _dest="$(dirname $bootstrap_tgz)"
       -
       -        if [[ -f "$bootstrap_tgz" ]]; then
       -                notice "tarball found already in $_dest"
       -        else
       -                notice "Creating boostrap tarball in $bootstrap_tgz"
       -                silly
       -
       -                pushd ${strapdir}
       -                mkdir -p ${_dest}
       -                silly
       -                sudo tar czfp "$bootstrap_tgz" \
       -                        --acls \
       -                        --selinux \
       -                        --xattrs \
       -                        --xattrs-include=security.capability \
       -                        --xattrs-include=user.pax.flags \
       -                        --exclude={./dev,./sys,./proc} . || zerr
       -                popd
       -        fi
       +        chroot-script -d thirdstage || { zerr; return 1; }
        }
        
       -bootstrap_tar_unpack() {
       -        fn bootstrap_tar_unpack $@
       -        local bootstrap_tgz="$1"
       -        req=(strapdir bootstrap_tgz)
       +bootstrap_stage4()
       +{
       +        fn bootstrap_stage4
       +        req=(strapdir extra_packages)
                ckreq || return 1
        
       -        [[ -n "$TAR_STAGE4" ]] && {
       -                [[ -f "$bootstrap_tgz" ]] || bootstrap_tgz="$bootstrap_tgz_stage3"
       -        }
       -        sudo rm -rf "${strapdir}"/*
       -        silly
       -        sudo tar xpf "$bootstrap_tgz" -C "$strapdir" --xattrs-include='*.*' --numeric-owner \
       -                --acls --selinux --xattrs
       -        sudo mkdir -p ${strapdir}/{boot,dev,sys,proc}
       +        sudo mkdir -p "$strapdir"/{boot,dev,proc,sys}
        
       -        conf_print_sourceslist | sudo tee $strapdir/etc/apt/sources.list >/dev/null
       -
       -        cat <<EOF | sudo tee ${strapdir}/postunpack >/dev/null
       +        cat <<EOF | sudo tee "$strapdir/fourthstage" >/dev/null
        #!/bin/sh
        apt-get update
        
       -## check if all our extra_packages exist
       +# check if all our extra_packages exist
        allpkgs="\$(apt-cache search '.' | cut -d' ' -f1)"
       -for i in ${extra_packages} ; do
       +for i in ${extra_packages}; do
                printf "%s" "\$allpkgs" | grep -q "^\$i$" || {
                        case "\$i" in
       -                        --*) continue ;;
       -                        *)   missing="\$missing \$i" ;;
       +                --*) continue;;
       +                *)   missing="\$missing \$i" ;;
                        esac
                }
        done
        
       -[ -n "\$missing" ] && {
       -        printf "\033[1;31m[!!] some extra packages don't exist\033[0m\n"
       +if [ -n "\$missing" ]; then
       +        printf "\033[1;31m[!!] Some extra packages don't exist:\033[0m\n"
                printf "%s\n" "\$missing"
                exit 1
       -}
       -
       -apt-get --yes --force-yes upgrade
       -apt-get --yes --force-yes install ${extra_packages_option} ${extra_packages}
       -apt-get --yes --force-yes autoremove
       +fi
        
       +apt-get --yes --force-yes upgrade || exit 1
       +apt-get --yes --force-yes install ${extra_packages_option} ${extra_packages} || exit 1
       +apt-get --yes --force-yes --purge autoremove || exit 1
        apt-get clean
        EOF
        
       -        chroot-script -d postunpack || zerr
       +        chroot-script -d fourthstage || { zerr; return 1; }
        
                for i in $inittab; do
       -                grep -q "^$i" $strapdir/etc/inittab && continue
       -                print "$i" | sudo tee -a $strapdir/etc/inittab >/dev/null
       +                grep -q "$^i" "$strapdir/etc/inittab" && continue
       +                echo "$i" | sudo tee -a "$strapdir/etc/inittab" >/dev/null
                done || true
        
                for i in $custmodules; do
       -                grep -q "^$i" $strapdir/etc/modules && continue
       -                print "$i" | sudo tee -a $strapdir/etc/modules >/dev/null
       +                grep -q "^$i" "$strapdir/etc/modules" && continue
       +                echo "$i" | sudo tee -a "$strapdir/etc/modules" >/dev/null
                done || true
       +}
       +
       +qemu_install_user()
       +{
       +        fn qemu_install_user "$*"
       +        req=(arch _target)
       +        local _target="$1"
       +        ckreq || return 1
       +
       +        case "$(uname -m)" in
       +        arm*|aarch*)
       +                return
       +                ;;
       +        esac
       +
       +        notice "Installing qemu-user-static"
       +        case "$arch" in
       +        armel)
       +                sudo cp -a "$armel_qemu_bin" "$_target/usr/bin/" || { zerr; return 1; }
       +                ;;
       +        armhf)
       +                sudo cp -a "$armhf_qemu_bin" "$_target/usr/bin/" || { zerr; return 1; }
       +                ;;
       +        arm64)
       +                sudo cp -a "$arm64_qemu_bin" "$_target/usr/bin/" || { zerr; return 1; }
       +                ;;
       +        esac
       +}
       +
       +bootstrap_cpio_pack()
       +{
       +        fn bootstrap_cpio_pack "$*"
       +        req=(_bootstrap_cpio strapdir)
       +        local _bootstrap_cpio="$1"
       +        ckreq || return 1
       +
       +        local _dest="$(dirname "$_bootstrap_cpio")"
       +        if [[ -f "$_bootstrap_cpio" ]]; then
       +                notice "cpio archive already found in $_dest"
       +                return
       +        fi
       +
       +        notice "Creating bootstrap cpio archive: $_bootstrap_cpio"
       +        silly
       +
       +        pushd "$strapdir"
       +        mkdir -p "$_dest"
       +        sudo find . \
       +                -not -path "./dev/*" \
       +                -a -not -path "./proc/*" \
       +                -a -not -path "./sys/*" \
       +                | sudo cpio -o --format=newc \
       +                | gzip - > "$_bootstrap_cpio" || { zerr; return 1; }
       +        popd
       +}
       +
       +bootstrap_cpio_unpack()
       +{
       +        fn bootstrap_cpio_unpack "$*"
       +        req=(_bootstrap_cpio strapdir)
       +        local _bootstrap_cpio="$1"
       +        ckreq || return 1
       +
       +        notice "Unpacking bootstrap cpio archive: $_bootstrap_cpio"
       +        silly
       +
       +        sudo rm -rf "${strapdir}"/*
       +
       +        pushd "$strapdir" || { zerr; return 1; }
       +        zcat "$_bootstrap_cpio" | sudo cpio -id || { zerr; return 1; }
       +        popd
        
       -        [[ -n "$TAR_STAGE4" ]] && bootstrap_tar_pack "$bootstrap_tgz_stage4" || true
       +        sudo mkdir -p "$strapdir"/{boot,dev,proc,sys}
        }
        
       -blend_bootstrap_setup() {
       -        fn blend_bootstrap_setup "noop"
       -        return 0
       +blend_bootstrap_setup()
       +{
       +        fn blend_bootstrap_setup "(noop)"
       +        return
        }
 (DIR) diff --git a/zlibs/cache b/zlibs/cache
       t@@ -1,83 +0,0 @@
       -#!/usr/bin/env zsh
       -# Copyright (c) 2017 Dyne.org Foundation
       -# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
       -#
       -# This file is part of libdevuansdk
       -#
       -# This source code 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.
       -#
       -# This software 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 this source code. If not, see <http://www.gnu.org/licenses/>.
       -
       -aptcache() {
       -    fn aptcache "$*"
       -    req=(aptcachedir watdo werdo APT_CACHE)
       -    local watdo="$1"
       -    local werdo="$2"
       -    ckreq || return 1
       -
       -    [[ $APT_CACHE = 1 ]] || return 0
       -
       -    case "$watdo" in
       -        on)
       -            act "mounting local apt cache"
       -            sudo mount -o bind "$aptcachedir" "$werdo" || zerr
       -            ;;
       -        off)
       -            act "umounting local apt cache"
       -            sudo umount "$werdo" || zerr
       -            ;;
       -    esac
       -}
       -
       -fill_apt_cache() {
       -    fn fill_apt_cache
       -    req=(strapdir APT_CACHE aptcachedir)
       -    ckreq || return 1
       -
       -    [[ $APT_CACHE = 1 ]] || return 0
       -
       -    notice "filling local apt cache"
       -
       -        cp -fv $strapdir/var/cache/apt/archives/*.deb $aptcachedir
       -
       -        pushd "$aptcachedir"
       -                dpkg-scanpackages . /dev/null > Packages
       -                gzip -c Packages > Packages.gz
       -                cat <<EOF > Release
       -Origin: ${os}
       -Suite: ${release}
       -Version: ${version}
       -Architectures: alpha amd64 arm64 armel armhf hppa i386 ia64 mips mipsel powerpc ppc64el s390x sparc
       -MD5sum:
       - $(md5sum Packages    | cut -d' ' -f1)    $(du -b Packages)
       - $(md5sum Packages.gz | cut -d' ' -f1)    $(du -b Packages.gz)
       -SHA1:
       - $(sha1sum Packages    | cut -d' ' -f1)    $(du -b Packages)
       - $(sha1sum Packages.gz | cut -d' ' -f1)    $(du -b Packages.gz)
       -SHA256:
       - $(sha256sum Packages    | cut -d' ' -f1)    $(du -b Packages)
       - $(sha256sum Packages.gz | cut -d' ' -f1)    $(du -b Packages.gz)
       -EOF
       -                rm -f Packages
       -                gpg --sign --detach-sign -a --sign-with $aptcachegpg Release || zerr
       -                mv Release.asc Release.gpg
       -        popd
       -
       -
       -        sudo sed -i '/deb file:\/mnt/d' "$strapdir/etc/apt/sources.list"
       -        notice "removing apt cache gpg pubkey"
       -        cat <<EOF | sudo tee ${strapdir}/delcachepubkey >/dev/null
       -#!/bin/sh
       -apt-key del ${aptcachegpg}
       -EOF
       -        chroot-script delcachepubkey || zerr
       -}
 (DIR) diff --git a/zlibs/helpers b/zlibs/helpers
       t@@ -1,5 +1,6 @@
        #!/usr/bin/env zsh
       -# Copyright (c) 2016-2017 Dyne.org Foundation
       +# shellcheck shell=bash
       +# Copyright (c) 2016-2020 Dyne.org Foundation
        # libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
        #
        # This file is part of libdevuansdk
       t@@ -17,101 +18,109 @@
        # You should have received a copy of the GNU General Public License
        # along with this source code. If not, see <http://www.gnu.org/licenses/>.
        
       -## helper functions that make my life easier
       -
       -vars+=(loopdevice)
       -
       -build_image_dist() {
       -        fn build_image_dist
       -        req=(arch size parted_type)
       -        if [[ $parted_type = gpt ]]; then
       -                req+=(gpt_boot gpt_root)
       -        elif [[ $parted_type = dos ]]; then
       -                req+=(parted_root parted_boot)
       -        fi
       -        req+=(workdir strapdir image_name)
       +build_arm_dist()
       +{
       +        fn build_arm_dist
       +        req=(workdir strapdir os arch size parted_type)
       +        case "$parted_type" in
       +        gpt) req+=(gpt_boot gpt_root) ;;
       +        dos) req+=(dos_boot dos_root) ;;
       +        *) die "Unknown parted_type: $parted_type. Supported is gpt|dos."
       +                zerr; return 1
       +                ;;
       +        esac
                ckreq || return 1
        
       -        notice "building complete dist image"
       -        act "$image_name"
       -
       -        bootstrap_complete_base            || { zerr; wrapup }
       -        blend_preinst                      || { zerr; wrapup }
       -        image_prepare_raw                  || { zerr; wrapup }
       -        image_partition_raw_${parted_type} || { zerr; wrapup }
       -        build_kernel_${arch}               || { zerr; wrapup }
       -        blend_postinst                     || { zerr; wrapup }
       -        rsync_to_raw_image                 || { zerr; wrapup }
       -        image_pack_dist                    || { zerr; wrapup }
       +        notice "Building complete Arm image(s)"
       +
       +        bootstrap_complete_base        || { zerr; return 1; }
       +        blend_preinst                  || { zerr; return 1; }
       +        image_prepare_raw              || { zerr; return 1; }
       +        image_connect_raw              || { zerr; return 1; }
       +        image_partition_${parted_type} || { zerr; return 1; }
       +        image_format_partitions        || { zerr; return 1; }
       +        build_kernel_${arch}           || { zerr; return 1; }
       +        image_mount                    || { zerr; return 1; }
       +        strapdir_to_image              || { zerr; return 1; }
       +        blend_postinst                 || { zerr; return 1; }
       +        image_umount                   || { zerr; return 1; }
       +        image_disconnect_raw           || { zerr; return 1; }
       +        image_pack_dist                || { zerr; return 1; }
       +        clean_strapdir                 || { zerr; return 1; }
        }
        
       -build_iso_dist() {
       +build_iso_dist()
       +{
                fn build_iso_dist
                req=(workdir strapdir os arch)
                ckreq || return 1
        
       -        notice "building complete iso image"
       -
       -        bootstrap_complete_base || { zerr; wrapup }
       -        blend_preinst           || { zerr; wrapup }
       -        iso_prepare_strap       || { zerr; wrapup }
       -        build_kernel_${arch}    || { zerr; wrapup }
       -        iso_setup_isolinux      || { zerr; wrapup }
       -        iso_write_isolinux_cfg  || { zerr; wrapup }
       -        #[[ $INSTALLER = 1 ]] && iso_setup_installer || zerr
       -        blend_postinst          || { zerr; wrapup }
       -        fill_apt_cache          || { zerr; wrapup }
       -        iso_squash_strap        || { zerr; wrapup }
       -        iso_xorriso_build       || { zerr; wrapup }
       +        notice "Building complete iso image(s)"
       +
       +        bootstrap_complete_base || { zerr; return 1; }
       +        blend_preinst           || { zerr; return 1; }
       +        iso_prepare_strap       || { zerr; return 1; }
       +        iso_setup_isolinux      || { zerr; return 1; }
       +        iso_write_isolinux_cfg  || { zerr; return 1; }
       +        blend_postinst          || { zerr; return 1; }
       +        iso_squash_strap        || { zerr; return 1; }
       +        iso_xorriso_build       || { zerr; return 1; }
        }
        
       -build_vagrant_dist() {
       -        fn build_vagrant_dist
       -        req=(workdir strapdir os arch imageformat)
       +build_vm_dist()
       +{
       +        fn build_vm_dist
       +        req=(workdir strapdir os arch size imageformat parted_type)
       +        case "$parted_type" in
       +        gpt) req+=(gpt_boot gpt_root) ;;
       +        dos) req+=(dos_boot dos_root) ;;
       +        *) die "Unknown parted_type: $parted_type. Supported is gpt|dos."
       +                zerr; return 1
       +                ;;
       +        esac
                ckreq || return 1
        
       -        notice "building complete vagrant image"
       -
       -        image_${imageformat}_as_strapdir   || { zerr; wrapup }
       -        bootstrap_complete_base            || { zerr; wrapup }
       -        vm_inject_overrides                || { zerr; wrapup }
       -        blend_preinst                      || { zerr; wrapup }
       -        vm_setup_grub                      || { zerr; wrapup }
       -        blend_postinst                     || { zerr; wrapup }
       -        vm_umount_${imageformat}           || { zerr; wrapup }
       -        vm_vbox_setup                      || { zerr; wrapup }
       -        vm_vagrant_package                 || { zerr; wrapup }
       -        vm_init_cloud                      || { zerr; wrapup }
       -        vm_pack_dist                       || { zerr; wrapup }
       -}
       -
       -getfield() {
       -        fn getfield $*
       -        print "$1" | \
       -                grep "^$2=" | \
       -                sed -e 's:.*=\(.*\)$:\1:g' | \
       -                sed -e 's:^"\(.*\)"$:\1:g'
       +        notice "Building complete VM image(s)"
       +
       +        bootstrap_complete_base        || { zerr; return 1; }
       +        vm_inject_overrides            || { zerr; return 1; }
       +        blend_preinst                  || { zerr; return 1; }
       +        image_prepare_raw              || { zerr; return 1; }
       +        image_connect_raw              || { zerr; return 1; }
       +        image_partition_${parted_type} || { zerr; return 1; }
       +        image_format_partitions        || { zerr; return 1; }
       +        image_mount                    || { zerr; return 1; }
       +        strapdir_to_image              || { zerr; return 1; }
       +        vm_setup_grub                  || { zerr; return 1; }
       +        blend_postinst                 || { zerr; return 1; }
       +        image_umount                   || { zerr; return 1; }
       +        image_disconnect_raw           || { zerr; return 1; }
       +        if [[ "$imageformat" = qcow2 ]]; then
       +                image_raw_to_qcow2         || { zerr; return 1; }
       +        fi
       +        image_raw_to_vdi               || { zerr; return 1; }
       +        vm_pack_dist                   || { zerr; return 1; }
       +        clean_strapdir                 || { zerr; return 1; }
        }
        
       -add-user() {
       -        fn add-user $*
       -        local user="$1"
       -        local pass="$2"
       -        req=(strapdir user pass)
       +clean_strapdir()
       +{
       +        fn clean_strapdir
       +        req=(strapdir)
                ckreq || return 1
        
       -        notice "adding user $user:$pass"
       +        if [[ "$DEBUG" = 1 ]]; then
       +                return
       +        fi
        
       -        cat <<EOF | sudo tee ${strapdir}/adduser
       -#!/bin/sh
       -useradd -m ${user}
       -echo "${user}:${pass}" | chpasswd
       -EOF
       -        chroot-script adduser || zerr
       +        notice "Cleaning strapdir"
       +
       +        sudo rm -rf "$strapdir"
        }
        
       -devprocsys() {
       -        fn devprocsys "$@"
       +devprocsys()
       +{
       +        fn devprocsys "$*"
                local watdo="$1"
                local werdo="$2"
                req=(watdo werdo)
       t@@ -124,79 +133,17 @@ devprocsys() {
                        sudo mount -o bind /dev/pts $werdo/dev/pts && act "mounted devpts" && \
                        return 0
                elif [[ $watdo = umount ]]; then
       -                sudo umount $werdo/dev/pts  && act "umounted devpts" && sleep 1
       -                sudo umount $werdo/dev      && act "umounted dev"    && sleep 1
       -                sudo umount $werdo/proc     && act "umounted proc"   && sleep 1
       -                sudo umount $werdo/sys      && act "umounted sys"    && sleep 1
       +                sudo umount $werdo/dev/pts  && act "umounted devpts"
       +                sudo umount $werdo/dev      && act "umounted dev"
       +                sudo umount $werdo/proc     && act "umounted proc"
       +                sudo umount $werdo/sys      && act "umounted sys"
                        return 0
                fi
       -        return 1
       -}
       -
       -wrapup() {
       -        # a hopefully clean exit
       -        fn wrapup
       -        req=(strapdir)
       -        ckreq || {
       -                die "something is very wrong"
       -                die "cleanup yourself, sorry"
       -                exit 1
       -        }
       -
       -        devprocsys umount $strapdir
       -        exit 1
       +        zerr; return 1
        }
        
       -findloopdev() {
       -        fn findloopdev
       -        req=(workdir image_name)
       -        ckreq || return 1
       -
       -        notice "finding a free loopdevice"
       -
       -        loopdevice=$(sudo losetup -f --show $workdir/${image_name}.img)
       -        sudo partx -av $loopdevice || zerr
       -
       -        func "loopdevice: $loopdevice"
       -        silly sleep 2
       -}
       -
       -findfreenbd() {
       -        fn findfreenbd
       -
       -        notice "looking for a free /dev/nbd"
       -
       -        for i in $(seq 0 8); do
       -                grep "^/dev/nbd${i}" /proc/mounts >/dev/null || {
       -                        print "/dev/nbd${i}"
       -                        break
       -                }
       -        done
       -}
       -
       -qemu_install_user() {
       -        fn qemu_install_user
       -        req=(arch strapdir)
       -        ckreq || return 1
       -
       -        [[ "$(uname -m)" =~ "arm" ]]   && return
       -        [[ "$(uname -m)" =~ "aarch" ]] && return
       -
       -        notice "installing qemu-user-static"
       -        case "$arch" in
       -                armel)
       -                        sudo cp -a "$armel_qemu_bin" "$strapdir/usr/bin"
       -                        ;;
       -                armhf)
       -                        sudo cp -a "$armhf_qemu_bin" "$strapdir/usr/bin"
       -                        ;;
       -                arm64)
       -                        sudo cp -a "$arm64_qemu_bin" "$strapdir/usr/bin"
       -                        ;;
       -        esac
       -}
       -
       -dpkgdivert() {
       +dpkgdivert()
       +{
                fn dpkgdivert "$@"
                req=(watdo werdo)
                local watdo="$1"
       t@@ -207,8 +154,8 @@ dpkgdivert() {
                        cat <<EOF | sudo tee ${werdo}/dpkgdivert >/dev/null
        #!/bin/sh
        dpkg-divert --add --local \
       -        --divert /usr/sbin/invoke-rc.d.chroot \
       -        --rename /usr/sbin/invoke-rc.d
       +--divert /usr/sbin/invoke-rc.d.chroot \
       +--rename /usr/sbin/invoke-rc.d
        cp /bin/true /usr/sbin/invoke-rc.d
        echo -e "#!/bin/sh\nexit 101" > /usr/sbin/policy-rc.d
        chmod +x /usr/sbin/policy-rc.d
       t@@ -222,163 +169,98 @@ dpkg-divert --remove --rename /usr/sbin/invoke-rc.d
        EOF
                fi
        
       -        chroot-script dpkgdivert || zerr
       +        chroot-script "$werdo/dpkgdivert" || { zerr; return 1; }
        }
        
       -enableserv() {
       -        fn enableserv "$@"
       -        local service="$1"
       -        req=(service strapdir)
       +chroot-script()
       +{
       +        fn chroot-script "$*"
       +        req=(R workdir strapdir)
                ckreq || return 1
        
       -        cat <<EOF | sudo tee -a ${strapdir}/enserv >/dev/null
       -#!/bin/sh
       -update-rc.d ${service} enable
       -EOF
       -
       -        notice "enabling $service service"
       -        chroot-script enserv
       -}
       -
       -disableserv() {
       -        fn disableserv "$@"
       -        local service="$1"
       -        req=(service strapdir)
       -        ckreq || return 1
       +        mkdir -p "$R/log"
        
       -        cat <<EOF | sudo tee -a ${strapdir}/disserv >/dev/null
       -#!/bin/sh
       -update-rc.d ${service} disable
       -EOF
       +        local _divert=""
       +        local _path=""
       +        local _script=""
        
       -        notice "disabling $service service"
       -        chroot-script disserv
       -}
       +        case "x$1" in
       +        x-d)
       +                _divert=1
       +                shift
       +                ;;
       +        esac
        
       -install-custdebs() {
       -        fn install-custdebs
       -        req=(R strapdir custom_deb_packages)
       -        ckreq || return 1
       +        if [[ "$(dirname "$1")" = "." ]]; then
       +                _path="$strapdir"
       +        else
       +                _path="$(dirname "$1")"
       +        fi
        
       -        sudo mkdir -p $strapdir/debs
       -        sudo cp $R/extra/custom-packages/*.deb $strapdir/debs/
       +        _script="$(basename "$1")"
        
       -        cat <<EOF | sudo tee ${strapdir}/install-debs >/dev/null
       -#!/bin/sh
       -cd /debs
       -for deb in ${custom_deb_packages}; do
       -        dpkg -i \$deb
       -        apt-get --yes --force-yes -f install
       -done
       -cd /
       -apt-get --yes --force-yes autoremove
       -rm -rf /debs
       -EOF
       -        chroot-script -d install-debs
       -}
       +        if [[ -n "$_divert" ]]; then
       +                devprocsys mount "$_path" || { zerr; return 1; }
       +                dpkgdivert on "$_path"    || { zerr; return 1; }
       +        fi
        
       -chroot-script() {
       -        fn chroot-script "$@"
       -        req=(strapdir)
       -        ckreq || return 1
       +        sudo sed -i "$_path/$_script" \
       +                -e 's@^#!/bin/sh@&\nexport DEBIAN_FRONTEND=noninteractive@' \
       +                -e 's@^#!/bin/sh@&\nexport LC_ALL=C@' \
       +                -e 's@^#!/bin/sh@&\nexport LANG=C@' \
       +                -e 's@^#!/bin/sh@&\nset -x ; exec 2>/'$_script'.log@'
        
       -        mkdir -p "$R/log"
       +        notice "Chrooting to execute '$_script' ..."
       +        sudo chmod +x "$_path/$_script"  || { zerr; return 1; }
       +        sudo chroot "$_path" "/$_script" || { zerr; return 1; }
       +        sudo mv -f "$_path/${_script}.log" "$R/log/"
        
       -        case "x$1" in
       -                x-d)
       -                        local script="$2"
       -                        devprocsys mount "$strapdir" || zerr
       -                        dpkgdivert on "$strapdir"    || zerr
       -                        [[ "$APT_CACHE" = 1 ]] && { aptcache on "$strapdir/mnt"  || zerr }
       -
       -                        ## logging
       -                        sudo sed -i "$strapdir/$script" \
       -                                -e 's@#!/bin/sh@#!/bin/sh\'$'\nset -x ; exec 2>/'$script'.log ; export DEBIAN_FRONTEND=noninteractive@'
       -
       -                        notice "chrooting to execute $script..."
       -                        sudo chmod +x  "$strapdir/$script"    || zerr
       -                        sudo chroot "$strapdir" "/$script" || zerr
       -                        sudo mv -f "$strapdir/${script}.log" "$R/log/"
       -
       -                        [[ "$APT_CACHE" = 1 ]] && { aptcache off "$strapdir/mnt" || zerr }
       -                        dpkgdivert off "$strapdir"    || zerr
       -                        devprocsys umount "$strapdir" || zerr
       -                        ;;
       -                *)
       -                        local script="$1"
       -                        [[ "$APT_CACHE" = 1 ]] && { aptcache on "$strapdir/mnt"  || zerr }
       -
       -                        ## logging
       -                        sudo sed -i "$strapdir/$script" \
       -                                -e 's@#!/bin/sh@#!/bin/sh\'$'\nset -x ; exec 2>/'$script'.log@'
       -
       -                        notice "chrooting to execute $script..."
       -                        sudo chmod +x  "$strapdir/$script"    || zerr
       -                        sudo chroot "$strapdir" "/$script" || zerr
       -                        sudo mv -f "$strapdir/${script}.log" "$R/log/"
       -
       -                        [[ "$APT_CACHE" = 1 ]] && { aptcache off "$strapdir/mnt" || zerr }
       -                        ;;
       -        esac
       +        if [[ -n "$_divert" ]]; then
       +                dpkgdivert off "$_path"    || { zerr; return 1; }
       +                devprocsys umount "$_path" || { zerr; return 1; }
       +        fi
        
       -        sudo rm -f $strapdir/$script
       +        sudo rm -f "$_path/$_script"
        }
        
       -install_fake_package() {
       -        fn install_fake_package "$@"
       -        req=(strapdir pkgname pkgver section)
       -        local pkgname="$1"
       -        local pkgver="$2"
       -        local section="$3"
       +findloopdev()
       +{
       +        fn findloopdev
       +        req=(workdir image_name)
                ckreq || return 1
        
       -        local _tmp="$strapdir/tmp"
       -        sudo mkdir -p "$_tmp/$pkgname"
       -
       -        cat <<EOF | sudo tee ${_tmp}/${pkgname}/${pkgname}_${pkgver}.control >/dev/null
       -Section: ${section}
       -Priority: optional
       -Homepage: https://devuan.org/
       -Standards-Version: 3.9.6
       -
       -Package: ${pkgname}
       -Version: ${pkgver}
       -Maintainer: Devuan developers <onelove@devuan.org>
       -Architecture: all
       -Description: (Fake) ${pkgname}
       -  Dummy package used to meet some dependencies without installing the
       -  real ${pkgname} package.
       -EOF
       +        local _l="$(sudo losetup -f --show "$workdir/${image_name}.img")"
       +        if [[ -z "$_l" ]]; then
       +                zerr; return 1
       +        fi
        
       -        cat <<EOF | sudo tee ${strapdir}/install-fake-package >/dev/null
       -#!/bin/sh
       -cd /tmp/${pkgname}
       -equivs-build ${pkgname}_${pkgver}.control \
       -        && dpkg -i ${pkgname}_${pkgver}_all.deb || exit 1
       -cd /tmp
       -rm -rf ${pkgname}
       -EOF
       -        chroot-script install-fake-package || zerr
       +        echo "$_l"
        }
        
       -blend_preinst() {
       -        fn blend_preinst
       -        func "not overriden"
       -        return 0
       -}
       +findnbddev()
       +{
       +        fn findnbddev
        
       -blend_postinst() {
       -        fn blend_postinst
       -        func "not overriden"
       -        return 0
       +        notice "Finding a free /dev/nbd device"
       +
       +        for i in $(seq 0 8); do
       +                grep -q "^/dev/nbd${i}" /proc/mounts || {
       +                        echo "/dev/nbd${i}"
       +                        return
       +                }
       +        done
       +
       +        zerr; return 1
        }
        
       -silly() {
       +silly()
       +{
                fn silly "$@"
                local arg1="$1"
                local arg2="$2"
       -        ## cheers mailpile!
       -        funneh=("do not think of purple hippos"
       +        # Cheers Mailpile!
       +        funneh=(
       +                "do not think of purple hippos"
                        "increasing entropy & scrambling bits"
                        "indexing kittens..."
                        "patching bugs..."
       t@@ -406,10 +288,20 @@ silly() {
                        "Supplying monkeys with typewriters"
                        "Swapping time and space"
                        "Self potato"
       -                "god is porco"
       +                "God is porco"
                        "A million hamsters are spinning their wheels right now"
                )
                local rnd=$(shuf -i1-$#funneh -n 1)
                act "${funneh[$rnd]}"
                [[ $arg1 = sleep ]] && sleep $arg2 || true
        }
       +
       +blend_preinst()
       +{
       +        fn blend_preinst "(noop)"
       +}
       +
       +blend_postinst()
       +{
       +        fn blend_postinst "(noop)"
       +}
 (DIR) diff --git a/zlibs/imaging b/zlibs/imaging
       t@@ -1,4 +1,5 @@
        #!/usr/bin/env zsh
       +# shellcheck shell=bash
        # Copyright (c) 2016-2020 Dyne.org Foundation
        # libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
        #
       t@@ -17,305 +18,337 @@
        # You should have received a copy of the GNU General Public License
        # along with this source code. If not, see <http://www.gnu.org/licenses/>.
        
       -## imagine images
       +vars+=(bootpart rootpart loopdevice)
        
       -vars+=(image_name bootpart rootpart loopdevice filesystem)
       -arrs+=(fsargs)
       +strapdir_to_image()
       +{
       +        fn strapdir_to_image
       +        req=(workdir strapdir bootpart rootpart loopdevice)
       +        ckreq || return 1
       +
       +        notice "Copying strapdir to image ..."
       +
       +        if [[ ! -d "$workdir/mnt" ]]; then
       +                die "$workdir/mnt doesn't exist. Did you run image_mount?"
       +                zerr; return 1
       +        fi
        
       -image_prepare_raw() {
       +        pushd "$strapdir"
       +        sudo find . \
       +                -not -path "./dev/*" \
       +                -a -not -path "./proc/*" \
       +                -a -not -path "./sys/*" \
       +                | sudo cpio -p "$workdir/mnt" || { zerr; return 1; }
       +        popd
       +}
       +
       +image_prepare_raw()
       +{
                fn image_prepare_raw
                req=(workdir size image_name)
                ckreq || return 1
        
       -        notice "creating raw image file from zeroes..."
       +        notice "Creating raw image of $size MB"
       +        touch "$workdir/${image_name}.img"
       +        chattr +C "$workdir/${image_name}.img"
       +        dd if=/dev/zero of="$workdir/${image_name}.img" bs=1M count="$size" || { zerr; return 1; }
       +}
        
       -        dd if=/dev/zero \
       -                of=$workdir/${image_name}.img \
       -                bs=1M \
       -                count=$size
       +image_prepare_qcow2()
       +{
       +        fn image_prepare_qcow2
       +        req=(workdir size image_name)
       +        ckreq || return 1
       +
       +        notice "Creating qcow2 image of $size MB"
       +        touch "$workdir/${image_name}.qcow2"
       +        chattr +C "$workdir/${image_name}.qcow2"
       +        qemu-img create -f qcow2 "${workdir}/${image_name}.qcow2" "${size}M" || { zerr; return 1; }
        }
        
       -image_format_partitions() {
       +image_format_partitions()
       +{
                fn image_format_partitions
                req=(bootfs bootpart rootpart)
                ckreq || return 1
        
       -        notice "formatting partitions..."
       +        notice "Formatting image partitions"
       +
                case "$bootfs" in
       -                none)
       -                        act "skipping boot partition"
       -                        ;;
       -                vfat|fat|dos)
       -                        act "formatting boot as vfat"
       -                        sudo mkfs.vfat ${=bootopts} ${bootpart}
       -                        ;;
       -                ext4)
       -                        act "formatting boot as ext4"
       -                        sudo mkfs.ext4 ${=bootopts} ${bootpart}
       -                        ;;
       -                ext2)
       -                        act "formating boot as ext2"
       -                        sudo mkfs.ext2 ${=bootopts} ${bootpart}
       -                        ;;
       -                *)
       -                        error "unknown parted_bootfs type '$bootfs'"
       -                        zerr
       -                        ;;
       +        none)
       +                act "Skipping boot partition"
       +                ;;
       +        vfat|fat|dos)
       +                act "Formatting boot as VFAT"
       +                sudo mkfs.vfat ${=bootopts} "${bootpart}" || { zerr; return 1; }
       +                ;;
       +        ext?)
       +                act "Formatting boot as $bootfs"
       +                sudo mkfs.${bootfs} ${=bootopts} "${bootpart}" || { zerr; return 1; }
       +                ;;
       +        btrfs)
       +                act "Formatting boot as btrfs"
       +                sudo mkfs.btrfs ${=bootopts} "${bootpart}" || { zerr; return 1; }
       +                ;;
       +        "")
       +                die "No bootfs filesystem set!"
       +                zerr; return 1
       +                ;;
       +        *)
       +                die "Unimplemented filesystem: $bootfs"
       +                die "Please report it for inclusion."
       +                zerr; return 1
       +                ;;
                esac
        
       -        # default to ext4
       -        [[ -z "$rootfs" ]] && rootfs=ext4
       -
                case "$rootfs" in
       -                none)
       -                        act "skipping root partition"
       -                        ;;
       -                vfat|fat|dos)
       -                        act "formatting root as vfat"
       -                        sudo mkfs.vfat ${=rootopts} ${rootpart}
       -                        ;;
       -                ext4)
       -                        act "formatting root as ext4"
       -                        sudo mkfs.ext4 ${=rootopts} ${rootpart}
       -                        ;;
       -                ext2)
       -                        act "formating root as ext2"
       -                        sudo mkfs.ext2 ${=rootopts} ${rootpart}
       -                        ;;
       -                btrfs)
       -                        act "formatting root as btrfs"
       -                        sudo mfks.btrfs ${=rootopts} ${rootpart}
       -                        ;;
       -                *)
       -                        error "unknown parted_rootfs type '$rootfs'"
       -                        zerr
       -                        ;;
       +        none)
       +                act "Skipping root partition"
       +                ;;
       +        vfat|fat|dos)
       +                act "Formatting root as VFAT"
       +                sudo mkfs.vfat ${=rootopts} "${rootpart}" || { zerr; return 1; }
       +                ;;
       +        ext?)
       +                act "Formatting root as $rootfs"
       +                sudo mkfs.${rootfs} ${=rootopts} "${rootpart}" || { zerr; return 1; }
       +                ;;
       +        btrfs)
       +                act "Formatting root as btrfs"
       +                sudo mkfs.btrfs ${=rootopts} "${rootpart}" || { zerr; return 1; }
       +                ;;
       +        "")
       +                die "No rootfs filesystem set!"
       +                zerr; return 1
       +                ;;
       +        *)
       +                die "Unimplemented filesystem: $rootfs"
       +                die "Please report it for inclusion."
       +                zerr; return 1
       +                ;;
                esac
        }
        
       -image_partition_raw_dos() {
       -        fn image_partition_raw_dos
       -        req=(workdir image_name parted_boot parted_root)
       +image_connect_raw()
       +{
       +        fn image_connect_raw
       +        req=(workdir image_name)
                ckreq || return 1
        
       -        notice "partitioning raw dos image..."
       -
       -        parted $workdir/${image_name}.img --script -- mklabel msdos
       -        parted $workdir/${image_name}.img --script -- mkpart primary ${parted_boot}
       -        parted $workdir/${image_name}.img --script -- mkpart primary ${parted_root}
       -        [ -n "$bootable_part" ] && \
       -                parted "$workdir/${image_name}.img" --script -- set "$bootable_part" boot on
       -
       -        ## get loopdevice (see ./helpers)
       -        findloopdev
       +        notice "Connecting raw image to loop device"
        
       -        bootpart=${loopdevice}p1
       -        rootpart=${loopdevice}p2
       +        loopdevice="$(findloopdev)"
       +        if [[ -z "$loopdevice" ]]; then
       +                die "Didn't find a free loop device"
       +                zerr; return 1
       +        fi
        
       -        image_format_partitions
       +        bootpart="${loopdevice}p1"
       +        rootpart="${loopdevice}p2"
        }
        
       -image_partition_raw_gpt() {
       -        fn image_partition_raw_gpt
       -        req=(workdir image_name gpt_boot gpt_root)
       +image_connect_qcow2()
       +{
       +        fn image_connect_qcow2
       +        req=(workdir image_name)
                ckreq || return 1
        
       -        notice "partitioning raw gpt image..."
       +        notice "Connecting qcow2 image to nbd device"
        
       -        parted $workdir/${image_name}.img --script -- mklabel gpt || zerr
       -        cgpt create -z $workdir/${image_name}.img || zerr
       -        cgpt create    $workdir/${image_name}.img || zerr
       +        sudo modprobe nbd max_part=8 || { zerr; return 1; }
       +        loopdevice="$(findnbddev)"
       +        if [[ -z "$loopdevice" ]]; then
       +                die "Didn't find a free nbd device"
       +                zerr; return 1
       +        fi
        
       -        cgpt add -i 1 -t kernel -b ${gpt_boot[1]} \
       -                -s ${gpt_boot[2]} \
       -                -l kernel -S 1 -T 5 -P 10 $workdir/${image_name}.img
       +        sudo qemu-nbd --connect="${loopdevice}" "$workdir/${image_name}.qcow2" || { zerr; return 1; }
       +}
        
       -        cgpt add -i 2 -t data -b ${gpt_root[1]} \
       -                -s $(expr $(cgpt show $workdir/${image_name}.img | \
       -                awk '/Sec GPT table/ {print $1}') - ${gpt_root[1]}) \
       -                -l Root $workdir/${image_name}.img
       +image_partition_dos()
       +{
       +        fn image_partition_dos
       +        req=(loopdevice bootpart rootpart dos_boot dos_root)
       +        ckreq || return 1
        
       -        findloopdev
       +        notice "Partitioning dos image"
        
       -        bootpart="${loopdevice}p1"
       -        rootpart="${loopdevice}p2"
       +        sudo parted "$loopdevice" --script -- mklabel msdos || { zerr; return 1; }
       +        sudo parted "$loopdevice" --script -- mkpart primary "$dos_boot" || { zerr; return 1; }
       +        sudo parted "$loopdevice" --script -- mkpart primary "$dos_root" || { zerr; return 1; }
       +        if [[ -n "$bootable_part" ]]; then
       +                sudo parted "$loopdevice" --script -- set "$bootable_part" boot on
       +        fi
        
       -        image_format_partitions
       +        sudo partprobe "$loopdevice" || { zerr; return 1; }
        }
        
       -image_pack_dist() {
       -        fn image_pack_dist
       -        req=(loopdevice image_name strapdir workdir)
       +image_mount()
       +{
       +        fn image_mount
       +        req=(workdir bootpart rootpart bootfs)
                ckreq || return 1
        
       -        notice "packaging image for dist"
       +        notice "Mounting image to $workdir/mnt"
        
       -        act "rechecking filesystem"
       -        sudo e2fsck -fy ${loopdevice}p2
       -        sudo resize2fs ${loopdevice}p2
       +        mkdir -p "$workdir/mnt"
       +        sudo mount "$rootpart" "$workdir/mnt" || { zerr; return 1; }
       +        act "Mounted root partition"
        
       -        sleep 2
       -
       -        [[ $parted_type = gpt ]] && {
       -                sudo cgpt repair $loopdevice
       -                sleep 1
       -        }
       -
       -        case "$device_name" in
       -                pinephone-dontbeevil)
       -                        notice "dd-ing u-boot bootloader to image"
       -                        sudo dd if="$R/dist/u-boot-sunxi-with-spl-sopine.bin" \
       -                                of="$loopdevice" bs=1024 seek=8 || zerr
       -                        ;;
       -        esac
       +        if [[ "$bootfs" = none ]]; then
       +                return
       +        fi
        
       -        sudo partx -dv $loopdevice || {
       -                die "partx failed to remove $loopdevice"
       -                zerr
       -        }
       -        sudo losetup -d $loopdevice || {
       -                die "losetup failed to remove $loopdevice"
       -                zerr
       -        }
       +        sudo mkdir -p "$workdir/mnt/boot"
       +        sudo mount "$bootpart" "$workdir/mnt/boot" || { zerr; return 1; }
       +        act "Mounted boot partition"
       +}
        
       -        if [[ -n "$nocompressimage" ]]; then
       -                _suffix="img"
       -        else
       -                _suffix="img.xz"
       -        fi
       +image_umount()
       +{
       +        fn image_umount
       +        req=(workdir bootpart rootpart)
       +        ckreq || return 1
        
       -        pushd $workdir
       +        notice "Umounting image from $workdir/mnt"
        
       -        [[ -n "$nocompressimage" ]] || {
       -                if which pixz > /dev/null ; then
       -                        xzcomp=$(which pixz)
       -                else
       -                        xzcomp=$(which xz)
       -                fi
       +        sudo umount -R "$workdir/mnt" || { zerr; return 1; }
       +        act "Umounted"
        
       -                notice "compressing image with $xzcomp"
       -                silly
       +        act "Flushing bytes and buffers"
       +        sudo blockdev --flushbufs "$loopdevice" || { zerr; return 1; }
       +        sudo python -c 'import os; os.fsync(open("'$loopdevice'", "r+b"))' || { zerr; return 1; }
       +}
        
       -                $xzcomp "${image_name}.img"
       -        }
       +image_disconnect_raw()
       +{
       +        fn image_disconnect_raw
       +        req=(loopdevice bootfs rootfs bootpart rootpart)
       +        ckreq || return 1
        
       -        mkdir -p "$R/dist"
       -        mv -v ${image_name}.${_suffix} $R/dist/
       +        notice "Disconnecting image from $loopdevice"
        
       -        pushd "$R/dist"
       -        notice "generating sha256 for ${image_name}.${_suffix}"
       -        sha256sum ${image_name}.${_suffix} > ${image_name}.${_suffix}.sha
       -        notice "generating sha256 for ${image_name}.tar.gz"
       -        sha256sum ${image_name}.tar.gz > ${image_name}.tar.gz.sha
       -        popd
       +        act "Rechecking filesystems"
       +        case "$bootfs" in
       +        ext?)
       +                sudo e2fsck -fy "$bootpart"
       +                sudo resize2fs "$bootpart"
       +                ;;
       +        esac
        
       -        popd
       +        case "$rootfs" in
       +        ext?)
       +                sudo e2fsck -fy "$rootpart"
       +                sudo resize2fs "$rootpart"
       +                ;;
       +        esac
        
       -        [[ $DEBUG = 1 ]] || sudo rm -r $workdir
       +        act "Disconnecting"
       +        sudo partx -dv "$loopdevice" || {
       +                die "partx failed to remove $loopdevice"
       +                zerr; return 1
       +        }
        
       -        notice "finished packing $image_name"
       -        act "find it in $R/dist/"
       -        act "thanks for being patient!"
       +        sudo losetup -d "$loopdevice" || {
       +                die "losetup failed to remove $loopdevice"
       +                zerr; return 1
       +        }
        }
        
       -image_raw_mount() {
       -        fn image_raw_mount
       -        req=(workdir bootpart rootpart bootfs)
       +image_disconnect_qcow2()
       +{
       +        fn image_disconnect_qcow2
       +        req=(loopdevice bootfs rootfs bootpart rootpart)
                ckreq || return 1
        
       -        mkdir -p $workdir/mnt
       -        sudo mount $rootpart $workdir/mnt && \
       -                act "mounted root partition" || zerr
       +        notice "Disconnecting image from $loopdevice"
        
       -        [[ "$bootfs" == none ]] || {
       -                sudo mkdir -p $workdir/mnt/boot
       -                sudo mount $bootpart $workdir/mnt/boot && \
       -                        act "mounted boot partition" || zerr
       -        }
       -}
       +        act "Rechecking filesystems"
       +        case "$bootfs" in
       +        ext?)
       +                sudo e2fsck -fy "$bootpart"
       +                sudo resize2fs "$bootpart"
       +                ;;
       +        esac
        
       -image_raw_umount() {
       -        fn image_raw_umount
       -        req=(workdir bootpart rootpart)
       -        ckreq || return 1
       +        case "$rootfs" in
       +        ext?)
       +                sudo e2fsck -fy "$rootpart"
       +                sudo resize2fs "$rootpart"
       +                ;;
       +        esac
        
       -        [[ "$bootfs" == none ]] || {
       -                sudo umount $workdir/mnt/boot && act "unmounted boot partition" || zerr
       -                sleep 1
       -        }
       -        sudo umount $workdir/mnt      && act "unmounted root partition" || zerr
       +        act "Disconnecting"
       +
       +        sudo qemu-nbd --disconnect "$loopdevice" || { zerr; return 1; }
        }
        
       -image_raw_as_strapdir() {
       -        fn image_raw_as_strapdir
       -        req=(workdir strapdir size)
       +image_raw_to_qcow2()
       +{
       +        fn image_raw_to_qcow2
       +        req=(image_name workdir)
                ckreq || return 1
        
       -        pushd "$workdir"
       -
       -        notice "creating raw image of $size MB"
       -        sudo rm -f base.raw
       -        sudo qemu-img create -f raw base.raw ${size}M   || zerr
       -        notice "partitioning"
       -        sudo parted base.raw mktable msdos              || zerr
       -        sudo parted base.raw mkpart primary '0%' '100%' || zerr
       -        loopdevice=$(losetup --find)
       -        sudo losetup -P $loopdevice base.raw || zerr
       -        sudo mkfs.ext4 ${loopdevice}p1       || zerr
       -
       -        notice "mounting raw image to strapdir"
       -        sudo mount ${loopdevice}p1 $strapdir
       -        echo 1 | sudo tee ${strapdir}/.keep >/dev/null
       +        notice "Converting raw image to qcow2"
       +        pushd "$workdir" || { zerr; return 1; }
       +        touch "${image_name}.qcow2"
       +        chattr +C "${image_name}.qcow2"
       +        qemu-img convert -f raw -O qcow2 "${image_name}.img" "${image_name}.qcow2" || { zerr; return 1; }
                popd
        }
        
       -image_qcow2_as_strapdir() {
       -        fn image_qcow2_as_strapdir
       -        req=(workdir strapdir size)
       +image_raw_to_vdi()
       +{
       +        fn image_raw_to_vdi
       +        req=(image_name workdir)
                ckreq || return 1
        
       -        pushd "$workdir"
       -
       -        # default filesystem fallback to ext4
       -        filesystem=${filesystem:-ext4}
       -
       -        notice "creating qcow2 image of $size MB formatted with $filesystem"
       -        rm -f base.qcow2
       -        qemu-img create -f qcow2 base.qcow2 ${size}M     || zerr
       -        sudo modprobe nbd max_part=8                     || zerr
       -        loopdevice="$(findfreenbd)"
       -        [ -n "$loopdevice" ]                             || zerr
       -        act "$loopdevice"
       -        sudo qemu-nbd --connect=${loopdevice} base.qcow2 || zerr
       -
       -        notice "partitioning"
       -        sudo parted ${loopdevice} mktable msdos              || zerr
       -        sudo parted ${loopdevice} mkpart primary '0%' '100%' || zerr
       -
       -        notice "formatting with $filesystem"
       -        command -v mkfs.${filesystem} >/dev/null || {
       -                error "filesystem tools not found in path: mkfs.${filesystem}"
       -                zerr }
       -        sudo mkfs.${filesystem} ${=fsargs} ${loopdevice}p1 || zerr
       -
       -        notice "mounting qcow2 image to strapdir"
       -        sudo mount ${loopdevice}p1 $strapdir || zerr
       -        echo 1 | sudo tee ${strapdir}/.keep >/dev/null
       +        notice "Converting raw image to vdi"
       +        pushd "$workdir" || { zerr; return 1; }
       +        touch "${image_name}.vdi"
       +        chattr +C "${image_name}.vdi"
       +        qemu-img convert -f raw -O vdi "${image_name}.img" "${image_name}.vdi" || { zerr; return 1; }
       +        #VBoxManage modifyhd "${image_name}.vdi" --type immutable --compact || { zerr; return 1; }
                popd
        }
        
       -tar_strapdir() {
       -        fn tar_strapdir
       -        req=(strapdir)
       +image_pack_dist()
       +{
       +        fn image_pack_dist
       +        req=(R image_name workdir)
                ckreq || return 1
        
       -        notice "creating a tarbomb of the rootfs..."
       -        mkdir -p "$R/dist"
       +        notice "Packing up built images"
       +
       +        local _xzcomp=""
       +        local _rsuffix="img"
       +
       +        if [[ -n "$COMPRESS_IMAGE" ]]; then
       +                if command -v pixz >/dev/null; then
       +                        _xzcomp="$(command -v pixz)"
       +                else
       +                        _xzcomp="$(command -v xz)"
       +                fi
       +                _rsuffix="img.xz"
       +        fi
       +
       +        pushd "$workdir" || { zerr; return 1; }
       +
       +        if [[ -n "$COMPRESS_IMAGE" ]]; then
       +                act "Compressing images with $_xzcomp"
       +                silly
       +                $_xzcomp "${image_name}.img" || { zerr; return 1; }
       +                # TODO: cpio image?
       +        fi
       +
       +        act "Calculating sha256 checksums"
                silly
       -        pushd "$strapdir"
       -        sudo tar czf "$R/dist/${image_name}.tar.gz" . \
       -                --acls --selinux --xattrs \
       -                --xattrs-include=security.capability \
       -                --xattrs-include=user.pax.flags || zerr
       +        sha256sum "${image_name}.${_rsuffix}" > "${image_name}.${_rsuffix}.sha256"
       +        # TODO: cpio image?
       +        mkdir -p "$R/dist"
       +        mv -v "${image_name}".* "$R/dist" || { zerr; return 1; }
       +
       +        notice "Done! Thanks for being patient!"
       +
                popd
        }
 (DIR) diff --git a/zlibs/iso b/zlibs/iso
       t@@ -1,5 +1,6 @@
        #!/usr/bin/env zsh
       -# Copyright (c) 2016-2017 Dyne.org Foundation
       +# shellcheck shell=bash
       +# Copyright (c) 2016-2020 Dyne.org Foundation
        # libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
        #
        # This file is part of libdevuansdk
       t@@ -17,54 +18,55 @@
        # You should have received a copy of the GNU General Public License
        # along with this source code. If not, see <http://www.gnu.org/licenses/>.
        
       -## burn baby
       +vars+=(MKEFI)
        
       -#[[ $INSTALLER = 1 ]] && base_packages+=(grub-pc)
       -
       -iso_prepare_strap() {
       +iso_prepare_strap()
       +{
                fn iso_prepare_strap
                req=(strapdir)
                ckreq || return 1
        
       -        notice "preparing strapdir for livecd"
       +        notice "Preparing strapdir for Live CD"
        
       -        cat <<EOF | sudo tee ${strapdir}/isoprep >/dev/null
       +        cat <<EOF | sudo tee "$strapdir/isoprep" >/dev/null
        #!/bin/sh
        apt-get update
       -apt-get --yes --force-yes install dialog live-boot live-boot-initramfs-tools
       -apt-get --yes --force-yes autoremove
       +apt-get --yes --force-yes install dialog live-boot live-boot-initramfs-tools || exit 1
       +apt-get --yes --force-yes --purge autoremove || exit 1
        EOF
        
       -        chroot-script -d isoprep    || zerr
       +        chroot-script -d isoprep || { zerr; return 1; }
        }
        
       -iso_setup_isolinux() {
       +iso_setup_isolinux()
       +{
                fn iso_setup_isolinux
                req=(workdir strapdir)
                ckreq || return 1
        
       -        notice "setting up isolinux"
       +        notice "Setting up isolinux"
        
       -        pushd $workdir
       +        pushd "$workdir" || { zerr; return 1; }
                sudo mkdir -p binary/{live,isolinux}
       -        act "copying kernel and initrd"
       -        sudo cp $strapdir/boot/vmlinuz* binary/live/vmlinuz
       -        sudo cp $strapdir/boot/initrd*  binary/live/initrd.img
       -        #sudo cp $strapdir/boot/memtest86+.bin binary/live/memtest
       -
       -        sudo cp "$R"/extra/syslinux/isolinux.bin binary/isolinux || zerr
       -        sudo cp "$R"/extra/syslinux/*.c32 binary/isolinux || zerr
       +        act "Copyring kernel and initrd"
       +        sudo cp "$strapdir/boot/"vmlinuz* binary/live/vmlinuz || { zerr; return 1; }
       +        sudo cp "$strapdir/boot/"initrd*  binary/live/initrd.img || { zerr; return 1; }
       +        #sudo cp "$strapdir/boot/memtest86+.bin binary/live/memtest || { zerr; return 1; }
        
       +        sudo cp "$R/extra/syslinux/isolinux.bin" binary/isolinux || { zerr; return 1; }
       +        sudo cp "$R"/extra/syslinux/*.c32 binary/isolinux || { zerr; return 1; }
                popd
        }
        
       -iso_write_isolinux_cfg() {
       +iso_write_isolinux_cfg()
       +{
                fn iso_write_isolinux_cfg
                req=(workdir arch os)
                ckreq || return 1
        
       -        notice "writing isolinux configuration"
       -        cat <<EOF | sudo tee ${workdir}/binary/isolinux/isolinux.cfg >/dev/null
       +        notice "Writing isolinux configuration"
       +
       +        cat <<EOF | sudo tee "$workdir/binary/isolinux/isolinux.cfg" >/dev/null
        ui vesamenu.c32
        prompt 0
        menu title ${os} boot menu
       t@@ -80,49 +82,51 @@ endtext
        EOF
        }
        
       -iso_squash_strap() {
       +iso_squash_strap()
       +{
                fn iso_squash_strap
                req=(workdir strapdir)
                ckreq || return 1
        
       -        notice "creating squashfs out of strapdir"
       +        notice "Creating squashfs out of strapdir"
        
                case "$arch" in
       -                amd64|i386)
       -                        _compfilt="-Xbcj x86"
       -                        ;;
       -                arm*)
       -                        _compfilt="-Xbcj arm"
       -                        ;;
       -                *)
       -                        _compfilt=""
       -                        ;;
       +        amd64|i386)
       +                _compfilt="-Xbcj x86"
       +                ;;
       +        arm*)
       +                _compfilt="-Xbcj arm"
       +                ;;
       +        *)
       +                _compfilt=""
       +                ;;
                esac
       -        pushd $workdir
       -        sudo mksquashfs $strapdir binary/live/filesystem.squashfs \
       -                -comp xz ${=_compfilt} -noappend || zerr
        
       +        pushd "$workdir" || { zerr; return 1; }
       +        sudo mksquashfs "$strapdir" binary/live/filesystem.squashfs \
       +                -comp xz ${=_compfilt} -noappend || { zerr; return 1; }
                popd
        }
        
       -iso_xorriso_build() {
       +iso_xorriso_build()
       +{
                fn iso_xorriso_build
                req=(workdir image_name)
                ckreq || return 1
        
       -        notice "building iso..."
       +        notice "Building iso..."
                isoname="${image_name}-live.iso"
        
       -        [[ -n "$mkefi" ]] && {
       -        uefi_opt="-eltorito-alt-boot -e boot/grub/efiboot.img -isohybrid-gpt-basdat -no-emul-boot"
       -        }
       +        if [[ -n "$MKEFI" ]]; then
       +                uefi_opt="-eltorito-alt-boot -e boot/grub/efiboot.img -isohybrid-gpt-basdat -no-emul-boot"
       +        fi
        
       -        isohybrid="$R"/extra/syslinux/isohdpfx.bin
       +        isohybrid="$R/extra/syslinux/isohdpfx.bin"
        
       -        mkdir -p $R/dist
       -        pushd $workdir
       +        mkdir -p "$R/dist"
       +        pushd "$workdir"
                sudo xorriso -as mkisofs -r -J -joliet-long -l \
       -                -isohybrid-mbr $isohybrid \
       +                -isohybrid-mbr "$isohybrid" \
                        -partition_offset 16 \
                        -A "${os} Live - ${arch}" \
                        -b isolinux/isolinux.bin \
       t@@ -131,21 +135,20 @@ iso_xorriso_build() {
                        -boot-load-size 4 \
                        -boot-info-table \
                        ${=uefi_opt} \
       -                -o $R/dist/$isoname \
       -                binary || zerr
       +                -o "$R/dist/$isoname" \
       +                binary || { zerr; return 1; }
                popd
       -        unset uefi_opt
        
       -        [[ "$DEBUG" = 1 ]] || {
       -                [[ -n "$workdir" ]] && sudo rm -rf "$workdir"
       -        }
       -}
       +        act "Calculating sha256 checksums"
       +        pushd "$R/dist" || { zerr; return 1; }
       +        sha256sum "$isoname" > "${isoname}.sha256"
       +        popd
        
       -iso_setup_installer() {
       -        fn iso_setup_installer
       +        if [[ "$DEBUG" = 1 ]]; then
       +                return
       +        fi
        
       -        notice "setting up devuan-installer"
       -        sudo cp $R/extra/installer/* $strapdir/
       +        sudo rm -rf "$workdir"
        
       -        ## TODO: init to script
       +        notice "Done! Thanks for being patient!"
        }
 (DIR) diff --git a/zlibs/kernel b/zlibs/kernel
       t@@ -1,40 +0,0 @@
       -#!/usr/bin/env zsh
       -# Copyright (c) 2016-2017 Dyne.org Foundation
       -# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
       -#
       -# This file is part of libdevuansdk
       -#
       -# This source code 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.
       -#
       -# This software 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 this source code. If not, see <http://www.gnu.org/licenses/>.
       -
       -## all windows users are suckers
       -
       -build_kernel_${arch}() {
       -        fn build_kernel_${arch}
       -        req=(strapdir arch)
       -        ckreq || return 1
       -
       -        local kernel_base="linux-image"
       -        case "$arch" in
       -                amd64) local kernel="${kernel_base}-amd64";;
       -                i386)  local kernel="${kernel_base}-586";;
       -        esac
       -
       -        notice "installing stock kernel for $arch"
       -
       -        cat <<EOF | sudo tee ${strapdir}/install-linux
       -#!/bin/sh
       -apt-get --yes --force-yes install ${kernel}
       -EOF
       -        chroot-script -d install-linux || zerr
       -}
 (DIR) diff --git a/zlibs/rsync b/zlibs/rsync
       t@@ -1,44 +0,0 @@
       -#!/usr/bin/env zsh
       -# Copyright (c) 2016-2020 Dyne.org Foundation
       -# libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
       -#
       -# This file is part of libdevuansdk
       -#
       -# This source code 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.
       -#
       -# This software 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 this source code. If not, see <http://www.gnu.org/licenses/>.
       -
       -## ilpd
       -
       -rsync_to_raw_image() {
       -        fn rsync_to_raw_image
       -        req=(workdir strapdir bootpart rootpart)
       -        ckreq || return 1
       -
       -        notice "Preparing to rsync and tar the rootfs..."
       -        image_raw_mount
       -        silly sleep 1
       -
       -        mkdir -p $R/dist
       -        pushd $strapdir
       -                tar_strapdir || zerr
       -
       -                notice "rsyncing strapdir to raw image..."
       -                sudo rsync -HPaq ./* $workdir/mnt || {
       -                        image_raw_umount
       -                        die "not enough space, please report a bug"
       -                        zerr
       -                }
       -        popd
       -
       -        image_raw_umount
       -}
 (DIR) diff --git a/zlibs/sysconf b/zlibs/sysconf
       t@@ -1,5 +1,5 @@
        #!/usr/bin/env zsh
       -# Copyright (c) 2016-2019 Dyne.org Foundation
       +# Copyright (c) 2016-2020 Dyne.org Foundation
        # libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
        #
        # This file is part of libdevuansdk
       t@@ -95,7 +95,6 @@ conf_print_resolvconf() {
                fn conf_print_resolvconf
        
                cat <<EOF
       -## google's nameservers
        nameserver 8.8.8.8
        nameserver 8.8.4.4
        EOF
       t@@ -106,21 +105,14 @@ conf_print_sourceslist() {
                req=(mirror release section)
                ckreq || return 1
        
       -        [[ $APT_CACHE = 1 ]] && {
       -                cat <<EOF
       -deb file:/mnt ./
       -
       -EOF
       -        }
       -
                cat <<EOF
       -## package repositories
       +# Package repositories
        deb ${mirror} ${release} ${section}
        deb ${mirror} ${release}-updates ${section}
        deb ${mirror} ${release}-security ${section}
        #deb ${mirror} ${release}-backports ${section}
        
       -## source repositories
       +# Source repositories
        #deb-src ${mirror} ${release} ${section}
        #deb-src ${mirror} ${release}-updates ${section}
        #deb-src ${mirror} ${release}-security ${section}
 (DIR) diff --git a/zlibs/vm b/zlibs/vm
       t@@ -1,5 +1,6 @@
        #!/usr/bin/env zsh
       -# Copyright (c) 2016-2018 Dyne.org Foundation
       +# shellcheck shell=bash
       +# Copyright (c) 2016-2020 Dyne.org Foundation
        # libdevuansdk is maintained by Ivan J. <parazyd@dyne.org>
        #
        # This file is part of libdevuansdk
       t@@ -17,17 +18,17 @@
        # You should have received a copy of the GNU General Public License
        # along with this source code. If not, see <http://www.gnu.org/licenses/>.
        
       -## ma baker
       -
        vars+=(vmname)
        
       -vm_inject_overrides() {
       +vm_inject_overrides()
       +{
                fn vm_inject_overrides
                req=(strapdir)
                ckreq || return 1
        
       -        notice "injecting rootfs overrides"
       -        cat <<EOF | sudo tee ${strapdir}/etc/rc.local >/dev/null
       +        notice "Injecting rootfs overrides"
       +
       +        cat <<EOF | sudo tee "$strapdir/etc/rc.local" >/dev/null
        #!/bin/sh
        # rc.local for base images
        
       t@@ -35,210 +36,69 @@ vm_inject_overrides() {
        
        exit 0
        EOF
       -        sudo chmod +x $strapdir/etc/rc.local
       +        sudo chmod +x "$strapdir/etc/rc.local"
        
       -        print "rootfs / rootfs rw 0 0" | sudo tee ${strapdir}/etc/fstab >/dev/null
       -
       -        sudo sed -i ${strapdir}/etc/ssh/sshd_config \
       +        sudo sed -i "$strapdir/etc/ssh/sshd_config" \
                        -e 's/#PermitRootLogin .*/PermitRootLogin yes/' \
       -                -e 's/PermitRootLogin .*/PermitRootLogin yes/'|| zerr
       +                -e 's/PermitRootLogin .*/PermitRootLogin yes/' || { zerr; return 1; }
        }
        
       -vm_setup_grub() {
       +vm_setup_grub()
       +{
                fn vm_setup_grub
       -        req=(strapdir loopdevice)
       +        req=(workdir loopdevice bootfs)
                ckreq || return 1
        
       -        notice "setting up grub"
       -        cat <<EOF | sudo tee ${strapdir}/setupgrub >/dev/null
       +        notice "Setting up grub"
       +
       +        cat <<EOF | sudo tee "$workdir/mnt/setupgrub" >/dev/null
        #!/bin/sh
       -export DEBIAN_FRONTEND=noninteractive
       -apt-get --yes --force-yes install linux-image-amd64 grub-pc
       -sed -e 's:GRUB_TIMEOUT=5:GRUB_TIMEOUT=1:' -i /etc/default/grub
       -sed -e 's:GRUB_CMDLINE_LINUX_DEFAULT=".*":GRUB_CMDLINE_LINUX_DEFAULT="net.ifnames=0":' \
       -        -i /etc/default/grub
       -update-grub
       -grub-install --no-floppy --recheck --modules="biosdisk part_msdos" \
       -        ${loopdevice}
       -sed -e 's:${loopdevice}p1:/dev/sda1:g' -i /boot/grub/grub.cfg
       -sync; sync; sync
       +grub-install "${loopdevice}" || exit 1
       +grub-mkconfig -o /boot/grub/grub.cfg || exit 1
        EOF
       -        chroot-script -d setupgrub  || zerr
       -}
       -
       -vm_umount_${imageformat}() {
       -        fn vm_umount_${imageformat}
       -        req=(strapdir loopdevice imageformat)
       -        ckreq || return 1
       -
       -        notice "remounting ${imageformat} image"
       -        sudo mount -o remount,ro $strapdir || zerr
       -
       -        notice "flushing bytes and buffers"
       -        sudo blockdev --flushbufs $loopdevice || zerr
       -        sudo python -c 'import os;os.fsync(open("'${loopdevice}'", "r+b"))' || zerr
       -
       -        notice "unmounting ${imageformat} image from strapdir"
       -        sudo umount $strapdir || zerr
       -        silly sleep 1
       -        sudo rmdir $strapdir  || zerr
       -
       -        notice "cleaning up"
       -        case "$imageformat" in
       -                raw)
       -                        sudo losetup -d ${loopdevice} || zerr
       -                        ;;
       -                qcow2)
       -                        sudo qemu-nbd --disconnect ${loopdevice} || zerr
       -                        ;;
       -                *)
       -                        zerr
       -                        ;;
       -        esac
       -        silly sleep 1
       -}
       -
       -vm_vbox_setup() {
       -        fn vm_vbox_setup
       -        req=(workdir imageformat)
       -        ckreq || return 1
       -
       -        notice "converting ${imageformat} image to vdi"
       -        pushd $workdir
       -        qemu-img convert \
       -                -f ${imageformat} \
       -                -O vdi \
       -                base.${imageformat} \
       -                base.vdi || zerr
       -        VBoxManage modifyhd base.vdi --type immutable --compact || zerr
       -
       -        vmname="${os}-${release}-prevagrant-${RANDOM}"
       -        notice "importing base.vdi to a VBox"
       -        act "creating vm"
       -        VBoxManage createvm --name "$vmname" --ostype Debian_64 --register || zerr
       -
       -        act "setting up ram and group"
       -        VBoxManage modifyvm "$vmname" --memory 256 --groups /vmsdk || zerr
       -
       -        act "setting up storage"
       -        VBoxManage storagectl "$vmname" --name "IDE Controller" --add ide || zerr
       -
       -        act "attaching storage"
       -        VBoxManage storageattach "$vmname" --storagectl "IDE Controller" --port 0 \
       -                --device 0 --type hdd --medium base.vdi || zerr
       -
       -        vminfo="$(VBoxManage showvminfo "$vmname" --machinereadable)"
       -        diskuuid="$(getfield "$vminfo" '"IDE Controller-ImageUUID-0-0"')"
       -
       -        act "autoreset off on storage"
       -        VBoxManage modifyhd "$diskuuid" --autoreset off || zerr
       -
       -        act "setting up nat network"
       -        VBoxManage modifyvm "$vmname" --nic1 nat || zerr
       -        popd
       +        chroot-script -d "$workdir/mnt/setupgrub" || { zerr; return 1; }
        }
        
       -vm_vagrant_package() {
       -        fn vm_vagrant_package
       -        req=(workdir vmname)
       -        ckreq || return 1
       -
       -        notice "packaging a vagrant box"
       -
       -        pushd $workdir
       -        act "creating vagrantfile"
       -        cat <<EOF > Vagrantfile
       -Vagrant.configure("2") do |config|
       -        config.vm.box = "devuanbox.box"
       -        config.ssh.username = "root"
       -        config.ssh.password = "toor"
       -        config.vm.guest = :debian
       -        config.vm.synced_folder ".", "/vagrant", disabled: true
       -        # https://github.com/dotless-de/vagrant-vbguest
       -end
       -EOF
       -        act "creating metadata.json"
       -        cat <<EOF > metadata.json
       +vm_pack_dist()
        {
       -        "provider": "virtualbox"
       -}
       -EOF
       -        notice "actually packaging..."
       -        vagrant package --base "$vmname" --output ${vm_name}.box \
       -                --include metadata.json --vagrantfile Vagrantfile || zerr
       -        popd
       -}
       -
       -vm_init_cloud() {
       -        fn vm_init_cloud
       -        req=(workdir strapdir imageformat loopdevice)
       +        fn vm_pack_dist
       +        req=(R workdir image_name imageformat)
                ckreq || return 1
        
       -        [[ -n "$makecloud" ]] || return
       -        [[ "$imageformat" = qcow2 ]] || {
       -                die "imageformat is not qcow2"
       -                zerr
       -        }
       +        notice "Packing up built images"
        
       -        notice "Creating a cloud-based image"
       -        pushd "$workdir"
       -        cp -v "base.qcow2" "base-cloud.qcow2"
       +        local _xzcomp=""
       +        local _rsuffix="${imageformat}"
       +        local _vsuffix="vdi"
        
       -        notice "Connecting qemu-nbd and mounting"
       -        sudo mkdir -p "$strapdir"
       -        sudo qemu-nbd --connect=${loopdevice} base-cloud.qcow2 || zerr
       -        silly sleep 1
       -        sudo mount ${loopdevice}p1 $strapdir || zerr
       +        if [[ -n "$COMPRESS_IMAGE" ]]; then
       +                if command -v pixz >/dev/null; then
       +                        _xzcomp="$(command -v pixz)"
       +                else
       +                        _xzcomp="$(command -v xz)"
       +                fi
       +                _rsuffix="${imageformat}.xz"
       +                _vsuffix="vdi.xz"
       +        fi
        
       -        notice "Installing cloud-init"
       -        cat <<EOF | sudo tee ${strapdir}/initcloud >/dev/null
       -#!/bin/sh
       +        pushd "$workdir" || { zerr; return 1; }
        
       -apt-get update
       -apt-get --yes --force-yes install cloud-init
       -apt-get clean
       -EOF
       -        chroot-script -d initcloud || zerr
       -        vm_umount_${imageformat} || zerr
       -        popd
       -}
       +        if [[ -n "$COMPRESS_IMAGE" ]]; then
       +                act "Compressing images with $_xzcomp"
       +                silly
       +                $_xzcomp "${image_name}.${imageformat}" || { zerr; return 1; }
       +                $_xzcomp "${image_name}.vdi" || { zerr; return 1; }
       +        fi
        
       -vm_pack_dist() {
       -        fn vm_pack_dist
       -        req=(workdir imageformat)
       -        ckreq || return 1
       +        act "Calculating sha256 checksums"
       +        silly
       +        sha256sum "${image_name}.${_rsuffix}" > "${image_name}.${_rsuffix}.sha256"
       +        sha256sum "${image_name}.${_vsuffix}" > "${image_name}.${_vsuffix}.sha256"
        
       -        notice "packing up dist"
       -        mkdir -p $R/dist
       -        mv $workdir/${vm_name}.box $R/dist
       -        mv $workdir/base.${imageformat} $R/dist/${vm_name}.${imageformat}
       -        cp $workdir/base.vdi $R/dist/${vm_name}.vdi
       +        mkdir -p "$R/dist"
       +        mv -v "${image_name}".* "$R/dist" || { zerr; return 1; }
        
       -        [[ -n "$makecloud" ]] && \
       -                mv $workdir/base-cloud.${imageformat} \
       -                        $R/dist/${vm_name}-cloud.${imageformat}
       +        notice "Done! Thanks for being patient!"
        
       -        act "calculating sha256 sums..."
       -        silly
       -        sha256sum $R/dist/${vm_name}.box > \
       -                $R/dist/${vm_name}.box.sha
       -        sha256sum $R/dist/${vm_name}.${imageformat} > \
       -                $R/dist/${vm_name}.${imageformat}.sha
       -        sha256sum $R/dist/${vm_name}.vdi > \
       -                $R/dist/${vm_name}.vdi.sha
       -        [[ -n "$makecloud" ]] && \
       -                sha256sum $R/dist/${vm_name}-cloud.${imageformat} > \
       -                        $R/dist/${vm_name}-cloud.${imageformat}.sha
       -
       -        notice "cleaning up virtualbox leftovers"
       -        pushd "$workdir"
       -                VBoxManage unregistervm "$vmname" --delete
       -                rm -f metadata.json Vagrantfile
       -                rm -rf .vagrant
                popd
       -        rm -rf "$workdir"
       -        rm -rf "$HOME/VirtualBox VMs/vmsdk"
       -
       -        notice "done!"
       -        ls -1 $R/dist
        }