#!/bin/sh -e set -e def_arch=$(uname -m) def_ver="1.0-rc1" readonly PROGNAME=$(basename $0) [ -z $ZSH_VERSION ] || set -y warn() { printf '>>> ' printf '\033[01;33mWARNING\033[00;39m ' printf '>>> ' printf '\033[01;33mWARNING\033[00;39m ' printf '>>> ' printf '\033[01;33mWARNING\033[00;39m ' printf '>>> ' printf '\033[01;33mWARNING\033[00;39m ' printf '>>>\n' } fatal() { printf '>>> ' printf '\033[01;31mERROR\033[00;39m ' printf '>>> ' printf '\033[01;31mERROR\033[00;39m ' printf '>>> ' printf '\033[01;31mERROR\033[00;39m ' printf '>>> ' printf '\033[01;31mERROR\033[00;39m ' printf '>>>\n' } ensure_commands() { if ! command -v apk>/dev/null 2>/dev/null; then fatal printf 'You must have apk installed. On Gentoo, see sys-devel/apk-tools.\n' exit 127 fi if ! command -pv cpio>/dev/null 2>/dev/null; then fatal printf 'You must have cpio installed. On Gentoo, see app-arch/cpio.\n' exit 127 fi if ! command -v mksquashfs>/dev/null 2>/dev/null; then fatal printf 'You must have mksquashfs installed. On Gentoo, see sys-fs/squashfs-tools.\n' exit 127 fi if ! command -v xorriso>/dev/null 2>/dev/null; then fatal printf 'You must have xorriso installed:\n\n' printf '* cdrkit (Alpine, Gentoo) will not generate a usable PPC ISO.\n' printf '* wodim (Debian) will not generate a usable PPC64 ISO.\n' printf '* cdrtools (Schily) will overrun the PPC64 ISO and write junk to grubcore.img.\n' printf '\nSorry, but xorriso really is required.\n' exit 127 fi } usage() { printf 'usage: %s [-a ARCH] [-f|--full] [-k|--kind KIND] [-p|--phase PHASE] [-v VERSION] [--help]\n\n' $PROGNAME printf 'Create an Adélie Linux CD image (.ISO) using the specified parameters.\n\n' printf 'Default ARCH: %s\n' $def_arch printf 'Default VERSION: %s\n' $def_ver printf 'Valid phases: clean install initrd iso all\n' } [ -d /etc/apk/cache ] && def_cache=/etc/apk/cache while [ -n "$1" ]; do case $1 in -a | --arch) shift readonly MY_ARCH=$1 ;; -h | --help) usage exit ;; -f | --full) readonly DO_FULL=full ;; -k | --kind) shift readonly MY_KIND=$1 ;; -p | --phase) shift readonly MY_PHASE=$1 ;; -s | --sign) readonly SIGN=yes ;; -v | --version) shift readonly MY_VER=$1 ;; -c | --cache) shift readonly MY_CACHE=$1 ;; --no-cache) unset def_cache ;; *) usage >&2 exit 127 ;; esac shift done set -a readonly ARCH=${MY_ARCH:-$def_arch} readonly KIND=${MY_KIND:-live} readonly LDARCH=${LDARCH:-$ARCH} readonly PHASE=${MY_PHASE:-all} readonly VERSION=${MY_VER:-$def_ver} readonly APKVER=${MY_APKVER:-$VERSION} readonly URL=${MY_URL:-https://distfiles.adelielinux.org/adelie/$APKVER/} readonly CACHE=${MY_CACHE:-$def_cache} set +a ensure_commands header() { printf '\033[01;32m * \033[37m%s\033[00;39m\n' "$1" } header 'Adélie Linux CD Creation Tool' printf '\n' clean_dirs() { warn printf 'This will erase all files at the directories %s/cdroot-%s\n' `pwd` $ARCH printf '%s/initrd-%s and %s/squashroot-%s.\n\n' `pwd` $ARCH `pwd` $ARCH printf 'When you are ready, press RETURN. To cancel, press Ctrl-C.\n' read dontcare rm -rf cdroot-$ARCH rm -rf initrd-$ARCH rm -rf squashroot-$ARCH mkdir cdroot-$ARCH mkdir initrd-$ARCH mkdir squashroot-$ARCH } install_pkgs() { header "Installing base system to squash root..." readonly PACKAGES="$(cat packages/base 2>/dev/null | tr '\n' ' ' || fatal 'No core packages specified')" readonly ARCH_PKGS="$(cat packages/arch/$ARCH 2>/dev/null | tr '\n' ' ' || echo '')" readonly KIND_PKGS="$(cat packages/kind/$KIND 2>/dev/null | tr '\n' ' ' || echo '')" mkdir -p squashroot-$ARCH/etc/apk cp -r keys squashroot-$ARCH/etc/apk/ # Disable grub trigger. mkdir -p squashroot-$ARCH/etc/default printf "ADELIE_MANUAL_CONFIG=1\n" >> squashroot-$ARCH/etc/default/grub mkdir -p squashroot-$ARCH/dev mknod squashroot-$ARCH/dev/urandom c 1 9 mkdir -p squashroot-$ARCH/usr/sbin apk --arch $ARCH \ ${CACHE:+--cache-dir "${CACHE}"} \ -X "$URL/system/$EXTRA_MIRROR" \ -X "$URL/user/$EXTRA_MIRROR" \ -U --root squashroot-$ARCH --initdb add $PACKAGES $ARCH_PKGS $KIND_PKGS } make_structure() { mkdir -p squashroot-$ARCH/home/live cp squashroot-$ARCH/etc/skel/.zshrc squashroot-$ARCH/home/live/ chown 1000:1000 squashroot-$ARCH/home/live/.zshrc mkdir squashroot-$ARCH/target mkdir -p squashroot-$ARCH/media/live for _runlevel in sysinit boot default shutdown; do mkdir -p squashroot-$ARCH/etc/runlevels/$_runlevel done echo 'adelie-live' > squashroot-$ARCH/etc/hostname echo 'mtab_is_file=no' > squashroot-$ARCH/etc/conf.d/mtab for siservice in udev udev-trigger lvmetad; do ln -s /etc/init.d/$siservice \ squashroot-$ARCH/etc/runlevels/sysinit/$siservice done for bootservice in root binfmt bootmisc fsck hostname hwclock keymaps \ localmount loopback modules mtab procfs sysctl sysfsconf \ termencoding tmpfiles.setup urandom; do ln -s /etc/init.d/$bootservice \ squashroot-$ARCH/etc/runlevels/boot/$bootservice done readonly BASE_SERVICES="$(cat services/base 2>/dev/null | tr '\n' ' ' || echo '')" readonly KIND_SERVICES="$(cat services/kind/$KIND 2>/dev/null | tr '\n' ' ' || echo '')" [ -z BASE_SERVICES ] || for base_service in $BASE_SERVICES; do ln -s /etc/init.d/$base_service \ sqaushroot-$ARCH/etc/runlevels/default/$base_service done [ -z KIND_SERVICES ] || for service in $KIND_SERVICES; do ln -s /etc/init.d/$service \ sqaushroot-$ARCH/etc/runlevels/default/$service done cat >squashroot-$ARCH/etc/fstab <<- FSTAB # Welcome to Adélie Linux. # This fstab(5) is for the live media only. Do not edit or use for your installation. tmpfs /tmp tmpfs defaults 0 1 proc /proc proc defaults 0 1 FSTAB sed -i 's#/root:/bin/sh$#/root:/bin/zsh#' squashroot-$ARCH/etc/passwd echo 'live:x:1000:1000:Live User:/home/live:/bin/zsh' >> squashroot-$ARCH/etc/passwd echo 'live:x:1000:' >> squashroot-$ARCH/etc/group echo 'live::::::::' >> squashroot-$ARCH/etc/shadow chown 1000:1000 squashroot-$ARCH/home/live sed -i 's/pam_unix.so$/pam_unix.so nullok_secure/' squashroot-$ARCH/etc/pam.d/base-auth cat >squashroot-$ARCH/etc/resolv.conf <<- RESOLVE nameserver 2620:fe::fe nameserver 9.9.9.9 nameserver 149.112.112.112 RESOLVE cat >squashroot-$ARCH/etc/apk/repositories <<-REPOS https://distfiles.adelielinux.org/adelie/$APKVER/system/$EXTRA_MIRROR https://distfiles.adelielinux.org/adelie/$APKVER/user/$EXTRA_MIRROR REPOS # Saves first-sync on the media if a package is required. apk --root squashroot-$ARCH update cat >squashroot-$ARCH/etc/issue <<-ISSUE Welcome to Adélie Linux! You may log in as 'root' to install, or 'live' to play around. Have fun. ISSUE if test -n "${DO_FULL+full}"; then # This ensures we have documentation available on-disc, and to install. apk --arch $ARCH \ ${CACHE:+--cache-dir "${CACHE}"} \ -X "$URL/system/$EXTRA_MIRROR" \ -X "$URL/user/$EXTRA_MIRROR" \ --root squashroot-$ARCH add docs readonly PACKAGES_DIR=squashroot-$ARCH/packages/$ARCH mkdir -p $PACKAGES_DIR # Fetch all APKs. apk --arch $ARCH \ ${CACHE:+--cache-dir "${CACHE}"} \ -X "$URL/system/$EXTRA_MIRROR" \ -X "$URL/user/$EXTRA_MIRROR" \ --root squashroot-$ARCH fetch -o $PACKAGES_DIR $(apk --root squashroot-$ARCH info) # Sign the index using the signing key used by abuild. if test -n "${SIGN+doit}"; then apk index --description "$VERSION/$ARCH Live CD" -o .tmp.APKINDEX.tar.gz $PACKAGES_DIR/*.apk abuild-sign -q .tmp.APKINDEX.tar.gz mv .tmp.APKINDEX.tar.gz $PACKAGES_DIR/APKINDEX.tar.gz fi fi cp AdelieTux.icns cdroot-$ARCH/.VolumeIcon.icns } squash_it() { header 'Creating compressed file system image...' mksquashfs squashroot-$ARCH cdroot-$ARCH/$ARCH.squashfs -noappend } make_initrd() { header 'Creating initrd structure...' # mount points mkdir initrd-$ARCH/dev mkdir initrd-$ARCH/media for _rootdir in newroot lowerroot upperroot; do mkdir initrd-$ARCH/$_rootdir chmod 755 initrd-$ARCH/$_rootdir done mkdir initrd-$ARCH/proc mkdir initrd-$ARCH/sys # manual /dev nodes for initial udev startup mknod -m 600 initrd-$ARCH/dev/console c 5 1 mknod -m 666 initrd-$ARCH/dev/null c 1 3 mknod -m 666 initrd-$ARCH/dev/ptmx c 5 2 mknod -m 666 initrd-$ARCH/dev/random c 1 8 mknod -m 666 initrd-$ARCH/dev/tty c 5 0 mknod -m 620 initrd-$ARCH/dev/tty1 c 4 1 mknod -m 666 initrd-$ARCH/dev/urandom c 1 9 mknod -m 666 initrd-$ARCH/dev/zero c 1 5 # base mkdir initrd-$ARCH/lib cp squashroot-$ARCH/lib/ld-musl-$LDARCH.so.1 initrd-$ARCH/lib/ cp squashroot-$ARCH/lib/libblkid.so.1 initrd-$ARCH/lib/ cp squashroot-$ARCH/lib/libuuid.so.1 initrd-$ARCH/lib/ # udev mkdir -p initrd-$ARCH/etc/udev mkdir initrd-$ARCH/run mkdir initrd-$ARCH/sbin cp squashroot-$ARCH/bin/udevadm initrd-$ARCH/sbin/ cp squashroot-$ARCH/sbin/udevd initrd-$ARCH/sbin/ cp squashroot-$ARCH/lib/libkmod.so.2 initrd-$ARCH/lib/ cp squashroot-$ARCH/lib/liblzma.so.5 initrd-$ARCH/lib/ cp squashroot-$ARCH/lib/libudev.so.1 initrd-$ARCH/lib/ cp squashroot-$ARCH/lib/libz.so.1 initrd-$ARCH/lib/ # init cp cdinit-$ARCH initrd-$ARCH/init header 'Compressing initrd...' (cd initrd-$ARCH; find . | cpio -H newc -o) > cdroot-$ARCH/initrd-$ARCH gzip -9 cdroot-$ARCH/initrd-$ARCH mv cdroot-$ARCH/initrd-$ARCH.gz cdroot-$ARCH/initrd-$ARCH } prepare_cdroot() { if test -f post/arch/$ARCH.sh; then header 'Running architecture-specific scripts...' sh post/arch/$ARCH.sh fi if test -f post/kind/$KIND.sh; then header "Running $KIND script..." sh post/kind/$KIND.sh fi header 'Adding kernel...' mv squashroot-$ARCH/boot/vmlinu* cdroot-$ARCH/bzImage-$ARCH } create_iso() { CD_VERSION="$VERSION" header 'Creating the CD...' readonly CD_PARAMS="$(cat iso-params-$ARCH | tr '\n' ' ')" CD_VERSION=$(echo $CD_VERSION | sed s/-alpha/a/) CD_VERSION=$(echo $CD_VERSION | sed s/-beta/b/) CD_VERSION=$(echo $CD_VERSION | sed s/-rc/rc/) mkdir -p out xorriso -as mkisofs -o out/adelie-${DO_FULL:-live}-$ARCH-$VERSION-$(date +%Y%m%d).iso -joliet -rational-rock -V "Adelie $CD_VERSION $ARCH" ${CD_PARAMS} cdroot-$ARCH } case $PHASE in clean) clean_dirs ;; install) install_pkgs make_structure ;; initrd) make_initrd ;; iso) create_iso ;; all) clean_dirs install_pkgs make_structure make_initrd squash_it prepare_cdroot create_iso ;; all_but_iso) clean_dirs install_pkgs make_structure make_initrd squash_it prepare_cdroot ;; *) fatal printf 'Unknown phase %s. Stop.\n' $PHASE ;; esac