diff options
Diffstat (limited to 'archiso/mkarchiso')
-rwxr-xr-x | archiso/mkarchiso | 273 |
1 files changed, 196 insertions, 77 deletions
diff --git a/archiso/mkarchiso b/archiso/mkarchiso index 1c3242d..31abd2c 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -2,15 +2,20 @@ 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="PARABOLA_$(date +%Y%m)" iso_publisher="Parabola GNU/Linux-libre <https://parabolagnulinux.org>" iso_application="Parabola Live/Rescue CD" install_dir="libre" +work_dir="work" +out_dir="out" # Show an INFO message # $1: message string @@ -42,6 +47,44 @@ _show_space_usage () { _msg_info "Total: ${_total} MiB (100%) | Used: ${_used} MiB (${_pct_u}) | Avail: ${_avail} MiB ($((100 - ${_pct_u%\%}))%)" } +_chroot_mount () { + mount -t devtmpfs dev "${work_dir}/root-image/dev" + mount -t devpts devpts "${work_dir}/root-image/dev/pts" + mount -t tmpfs devshm "${work_dir}/root-image/dev/shm" + mount -t proc proc "${work_dir}/root-image/proc" + mount -t tmpfs run "${work_dir}/root-image/run" + mount -t sysfs sys "${work_dir}/root-image/sys" + mount -t tmpfs tmp "${work_dir}/root-image/tmp" + + trap '_chroot_umount' EXIT HUP INT TERM +} + +_chroot_umount () { + umount "${work_dir}/root-image/tmp" + umount "${work_dir}/root-image/sys" + umount "${work_dir}/root-image/run" + umount "${work_dir}/root-image/proc" + umount "${work_dir}/root-image/dev/shm" + umount "${work_dir}/root-image/dev/pts" + umount "${work_dir}/root-image/dev" + + trap - EXIT HUP INT TERM +} + +_chroot_init() { + if [[ ! -d ${work_dir}/root-image/var/cache/pacman ]]; then + mkdir -p ${work_dir}/root-image/{dev,proc,run,sys,tmp,var/lib/pacman} + _pacman "base" + _pacman "syslinux" + fi +} + +_chroot_run() { + _chroot_mount + eval chroot ${work_dir}/root-image "${run_cmd}" + _chroot_umount +} + # Mount a filesystem (trap signals in case of error for unmounting it # $1: source image # $2: mount-point @@ -97,30 +140,44 @@ _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 " -C <file> Config file for pacman. Default ${pacman_conf}" + echo " -r <command> Run <command> inside root-image" + 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 " 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 " -v Enable verbose output" echo " -h This message" echo " commands:" - echo " create <dir>" - echo " create a base directory layout to work with" - echo " includes all specified packages" - echo " prepare <dir>" + 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 " checksum <dir>" + echo " checksum" echo " make a checksum.md5 for self-test" - echo " iso <dir> <image name>" + echo " pkglist" + echo " make a pkglist.txt of packages installed on root-image" + echo " iso <image name>" echo " build an iso image from the working dir" exit ${1} } # Shows configuration according to command mode. -# $1: create | prepare | iso +# $1: init | install | run | prepare | checksum | iso _show_config () { local _mode="$1" echo @@ -130,14 +187,22 @@ _show_config () { _msg_info " Working directory: ${work_dir}" _msg_info " Installation directory: ${install_dir}" case "${_mode}" in - create) + 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) ;; checksum) ;; + pkglist) + ;; iso) _msg_info " Image name: ${img_name}" _msg_info " Disk label: ${iso_label}" @@ -153,20 +218,23 @@ _pacman () { _msg_info "Installing packages to '${work_dir}/root-image/'..." + _chroot_mount + if [[ "${quiet}" = "y" ]]; then - mkarchroot -n -C "${pacman_conf}" -f "${work_dir}/root-image" $* &> /dev/null + pacman -Sy -r "${work_dir}/root-image" --config "${pacman_conf}" --needed --noconfirm $* &> /dev/null else - mkarchroot -n -C "${pacman_conf}" -f "${work_dir}/root-image" $* + pacman -Sy -r "${work_dir}/root-image" --config "${pacman_conf}" --needed --noconfirm $* fi - # Cleanup - find "${work_dir}" -name "*.pacnew" -name "*.pacsave" -name "*.pacorig" -delete + _chroot_umount + _msg_info "Packages installed successfully!" } # Cleanup root-image _cleanup () { - _msg_info "Cleaning up what we can on root-image" + _msg_info "Cleaning up what we can on root-image..." + # remove the initcpio images that were generated for the host system if [[ -d "${work_dir}/root-image/boot" ]]; then find "${work_dir}/root-image/boot" -name '*.img' -delete @@ -195,10 +263,13 @@ _cleanup () { if [[ -d "${work_dir}/root-image/tmp" ]]; then find "${work_dir}/root-image/tmp" -mindepth 1 -delete fi - # Delete etc/mtab if not is a symlink. + # Delete package pacman related files. + find "${work_dir}" -name "*.pacnew" -name "*.pacsave" -name "*.pacorig" -delete + # Create etc/mtab if not is a symlink. if [[ ! -L "${work_dir}/root-image/etc/mtab" ]]; then - rm -f "${work_dir}/root-image/etc/mtab" + ln -sf "/proc/self/mounts" "${work_dir}/root-image/etc/mtab" fi + _msg_info "Done!" } # Makes a SquashFS filesystem image of file/directory passes as argument with desired compression. @@ -217,9 +288,9 @@ _mksfs () { _msg_info "Creating SquashFS image for '${work_dir}/${_src}', This may take some time..." local _seconds=${SECONDS} if [[ "${quiet}" = "y" ]]; then - mksquashfs "${work_dir}/${_src}" "${_sfs_img}" -noappend -comp "${_sfs_comp}" &> /dev/null + mksquashfs "${work_dir}/${_src}" "${_sfs_img}" -noappend -comp "${_sfs_comp}" -no-progress &> /dev/null else - mksquashfs "${work_dir}/${_src}" "${_sfs_img}" -noappend -comp "${_sfs_comp}" + mksquashfs "${work_dir}/${_src}" "${_sfs_img}" -noappend -comp "${_sfs_comp}" -no-progress fi _seconds=$((SECONDS - _seconds)) printf "[mkarchiso] INFO: Image creation done in %02d:%02d minutes\n" $((_seconds / 60)) $((_seconds % 60)) @@ -227,7 +298,7 @@ _mksfs () { # Makes a filesystem from a source directory. # $1: Source directory -# $2: Target filesystem type (ext4 | ext3 | ext2 | xfs) +# $2: Target filesystem type (ext4 | ext3 | ext2 | xfs | btrfs) # $3: Size of target filesystem. Can be an absolute value in MiB, or relative value of desired free space (1% - 99%) _mkfs () { local _src="${1}" @@ -257,7 +328,7 @@ _mkfs () { fi fi - _msg_info "Creating ${_fs_type} image of ${_fs_size} MiB" + _msg_info "Creating ${_fs_type} image of ${_fs_size} MiB..." rm -f "${_fs_img}" dd of="${_fs_img}" count=0 bs=1M seek=${_fs_size} &> /dev/null local _qflag="" @@ -280,53 +351,97 @@ _mkfs () { xfs) mkfs.xfs ${_qflag} "${_fs_img}" ;; + btrfs) + mkfs.btrfs -M "${_fs_img}" + ;; *) _msg_error "Invalid filesystem: ${_fs_type}" 1 ;; esac + _msg_info "Done!" _mount_fs "${_fs_img}" "${work_dir}/mnt/${_src}" - _msg_info "Copying '${_fs_src}/' to '${work_dir}/mnt/${_src}/'" - rsync -aH "${_fs_src}/" "${work_dir}/mnt/${_src}/" + _msg_info "Copying '${_fs_src}/' to '${work_dir}/mnt/${_src}/'..." + cp -aT "${_fs_src}/" "${work_dir}/mnt/${_src}/" + _msg_info "Done!" _umount_fs "${work_dir}/mnt/${_src}" } command_checksum () { _show_config checksum - _msg_info "Creating checksum file for self-test" - cd "${work_dir}/iso/${install_dir}" - find -type f ! -name checksum.md5 -print0 | xargs -0 md5sum > checksum.md5 - cd ${OLDPWD} - _msg_info "Done!" + local _chk_arch + + for _chk_arch in i686 x86_64; do + if _is_directory_changed "${work_dir}/iso/${install_dir}" "${work_dir}/iso/${install_dir}/checksum.${_chk_arch}.md5"; then + _msg_info "Creating checksum file for self-test (${_chk_arch})..." + cd "${work_dir}/iso/${install_dir}" + if [[ -d "${_chk_arch}" ]]; then + md5sum aitab > checksum.${_chk_arch}.md5 + find ${_chk_arch} -type f -print0 | xargs -0 md5sum >> checksum.${_chk_arch}.md5 + if [[ -d "any" ]]; then + find any -type f -print0 | xargs -0 md5sum >> checksum.${_chk_arch}.md5 + fi + fi + cd ${OLDPWD} + _msg_info "Done!" + fi + done +} + +command_pkglist () { + _show_config pkglist + + if _is_directory_changed "${work_dir}/root-image/var/lib/pacman/local" "${work_dir}/iso/${install_dir}/pkglist.${arch}.txt"; then + _msg_info "Creating a list of installed packages on live-enviroment..." + pacman -Sl -r "${work_dir}/root-image" --config "${pacman_conf}" | \ + awk '/\[installed\]$/ {print $1 "/" $2 "-" $3}' > \ + "${work_dir}/iso/${install_dir}/pkglist.${arch}.txt" + _msg_info "Done!" + fi + } # 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 - _show_config iso + # 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="--efi-boot EFI/archiso/efiboot.img" + fi - _is_directory_changed "${work_dir}/iso" "${img_name}" + _show_config iso - _msg_info "Creating ISO image..." - local _qflag="" - if [[ ${quiet} == "y" ]]; then - _qflag="-quiet" + if _is_directory_changed "${work_dir}/iso" "${out_dir}/${img_name}"; then + 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 \ + ${_iso_efi_boot_args} \ + -isohybrid-mbr ${work_dir}/iso/isolinux/isohdpfx.bin \ + -output "${out_dir}/${img_name}" \ + "${work_dir}/iso/" + _msg_info "Done! | $(ls -sh ${out_dir}/${img_name})" fi - mkisofs ${_qflag} -r -l \ - -b isolinux/isolinux.bin -c isolinux/boot.cat \ - -uid 0 -gid 0 \ - -udf -allow-limited-size -iso-level 3 \ - -input-charset utf-8 -p "prepared by mkarchiso" \ - -no-emul-boot -boot-load-size 4 -boot-info-table \ - -publisher "${iso_publisher}" \ - -A "${iso_application}" \ - -V "${iso_label}" \ - -o "${img_name}" "${work_dir}/iso/" - isohybrid "${img_name}" - _msg_info "Done! | $(ls -sh ${img_name})" } # Parse aitab and create each filesystem specified on that, and push it in "iso" directory. @@ -342,25 +457,15 @@ command_prepare () { if [[ ${_aitab_img} =~ ^# ]]; then continue fi - if [[ ${_aitab_sfs_comp} == "none" && ${_aitab_fs_type} == "none" ]]; then - _msg_error "In aitab, both fields 'sfs_comp' and 'fs_type' are set to none for '${_aitab_img}' image" 1 - fi local _src="${work_dir}/${_aitab_img}" local _dst="${work_dir}/iso/${install_dir}/${_aitab_arch}" mkdir -p "${_dst}" if [[ ${_aitab_fs_type} != "none" ]]; then - if [[ ${_aitab_sfs_comp} != "none" ]]; then - if _is_directory_changed "${_src}" "${_dst}/${_aitab_img}.fs.sfs"; then - _mkfs ${_aitab_img} ${_aitab_fs_type} ${_aitab_fs_size} - _mksfs ${_aitab_img}.fs ${_aitab_sfs_comp} - mv "${_src}.fs.sfs" "${_dst}" - rm "${_src}.fs" - fi - else - if _is_directory_changed "${_src}" "${_dst}/${_aitab_img}.fs"; then - _mkfs ${_aitab_img} ${_aitab_fs_type} ${_aitab_fs_size} - mv "${work_dir}/${_aitab_img}.fs" "${_dst}" - fi + if _is_directory_changed "${_src}" "${_dst}/${_aitab_img}.fs.sfs"; then + _mkfs ${_aitab_img} ${_aitab_fs_type} ${_aitab_fs_size} + _mksfs ${_aitab_img}.fs ${_aitab_sfs_comp} + mv "${_src}.fs.sfs" "${_dst}" + rm "${_src}.fs" fi else if _is_directory_changed "${_src}" "${_dst}/${_aitab_img}.sfs"; then @@ -373,7 +478,7 @@ command_prepare () { # Install packages on root-image. # A basic check to avoid double execution/reinstallation is done via hashing package names. -command_create () { +command_install () { if [[ ! -f "${pacman_conf}" ]]; then _msg_error "Pacman config file '${pacman_conf}' does not exist" 1 fi @@ -386,32 +491,43 @@ command_create () { _usage 1 fi - _show_config create + _show_config install local _pkg_list_hash _pkg_list_hash=$(echo ${pkg_list} | sort -u | md5sum | cut -c1-32) - if [[ -f "${work_dir}/create.${_pkg_list_hash}" ]]; then + if [[ -f "${work_dir}/install.${_pkg_list_hash}" ]]; then _msg_info "These packages are already installed, skipping." else - mkdir -p "${work_dir}/root-image/" _pacman "${pkg_list}" - : > "${work_dir}/create.${_pkg_list_hash}" + : > "${work_dir}/install.${_pkg_list_hash}" fi } +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:C:L:P:A:D:fvh' arg; do +while getopts 'p:r:C:L:P:A:D:w:o: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}" ;; v) quiet="n" ;; h|?) _usage 0 ;; *) @@ -429,15 +545,15 @@ if [[ $# -lt 1 ]]; then fi command_name="${1}" -if [[ $# -lt 2 ]]; then - _msg_error "No working directory specified" 0 - _usage 1 -fi -work_dir="${2}" - case "${command_name}" in - create) - command_create + init) + command_init + ;; + install) + command_install + ;; + run) + command_run ;; prepare) command_prepare @@ -445,12 +561,15 @@ case "${command_name}" in checksum) command_checksum ;; + pkglist) + command_pkglist + ;; iso) - if [[ $# -lt 3 ]]; then + if [[ $# -lt 2 ]]; then _msg_error "No image specified" 0 _usage 1 fi - img_name="${3}" + img_name="${2}" command_iso ;; *) |