#!/bin/bash # $Id$ isTrue() { case "$1" in [Tt][Rr][Uu][Ee]) return 0 ;; [Tt]) return 0 ;; [Yy][Ee][Ss]) return 0 ;; [Yy]) return 0 ;; 1) return 0 ;; esac return 1 } set_color_vars() { if ! isTrue "${NOCOLOR}" then BOLD=$'\e[0;01m' UNDER=$'\e[4m' GOOD=$'\e[32;01m' WARN=$'\e[33;01m' BAD=$'\e[31;01m' NORMAL=$'\e[0m' else BOLD='' UNDER='' GOOD='' WARN='' BAD='' NORMAL='' fi } set_color_vars dump_debugcache() { TODEBUGCACHE=no if [ -w "${LOGFILE}" ] then echo "${DEBUGCACHE}" >> "${LOGFILE}" else echo "WARNING: Cannot write to '${LOGFILE}'!" echo "${DEBUGCACHE}" fi DEBUGCACHE= } # print_info(loglevel, print [, newline [, prefixline [, forcefile ] ] ]) print_info() { local reset_x=0 if [ -o xtrace ] then set +x reset_x=1 fi local NEWLINE=1 local FORCEFILE=1 local PREFIXLINE=1 local SCRPRINT=0 local STR='' [[ ${#} -lt 2 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes at least two arguments (${#} given)!" [[ ${#} -gt 5 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes at most five arguments (${#} given)!" # IF 3 OR MORE ARGS, CHECK IF WE WANT A NEWLINE AFTER PRINT if [ ${#} -gt 2 ] then if isTrue "$3" then NEWLINE=1 else NEWLINE=0 fi fi # IF 4 OR MORE ARGS, CHECK IF WE WANT TO PREFIX WITH A * if [ ${#} -gt 3 ] then if isTrue "$4" then PREFIXLINE=1 else PREFIXLINE=0 fi fi # IF 5 OR MORE ARGS, CHECK IF WE WANT TO FORCE OUTPUT TO DEBUG # FILE EVEN IF IT DOESN'T MEET THE MINIMUM DEBUG REQS if [ ${#} -gt 4 ] then if isTrue "$5" then FORCEFILE=1 else FORCEFILE=0 fi fi # PRINT TO SCREEN ONLY IF PASSED LOGLEVEL IS HIGHER THAN # OR EQUAL TO SET LOG LEVEL if [[ ${1} -lt ${LOGLEVEL} || ${1} -eq ${LOGLEVEL} ]] then SCRPRINT=1 fi # RETURN IF NOT OUTPUTTING ANYWHERE if [ ${SCRPRINT} -ne 1 -a ${FORCEFILE} -ne 1 ] then [ ${reset_x} -eq 1 ] && set -x return 0 fi # STRUCTURE DATA TO BE OUTPUT TO SCREEN, AND OUTPUT IT if [ ${SCRPRINT} -eq 1 ] then if [ ${PREFIXLINE} -eq 1 ] then STR="${GOOD}*${NORMAL} ${2}" else STR="${2}" fi printf "%b" "${STR}" if [ ${NEWLINE} -ne 0 ] then echo fi fi # STRUCTURE DATA TO BE OUTPUT TO FILE, AND OUTPUT IT if [ ${SCRPRINT} -eq 1 -o ${FORCEFILE} -eq 1 ] then local STRR=${2//${WARN}/} STRR=${STRR//${BAD}/} STRR=${STRR//${BOLD}/} STRR=${STRR//${NORMAL}/} if [ ${PREFIXLINE} -eq 1 ] then STR="* ${STRR}" else STR="${STRR}" fi if isTrue "${TODEBUGCACHE}" then DEBUGCACHE="${DEBUGCACHE}${STR}" else printf "%b" "${STR}" >> "${LOGFILE}" fi if [ ${NEWLINE} -ne 0 ] then if isTrue "${TODEBUGCACHE}" then DEBUGCACHE="${DEBUGCACHE}"$'\n' else echo >> "${LOGFILE}" fi fi fi [ ${reset_x} -eq 1 ] && set -x return 0 } print_error() { GOOD=${BAD} print_info "$@" } print_warning() { GOOD=${WARN} print_info "$@" } can_run_programs_compiled_by_genkernel() { local can_run_programs=no if ! isTrue "$(tc-is-cross-compiler)" then can_run_programs=yes else if [[ ${CBUILD} = x86_64* && ${ARCH} == "x86" ]] then can_run_programs=yes elif [[ ${CBUILD} = powerpc64* && ${ARCH} == "powerpc" ]] then can_run_programs=yes fi fi echo "${can_run_programs}" } has_space_characters() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local testvalue=${1} local has_space_characters=no local space_pattern='[[:space:]]' if [[ "${testvalue}" =~ ${space_pattern} ]] then has_space_characters=yes fi echo "${has_space_characters}" } is_glibc() { if ! hash getconf &>/dev/null then gen_die "getconf not found. Unable to determine libc implementation!" fi local is_glibc=no getconf GNU_LIBC_VERSION &>/dev/null [ $? -eq 0 ] && is_glibc=yes echo "${is_glibc}" } is_gzipped() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local file_to_check=${1} if [ ! -f "${file_to_check}" ] then gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): File '${file_to_check}' does not exist!" fi local file_is_gzipped=no local file_mimetype=$(file --brief --mime-type "${file_to_check}" 2>/dev/null) case "${file_mimetype}" in application/x-gzip) file_is_gzipped=yes ;; application/gzip) file_is_gzipped=yes ;; esac echo "${file_is_gzipped}" } is_psf_file() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local file_to_check=${1} if [ ! -f "${file_to_check}" ] then gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): File '${file_to_check}' does not exist!" fi local file_is_psf=no local file_brief=$(file --brief "${file_to_check}" 2>/dev/null) if [[ "${file_brief}" == *"PC Screen Font"* ]] then file_is_psf=yes fi echo "${file_is_psf}" } is_valid_ssh_host_keys_parameter_value() { local parameter_value=${1} local is_valid=no case "${parameter_value}" in create|create-from-host|runtime) is_valid=yes ;; esac echo "${is_valid}" } is_valid_triplet() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local triplet=${1} local is_triplet=no if [[ "${triplet}" =~ ^[^-]{2,}-[^-]{2,}-.{2,} ]] then is_triplet=yes fi echo "${is_triplet}" } # var_replace(var_name, var_value, string) # $1 = variable name # $2 = variable value # $3 = string var_replace() { [[ ${#} -ne 3 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly three arguments (${#} given)!" # Escape '\' and '.' in $2 to make it safe to use # in the later sed expression local SAFE_VAR SAFE_VAR=$(echo "${2}" | sed -e 's#\([/.]\)#\\\1#g') echo "${3}" | sed -e "s/%%${1}%%/${SAFE_VAR}/g" - if [ $? -ne 0 ] then gen_die "var_replace() failed: 1: '${1}' 2: '${2}' 3: '${3}'" fi } arch_replace() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" var_replace "ARCH" "${ARCH}" "${1}" } cache_replace() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" var_replace "CACHE" "${GK_V_CACHEDIR}" "${1}" } kv_replace() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" var_replace "KV" "${KV}" "${1}" } # Internal func. The first argument is the version info to expand. # Query the preprocessor to improve compatibility across different # compilers rather than maintaining a --version flag matrix. #335943 _gcc_fullversion() { local ver="$1"; shift set -- $($(tc-getCPP "$@") -E -P - <<<"__GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__") eval echo "$ver" } # @FUNCTION: gcc-fullversion # @RETURN: compiler version (major.minor.micro: [3.4.6]) gcc-fullversion() { _gcc_fullversion '$1.$2.$3' "$@" } # @FUNCTION: gcc-version # @RETURN: compiler version (major.minor: [3.4].6) gcc-version() { _gcc_fullversion '$1.$2' "$@" } # @FUNCTION: gcc-major-version # @RETURN: major compiler version (major: [3].4.6) gcc-major-version() { _gcc_fullversion '$1' "$@" } # @FUNCTION: gcc-minor-version # @RETURN: minor compiler version (minor: 3.[4].6) gcc-minor-version() { _gcc_fullversion '$2' "$@" } # @FUNCTION: gcc-micro-version # @RETURN: micro compiler version (micro: 3.4.[6]) gcc-micro-version() { _gcc_fullversion '$3' "$@" } gen_die() { set +x dump_debugcache if [ "$#" -gt '0' ] then print_error 1 "ERROR: ${1}" fi if [[ -n "${GK_MASTER_PID}" && ${BASHPID} != ${GK_MASTER_PID} ]] then # We died in a subshell! Let's trigger trap function... kill -s SIGTERM ${GK_MASTER_PID} else if [ -z "${GK_DIED_IN}" ] then GK_DIED_IN="$(get_useful_function_stack)" else # We are already dying exit 1 fi # Don't trust $LOGFILE before determine_real_args() was called if [ -n "${CMD_LOGFILE}" -a -s "${LOGFILE}" ] then print_error 1 "Please consult '${LOGFILE}' for more information and any" print_error 1 "errors that were reported above." print_error 1 '' fi print_error 1 "Report any genkernel bugs to bugs.gentoo.org and" print_error 1 "assign your bug to genkernel@gentoo.org. Please include" print_error 1 "as much information as you can in your bug report; attaching" print_error 1 "'${LOGFILE}' so that your issue can be dealt with effectively." print_error 1 '' print_error 1 "Please do ${BOLD}*not*${NORMAL} report ${BOLD}kernel${NORMAL} compilation failures as genkernel bugs!" print_error 1 '' restore_boot_mount_state # Cleanup temp dirs and caches if requested cleanup fi exit 1 } get_grep_cmd_for_file() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local config_file=${1} local grep_cmd=${GREP_CMD} if isTrue "$(is_gzipped "${config_file}")" then grep_cmd=${ZGREP_CMD} fi # zgrep for example is optional if [ -z "${grep_cmd}" ] then gen_die "$(get_useful_function_stack "${FUNCNAME}")No grep implementation found which can process '${config_file}'!" fi echo "${grep_cmd}" } # @FUNCTION: get_indent # @USAGE: # @DESCRIPTION: # Returns the indent level in spaces. # # Indentation level. get_indent() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local _level=${1} local _indent= local _indentTemplate=" " local i=0 while [[ ${i} -lt ${_level} ]] do _indent+=${_indentTemplate} i=$[$i+1] done echo "${_indent}" } get_initramfs_compression_method_by_compression() { local -a methods=() methods+=( XZ ) methods+=( LZMA ) methods+=( ZSTD ) methods+=( GZIP ) methods+=( BZIP2 ) methods+=( LZO ) methods+=( LZ4 ) echo "${methods[@]}" } get_initramfs_compression_method_by_speed() { local -a methods=() methods+=( LZ4 ) methods+=( ZSTD ) methods+=( LZO ) methods+=( GZIP ) methods+=( BZIP2 ) methods+=( LZMA ) methods+=( XZ ) echo "${methods[@]}" } setup_cache_dir() { if [ ! -d "${GK_V_CACHEDIR}" ] then mkdir -p "${GK_V_CACHEDIR}" || gen_die "Failed to create '${GK_V_CACHEDIR}'!" fi if isTrue "${CLEAR_CACHEDIR}" then print_info 2 "Clearing cache dir contents from ${CACHE_DIR} ..." while read i do print_info 3 "$(get_indent 1)>> removing ${i}" rm "${i}" done < <(find "${CACHE_DIR}" -maxdepth 2 -type f -name '*.tar.*' -o -name '*.bz2' -o -name '*.xz') fi } cleanup() { # Child processes we maybe want to kill can only appear in # current session local session=$(ps -o sess= ${$} 2>/dev/null | awk '{ print $1 }') if [ -n "${session}" ] then # Time to kill any still running child process. # All our childs will have GK_SHARE environment variable set. local -a killed_pids local pid_to_kill= while IFS= read -r -u 3 pid_to_kill do # Don't kill ourselves or we will trigger trap [ "${pid_to_kill}" = "${BASHPID}" ] && continue # Killing process group allows us to catch grandchilds # with clean environment, too. if kill -${pid_to_kill} &>/dev/null then killed_pids+=( ${pid_to_kill} ) fi done 3< <(ps e -s ${session} 2>/dev/null | grep GK_SHARE= 2>/dev/null | awk '{ print $1 }') if [ ${#killed_pids[@]} -gt 0 ] then # Be patient -- still running process could prevent cleanup! sleep 3 # Add one valid pid so that ps command won't fail killed_pids+=( ${BASHPID} ) killed_pids=$(IFS=,; echo "${killed_pids[*]}") # Processes had enough time to gracefully terminate! while IFS= read -r -u 3 pid_to_kill do # Don't kill ourselves or we will trigger trap [ "${pid_to_kill}" = "${BASHPID}" ] && continue kill -9 -${pid_to_kill} &>/dev/null done 3< <(ps --no-headers -q ${killed_pids} 2>/dev/null | awk '{ print $1 }') fi else print_warning 1 "Failed to determine session leader; Will not try to stop child processes" fi if isTrue "${CLEANUP}" then if [ -n "${TEMP}" -a -d "${TEMP}" ] then rm -rf "${TEMP}" fi if isTrue "${POSTCLEAR}" then echo print_info 2 'Running final cache/tmp cleanup ...' print_info 3 "CACHE_DIR: ${CACHE_DIR}" CLEAR_CACHEDIR=yes setup_cache_dir echo print_info 3 "TMPDIR: ${TMPDIR}" clear_tmpdir fi else print_info 2 "--no-cleanup is set; Skipping cleanup ..." print_info 3 "TEMP: ${TEMP}" print_info 3 "CACHE_DIR: ${CACHE_DIR}" print_info 3 "TMPDIR: ${TMPDIR}" fi GK_TIME_END=$(date +%s) let GK_TIME_RUNTIME_SECONDS=${GK_TIME_END}-${GK_TIME_START} let GK_TIME_RUNTIME_DAYS=${GK_TIME_RUNTIME_SECONDS}/86400 TZ= printf ">>> Ended on: $(date +"%Y-%m-%d %H:%M:%S") (after %d days%(%k hours %M minutes %S seconds)T)\n" ${GK_TIME_RUNTIME_DAYS} ${GK_TIME_RUNTIME_SECONDS} >> "${LOGFILE}" 2>/dev/null } clear_tmpdir() { if isTrue "${CMD_INSTALL}" then TMPDIR_CONTENTS=$(ls "${TMPDIR}") print_info 2 "Removing tmp dir contents" for i in ${TMPDIR_CONTENTS} do print_info 3 "$(get_indent 1)>> removing ${i}" rm -r "${TMPDIR}/${i}" done fi } # @FUNCTION: copy_image_with_preserve # @USAGE: # @DESCRIPTION: # Function to copy various kernel boot image products to the boot directory, # preserve a generation of old images (just like the manual kernel build's # "make install" does), and maintain the symlinks (if enabled). # # Symlink in the boot directory. Path not included. # # Fully qualified path name of the source image. # # Name of the destination image in the boot directory, # no path included. copy_image_with_preserve() { [[ ${#} -ne 3 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly three arguments (${#} given)!" local symlinkName=${1} local newSrceImage=${2} local fullDestName=${3} local currDestImage local prevDestImage print_info 3 "Shall copy new ${symlinkName} image, " 0 # Old product might be a different version. If so, we need to read # the symlink to see what it's name is, if there are symlinks. cd "${KERNEL_OUTPUTDIR}" || gen_die "Failed to chdir to '${KERNEL_OUTPUTDIR}'!" if isTrue "${SYMLINK}" then print_info 3 "automatically managing symlinks and old images." 1 0 if [ -e "${BOOTDIR}/${symlinkName}" ] then # JRG: Do I need a special case here for when the standard symlink # name is, in fact, not a symlink? currDestImage=$(readlink --no-newline "${BOOTDIR}/${symlinkName}") print_info 4 "Current ${symlinkName} symlink exists:" print_info 4 " ${currDestImage}" else currDestImage="${fullDestName}" print_info 4 "Current ${symlinkName} symlink does NOT exist." print_info 4 " Defaulted to: ${currDestImage}" fi if [ -e "${BOOTDIR}/${symlinkName}.old" ] then # JRG: Do I need a special case here for when the standard symlink # name is, in fact, not a symlink? prevDestImage=$(readlink --no-newline "${BOOTDIR}/${symlinkName}.old") print_info 4 "Old ${symlinkName} symlink exists:" print_info 4 " ${prevDestImage}" else prevDestImage="${fullDestName}.old" print_info 4 "Old ${symlinkName} symlink does NOT exist." print_info 4 " Defaulted to: ${prevDestImage}" fi else print_info 3 "symlinks not being handled by genkernel." 1 0 currDestImage="${fullDestName}" prevDestImage="${fullDestName}.old" fi if [ -e "${BOOTDIR}/${currDestImage}" ] then local currDestImageExists=yes print_info 4 "Actual image file '${BOOTDIR}/${currDestImage}' does exist." else local currDestImageExists=no print_info 4 "Actual image file '${BOOTDIR}/${currDestImage}' does NOT exist." fi if [ -e "${BOOTDIR}/${prevDestImage}" ] then local prevDestImageExists=yes print_info 4 "Actual old image file '${BOOTDIR}/${prevDestImage}' does exist." else local prevDestImageExists=no print_info 4 "Actual old image file '${BOOTDIR}/${prevDestImage}' does NOT exist." fi # When symlinks are not being managed by genkernel, old symlinks might # still be useful. Leave 'em alone unless managed. if isTrue "${SYMLINK}" then local -a old_symlinks=() old_symlinks+=( "${BOOTDIR}/${symlinkName}" ) old_symlinks+=( "${BOOTDIR}/${symlinkName}.old" ) local old_symlink= for old_symlink in "${old_symlinks[@]}" do if [ -L "${old_symlink}" ] then print_info 4 "Deleting old symlink '${old_symlink}' ..." rm "${old_symlink}" || gen_die "Failed to delete '${old_symlink}'!" else print_info 4 "Old symlink '${old_symlink}' does NOT exist; Skipping ..." fi done unset old_symlinks old_symlink fi # We only erase the .old image when it is the exact same version as the # current and new images. Different version .old (and current) images are # left behind. This is consistent with how "make install" of the manual # kernel build works. if [ "${currDestImage}" == "${fullDestName}" ] then # Case for new and currrent of the same base version. print_info 4 "Same base version (${currDestImage})." if isTrue "${currDestImageExists}" then if [ -e "${BOOTDIR}/${currDestImage}.old" ] then print_info 3 "Deleting old identical ${symlinkName} version '${BOOTDIR}/${currDestImage}.old' ..." rm "${BOOTDIR}/${currDestImage}.old" \ || gen_die "Failed to delete '${BOOTDIR}/${currDestImage}.old'!" fi print_info 3 "Moving '${BOOTDIR}/${currDestImage}' to '${BOOTDIR}/${currDestImage}.old' ..." mv "${BOOTDIR}/${currDestImage}" "${BOOTDIR}/${currDestImage}.old" \ || gen_die "Could not rename the old ${symlinkName} image!" prevDestImage="${currDestImage}.old" prevDestImageExists=yes fi else # Case for new / current not of the same base version. print_info 4 "Different base version." prevDestImage="${currDestImage}" currDestImage="${fullDestName}" fi print_info 3 "Copying '${newSrceImage}' to '${BOOTDIR}/${currDestImage}' ..." cp -aL "${newSrceImage}" "${BOOTDIR}/${currDestImage}" \ || gen_die "Failed to copy '${newSrceImage}' to '${BOOTDIR}/${currDestImage}'!" if isTrue "${SYMLINK}" then print_info 3 "Creating '${symlinkName}' -> '${currDestImage}' symlink ..." ln -s "${currDestImage}" "${BOOTDIR}/${symlinkName}" \ || gen_die "Failed to create '${symlinkName}' -> '${currDestImage}' symlink!" if isTrue "${prevDestImageExists}" then print_info 3 "Creating '${symlinkName}.old' -> '${prevDestImage}' symlink ..." ln -s "${prevDestImage}" "${BOOTDIR}/${symlinkName}.old" \ || "Failed to create '${symlinkName}.old' -> '${prevDestImage}' symlink!" fi fi } dropbear_create_key() { [[ ${#} -ne 2 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly two arguments (${#} given)!" local key_file=${1} local command=${2} local key_type=$(dropbear_get_key_type_from_filename "${key_file}") local -a envvars=( "GK_SHARE='${GK_SHARE}'" "LOGLEVEL='${LOGLEVEL}'" "LOGFILE='${LOGFILE}'" "NOCOLOR='${NOCOLOR}'" "PATH='${PATH}'" "TEMP='${TEMP}'" ) envvars+=( "DROPBEAR_COMMAND='${command}'" "DROPBEAR_KEY_FILE='${key_file}'" "DROPBEAR_KEY_TYPE='${key_type}'" ) if isTrue "${SANDBOX}" then envvars+=( "SANDBOX_LOG='$(get_temp_file "sandbox_XXXXXX.log")'" ) envvars+=( "SANDBOX_WRITE='${LOGFILE}:${TEMP}:/proc/thread-self/attr/fscreate'" ) fi # set up worker signal handler local error_msg_detail="Failed to create dropbear key '${key_file}'!" local error_msg="gen_worker.sh aborted: ${error_msg_detail}" trap "gen_die \"${error_msg}\"" SIGABRT SIGHUP SIGQUIT SIGINT SIGTERM local dropbear_command=( "env -i" ) dropbear_command+=( "${envvars[*]}" ) dropbear_command+=( "${SANDBOX_COMMAND}" ) dropbear_command+=( "${GK_SHARE}/gen_worker.sh" ) dropbear_command+=( "dropbear" ) dropbear_command+=( "2>&1" ) eval "${dropbear_command[@]}" local RET=$? # restore default trap set_default_gk_trap [ ${RET} -ne 0 ] && gen_die "$(get_useful_function_stack)${error_msg_detail}" } dropbear_get_key_type_from_filename() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local key=${1} local type= case "${key}" in *_dss_*) type=dss ;; *_ecdsa_*) type=ecdsa ;; *_ed25519_*) type=ed25519 ;; *_rsa_*) type=rsa ;; *) gen_die "Failed to determine key type from '${key}'!" ;; esac echo "${type}" } dropbear_generate_key_info_file() { [[ ${#} -ne 3 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly three arguments (${#} given)!" local command=${1} local key_info_file=${2} local initramfs_dropbear_dir=${3} local key_file="${initramfs_dropbear_dir}/$(basename "${key_info_file/%_key.*/_key}")" local key_type=$(dropbear_get_key_type_from_filename "${key_file}") local -a envvars=( "GK_SHARE='${GK_SHARE}'" "LOGLEVEL='${LOGLEVEL}'" "LOGFILE='${LOGFILE}'" "NOCOLOR='${NOCOLOR}'" "PATH='${PATH}'" "TEMP='${TEMP}'" ) envvars+=( "DROPBEAR_COMMAND='${command}'" "DROPBEAR_KEY_FILE='${key_file}'" "DROPBEAR_KEY_TYPE='${key_type}'" "DROPBEAR_KEY_INFO_FILE='${key_info_file}'" ) if isTrue "${SANDBOX}" then envvars+=( "SANDBOX_LOG='$(get_temp_file "sandbox_XXXXXX.log")'" ) envvars+=( "SANDBOX_WRITE='${LOGFILE}:${TEMP}:/proc/thread-self/attr/fscreate'" ) fi # set up worker signal handler local error_msg_detail="Failed to extract dropbear key information from '${key_file}'!" local error_msg="gen_worker.sh aborted: ${error_msg_detail}" trap "gen_die \"${error_msg}\"" SIGABRT SIGHUP SIGQUIT SIGINT SIGTERM local dropbear_command=( "env -i" ) dropbear_command+=( "${envvars[*]}" ) dropbear_command+=( "${SANDBOX_COMMAND}" ) dropbear_command+=( "${GK_SHARE}/gen_worker.sh" ) dropbear_command+=( "dropbear" ) dropbear_command+=( "2>&1" ) eval "${dropbear_command[@]}" local RET=$? # restore default trap set_default_gk_trap [ ${RET} -ne 0 ] && gen_die "$(get_useful_function_stack)${error_msg_detail}" } # @FUNCTION: debug_breakpoint # @USAGE: [] # @DESCRIPTION: # Internal helper function which can be used during development to act like # a breakpoint. I.e. will stop execution and show some variables. # # Give breakpoint a name debug_breakpoint() { set +x local name=${1} [ -n "${name}" ] && name=" '${name}'" echo "Debug breakpoint${name} reached" echo "TEMP: ${TEMP}" [[ -n "${WORKDIR}" ]] && echo "WORKDIR: ${WORKDIR}" [[ -n "${S}" ]] && echo "S: ${S}" [[ -n "${D}" ]] && echo "D: ${D}" if [ -n "${GK_WORKER_MASTER_PID}" ] then [[ ${BASHPID:-$(__bashpid)} == ${GK_WORKER_MASTER_PID} ]] || kill -s SIGTERM ${GK_WORKER_MASTER_PID} else [[ ${BASHPID:-$(__bashpid)} == ${GK_MASTER_PID} ]] || kill -s SIGTERM ${GK_MASTER_PID} fi exit 99 } get_chost_libdir() { local cc=$(tc-getCC) local test_file=$(${cc} -print-file-name=libc.a 2>/dev/null) if [ -z "${test_file}" ] then gen_die "$(get_useful_function_stack "${FUNCNAME}")Unable to determine CHOST's libdir: '${cc} -print-file-name=libc.a' returned nothing!" elif [[ "${test_file}" == "libc.a" ]] then gen_die "$(get_useful_function_stack "${FUNCNAME}")Unable to determine CHOST's libdir: '${cc} -print-file-name=libc.a' returned no path!" fi local test_file_realpath=$(realpath "${test_file}" 2>/dev/null) if [ -z "${test_file_realpath}" ] then gen_die "$(get_useful_function_stack "${FUNCNAME}")Unable to determine CHOST's libdir: 'realpath \"${test_file}\"' returned nothing!" fi local libdir=$(dirname "${test_file_realpath}" 2>/dev/null) if [ -z "${libdir}" ] then gen_die "$(get_useful_function_stack "${FUNCNAME}")Unable to determine CHOST's libdir!" fi echo "${libdir}" } get_du() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" [ -z "${DU_COMMAND}" ] && return local sz=( $("${DU_COMMAND}" -hs "${1}" 2>/dev/null) ) echo "${sz[0]}" } _get_gkpkg_var_value() { [[ ${#} -ne 2 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly two arguments (${#} given)!" local VARNAME=${1} case "${VARNAME}" in BINPKG|DEPS|PN|PV|SRCDIR|SRCTAR) ;; *) # Let's make variable support explicit gen_die "$(get_useful_function_stack)Variable '${VARNAME}' is not supported by ${FUNCNAME}()!" ;; esac local PN=${2} [[ -z "${PN}" ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!" [[ -z "${GKPKG_LOOKUP_TABLE[${PN}]}" ]] \ && gen_die "$(get_useful_function_stack)Internal error: Package '${PN}' is unknown! Was package added to software.sh?" local REQUESTED_VARNAME="${GKPKG_LOOKUP_TABLE[${PN}]}_${VARNAME}" local REQUESTED_VALUE="${!REQUESTED_VARNAME}" [[ ${VARNAME} != 'DEPS' && -z "${REQUESTED_VALUE}" ]] \ && gen_die "$(get_useful_function_stack)Internal error: Variable '${REQUESTED_VARNAME}' is not set!" echo "${REQUESTED_VALUE}" } get_gkpkg_binpkg() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local PN=${1} _get_gkpkg_var_value BINPKG ${PN} } get_gkpkg_deps() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local PN=${1} [[ -z "${PN}" ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!" _get_gkpkg_var_value DEPS ${PN} } get_gkpkg_srcdir() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local PN=${1} [[ -z "${PN}" ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!" _get_gkpkg_var_value SRCDIR ${PN} } get_gkpkg_srctar() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local PN=${1} [[ -z "${PN}" ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!" _get_gkpkg_var_value SRCTAR ${PN} } get_gkpkg_version() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!" local PN=${1} [[ -z "${PN}" ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!" _get_gkpkg_var_value PV ${PN} } # @FUNCTION: get_tar_cmd # @USAGE: # @DESCRIPTION: # Returns tar command which can make use of pbzip2, pxz or pigz when # possible. # # Archive file get_tar_cmd() { [[ ${#} -ne 1 ]] \ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one arguments (${#} given)!" local archive_file=${1} local -a tar_cmd tar_cmd+=( "${TAR_COMMAND}" ) tar_cmd+=( '-c' ) local pcmd if [[ "${archive_file}" == *.tar.bz2 ]] then pcmd=$(which pbzip2 2>/dev/null) elif [[ "${archive_file}" == *.tar.xz ]] then pcmd=$(which pxz 2>/dev/null) elif [[ "${archive_file}" == *.tar.gz ]] then pcmd=$(which pigz 2>/dev/null) fi if [ -n "${pcmd}" ] then tar_cmd+=( "-I ${pcmd}" ) else tar_cmd+=( '-a' ) fi tar_cmd+=( '-pf' ) tar_cmd+=( "${archive_file}" ) echo "${tar_cmd[@]}" } get_tc_vars() { local -a tc_vars=() tc_vars+=( AR ) tc_vars+=( AS ) tc_vars+=( CC ) tc_vars+=( CPP ) tc_vars+=( CXX ) tc_vars+=( LD ) tc_vars+=( STRIP ) tc_vars+=( NM ) tc_vars+=( RANLIB ) tc_vars+=( READELF ) tc_vars+=( OBJCOPY ) tc_vars+=( OBJDUMP ) tc_vars+=( PKG_CONFIG ) echo "${tc_vars[@]}" } # @FUNCTION: get_temp_file # @USAGE: [