summaryrefslogtreecommitdiffstats
path: root/build_tools/archiso-19/archiso/mkarchiso
diff options
context:
space:
mode:
Diffstat (limited to 'build_tools/archiso-19/archiso/mkarchiso')
-rwxr-xr-xbuild_tools/archiso-19/archiso/mkarchiso392
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: