diff --git a/configure b/configure index bae60da..6666842 100755 --- a/configure +++ b/configure @@ -23,6 +23,7 @@ GENTOO_INSTALL_REPO_DIR="$(get_source_dir)" export GENTOO_INSTALL_REPO_DIR export GENTOO_INSTALL_REPO_SCRIPT_ACTIVE=true +# shellcheck source=./scripts/utils.sh source "$GENTOO_INSTALL_REPO_DIR/scripts/utils.sh" # Remember actual config file path @@ -231,6 +232,7 @@ function create_btrfs_raid_layout() { function create_btrfs_centric_layout() { PARTITIONING_SCHEME="btrfs_centric" + # shellcheck disable=SC2034 local known_arguments=('+swap' '?type' '?raid_type' '?luks') local extra_arguments=() declare -A arguments; parse_arguments "$@" @@ -302,6 +304,7 @@ function load_config() { PARTITIONING_SCHEME="custom" # Load settings + # shellcheck disable=SC1090 source "$1" || die "Could not load given configuration." # After loading a config no unsaved changes exist. @@ -912,7 +915,7 @@ function PARTITIONING_DEVICES_menu() { --title "Select devices" \ --inputbox "Enter the path of all devices which you want to partition, separated by space. (e.g. /dev/sda /dev/sdb).$invalid_line" \ "${INPUTBOX_SIZE[@]}" "${PARTITIONING_DEVICES[*]}" - PARTITIONING_DEVICES=($dialog_out) + read -ra PARTITIONING_DEVICES <<< "$dialog_out" UNSAVED_CHANGES=true } diff --git a/install b/install index ccd747c..50401b7 100755 --- a/install +++ b/install @@ -10,7 +10,8 @@ function get_source_dir() { local source="${BASH_SOURCE[0]}" while [[ -h $source ]] do - local tmp="$(cd -P "$(dirname "${source}")" && pwd)" + local tmp + tmp="$(cd -P "$(dirname "${source}")" && pwd)" source="$(readlink "${source}")" [[ $source != /* ]] && source="${tmp}/${source}" done @@ -18,17 +19,23 @@ function get_source_dir() { echo -n "$(realpath "$(dirname "${source}")")" } -export ACTUAL_WORKING_DIRECTORY="$(realpath "$(pwd)")" -export GENTOO_INSTALL_REPO_DIR_ORIGINAL="$(get_source_dir)" +ACTUAL_WORKING_DIRECTORY="$(realpath "$(pwd)")" || exit 1 +export ACTUAL_WORKING_DIRECTORY +GENTOO_INSTALL_REPO_DIR_ORIGINAL="$(get_source_dir)" +export GENTOO_INSTALL_REPO_DIR_ORIGINAL export GENTOO_INSTALL_REPO_DIR="$GENTOO_INSTALL_REPO_DIR_ORIGINAL" export GENTOO_INSTALL_REPO_SCRIPT_ACTIVE=true export GENTOO_INSTALL_REPO_SCRIPT_PID=$$ umask 0077 +# shellcheck source=./scripts/utils.sh source "$GENTOO_INSTALL_REPO_DIR/scripts/utils.sh" +# shellcheck source=./scripts/config.sh source "$GENTOO_INSTALL_REPO_DIR/scripts/config.sh" +# shellcheck source=./scripts/functions.sh source "$GENTOO_INSTALL_REPO_DIR/scripts/functions.sh" +# shellcheck source=./scripts/main.sh source "$GENTOO_INSTALL_REPO_DIR/scripts/main.sh" @@ -67,7 +74,7 @@ while [[ $# -gt 0 ]]; do "-c"|"--config") [[ -f "$2" ]] \ || die "Config file not found: '$2'" - CONFIG="$(cd "$ACTUAL_WORKING_DIRECTORY"; realpath --relative-to="$GENTOO_INSTALL_REPO_DIR" "$2" 2>/dev/null)" + CONFIG="$(cd "$ACTUAL_WORKING_DIRECTORY" && realpath --relative-to="$GENTOO_INSTALL_REPO_DIR" "$2" 2>/dev/null)" || die "Could not determine realpath to config" shift ;; "-R"|"--chroot") @@ -108,7 +115,8 @@ fi [[ -e "$CONFIG" ]] \ || die "Configuration file '$CONFIG' does not exist. To run the configurator, omit '-i' or " -source "$CONFIG" +# shellcheck disable=SC1090 +source "$CONFIG" || die "Could not source config" [[ $I_HAVE_READ_AND_EDITED_THE_CONFIG_PROPERLY == "true" ]] \ || die "You have not properly read the config. Edit the config file and set I_HAVE_READ_AND_EDITED_THE_CONFIG_PROPERLY=true to continue." diff --git a/scripts/config.sh b/scripts/config.sh index fb2622d..c82b224 100644 --- a/scripts/config.sh +++ b/scripts/config.sh @@ -1,3 +1,4 @@ +# shellcheck source=./scripts/protection.sh source "$GENTOO_INSTALL_REPO_DIR/scripts/protection.sh" || exit 1 @@ -28,17 +29,17 @@ USED_BTRFS=false # An array of disk related actions to perform DISK_ACTIONS=() # An array of dracut parameters needed to boot the selected configuration -DISK_DRACUT_CMDLINE=("rd.vconsole.keymap=$KEYMAP_INITRAMFS") +DISK_DRACUT_CMDLINE=() # An associative array from disk id to a resolvable string -declare -A DISK_ID_TO_RESOLVABLE +declare -gA DISK_ID_TO_RESOLVABLE # An associative array from disk id to parent gpt disk id (only for partitions) -declare -A DISK_ID_PART_TO_GPT_ID +declare -gA DISK_ID_PART_TO_GPT_ID # An associative array to check for existing ids (maps to uuids) -declare -A DISK_ID_TO_UUID +declare -gA DISK_ID_TO_UUID # An associative set to check for correct usage of size=remaining in gpt tables -declare -A DISK_GPT_HAD_SIZE_REMAINING +declare -gA DISK_GPT_HAD_SIZE_REMAINING -only_one_of() { +function only_one_of() { local previous="" local a for a in "$@"; do @@ -52,7 +53,7 @@ only_one_of() { done } -create_new_id() { +function create_new_id() { local id="${arguments[$1]}" [[ $id == *';'* ]] \ && die_trace 2 "Identifier contains invalid character ';'" @@ -61,13 +62,13 @@ create_new_id() { DISK_ID_TO_UUID[$id]="$(load_or_generate_uuid "$(base64 -w 0 <<< "$id")")" } -verify_existing_id() { +function verify_existing_id() { local id="${arguments[$1]}" [[ -v DISK_ID_TO_UUID[$id] ]] \ || die_trace 2 "Identifier $1='$id' not found" } -verify_existing_unique_ids() { +function verify_existing_unique_ids() { local arg="$1" local ids="${arguments[$arg]}" @@ -87,7 +88,7 @@ verify_existing_unique_ids() { done } -verify_option() { +function verify_option() { local opt="$1" shift @@ -104,7 +105,7 @@ verify_option() { # Named arguments: # new_id: Id for the new gpt table # device|id: The operand block device or previously allocated id -create_gpt() { +function create_gpt() { local known_arguments=('+new_id' '+device|id') local extra_arguments=() declare -A arguments; parse_arguments "$@" @@ -124,7 +125,7 @@ create_gpt() { # size: Size for the new partition, or 'remaining' to allocate the rest # type: The parition type, either (bios, efi, swap, raid, luks, linux) (or a 4 digit hex-code for gdisk). # id: The operand device id -create_partition() { +function create_partition() { local known_arguments=('+new_id' '+id' '+size' '+type') local extra_arguments=() declare -A arguments; parse_arguments "$@" @@ -136,6 +137,7 @@ create_partition() { [[ -v "DISK_GPT_HAD_SIZE_REMAINING[${arguments[id]}]" ]] \ && die_trace 1 "Cannot add another partition to table (${arguments[id]}) after size=remaining was used" + # shellcheck disable=SC2034 [[ ${arguments[size]} == "remaining" ]] \ && DISK_GPT_HAD_SIZE_REMAINING[${arguments[id]}]=true @@ -150,7 +152,7 @@ create_partition() { # level: Raid level # name: Raid name (/dev/md/) # ids: Comma separated list of all member ids -create_raid() { +function create_raid() { USED_RAID=true local known_arguments=('+new_id' '+level' '+name' '+ids') @@ -171,7 +173,7 @@ create_raid() { # Named arguments: # new_id: Id for the new luks # id: The operand device id -create_luks() { +function create_luks() { USED_LUKS=true local known_arguments=('+new_id' '+name' '+device|id') @@ -194,7 +196,7 @@ create_luks() { # Named arguments: # new_id: Id for the new luks # device: The device -create_dummy() { +function create_dummy() { local known_arguments=('+new_id' '+device') local extra_arguments=() declare -A arguments; parse_arguments "$@" @@ -212,7 +214,7 @@ create_dummy() { # id: Id of the device / partition created earlier # type: One of (bios, efi, swap, ext4) # label: The label for the formatted disk -format() { +function format() { local known_arguments=('+id' '+type' '?label') local extra_arguments=() declare -A arguments; parse_arguments "$@" @@ -232,7 +234,7 @@ format() { # ids: List of ids for devices / partitions created earlier. Must contain at least 1 element. # pool_type: The zfs pool type # encrypt: Whether or not to encrypt the pool -format_zfs() { +function format_zfs() { USED_ZFS=true local known_arguments=('+ids' '?pool_type' '?encrypt') @@ -247,7 +249,7 @@ format_zfs() { # Named arguments: # ids: List of ids for devices / partitions created earlier. Must contain at least 1 element. # label: The label for the formatted disk -format_btrfs() { +function format_btrfs() { USED_BTRFS=true local known_arguments=('+ids' '?raid_type' '?label') @@ -260,7 +262,7 @@ format_btrfs() { } # Returns a comma separated list of all registered ids matching the given regex. -expand_ids() { +function expand_ids() { local regex="$1" for id in "${!DISK_ID_TO_UUID[@]}"; do [[ $id =~ $regex ]] \ @@ -274,7 +276,7 @@ expand_ids() { # type=[efi|bios] Selects the boot type. Defaults to efi if not given. # luks=[true|false] Encrypt root partition. Defaults to false if not given. # root_fs=[ext4|btrfs] Root filesystem -create_classic_single_disk_layout() { +function create_classic_single_disk_layout() { local known_arguments=('+swap' '?type' '?luks' '?root_fs') local extra_arguments=() declare -A arguments; parse_arguments "$@" @@ -283,15 +285,9 @@ create_classic_single_disk_layout() { || die_trace 1 "Expected exactly one positional argument (the device)" local device="${extra_arguments[0]}" local size_swap="${arguments[swap]}" - local type="${arguments[type]}" + local type="${arguments[type]:-efi}" local use_luks="${arguments[luks]:-false}" local root_fs="${arguments[root_fs]:-ext4}" - local efi=true - case "$type" in - 'bios') efi=false type=bios ;; - 'efi'|'') efi=true type=efi ;; - *) die_trace 1 "Invalid argument type=$type, must be one of (bios, efi)" ;; - esac create_gpt new_id=gpt device="$device" create_partition new_id="part_$type" id=gpt size=256MiB type="$type" @@ -330,7 +326,7 @@ create_classic_single_disk_layout() { fi } -create_single_disk_layout() { +function create_single_disk_layout() { die "'create_single_disk_layout' is deprecated, please use 'create_classic_single_disk_layout' instead. It is fully option-compatible to the old version." } @@ -341,7 +337,7 @@ create_single_disk_layout() { # type=[efi|bios] Selects the boot type. Defaults to efi if not given. # encrypt=[true|false] Encrypt zfs pool. Defaults to false if not given. # pool_type=[stripe|mirror] Select raid type. Defaults to stripe. -create_zfs_centric_layout() { +function create_zfs_centric_layout() { local known_arguments=('+swap' '?type' '?pool_type' '?encrypt') local extra_arguments=() declare -A arguments; parse_arguments "$@" @@ -351,14 +347,8 @@ create_zfs_centric_layout() { local device="${extra_arguments[0]}" local size_swap="${arguments[swap]}" local pool_type="${arguments[pool_type]:-stripe}" - local type="${arguments[type]}" + local type="${arguments[type]:-efi}" local encrypt="${arguments[encrypt]:-false}" - local efi=true - case "$type" in - 'bios') efi=false type=bios ;; - 'efi'|'') efi=true type=efi ;; - *) die_trace 1 "Invalid argument type=$type, must be one of (bios, efi)" ;; - esac # Create layout on first disk create_gpt new_id="gpt_dev0" device="${extra_arguments[0]}" @@ -401,7 +391,7 @@ create_zfs_centric_layout() { # swap= Create a swap partition with given size for each disk, or no swap at all if set to false # type=[efi|bios] Selects the boot type. Defaults to efi if not given. # root_fs=[ext4|btrfs] Root filesystem -create_raid0_luks_layout() { +function create_raid0_luks_layout() { local known_arguments=('+swap' '?type' '?root_fs') local extra_arguments=() declare -A arguments; parse_arguments "$@" @@ -409,14 +399,8 @@ create_raid0_luks_layout() { [[ ${#extra_arguments[@]} -gt 0 ]] \ || die_trace 1 "Expected at least one positional argument (the devices)" local size_swap="${arguments[swap]}" - local type="${arguments[type]}" + local type="${arguments[type]:-efi}" local root_fs="${arguments[root_fs]:-ext4}" - local efi=true - case "$type" in - 'bios') efi=false type=bios ;; - 'efi'|'') efi=true type=efi ;; - *) die_trace 1 "Invalid argument type=$type, must be one of (bios, efi)" ;; - esac for i in "${!extra_arguments[@]}"; do create_gpt new_id="gpt_dev${i}" device="${extra_arguments[$i]}" @@ -463,7 +447,7 @@ create_raid0_luks_layout() { # type=[efi|bios] Selects the boot type. Defaults to efi if not given. # luks=[true|false] Encrypt root partition and btrfs devices. Defaults to false if not given. # raid_type=[raid0|raid1] Select raid type. Defaults to raid0. -create_btrfs_centric_layout() { +function create_btrfs_centric_layout() { local known_arguments=('+swap' '?type' '?raid_type' '?luks') local extra_arguments=() declare -A arguments; parse_arguments "$@" @@ -473,14 +457,8 @@ create_btrfs_centric_layout() { local device="${extra_arguments[0]}" local size_swap="${arguments[swap]}" local raid_type="${arguments[raid_type]:-raid0}" - local type="${arguments[type]}" + local type="${arguments[type]:-efi}" local use_luks="${arguments[luks]:-false}" - local efi=true - case "$type" in - 'bios') efi=false type=bios ;; - 'efi'|'') efi=true type=efi ;; - *) die_trace 1 "Invalid argument type=$type, must be one of (bios, efi)" ;; - esac # Create layout on first disk create_gpt new_id="gpt_dev0" device="${extra_arguments[0]}" @@ -529,6 +507,6 @@ create_btrfs_centric_layout() { DISK_ID_ROOT_MOUNT_OPTS="defaults,noatime,compress=zstd,subvol=/root" } -create_btrfs_raid_layout() { +function create_btrfs_raid_layout() { die "'create_btrfs_raid_layout' is deprecated, please use 'create_btrfs_centric_layout' instead. It is fully option-compatible to the old version." } diff --git a/scripts/functions.sh b/scripts/functions.sh index 3f7d543..900815c 100644 --- a/scripts/functions.sh +++ b/scripts/functions.sh @@ -1,15 +1,16 @@ +# shellcheck source=./scripts/protection.sh source "$GENTOO_INSTALL_REPO_DIR/scripts/protection.sh" || exit 1 ################################################ # Functions -check_has_program() { +function check_has_program() { type "$1" &>/dev/null \ || die "Missing program: '$1'" } -sync_time() { +function sync_time() { einfo "Syncing time" ntpd -g -q \ || die "Could not sync time with remote server" @@ -20,7 +21,7 @@ sync_time() { || die "Could not save time to hardware clock" } -check_config() { +function check_config() { [[ $KEYMAP =~ ^[0-9A-Za-z-]*$ ]] \ || die "KEYMAP contains invalid characters" @@ -57,11 +58,11 @@ check_config() { fi } -preprocess_config() { +function preprocess_config() { check_config } -prepare_installation_environment() { +function prepare_installation_environment() { einfo "Preparing installation environment" check_has_program gpg @@ -87,7 +88,7 @@ prepare_installation_environment() { sync_time } -add_summary_entry() { +function add_summary_entry() { local parent="$1" local id="$2" local name="$3" @@ -111,7 +112,7 @@ add_summary_entry() { summary_desc[$id]="$desc" } -summary_color_args() { +function summary_color_args() { for arg in "$@"; do if [[ -v "arguments[$arg]" ]]; then printf '%-28s ' "$arg=${arguments[$arg]}" @@ -119,7 +120,7 @@ summary_color_args() { done } -disk_create_gpt() { +function disk_create_gpt() { local new_id="${arguments[new_id]}" if [[ $disk_action_summarize_only == "true" ]]; then if [[ -v arguments[id] ]]; then @@ -148,7 +149,7 @@ disk_create_gpt() { partprobe "$device" } -disk_create_partition() { +function disk_create_partition() { local new_id="${arguments[new_id]}" local id="${arguments[id]}" local size="${arguments[size]}" @@ -164,7 +165,9 @@ disk_create_partition() { arg_size="+$size" fi - local device="$(resolve_device_by_id "$id")" + local device + device="$(resolve_device_by_id "$id")" \ + || die "Could not resolve device with id=$id" local partuuid="${DISK_ID_TO_UUID[$new_id]}" local extra_args="" case "$type" in @@ -184,7 +187,7 @@ disk_create_partition() { partprobe "$device" } -disk_create_raid() { +function disk_create_raid() { local new_id="${arguments[new_id]}" local level="${arguments[level]}" local name="${arguments[name]}" @@ -204,10 +207,12 @@ disk_create_raid() { local devices_desc="" local devices=() local id + local dev # Splitting is intentional here # shellcheck disable=SC2086 for id in ${ids//';'/ }; do - local dev="$(resolve_device_by_id "$id")" + dev="$(resolve_device_by_id "$id")" \ + || die "Could not resolve device with id=$id" devices+=("$dev") devices_desc+="$dev ($id), " done @@ -229,7 +234,7 @@ disk_create_raid() { || die "Could not create raid$level array '$mddevice' ($new_id) on $devices_desc" } -disk_create_luks() { +function disk_create_luks() { local new_id="${arguments[new_id]}" local name="${arguments[name]}" if [[ $disk_action_summarize_only == "true" ]]; then @@ -284,7 +289,7 @@ disk_create_luks() { || die "Could not open luks encrypted device $device_desc" } -disk_create_dummy() { +function disk_create_dummy() { local new_id="${arguments[new_id]}" local device="${arguments[device]}" if [[ $disk_action_summarize_only == "true" ]]; then @@ -293,7 +298,7 @@ disk_create_dummy() { fi } -init_btrfs() { +function init_btrfs() { local device="$1" local desc="$2" mkdir -p /btrfs \ @@ -308,7 +313,7 @@ init_btrfs() { || die "Could not unmount btrfs on $desc" } -disk_format() { +function disk_format() { local id="${arguments[id]}" local type="${arguments[type]}" local label="${arguments[label]}" @@ -317,7 +322,9 @@ disk_format() { return 0 fi - local device="$(resolve_device_by_id "$id")" + local device + device="$(resolve_device_by_id "$id")" \ + || die "Could not resolve device with id=$id" einfo "Formatting $device ($id) with $type" case "$type" in 'bios'|'efi') @@ -362,10 +369,24 @@ disk_format() { esac } -disk_format_zfs() { +function disk_format_zfs() { + local ids="${arguments[ids]}" + local label="${arguments[label]}" + local pool_type="${arguments[pool_type]}" + local encrypt="${arguments[encrypt]}" + if [[ $disk_action_summarize_only == "true" ]]; then + local id + # Splitting is intentional here + # shellcheck disable=SC2086 + for id in ${ids//';'/ }; do + add_summary_entry "$id" "__fs__$id" "zfs" "(fs)" "$(summary_color_args label)" + done + return 0 + fi + } -disk_format_btrfs() { +function disk_format_btrfs() { local ids="${arguments[ids]}" local label="${arguments[label]}" local raid_type="${arguments[raid_type]}" @@ -382,10 +403,12 @@ disk_format_btrfs() { local devices_desc="" local devices=() local id + local dev # Splitting is intentional here # shellcheck disable=SC2086 for id in ${ids//';'/ }; do - local dev="$(resolve_device_by_id "$id")" + dev="$(resolve_device_by_id "$id")" \ + || die "Could not resolve device with id=$id" devices+=("$dev") devices_desc+="$dev ($id), " done @@ -408,7 +431,7 @@ disk_format_btrfs() { init_btrfs "${devices[0]}" "btrfs array ($devices_desc)" } -apply_disk_action() { +function apply_disk_action() { unset known_arguments unset arguments; declare -A arguments; parse_arguments "$@" case "${arguments[action]}" in @@ -424,7 +447,7 @@ apply_disk_action() { esac } -print_summary_tree_entry() { +function print_summary_tree_entry() { local indent_chars="" local indent="0" local d="1" @@ -471,7 +494,7 @@ print_summary_tree_entry() { "$desc")" } -print_summary_tree() { +function print_summary_tree() { local root="$1" local depth="$((depth + 1))" local has_children=false @@ -489,7 +512,9 @@ print_summary_tree() { fi if [[ $has_children == "true" ]]; then - local count="$(tr ';' '\n' <<< "$children" | grep -c '\S')" + local count + count="$(tr ';' '\n' <<< "$children" | grep -c '\S')" \ + || count=0 local idx=0 # Splitting is intentional here # shellcheck disable=SC2086 @@ -505,7 +530,7 @@ print_summary_tree() { fi } -apply_disk_actions() { +function apply_disk_actions() { local param local current_params=() for param in "${DISK_ACTIONS[@]}"; do @@ -518,7 +543,7 @@ apply_disk_actions() { done } -summarize_disk_actions() { +function summarize_disk_actions() { elog "Current lsblk output:" for_line_in <(lsblk \ || die "Error in lsblk") elog @@ -542,7 +567,7 @@ summarize_disk_actions() { elog ──────────────────────────────────────────────────────────────────────────────── } -apply_disk_configuration() { +function apply_disk_configuration() { summarize_disk_actions ask "Do you really want to apply this disk configuration?" \ @@ -558,7 +583,7 @@ apply_disk_configuration() { || die "Error in lsblk") elog } -mount_efivars() { +function mount_efivars() { # Skip if already mounted mountpoint -q -- "/sys/firmware/efi/efivars" \ && return @@ -569,7 +594,7 @@ mount_efivars() { || die "Could not mount efivarfs" } -mount_by_id() { +function mount_by_id() { local dev local id="$1" local mountpoint="$2" @@ -588,11 +613,11 @@ mount_by_id() { || die "Could not mount device '$dev'" } -mount_root() { +function mount_root() { mount_by_id "$DISK_ID_ROOT" "$ROOT_MOUNTPOINT" } -bind_repo_dir() { +function bind_repo_dir() { # Use new location by default export GENTOO_INSTALL_REPO_DIR="$GENTOO_INSTALL_REPO_BIND" @@ -609,7 +634,7 @@ bind_repo_dir() { || die "Could not bind mount '$GENTOO_INSTALL_REPO_DIR_ORIGINAL' to '$GENTOO_INSTALL_REPO_BIND'" } -download_stage3() { +function download_stage3() { cd "$TMP_DIR" \ || die "Could not cd into '$TMP_DIR'" @@ -660,7 +685,7 @@ download_stage3() { fi } -extract_stage3() { +function extract_stage3() { mount_root [[ -n $CURRENT_STAGE3 ]] \ @@ -684,7 +709,7 @@ extract_stage3() { || die "Could not cd into '$TMP_DIR'" } -gentoo_umount() { +function gentoo_umount() { if mountpoint -q -- "$ROOT_MOUNTPOINT"; then einfo "Unmounting root filesystem" umount -R -l "$ROOT_MOUNTPOINT" \ @@ -692,13 +717,13 @@ gentoo_umount() { fi } -init_bash() { +function init_bash() { source /etc/profile umask 0077 export PS1='(chroot) \[\]\u\[\]@\h \[\]\w \[\]\$ \[\]' }; export -f init_bash -env_update() { +function env_update() { env-update \ || die "Error in env-update" source /etc/profile \ @@ -706,19 +731,19 @@ env_update() { umask 0077 } -mkdir_or_die() { +function mkdir_or_die() { # shellcheck disable=SC2174 mkdir -m "$1" -p "$2" \ || die "Could not create directory '$2'" } -touch_or_die() { +function touch_or_die() { touch "$2" \ || die "Could not touch '$2'" chmod "$1" "$2" } -gentoo_chroot() { +function gentoo_chroot() { if [[ $# -eq 0 ]]; then gentoo_chroot /bin/bash --init-file <(echo 'init_bash') fi @@ -760,7 +785,7 @@ gentoo_chroot() { || die "Failed to chroot into '$ROOT_MOUNTPOINT'" } -enable_service() { +function enable_service() { if [[ $SYSTEMD == "true" ]]; then systemctl enable "$1" \ || die "Could not enable $1 service" diff --git a/scripts/main.sh b/scripts/main.sh index 700636e..5f812e3 100644 --- a/scripts/main.sh +++ b/scripts/main.sh @@ -1,10 +1,11 @@ +# shellcheck source=./scripts/protection.sh source "$GENTOO_INSTALL_REPO_DIR/scripts/protection.sh" || exit 1 ################################################ # Functions -install_stage3() { +function install_stage3() { [[ $# == 0 ]] || die "Too many arguments" prepare_installation_environment @@ -13,7 +14,7 @@ install_stage3() { extract_stage3 } -configure_base_system() { +function configure_base_system() { einfo "Generating locales" echo "$LOCALES" > /etc/locale.gen \ || die "Could not write /etc/locale.gen" @@ -87,7 +88,7 @@ configure_base_system() { env_update } -configure_portage() { +function configure_portage() { # Prepare /etc/portage for autounmask mkdir_or_die 0755 "/etc/portage/package.use" touch_or_die 0644 "/etc/portage/package.use/zz-autounmask" @@ -110,7 +111,7 @@ configure_portage() { fi } -install_sshd() { +function install_sshd() { einfo "Installing sshd" install -m0600 -o root -g root "$GENTOO_INSTALL_REPO_DIR/contrib/sshd_config" /etc/ssh/sshd_config \ || die "Could not install /etc/ssh/sshd_config" @@ -119,7 +120,7 @@ install_sshd() { || die "Could not create group 'sshusers'" } -generate_initramfs() { +function generate_initramfs() { local output="$1" # Generate initramfs @@ -133,7 +134,9 @@ generate_initramfs() { [[ $USED_BTRFS == "true" ]] \ && modules+=("btrfs") - local kver="$(readlink /usr/src/linux)" + local kver + kver="$(readlink /usr/src/linux)" \ + || die "Could not figure out kernel version from /usr/src/linux symlink." kver="${kver#linux-}" # Generate initramfs @@ -150,11 +153,11 @@ generate_initramfs() { "$output" } -get_cmdline() { - echo -n "${DISK_DRACUT_CMDLINE[*]} root=UUID=$(get_blkid_uuid_for_id "$DISK_ID_ROOT")" +function get_cmdline() { + echo -n "rd.vconsole.keymap=$KEYMAP_INITRAMFS ${DISK_DRACUT_CMDLINE[*]} root=UUID=$(get_blkid_uuid_for_id "$DISK_ID_ROOT")" } -install_kernel_efi() { +function install_kernel_efi() { try emerge --verbose sys-boot/efibootmgr # Copy kernel to EFI @@ -171,13 +174,17 @@ install_kernel_efi() { # Create boot entry einfo "Creating efi boot entry" - local efipartdev="$(resolve_device_by_id "$DISK_ID_EFI")" + local efipartdev + efipartdev="$(resolve_device_by_id "$DISK_ID_EFI")" \ + || die "Could not resolve device with id=$DISK_ID_EFI" local efipartnum="${efipartdev: -1}" - local gptdev="$(resolve_device_by_id "${DISK_ID_PART_TO_GPT_ID[$DISK_ID_EFI]}")" + local gptdev + gptdev="$(resolve_device_by_id "${DISK_ID_PART_TO_GPT_ID[$DISK_ID_EFI]}")" \ + || die "Could not resolve device with id=${DISK_ID_PART_TO_GPT_ID[$DISK_ID_EFI]}" try efibootmgr --verbose --create --disk "$gptdev" --part "$efipartnum" --label "gentoo" --loader '\EFI\vmlinuz.efi' --unicode 'initrd=\EFI\initramfs.img'" $(get_cmdline)" } -generate_syslinux_cfg() { +function generate_syslinux_cfg() { cat <> /etc/fstab \ || die "Could not append entry to fstab" } -generate_fstab() { +function generate_fstab() { einfo "Generating fstab" install -m0644 -o root -g root "$GENTOO_INSTALL_REPO_DIR/contrib/fstab" /etc/fstab \ || die "Could not overwrite /etc/fstab" @@ -251,7 +262,7 @@ generate_fstab() { fi } -install_ansible() { +function install_ansible() { einfo "Installing ansible" try emerge --verbose app-admin/ansible @@ -276,7 +287,7 @@ install_ansible() { || die "Could not add ansible to auxiliary groups" } -main_install_gentoo_in_chroot() { +function main_install_gentoo_in_chroot() { [[ $# == 0 ]] || die "Too many arguments" # Remove the root password, making the account accessible for automated @@ -388,7 +399,7 @@ main_install_gentoo_in_chroot() { einfo "Otherwise, you may now reboot your system." } -main_install() { +function main_install() { [[ $# == 0 ]] || die "Too many arguments" gentoo_umount @@ -400,11 +411,11 @@ main_install() { gentoo_umount } -main_chroot() { +function main_chroot() { gentoo_chroot "$@" gentoo_umount } -main_umount() { +function main_umount() { gentoo_umount } diff --git a/scripts/utils.sh b/scripts/utils.sh index d0cc0a9..0354f3d 100644 --- a/scripts/utils.sh +++ b/scripts/utils.sh @@ -1,49 +1,52 @@ +# shellcheck source=./scripts/protection.sh source "$GENTOO_INSTALL_REPO_DIR/scripts/protection.sh" || exit 1 -elog() { +function elog() { echo "[+] $*" } -einfo() { +function einfo() { echo "[+] $*" } -ewarn() { +function ewarn() { echo "[+] $*" >&2 } -eerror() { +function eerror() { echo "error: $*" >&2 } -die() { +function die() { eerror "$*" - [[ $$ == $GENTOO_INSTALL_REPO_SCRIPT_PID ]] \ + [[ $$ == "$GENTOO_INSTALL_REPO_SCRIPT_PID" ]] \ || kill "$GENTOO_INSTALL_REPO_SCRIPT_PID" exit 1 } # Prints an error with file:line info of the nth "stack frame". # 0 is this function, 1 the calling function, 2 its parent, and so on. -die_trace() { +function die_trace() { local idx="${1:-0}" shift echo "${BASH_SOURCE[$((idx + 1))]}:${BASH_LINENO[$idx]}: error: ${FUNCNAME[$idx]}: $*" >&2 exit 1 } -for_line_in() { +function for_line_in() { while IFS="" read -r line || [[ -n $line ]]; do "$2" "$line" done <"$1" } -flush_stdin() { +function flush_stdin() { local empty_stdin + # Unused variable is intentional. + # shellcheck disable=SC2034 while read -r -t 0.01 empty_stdin; do true; done } -ask() { +function ask() { local response while true; do flush_stdin @@ -58,7 +61,7 @@ ask() { done } -try() { +function try() { local response local cmd_status local prompt_parens="(Shell/retry/abort/continue/print)" @@ -97,7 +100,7 @@ try() { done } -countdown() { +function countdown() { echo -n "$1" >&2 local i="$2" @@ -109,15 +112,15 @@ countdown() { echo >&2 } -download_stdout() { +function download_stdout() { wget --quiet --https-only --secure-protocol=PFS -O - -- "$1" } -download() { +function download() { wget --quiet --https-only --secure-protocol=PFS --show-progress -O "$2" -- "$1" } -get_blkid_field_by_device() { +function get_blkid_field_by_device() { local blkid_field="$1" local device="$2" blkid -g \ @@ -132,13 +135,17 @@ get_blkid_field_by_device() { echo -n "$val" } -get_blkid_uuid_for_id() { - local dev="$(resolve_device_by_id "$1")" - local uuid="$(get_blkid_field_by_device 'UUID' "$dev")" +function get_blkid_uuid_for_id() { + local dev + dev="$(resolve_device_by_id "$1")" \ + || die "Could not resolve device with id=$dev" + local uuid + uuid="$(get_blkid_field_by_device 'UUID' "$dev")" \ + || die "Could not get UUID from blkid for device=$dev" echo -n "$uuid" } -get_device_by_blkid_field() { +function get_device_by_blkid_field() { local blkid_field="$1" local field_value="$2" blkid -g \ @@ -153,20 +160,20 @@ get_device_by_blkid_field() { echo -n "$dev" } -get_device_by_partuuid() { +function get_device_by_partuuid() { get_device_by_blkid_field 'PARTUUID' "$1" } -get_device_by_uuid() { +function get_device_by_uuid() { get_device_by_blkid_field 'UUID' "$1" } -cache_lsblk_output() { +function cache_lsblk_output() { CACHED_LSBLK_OUTPUT="$(lsblk --all --path --pairs --output NAME,PTUUID,PARTUUID)" \ || die "Error while executing lsblk to cache output" } -get_device_by_ptuuid() { +function get_device_by_ptuuid() { local ptuuid="${1,,}" local dev if [[ -n $CACHED_LSBLK_OUTPUT ]]; then @@ -182,15 +189,17 @@ get_device_by_ptuuid() { echo -n "$dev" } -uuid_to_mduuid() { +function uuid_to_mduuid() { local mduuid="${1,,}" mduuid="${mduuid//-/}" mduuid="${mduuid:0:8}:${mduuid:8:8}:${mduuid:16:8}:${mduuid:24:8}" echo -n "$mduuid" } -get_device_by_mdadm_uuid() { - local mduuid="$(uuid_to_mduuid "$1")" +function get_device_by_mdadm_uuid() { + local mduuid + mduuid="$(uuid_to_mduuid "$1")" \ + || die "Could not resolve mduuid from uuid=$1" local dev dev="$(mdadm --examine --scan)" \ || die "Error while executing mdadm to find array with UUID=$mduuid" @@ -203,11 +212,11 @@ get_device_by_mdadm_uuid() { echo -n "$dev" } -get_device_by_luks_name() { +function get_device_by_luks_name() { echo -n "/dev/mapper/$1" } -create_resolve_entry() { +function create_resolve_entry() { local id="$1" local type="$2" local arg="${3,,}" @@ -215,14 +224,14 @@ create_resolve_entry() { DISK_ID_TO_RESOLVABLE[$id]="$type:$arg" } -create_resolve_entry_device() { +function create_resolve_entry_device() { local id="$1" local dev="$2" DISK_ID_TO_RESOLVABLE[$id]="device:$dev" } -resolve_device_by_id() { +function resolve_device_by_id() { local id="$1" [[ -v DISK_ID_TO_RESOLVABLE[$id] ]] \ || die "Cannot resolve id='$id' to a block device (no table entry)" @@ -241,7 +250,7 @@ resolve_device_by_id() { esac } -load_or_generate_uuid() { +function load_or_generate_uuid() { local uuid local uuid_file="$UUID_STORAGE_DIR/$1" @@ -259,7 +268,7 @@ load_or_generate_uuid() { # Parses named arguments and stores them in the associative array `arguments`. # If given, the associative array `known_arguments` must contain a list of arguments # prefixed with + (mandatory) or ? (optional). "at least one of" can be expressed by +a|b|c. -parse_arguments() { +function parse_arguments() { local key local value local a diff --git a/tests/shellcheck.sh b/tests/shellcheck.sh new file mode 100755 index 0000000..d685000 --- /dev/null +++ b/tests/shellcheck.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Find the directory this script is stored in. (from: http://stackoverflow.com/questions/59895) +function get_source_dir() { + local source="${BASH_SOURCE[0]}" + while [[ -h $source ]] + do + local tmp + tmp="$(cd -P "$(dirname "${source}")" && pwd)" + source="$(readlink "${source}")" + [[ $source != /* ]] && source="${tmp}/${source}" + done + + echo -n "$(realpath "$(dirname "${source}")")" +} + +cd "$(get_source_dir)/.." +shellcheck -s bash --check-sourced --external-sources ./install +shellcheck -s bash --check-sourced --external-sources ./configure