From ff3c909175171199d64ed44c47ecab21b45d7b3b Mon Sep 17 00:00:00 2001 From: bill-auger Date: Sat, 15 Aug 2020 04:41:57 -0400 Subject: housekeeping --- src/chroot-tools/librechroot | 199 +++++++++++++++++++++---------------------- src/librefetch/librefetch | 14 +-- 2 files changed, 106 insertions(+), 107 deletions(-) diff --git a/src/chroot-tools/librechroot b/src/chroot-tools/librechroot index 52262c4..8a9f0e4 100755 --- a/src/chroot-tools/librechroot +++ b/src/chroot-tools/librechroot @@ -26,11 +26,11 @@ set -euE # You should have received a copy of the GNU General Public License # along with Parabola. If not, see . -# HACKING: if a command is added or removed, it must be changed in 4 places: +# HACKING: if a command is added or removed, take special notice of: # - the usage() text -# - the commands=() array -# - the case statement in main() that checks the number of arguments -# - the case statement in main() that runs them +# - the COMMANDS=() array +# - the the "validate CLI options" switch block which validates them +# - the "handle commands" switch block which handles them source "$(librelib conf)" @@ -60,6 +60,7 @@ detect_chroot_arch() # Usage: make_empty_repo $copydir make_empty_repo() { local copydir=$1 + mkdir -p "${copydir}/repo" bsdtar -czf "${copydir}/repo/repo.db.tar.gz" -T /dev/null ln -s "repo.db.tar.gz" "${copydir}/repo/repo.db" @@ -68,8 +69,9 @@ make_empty_repo() { # Usage: chroot_add_to_local_repo $copydir $pkgfiles... chroot_add_to_local_repo() { local copydir=$1; shift - mkdir -p "$copydir/repo" local pkgfile + + mkdir -p "$copydir/repo" for pkgfile in "$@"; do cp "$pkgfile" "$copydir/repo" pushd "$copydir/repo" >/dev/null @@ -105,6 +107,7 @@ calculate_directories() { check_mountpoint() { local file=$1 local mountpoint mountopts + mountpoint="$(df -P "$file"|sed '1d;s/.*\s//')" mountopts=($(LC_ALL=C mount|awk "{ if (\$3==\"$mountpoint\") { gsub(/[(,)]/, \" \", \$6); print \$6 } }")) ! in_array nosuid "${mountopts[@]}" && ! in_array noexec "${mountopts[@]}" @@ -121,10 +124,11 @@ readonly _mkarchroot="$(librelib chroot/mkarchroot)" arch_nspawn_flags=() sysd_nspawn_flags=() - hack_arch_nspawn_flags() { local copydir="$1" local makepkg_conf="$copydir/etc/makepkg.conf" + local CARCH=$(detect_chroot_arch "$makepkg_conf") + local setarch interpreter OPTIND=1 set -- "${arch_nspawn_flags[@]}" @@ -135,9 +139,6 @@ hack_arch_nspawn_flags() { esac done - local CARCH=$(detect_chroot_arch "$makepkg_conf") - local setarch interpreter - case $CARCH in armv7h|armv7l) setarch=armv7l; interpreter=/usr/bin/qemu-arm-static ;; *) setarch=$CARCH; interpreter=/usr/bin/qemu-$CARCH-static ;; @@ -169,8 +170,8 @@ hack_arch_nspawn_flags() { arch-nspawn() { local copydir=$1; shift local cmd=("$@") - local arch_nspawn_flags=("${arch_nspawn_flags[@]}") + hack_arch_nspawn_flags "$copydir" "$_arch_nspawn" \ @@ -185,8 +186,8 @@ arch-nspawn() { mkarchroot() { local copydir=$1; shift local pkgs=("$@") - local arch_nspawn_flags=("${arch_nspawn_flags[@]}") + hack_arch_nspawn_flags "$copydir" local cmd=( @@ -213,10 +214,15 @@ mkarchroot() { ################################################################################ readonly DEF_PACMANCONF_DIR=/usr/share/pacman/defaults +readonly COMMANDS=( + make sync delete + install-file install-name update clean-pkgs + run enter clean-repo help +) usage() { - eval "$(calculate_directories)" + # NOTE: assumes that 'calculate_directories' has executed local mount_msg="$(_ 'PATH[:INSIDE_PATH[:OPTIONS]]')" @@ -326,29 +332,35 @@ usage() { 'help' 'Show this message' } -readonly commands=( - noop make sync delete - install-file install-name update clean-pkgs - run enter clean-repo help -) +# Usage: ExitInvalidArgument error_fmt [ error_arg1 [ error_arg2 [ ... ] ] ] +ExitInvalidArgument() +{ + (( $# )) && error "$@" + print "See: \`%s help\` for usage" "${0##*/}" + + exit $EXIT_INVALIDARGUMENT +} # Globals: $CHROOTDIR, $CHROOT, $COPY, $rootdir and $copydir main() { COPY=$( [[ $LIBREUSER == root ]] && echo copy || echo "$LIBREUSER" ) - declare -i retconf=0 - load_conf chroot.conf CHROOTDIR CHROOT || retconf=$? + declare -i was_conf_error=0 + load_conf chroot.conf CHROOTDIR CHROOT || was_conf_error=$? - local target_arch=$(uname -m) local mode=enter opt declare -Ai used_opts - local tmp_pacmanconf="$(mktemp --tmpdir ${tmp_pacmanconf_prefix}.XXXXXXXXXX)" - local has_tmp_pacmanconf=0 - local def_pacmanconf - local def_makepkgconf + local target_arch=$(uname -m) + local def_pacmanconf="${DEF_PACMANCONF_DIR}"/pacman.conf.${target_arch} + local def_makepkgconf="${DEF_PACMANCONF_DIR}"/makepkg.conf.${target_arch} + local tmp_pacmanconf="$(mktemp --tmpdir librechroot-pacman.conf.XXXXXXXXXX)" + local seed_pacmanconf="${def_pacmanconf}" + local use_tmp_pacmanconf=0 + arch_nspawn_flags=( -C "$def_pacmanconf" + -M "$def_makepkgconf" ) - trap 'rm -f -- "$tmp_pacmanconf"' EXIT + trap "[[ -f \"$tmp_pacmanconf\" ]] && rm -f -- \"$tmp_pacmanconf\"" EXIT ## parse CLI options ## @@ -357,67 +369,72 @@ main() { case $opt in n ) CHROOT=$OPTARG ;; l ) COPY=$OPTARG ;; - N ) sysd_nspawn_flags+=(--private-network) ;; - C|M) target_arch=$(detect_chroot_arch "$OPTARG") - arch_nspawn_flags+=(-$opt "$OPTARG") ;; + C ) arch_nspawn_flags=( -$opt "$OPTARG" -M "$def_makepkgconf" ) ;; + M ) arch_nspawn_flags=( -$opt "$OPTARG" -C "$def_pacmanconf" ) + target_arch=$(detect_chroot_arch "$OPTARG") ;; A ) target_arch=$OPTARG def_pacmanconf="${DEF_PACMANCONF_DIR}"/pacman.conf.${target_arch} def_makepkgconf="${DEF_PACMANCONF_DIR}"/makepkg.conf.${target_arch} - arch_nspawn_flags+=( -C "${tmp_pacmanconf}" + seed_pacmanconf="${tmp_pacmanconf}" + arch_nspawn_flags+=( -C "${seed_pacmanconf}" -M "${def_makepkgconf}" ) - has_tmp_pacmanconf=1 ;; - w ) sysd_nspawn_flags+=("--bind=$OPTARG") ;; - r ) sysd_nspawn_flags+=("--bind-ro=$OPTARG") ;; - * ) usage >&2; return $EXIT_INVALIDARGUMENT ;; + use_tmp_pacmanconf=1 ;; + N ) sysd_nspawn_flags+=( --private-network ) ;; + w ) sysd_nspawn_flags+=( "--bind=$OPTARG" ) ;; + r ) sysd_nspawn_flags+=( "--bind-ro=$OPTARG" ) ;; + * ) ExitInvalidArgument ;; esac used_opts[$opt]+=1 done + mode=${!OPTIND} + shift $OPTIND + + + ## validate state ## + + if (( $was_conf_error )); then + error "Could not load chroot.conf configuration" + exit $was_conf_error + fi + + eval "$(calculate_directories)" + readonly LIBREUSER LIBREHOME + readonly CHROOTDIR CHROOT COPY + readonly rootdir copydir + readonly mode ## validate CLI options ## for opt in n l C M A; do if (( ${used_opts[$opt]:-0} > 1 )); then - error "Option -%s may only be given once" "$opt" - usage >&2 - return $EXIT_INVALIDARGUMENT + ExitInvalidArgument "$(_ 'Option -%s may only be given once')" "$opt" fi done if (( ${used_opts[A]:-0} && ( ${used_opts[C]:-0} || ${used_opts[M]:-0} ) )); then - error "Option -A may not be used together with -C or -M" - usage >&2 - return $EXIT_INVALIDARGUMENT + ExitInvalidArgument "$(_ 'Option -A may not be used together with -C or -M')" fi - shift $((OPTIND - 1)) - if [[ $# -lt 1 ]]; then - error "Must specify a command" - usage >&2 - return $EXIT_INVALIDARGUMENT + if [[ -z "${mode}" ]]; then + ExitInvalidArgument "$(_ 'Must specify a command')" fi - mode=$1 - if ! in_array "$mode" "${commands[@]}"; then - error "Unrecognized command: %s" "$mode" - usage >&2 - return $EXIT_INVALIDARGUMENT + if ! in_array "$mode" "${COMMANDS[@]}"; then + ExitInvalidArgument "$(_ 'Unrecognized command: %s')" "$mode" fi - shift + case "$mode" in help) usage return $EXIT_SUCCESS :;; - noop|make|sync|delete|update|enter|clean-pkgs|clean-repo) + make|sync|delete|update|enter|clean-pkgs|clean-repo) if [[ $# -gt 0 ]]; then - error 'Command `%s` does not take any arguments: %s' "$mode" "$*" - usage >&2 - return $EXIT_INVALIDARGUMENT + ExitInvalidArgument "$(_ 'Command `%s` does not take any arguments: %s')" "$mode" "$*" fi :;; install-file) if [[ $# -lt 1 ]]; then - error 'Command `%s` requires at least one file' "$mode" - usage >&2 - return $EXIT_INVALIDARGUMENT + ExitInvalidArgument "$(_ 'Command `%s` requires at least one file')" "$mode" + else local missing=() local file @@ -427,40 +444,33 @@ main() { fi done if [[ ${#missing[@]} -gt 0 ]]; then - error "%s: file(s) not found: %s" "$mode" "${missing[*]}" - return $EXIT_INVALIDARGUMENT + ExitInvalidArgument "$(_ '%s: file(s) not found: %s')" "$mode" "${missing[*]}" fi fi :;; install-name) if [[ $# -lt 1 ]]; then - error 'Command `%s` requires at least one package name' "$mode" - usage >&2 - return $EXIT_INVALIDARGUMENT + ExitInvalidArgument "$(_ 'Command `%s` requires at least one package name')" "$mode" fi :;; run) if [[ $# -lt 1 ]]; then - error 'Command `%s` requires at least one argument' "$mode" - usage >&2 - return $EXIT_INVALIDARGUMENT + ExitInvalidArgument "$(_ 'Command `%s` requires at least one argument')" "$mode" fi :;; esac - if (( has_tmp_pacmanconf )) && \ + if (( use_tmp_pacmanconf )) && \ ! [[ -f "${def_pacmanconf}" && -f "${def_makepkgconf}" ]]; then - error 'Unsupported architecture: %s' "${target_arch}" - plain 'See the files in %q for valid architectures.' "${DEF_PACMANCONF_DIR}/" - return $EXIT_INVALIDARGUMENT; + ExitInvalidArgument "$(_ 'Unsupported architecture: %s. See the files in %q for valid architectures.')" \ + "${target_arch}" "${DEF_PACMANCONF_DIR}/" fi ## process CLI options ## - if (( has_tmp_pacmanconf )); then + if (( use_tmp_pacmanconf )); then readonly REPOS_HEADER='###########################\n# Parabola standard repos #' - tmppacmanconf="$(mktemp --tmpdir librechroot-pacman.conf.XXXXXXXXXX)" - read -r -d '' VOLATILE_REPOS <<-'EOF' + readonly VOLATILE_REPOS='\ ##############################\ # Special-case build-support #\ ##############################\ @@ -479,31 +489,19 @@ main() { \ # Enable the volatile x86_64 [staging] repo only as needed\ # [staging]\ -# Server = http://mirror.archlinux.org/$arch/$repo/\ -EOF +# Server = http://mirror.archlinux.org/$arch/$repo/' # generate custom pacman.conf sed -r \ -e "s|^#?\\s*Architecture.+|Architecture = ${target_arch}|g" \ -e "s|^.*Include\s*=\s*/etc/pacman.d/.*\.conf|#&|" \ - -e "N ; /${REPOS_HEADER}/ i ${VOLATILE_REPOS} \n\n" \ + -e "N ; /${REPOS_HEADER}/ i ${VOLATILE_REPOS}\n\n" \ < "${def_pacmanconf}" \ > "${tmp_pacmanconf}" fi - ## finalize state ## - - [[ $retconf = 0 ]] || exit $retconf - eval "$(calculate_directories)" - - readonly LIBREUSER LIBREHOME - readonly CHROOTDIR CHROOT COPY - readonly rootdir copydir - readonly mode - - - ## business ## + ## chroot setup ## if (( EUID )); then error "This program must be run as root." @@ -515,22 +513,22 @@ EOF # Keep this lock for as long as we are running # Note that '9' is the same FD number as in mkarchroot et al. lock 9 "$copydir.lock" \ - "Waiting for existing lock on chroot copy to be released: [%s]" "$COPY" + "Waiting for existing lock on working copy to be released: [%s]" "$COPY" if [[ $mode != delete ]]; then if ! check_mountpoint "$copydir.lock"; then - error "Chroot copy is mounted with nosuid or noexec options: [%s]" "$COPY" + error "Chroot copy is mounted with 'nosuid' or noexec options: [%s]" "$COPY" return $EXIT_FAILURE fi if [[ ! -d $rootdir ]]; then - # Create build chroot + # Create chroot seed system # NOTE: ARM chroots require 'fakeroot-tcp' (BR #2775) local fakeroot_pkg=fakeroot$( [[ "${target_arch}" == 'armv7h' ]] && echo '-tcp' ) - local chroot_pkgs=$( pacman --config "${tmp_pacmanconf}" -Sgq base-devel | \ - sed "s|fakeroot|${fakeroot_pkg}|" ) + local chroot_pkgs=$( pacman --config "${seed_pacmanconf}" -Sgq base-devel | \ + sed "s|fakeroot|${fakeroot_pkg}|" ) - msg "Creating 'root' copy for chroot [%s]" "$CHROOT" + msg "Creating 'root' seed for chroot [%s]" "$CHROOT" mkarchroot "$rootdir" ${chroot_pkgs} /dev/null || ret=$EXIT_FAILURE + ${gpg_cmd[@]} "${filename}" &>/dev/null || ret=${EXIT_FAILURE} if (( ! ret )); then msg2 "Created signature file: %s. @@ -409,8 +408,9 @@ create_signature() { If you can not sign it now on this machine, you can take it home, and run librerelease on it. ${gpg_remind_msg}" - return $ret fi + + return ${ret} } -- cgit v1.2.2