tree-wide: fix shellcheck warnings and style consistency

This commit is contained in:
Mike Yuan 2022-12-20 16:38:44 +08:00
parent 560c00c9c2
commit 33cf482649
No known key found for this signature in database
GPG Key ID: 417471C0A40F58B3
5 changed files with 150 additions and 130 deletions

View File

@ -2,27 +2,30 @@
shopt -s extglob
# m4_include() is recognized as a function definition
# shellcheck source=common disable=SC1073,SC1065,SC1064,SC1072
m4_include(common)
setup=chroot_setup
unshare=0
userspec=''
chroot_args=()
usage() {
cat <<EOF
usage: ${0##*/} chroot-dir [command] [arguments...]
usage: ${0##*/} [options] chroot_dir [command [arguments...]]
-h Print this help message
Options:
-N Run in unshare mode as a regular user
-u <user>[:group] Specify non-root user and optional group to use
If 'command' is unspecified, ${0##*/} will launch /bin/bash.
-u <user>[:group] Specify non-root user and group (optional) to use
-h Print this help message
If 'command' is unspecified, arch-chroot will launch /bin/bash.
Note that when using arch-chroot, the target chroot directory *should* be a
mountpoint. This ensures that tools such as pacman(8) or findmnt(8) have an
accurate hierarchy of the mounted filesystems within the chroot.
If your chroot target is not a mountpoint, you can bind mount the directory on
itself to make it a mountpoint, i.e. 'mount --bind /your/chroot /your/chroot'.
itself to make it one, i.e. 'mount --bind chroot_dir chroot_dir'.
EOF
}
@ -74,32 +77,32 @@ chroot_add_resolv_conf() {
chroot_add_mount "$src" "$dest" --bind
}
while getopts ':hNu:' flag; do
if [[ -z $1 || $1 = @(-h|--help) ]]; then
usage
exit $(( $# ? 0 : 1 ))
fi
while getopts ':Nu:' flag; do
case $flag in
h)
usage
exit 0
;;
N)
setup=unshare_setup
unshare=1
;;
u)
userspec=$OPTARG
userspec="$OPTARG"
;;
:)
die '%s: option requires an argument -- '\''%s'\' "${0##*/}" "$OPTARG"
die "%s: option requires an argument -- '%s'" "${0##*/}" "$OPTARG"
;;
?)
die '%s: invalid option -- '\''%s'\' "${0##*/}" "$OPTARG"
die "%s: invalid option -- '%s'" "${0##*/}" "$OPTARG"
;;
esac
done
shift $(( OPTIND - 1 ))
(( $# )) || die 'No chroot directory specified'
chrootdir=$1
shift
chrootdir="$1"; shift
arch-chroot() {
(( EUID == 0 )) || die 'This script must be run with root privileges'
@ -125,3 +128,5 @@ if (( unshare )); then
else
arch-chroot
fi
# vim: et ts=2 sw=2 ft=sh:

122
common
View File

@ -1,3 +1,6 @@
#!/hint/bash
# shellcheck disable=SC2155,SC2064
# generated from util-linux source: libmount/src/utils.c
declare -A pseudofs_types=([anon_inodefs]=1
[apparmorfs]=1
@ -72,11 +75,12 @@ declare -A fsck_types=([btrfs]=0 # btrfs doesn't need a regular fsck utility
[vfat]=1
[xfs]=1)
# shellcheck disable=SC2059
out() { printf "$1 $2\n" "${@:3}"; }
error() { out "==> ERROR:" "$@"; } >&2
warning() { out "==> WARNING:" "$@"; } >&2
msg() { out "==>" "$@"; }
msg2() { out " ->" "$@";}
msg2() { out " ->" "$@"; }
warning() { out "==> WARNING:" "$@"; } >&2
error() { out "==> ERROR:" "$@"; } >&2
die() { error "$@"; exit 1; }
ignore_error() {
@ -86,23 +90,44 @@ ignore_error() {
in_array() {
local i
for i in "${@:2}"; do
[[ $1 = "$i" ]] && return 0
[[ "$1" = "$i" ]] && return 0
done
return 1
}
rev_array() {
local -n _arr="$1"
mapfile -t _arr < <(printf '%s\n' "${_arr[@]}" | tac)
}
chroot_add_mount() {
mount "$@" && CHROOT_ACTIVE_MOUNTS=("$2" "${CHROOT_ACTIVE_MOUNTS[@]}")
mount "$@" && CHROOT_ACTIVE_MOUNTS+=("$2")
}
chroot_maybe_add_mount() {
local cond=$1; shift
local cond="$1"; shift
if eval "$cond"; then
chroot_add_mount "$@"
fi
}
chroot_add_mount_lazy() {
mount "$@" && CHROOT_ACTIVE_LAZY+=("$2")
}
chroot_bind_device() {
touch "$2" && CHROOT_ACTIVE_FILES+=("$2")
chroot_add_mount "$1" "$2" --bind
}
chroot_add_link() {
ln -sf "$1" "$2" && CHROOT_ACTIVE_FILES+=("$2")
}
chroot_setup() {
CHROOT_ACTIVE_MOUNTS=()
[[ $(trap -p EXIT) ]] && die '(BUG): attempting to overwrite existing EXIT trap'
@ -121,28 +146,14 @@ chroot_setup() {
chroot_teardown() {
if (( ${#CHROOT_ACTIVE_MOUNTS[@]} )); then
rev_array CHROOT_ACTIVE_MOUNTS
umount "${CHROOT_ACTIVE_MOUNTS[@]}"
fi
unset CHROOT_ACTIVE_MOUNTS
}
chroot_add_mount_lazy() {
mount "$@" && CHROOT_ACTIVE_LAZY=("$2" "${CHROOT_ACTIVE_LAZY[@]}")
}
chroot_bind_device() {
touch "$2" && CHROOT_ACTIVE_FILES=("$2" "${CHROOT_ACTIVE_FILES[@]}")
chroot_add_mount $1 "$2" --bind
}
chroot_add_link() {
ln -sf "$1" "$2" && CHROOT_ACTIVE_FILES=("$2" "${CHROOT_ACTIVE_FILES[@]}")
}
unshare_setup() {
CHROOT_ACTIVE_MOUNTS=()
CHROOT_ACTIVE_LAZY=()
CHROOT_ACTIVE_FILES=()
CHROOT_ACTIVE_MOUNTS=() CHROOT_ACTIVE_LAZY=() CHROOT_ACTIVE_FILES=()
[[ $(trap -p EXIT) ]] && die '(BUG): attempting to overwrite existing EXIT trap'
trap 'unshare_teardown' EXIT
@ -167,17 +178,20 @@ unshare_teardown() {
chroot_teardown
if (( ${#CHROOT_ACTIVE_LAZY[@]} )); then
rev_array CHROOT_ACTIVE_LAZY
umount --lazy "${CHROOT_ACTIVE_LAZY[@]}"
fi
unset CHROOT_ACTIVE_LAZY
if (( ${#CHROOT_ACTIVE_FILES[@]} )); then
rev_array CHROOT_ACTIVE_FILES
rm "${CHROOT_ACTIVE_FILES[@]}"
fi
unset CHROOT_ACTIVE_FILES
}
pid_unshare="unshare --fork --pid"
# shellcheck disable=SC2034
mount_unshare="$pid_unshare --mount --map-auto --map-root-user --setuid 0 --setgid 0"
# This outputs code for declaring all variables to stdout. For example, if
@ -198,11 +212,11 @@ declare_all() {
}
try_cast() (
_=$(( $1#$2 ))
_=$(( ${1#"$2"} ))
) 2>/dev/null
valid_number_of_base() {
local base=$1 len=${#2} i=
local base="$1" len="${#2}" i
for (( i = 0; i < len; i++ )); do
try_cast "$base" "${2:i:1}" || return 1
@ -212,29 +226,29 @@ valid_number_of_base() {
}
mangle() {
local i= chr= out=
local {a..f}= {A..F}=
local i chr out
local {a..f}='' {A..F}=''
for (( i = 0; i < ${#1}; i++ )); do
chr=${1:i:1}
chr="${1:i:1}"
case $chr in
[[:space:]\\])
printf -v chr '%03o' "'$chr"
out+=\\
;;
esac
out+=$chr
out+="$chr"
done
printf '%s' "$out"
}
unmangle() {
local i= chr= out= len=$(( ${#1} - 4 ))
local {a..f}= {A..F}=
local i chr out len="$(( ${#1} - 4 ))"
local {a..f}='' {A..F}=''
for (( i = 0; i < len; i++ )); do
chr=${1:i:1}
chr="${1:i:1}"
case $chr in
\\)
if valid_number_of_base 8 "${1:i+1:3}" ||
@ -244,7 +258,7 @@ unmangle() {
fi
;;
esac
out+=$chr
out+="$chr"
done
printf '%s' "$out${1:i}"
@ -255,39 +269,37 @@ optstring_match_option() {
IFS=, read -ra patterns <<<"$1"
for pat in "${patterns[@]}"; do
if [[ $pat = *=* ]]; then
if [[ $pat = *'='* ]]; then
# "key=val" will only ever match "key=val"
candidate=$2
candidate="$2"
else
# "key" will match "key", but also "key=anyval"
candidate=${2%%=*}
candidate="${2%%=*}"
fi
[[ $pat = "$candidate" ]] && return 0
[[ "$pat" = "$candidate" ]] && return 0
done
return 1
}
optstring_remove_option() {
local o options_ remove=$2 IFS=,
local o _options remove="$2"
read -ra options_ <<<"${!1}"
for o in "${!options_[@]}"; do
optstring_match_option "$remove" "${options_[o]}" && unset 'options_[o]'
IFS=, read -ra _options <<<"${!1}"
for o in "${!_options[@]}"; do
optstring_match_option "$remove" "${_options[o]}" && unset '_options[o]'
done
declare -g "$1=${options_[*]}"
declare -g "$1=${_options[*]}"
}
optstring_normalize() {
local o options_ norm IFS=,
read -ra options_ <<<"${!1}"
local o _options norm
IFS=, read -ra _options <<<"${!1}"
# remove empty fields
for o in "${options_[@]}"; do
for o in "${_options[@]}"; do
[[ $o ]] && norm+=("$o")
done
@ -295,6 +307,12 @@ optstring_normalize() {
declare -g "$1=${norm[*]:-defaults}"
}
optstring_has_option() {
local o="${2%%=*}"
optstring_get_option "$1" "$o"
}
optstring_append_option() {
if ! optstring_has_option "$1" "$2"; then
declare -g "$1=${!1},$2"
@ -304,8 +322,6 @@ optstring_append_option() {
}
optstring_prepend_option() {
local options_=$1
if ! optstring_has_option "$1" "$2"; then
declare -g "$1=$2,${!1}"
fi
@ -327,14 +343,8 @@ optstring_get_option() {
return 1
}
optstring_has_option() {
local "${2%%=*}"
optstring_get_option "$1" "$2"
}
dm_name_for_devnode() {
read dm_name <"/sys/class/block/${1#/dev/}/dm/name"
read -r dm_name <"/sys/class/block/${1#/dev/}/dm/name"
if [[ $dm_name ]]; then
printf '/dev/mapper/%s' "$dm_name"
else
@ -351,3 +361,5 @@ fstype_is_pseudofs() {
fstype_has_fsck() {
(( fsck_types["$1"] ))
}
# vim: et ts=2 sw=2 ft=sh:

View File

@ -3,7 +3,7 @@ _genfstab() {
local cur prev words cword
_init_completion || return
local opts="-f -L -p -P -t -U -h"
local opts="-f -L -P -p -t -U -h"
case ${prev} in
-f)

View File

@ -1,7 +1,10 @@
#!/bin/bash
# shellcheck disable=SC2154 # optstring_*_option may export variables in runtime
shopt -s extglob
# m4_include() is recognized as a function definition
# shellcheck source=common disable=SC1073,SC1065,SC1064,SC1072
m4_include(common)
write_source() {
@ -43,7 +46,7 @@ write_source() {
}
optstring_apply_quirks() {
local varname=$1 fstype=$2
local varname="$1" fstype="$2"
# SELinux displays a 'seclabel' option in /proc/self/mountinfo. We can't know
# if the system we're generating the fstab for has any support for SELinux (as
@ -92,13 +95,13 @@ usage: ${0##*/} [options] root
-p Exclude pseudofs mounts (default behavior)
-P Include pseudofs mounts
-t <tag> Use TAG for source identifiers (TAG should be one of: LABEL,
UUID, PARTLABEL, PARTUUID)
UUID, PARTLABEL, PARTUUID)
-U Use UUIDs for source identifiers (shortcut for -t UUID)
-h Print this help message
genfstab generates output suitable for addition to an fstab file based on the
devices mounted under the mountpoint specified by the given root.
genfstab generates output suitable for addition to an fstab file based on
the devices mounted under the mountpoint specified by the given root.
EOF
}
@ -110,15 +113,12 @@ fi
while getopts ':f:LPpt:U' flag; do
case $flag in
f)
prefixfilter="$OPTARG"
;;
L)
bytag=LABEL
;;
U)
bytag=UUID
;;
f)
prefixfilter=$OPTARG
;;
P)
pseudofs=1
;;
@ -126,42 +126,45 @@ while getopts ':f:LPpt:U' flag; do
pseudofs=0
;;
t)
bytag=${OPTARG^^}
bytag="${OPTARG^^}"
;;
U)
bytag=UUID
;;
:)
die '%s: option requires an argument -- '\''%s'\' "${0##*/}" "$OPTARG"
die "%s: option requires an argument -- '%s'" "${0##*/}" "$OPTARG"
;;
?)
die '%s: invalid option -- '\''%s'\' "${0##*/}" "$OPTARG"
die "%s: invalid option -- '%s'" "${0##*/}" "$OPTARG"
;;
esac
done
shift $(( OPTIND - 1 ))
(( $# )) || die "No root directory specified"
root=$(realpath -mL "$1"); shift
(( $# )) || die 'No root directory specified'
root="$(realpath -mL "$1")"; shift
if ! mountpoint -q "$root"; then
die "$root is not a mountpoint"
die '%s: not a mountpoint' "$root"
fi
# handle block devices
findmnt -Recvruno SOURCE,TARGET,FSTYPE,OPTIONS,FSROOT "$root" |
while read -r src target fstype opts fsroot; do
if (( !pseudofs )) && fstype_is_pseudofs "$fstype"; then
if (( ! pseudofs )) && fstype_is_pseudofs "$fstype"; then
continue
fi
[[ $target = "$prefixfilter"* ]] || continue
[[ "$target" = "$prefixfilter"* ]] || continue
# default 5th and 6th columns
dump=0 pass=2
src=$(unmangle "$src")
target=$(unmangle "$target")
target=${target#$root}
src="$(unmangle "$src")"
target="$(unmangle "$target")"
target="/${target#"$root/"}"
if (( !foundroot )) && findmnt "$src" "$root" >/dev/null; then
if (( ! foundroot )) && findmnt "$src" "$root" >/dev/null; then
# this is root. we can't possibly have more than one...
pass=1 foundroot=1
fi
@ -171,7 +174,7 @@ findmnt -Recvruno SOURCE,TARGET,FSTYPE,OPTIONS,FSROOT "$root" |
pass=0
fi
if [[ $fsroot != / && $fstype != btrfs ]]; then
if [[ "$fsroot" != "/" && "$fstype" != "btrfs" ]]; then
# it's a bind mount
src=$(findmnt -funcevo TARGET "$src")$fsroot
src="/${src#$root/}"
@ -183,7 +186,7 @@ findmnt -Recvruno SOURCE,TARGET,FSTYPE,OPTIONS,FSROOT "$root" |
continue
fi
fstype=none
opts+=,bind
opts+=',bind'
pass=0
fi
@ -192,20 +195,20 @@ findmnt -Recvruno SOURCE,TARGET,FSTYPE,OPTIONS,FSROOT "$root" |
fuseblk)
# well-behaved FUSE filesystems will report themselves as fuse.$fstype.
# this is probably NTFS-3g, but let's just make sure.
if ! newtype=$(lsblk -no FSTYPE "$src") || [[ -z $newtype ]]; then
if ! newtype="$(lsblk -no FSTYPE "$src")" || [[ -z $newtype ]]; then
# avoid blanking out fstype, leading to an invalid fstab
error 'Failed to derive real filesystem type for FUSE device on %s' "$target"
else
fstype=$newtype
fstype="$newtype"
fi
;;
esac
optstring_apply_quirks "opts" "$fstype"
optstring_apply_quirks opts "$fstype"
# write one line
write_source "$src"
printf '\t%-10s' "/$(mangle "${target#/}")" "$fstype" "$opts"
printf '\t%-10s' "$(mangle "$target")" "$fstype" "$opts"
printf '\t%s %s' "$dump" "$pass"
printf '\n\n'
done
@ -213,20 +216,20 @@ done
# handle swaps devices
{
# ignore header
read
read -r
while read -r device type _ _ prio; do
options=defaults
if (( prio >= 0 )); then
options+=,pri=$prio
options+=",pri=$prio"
fi
# skip files marked deleted by the kernel
[[ $device = *'\040(deleted)' ]] && continue
[[ "$device" = *'\040(deleted)' ]] && continue
if [[ $type = file ]]; then
printf '%-20s' "${device#${root%/}}"
elif [[ $device = /dev/dm-+([0-9]) ]]; then
if [[ "$type" = "file" ]]; then
printf '%-20s' "${device#"${root%/}"}"
elif [[ "$device" = "/dev/dm-"+([0-9]) ]]; then
# device mapper doesn't allow characters we need to worry
# about being mangled, and it does the escaping of dashes
# for us in sysfs.
@ -235,7 +238,7 @@ done
write_source "$(unmangle "$device")"
fi
printf '\t%-10s\t%-10s\t%-10s\t0 0\n\n' 'none' 'swap' "$options"
printf '\t%-10s\t%-10s\t%-10s\t0 0\n\n' none swap "$options"
done
} </proc/swaps

View File

@ -10,18 +10,20 @@
shopt -s extglob
# m4_include() is recognized as a function definition
# shellcheck source=common disable=SC1073,SC1065,SC1064,SC1072
m4_include(common)
hostcache=0
copykeyring=1
initkeyring=0
copymirrorlist=1
copyconfig=0
pacman_config=/etc/pacman.conf
pacman_args=()
pacmode=-Sy
pacmode='-Sy'
setup=chroot_setup
unshare=0
copyconf=0
pacman_config=/etc/pacman.conf
usage() {
cat <<EOF
@ -37,12 +39,12 @@ usage: ${0##*/} [options] root [packages...]
-M Avoid copying the host's mirrorlist to the target
-N Run in unshare mode as a regular user
-P Copy the host's pacman config to the target
-U Use pacman -U to install packages
-U Use 'pacman -U' to install packages
-h Print this help message
pacstrap installs packages to the specified new root directory. If no packages
are given, pacstrap defaults to the "base" group.
pacstrap installs packages to the specified new root directory.
If no packages are given, pacstrap defaults to the 'base' metapackage.
EOF
}
@ -55,20 +57,20 @@ fi
while getopts ':C:cDGiKMNPU' flag; do
case $flag in
C)
pacman_config=$OPTARG
;;
D)
pacman_args+=(-dd)
pacman_config="$OPTARG"
;;
c)
hostcache=1
;;
i)
interactive=1
D)
pacman_args+=(-dd)
;;
G)
copykeyring=0
;;
i)
interactive=1
;;
K)
initkeyring=1
;;
@ -80,23 +82,23 @@ while getopts ':C:cDGiKMNPU' flag; do
unshare=1
;;
P)
copyconf=1
copyconfig=1
;;
U)
pacmode=-U
pacmode='-U'
;;
:)
die '%s: option requires an argument -- '\''%s'\' "${0##*/}" "$OPTARG"
die "%s: option requires an argument -- '%s'" "${0##*/}" "$OPTARG"
;;
?)
die '%s: invalid option -- '\''%s'\' "${0##*/}" "$OPTARG"
die "%s: invalid option -- '%s'" "${0##*/}" "$OPTARG"
;;
esac
done
shift $(( OPTIND - 1 ))
(( $# )) || die "No root directory specified"
newroot=$1; shift
(( $# )) || die 'No root directory specified'
newroot="$1"; shift
pacman_args+=("$pacmode" "${@:-base}" --config="$pacman_config")
if (( ! hostcache )); then
@ -131,16 +133,14 @@ pacstrap() {
fi
msg 'Installing packages to %s' "$newroot"
if ! $pid_unshare pacman -r "$newroot" "${pacman_args[@]}"; then
die 'Failed to install packages to new root'
fi
$pid_unshare pacman --root "$newroot" "${pacman_args[@]}" || die 'Failed to install packages to new root'
if (( copymirrorlist )); then
# install the host's mirrorlist onto the new root
cp -a /etc/pacman.d/mirrorlist "$newroot/etc/pacman.d/"
fi
if (( copyconf )); then
if (( copyconfig )); then
cp -a "$pacman_config" "$newroot/etc/pacman.conf"
fi
}