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: |