diff options
Diffstat (limited to 'build_tools/archiso-19/archiso/mkarchiso')
| -rwxr-xr-x | build_tools/archiso-19/archiso/mkarchiso | 392 | 
1 files changed, 392 insertions, 0 deletions
| diff --git a/build_tools/archiso-19/archiso/mkarchiso b/build_tools/archiso-19/archiso/mkarchiso new file mode 100755 index 0000000..5643525 --- /dev/null +++ b/build_tools/archiso-19/archiso/mkarchiso @@ -0,0 +1,392 @@ +#!/bin/bash + +set -e -u + +export LANG=C + +app_name=${0##*/} +arch=$(uname -m) +pkg_list="" +run_cmd="" +quiet="y" +pacman_conf="/etc/pacman.conf" +export iso_label="ARCH_$(date +%Y%m)" +iso_publisher="Arch Linux <http://www.archlinux.org>" +iso_application="Arch Linux Live/Rescue CD" +install_dir="arch" +work_dir="work" +out_dir="out" +sfs_comp="xz" + +# Show an INFO message +# $1: message string +_msg_info() { +    local _msg="${1}" +    echo "[mkarchiso] INFO: ${_msg}" +} + +# Show an ERROR message then exit with status +# $1: message string +# $2: exit code number (with 0 does not exit) +_msg_error() { +    local _msg="${1}" +    local _error=${2} +    echo +    echo "[mkarchiso] ERROR: ${_msg}" +    echo +    if [[ ${_error} -gt 0 ]]; then +        exit ${_error} +    fi +} + +_chroot_init() { +    mkdir -p ${work_dir}/airootfs +    _pacman "base syslinux" +} + +_chroot_run() { +    eval arch-chroot ${work_dir}/airootfs "${run_cmd}" +} + +_mount_airootfs() { +    trap "_umount_airootfs" EXIT HUP INT TERM +    mkdir -p "${work_dir}/mnt/airootfs" +    _msg_info "Mounting '${work_dir}/airootfs.img' on '${work_dir}/mnt/airootfs'" +    mount "${work_dir}/airootfs.img" "${work_dir}/mnt/airootfs" +    _msg_info "Done!" +} + +_umount_airootfs() { +    _msg_info "Unmounting '${work_dir}/mnt/airootfs'" +    umount "${work_dir}/mnt/airootfs" +    _msg_info "Done!" +    rmdir "${work_dir}/mnt/airootfs" +    trap - EXIT HUP INT TERM +} + +# Show help usage, with an exit status. +# $1: exit status number. +_usage () +{ +    echo "usage ${app_name} [options] command <command options>" +    echo " general options:" +    echo "    -p PACKAGE(S)    Package(s) to install, can be used multiple times" +    echo "    -r <command>     Run <command> inside airootfs" +    echo "    -C <file>        Config file for pacman." +    echo "                     Default: '${pacman_conf}'" +    echo "    -L <label>       Set a label for the disk" +    echo "                     Default: '${iso_label}'" +    echo "    -P <publisher>   Set a publisher for the disk" +    echo "                     Default: '${iso_publisher}'" +    echo "    -A <application> Set an application name for the disk" +    echo "                     Default: '${iso_application}'" +    echo "    -D <install_dir> Set an install_dir. All files will by located here." +    echo "                     Default: '${install_dir}'" +    echo "                     NOTE: Max 8 characters, use only [a-z0-9]" +    echo "    -w <work_dir>    Set the working directory" +    echo "                     Default: '${work_dir}'" +    echo "    -o <out_dir>     Set the output directory" +    echo "                     Default: '${out_dir}'" +    echo "    -c <comp_type>   Set SquashFS compression type (gzip, lzma, lzo, xz)" +    echo "                     Default: '${sfs_comp}'" +    echo "    -v               Enable verbose output" +    echo "    -h               This message" +    echo " commands:" +    echo "   init" +    echo "      Make base layout and install base group" +    echo "   install" +    echo "      Install all specified packages (-p)" +    echo "   run" +    echo "      run command specified by -r" +    echo "   prepare" +    echo "      build all images" +    echo "   pkglist" +    echo "      make a pkglist.txt of packages installed on airootfs" +    echo "   iso <image name>" +    echo "      build an iso image from the working dir" +    exit ${1} +} + +# Shows configuration according to command mode. +# $1: init | install | run | prepare | iso +_show_config () { +    local _mode="$1" +    echo +    _msg_info "Configuration settings" +    _msg_info "                  Command:   ${command_name}" +    _msg_info "             Architecture:   ${arch}" +    _msg_info "        Working directory:   ${work_dir}" +    _msg_info "   Installation directory:   ${install_dir}" +    case "${_mode}" in +        init) +            _msg_info "       Pacman config file:   ${pacman_conf}" +            ;; +        install) +            _msg_info "       Pacman config file:   ${pacman_conf}" +            _msg_info "                 Packages:   ${pkg_list}" +            ;; +        run) +            _msg_info "              Run command:   ${run_cmd}" +            ;; +        prepare) +            ;; +        pkglist) +            ;; +        iso) +            _msg_info "               Image name:   ${img_name}" +            _msg_info "               Disk label:   ${iso_label}" +            _msg_info "           Disk publisher:   ${iso_publisher}" +            _msg_info "         Disk application:   ${iso_application}" +            ;; +    esac +    echo +} + +# Install desired packages to airootfs +_pacman () +{ +    _msg_info "Installing packages to '${work_dir}/airootfs/'..." + +    if [[ "${quiet}" = "y" ]]; then +        pacstrap -C "${pacman_conf}" -c -d -G -M "${work_dir}/airootfs" $* &> /dev/null +    else +        pacstrap -C "${pacman_conf}" -c -d -G -M "${work_dir}/airootfs" $* +    fi + +    _msg_info "Packages installed successfully!" +} + +# Cleanup airootfs +_cleanup () { +    _msg_info "Cleaning up what we can on airootfs..." + +    # Delete initcpio image(s) +    if [[ -d "${work_dir}/airootfs/boot" ]]; then +        find "${work_dir}/airootfs/boot" -type f -name '*.img' -delete +    fi +    # Delete kernel(s) +    if [[ -d "${work_dir}/airootfs/boot" ]]; then +        find "${work_dir}/airootfs/boot" -type f -name 'vmlinuz*' -delete +    fi +    # Delete pacman database sync cache files (*.tar.gz) +    if [[ -d "${work_dir}/airootfs/var/lib/pacman" ]]; then +        find "${work_dir}/airootfs/var/lib/pacman" -maxdepth 1 -type f -delete +    fi +    # Delete pacman database sync cache +    if [[ -d "${work_dir}/airootfs/var/lib/pacman/sync" ]]; then +        find "${work_dir}/airootfs/var/lib/pacman/sync" -delete +    fi +    # Delete pacman package cache +    if [[ -d "${work_dir}/airootfs/var/cache/pacman/pkg" ]]; then +        find "${work_dir}/airootfs/var/cache/pacman/pkg" -type f -delete +    fi +    # Delete all log files, keeps empty dirs. +    if [[ -d "${work_dir}/airootfs/var/log" ]]; then +        find "${work_dir}/airootfs/var/log" -type f -delete +    fi +    # Delete all temporary files and dirs +    if [[ -d "${work_dir}/airootfs/var/tmp" ]]; then +        find "${work_dir}/airootfs/var/tmp" -mindepth 1 -delete +    fi +    # Delete package pacman related files. +    find "${work_dir}" \( -name "*.pacnew" -o -name "*.pacsave" -o -name "*.pacorig" \) -delete +    _msg_info "Done!" +} + +# Makes a filesystem from a source directory. +_mkairootfs () { +    if [[ ! -e "${work_dir}/airootfs" ]]; then +        _msg_error "The path '${work_dir}/airootfs' does not exist" 1 +    fi + +    _msg_info "Creating ext4 image of 32GiB..." +    truncate -s 32G "${work_dir}/airootfs.img" +    local _qflag="" +    if [[ ${quiet} == "y" ]]; then +        _qflag="-q" +    fi +    mkfs.ext4 ${_qflag} -O ^has_journal,^resize_inode -E lazy_itable_init=0 -m 0 -F "${work_dir}/airootfs.img" +    tune2fs -c 0 -i 0 "${work_dir}/airootfs.img" &> /dev/null +    _msg_info "Done!" +    _mount_airootfs +    _msg_info "Copying '${work_dir}/airootfs/' to '${work_dir}/mnt/airootfs/'..." +    cp -aT "${work_dir}/airootfs/" "${work_dir}/mnt/airootfs/" +    _msg_info "Done!" +    _umount_airootfs +    mkdir -p "${work_dir}/iso/${install_dir}/${arch}" +    _msg_info "Creating SquashFS image, this may take some time..." +    if [[ "${quiet}" = "y" ]]; then +        mksquashfs "${work_dir}/airootfs.img" "${work_dir}/iso/${install_dir}/${arch}/airootfs.sfs" -noappend -comp "${sfs_comp}" -no-progress &> /dev/null +    else +        mksquashfs "${work_dir}/airootfs.img" "${work_dir}/iso/${install_dir}/${arch}/airootfs.sfs" -noappend -comp "${sfs_comp}" -no-progress +    fi +    _msg_info "Done!" +    rm ${work_dir}/airootfs.img +} + +_mkchecksum () { +    _msg_info "Creating checksum file for self-test..." +    cd "${work_dir}/iso/${install_dir}/${arch}" +    md5sum airootfs.sfs > airootfs.md5 +    cd ${OLDPWD} +    _msg_info "Done!" +} + +command_pkglist () { +    _show_config pkglist + +    _msg_info "Creating a list of installed packages on live-enviroment..." +    pacman -Sl -r "${work_dir}/airootfs" --config "${pacman_conf}" | \ +        awk '/\[installed\]$/ {print $1 "/" $2 "-" $3}' > \ +        "${work_dir}/iso/${install_dir}/pkglist.${arch}.txt" +    _msg_info "Done!" + +} + +# Create an ISO9660 filesystem from "iso" directory. +command_iso () { +    local _iso_efi_boot_args="" + +    if [[ ! -f "${work_dir}/iso/isolinux/isolinux.bin" ]]; then +         _msg_error "The file '${work_dir}/iso/isolinux/isolinux.bin' does not exist." 1 +    fi +    if [[ ! -f "${work_dir}/iso/isolinux/isohdpfx.bin" ]]; then +         _msg_error "The file '${work_dir}/iso/isolinux/isohdpfx.bin' does not exist." 1 +    fi + +    # If exists, add an EFI "El Torito" boot image (FAT filesystem) to ISO-9660 image. +    if [[ -f "${work_dir}/iso/EFI/archiso/efiboot.img" ]]; then +        _iso_efi_boot_args="-eltorito-alt-boot +                            -e EFI/archiso/efiboot.img +                            -no-emul-boot +                            -isohybrid-gpt-basdat" +    fi + +    _show_config iso + +    mkdir -p ${out_dir} +    _msg_info "Creating ISO image..." +    local _qflag="" +    if [[ ${quiet} == "y" ]]; then +        _qflag="-quiet" +    fi +    xorriso -as mkisofs ${_qflag} \ +        -iso-level 3 \ +        -full-iso9660-filenames \ +        -volid "${iso_label}" \ +        -appid "${iso_application}" \ +        -publisher "${iso_publisher}" \ +        -preparer "prepared by mkarchiso" \ +        -eltorito-boot isolinux/isolinux.bin \ +        -eltorito-catalog isolinux/boot.cat \ +        -no-emul-boot -boot-load-size 4 -boot-info-table \ +        -isohybrid-mbr ${work_dir}/iso/isolinux/isohdpfx.bin \ +        ${_iso_efi_boot_args} \ +        -output "${out_dir}/${img_name}" \ +        "${work_dir}/iso/" +    _msg_info "Done! | $(ls -sh ${out_dir}/${img_name})" +} + +# create airootfs.sfs filesystem, and push it in "iso" directory. +command_prepare () { +    _show_config prepare + +    _cleanup +    _mkairootfs +    _mkchecksum +} + +# Install packages on airootfs. +# A basic check to avoid double execution/reinstallation is done via hashing package names. +command_install () { +    if [[ ! -f "${pacman_conf}" ]]; then +        _msg_error "Pacman config file '${pacman_conf}' does not exist" 1 +    fi + +    #trim spaces +    pkg_list="$(echo ${pkg_list})" + +    if [[ -z ${pkg_list} ]]; then +        _msg_error "Packages must be specified" 0 +        _usage 1 +    fi + +    _show_config install + +    _pacman "${pkg_list}" +} + +command_init() { +    _show_config init +    _chroot_init +} + +command_run() { +    _show_config run +    _chroot_run +} + +if [[ ${EUID} -ne 0 ]]; then +    _msg_error "This script must be run as root." 1 +fi + +while getopts 'p:r:C:L:P:A:D:w:o:c:vh' arg; do +    case "${arg}" in +        p) pkg_list="${pkg_list} ${OPTARG}" ;; +        r) run_cmd="${OPTARG}" ;; +        C) pacman_conf="${OPTARG}" ;; +        L) iso_label="${OPTARG}" ;; +        P) iso_publisher="${OPTARG}" ;; +        A) iso_application="${OPTARG}" ;; +        D) install_dir="${OPTARG}" ;; +        w) work_dir="${OPTARG}" ;; +        o) out_dir="${OPTARG}" ;; +        c) sfs_comp="${OPTARG}" ;; +        v) quiet="n" ;; +        h|?) _usage 0 ;; +        *) +            _msg_error "Invalid argument '${arg}'" 0 +            _usage 1 +            ;; +    esac +done + +shift $((OPTIND - 1)) + +if [[ $# -lt 1 ]]; then +    _msg_error "No command specified" 0 +    _usage 1 +fi +command_name="${1}" + +case "${command_name}" in +    init) +        command_init +        ;; +    install) +        command_install +        ;; +    run) +        command_run +        ;; +    prepare) +        command_prepare +        ;; +    pkglist) +        command_pkglist +        ;; +    iso) +        if [[ $# -lt 2 ]]; then +            _msg_error "No image specified" 0 +            _usage 1 +        fi +        img_name="${2}" +        command_iso +        ;; +    *) +        _msg_error "Invalid command name '${command_name}'" 0 +        _usage 1 +        ;; +esac + +# vim:ts=4:sw=4:et: | 
