genfstab,common: use named reference instead of globals

This commit is contained in:
Mike Yuan 2023-01-26 01:46:08 +08:00
parent f40fc1f2b0
commit 0e14a1a13b
No known key found for this signature in database
GPG Key ID: 417471C0A40F58B3
2 changed files with 82 additions and 64 deletions

132
common
View File

@ -89,10 +89,12 @@ ignore_error() {
in_array() { in_array() {
local i local i
local -n _arr="$1"
for i in "${@:2}"; do for i in "${_arr[@]}"; do
[[ "$1" = "$i" ]] && return 0 [[ "$i" = "$1" ]] && return 0
done done
return 1 return 1
} }
@ -349,83 +351,99 @@ unmangle() {
printf '%s' "$out${1:i}" printf '%s' "$out${1:i}"
} }
optstring_match_option() { optstring_match_one_option() {
local candidate pat patterns local options=() target="$2"
local -n _optstring_match="$1"
IFS=, read -ra patterns <<<"$1" IFS=, read -ra options <<<"$_optstring_match"
for pat in "${patterns[@]}"; do if [[ "$target" != *'='* ]]; then
if [[ $pat = *'='* ]]; then options=("${options[@]%%=*}")
# "key=val" will only ever match "key=val" fi
candidate="$2"
else
# "key" will match "key", but also "key=anyval"
candidate="${2%%=*}"
fi
[[ "$pat" = "$candidate" ]] && return 0 in_array options "$target"
done
return 1
} }
optstring_remove_option() { optstring_get_options() {
local o _options remove="$2" local i options=()
local -n _ret="$1" _optstring_get="$2"
local -i got=0
IFS=, read -ra _options <<<"${!1}" IFS=, read -ra options <<<"$_optstring_get"
for o in "${!_options[@]}"; do
optstring_match_option "$remove" "${_options[o]}" && unset '_options[o]' shift 2
for i in "${!options[@]}"; do
if optstring_match_one_option 'options[i]' "$1"; then
_ret+=(["${options[i]%%=*}"]="${options[i]//*=}")
got=1
fi
shift || break
done done
declare -g "$1=${_options[*]}" (( got ))
}
optstring_from_array() {
local optstring
local -n _optarray="$1"
optstring="$(printf ',%s' "${_optarray[@]}")"
optstring="${optstring:1}" # Remove the leading comma
printf '%s' "$optstring"
} }
optstring_normalize() { optstring_normalize() {
local o _options norm local i options=()
local -n _optstring_norm="$1"
IFS=, read -ra options <<<"$_optstring_norm"
IFS=, read -ra _options <<<"${!1}"
# remove empty fields # remove empty fields
for o in "${_options[@]}"; do for i in "${!options[@]}"; do
[[ $o ]] && norm+=("$o") [[ ${options[i]} ]] || unset 'options[i]'
done done
# avoid empty strings, reset to "defaults" # avoid empty strings, reset to "defaults"
declare -g "$1=${norm[*]:-defaults}" if (( ! ${#options[@]} )); then
} _optstring_norm="defaults"
else
optstring_has_option() { _optstring_norm="$(optstring_from_array options)"
local o="${2%%=*}"
optstring_get_option "$1" "$o"
}
optstring_append_option() {
if ! optstring_has_option "$1" "$2"; then
declare -g "$1=${!1},$2"
fi fi
optstring_normalize "$1"
} }
optstring_prepend_option() { optstring_remove_options() {
if ! optstring_has_option "$1" "$2"; then local i options=() target="$2"
declare -g "$1=$2,${!1}" local -n _optstring_remove="$1"
fi
optstring_normalize "$1" IFS=, read -ra options <<<"$_optstring_remove"
}
optstring_get_option() { for i in "${!options[@]}"; do
local _opts o optstring_match_one_option 'options[i]' "$target" && unset 'options[i]'
IFS=, read -ra _opts <<<"${!1}"
for o in "${_opts[@]}"; do
if optstring_match_option "$2" "$o"; then
declare -g "$o"
return 0
fi
done done
return 1 _optstring_remove="$(optstring_from_array options)"
}
optstring_append_one_option() {
local option="$2"
local -n _optstring_append="$1"
if ! optstring_match_one_option _optstring_append "$option"; then
_optstring_append+=",$option"
fi
optstring_normalize _optstring_append
}
optstring_prepend_one_option() {
local option="$2"
local -n _optstring_prepend="$1"
if ! optstring_match_one_option _optstring_prepend "$option"; then
_optstring_prepend="$option,$_optstring_prepend"
fi
optstring_normalize _optstring_prepend
} }
dm_name_for_devnode() { dm_name_for_devnode() {

View File

@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
# shellcheck disable=SC2154 # optstring_*_option may export variables in runtime
shopt -s extglob shopt -s extglob
@ -43,18 +42,19 @@ write_source() {
} }
optstring_apply_quirks() { optstring_apply_quirks() {
local varname="$1" fstype="$2" local fstype="$2"
local -n _optstring="$1"
# SELinux displays a 'seclabel' option in /proc/self/mountinfo. We can't know # 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 # if the system we're generating the fstab for has any support for SELinux (as
# one might install Arch from a Fedora environment), so let's remove it. # one might install Arch from a Fedora environment), so let's remove it.
optstring_remove_option "$varname" seclabel optstring_remove_options _optstring seclabel
# Prune 'relatime' option for any pseudofs. This seems to be a rampant # Prune 'relatime' option for any pseudofs. This seems to be a rampant
# default which the kernel often exports even if the underlying filesystem # default which the kernel often exports even if the underlying filesystem
# doesn't support it. Example: https://bugs.archlinux.org/task/54554. # doesn't support it. Example: https://bugs.archlinux.org/task/54554.
if fstype_is_pseudofs "$fstype"; then if fstype_is_pseudofs "$fstype"; then
optstring_remove_option "$varname" relatime optstring_remove_options _optstring relatime
fi fi
case $fstype in case $fstype in
@ -62,15 +62,15 @@ optstring_apply_quirks() {
# Having only one of subvol= and subvolid= is enough for mounting a btrfs subvolume # Having only one of subvol= and subvolid= is enough for mounting a btrfs subvolume
# And having subvolid= set prevents things like 'snapper rollback' to work, as it # And having subvolid= set prevents things like 'snapper rollback' to work, as it
# updates the subvolume in-place, leaving subvol= unchanged with a different subvolid. # updates the subvolume in-place, leaving subvol= unchanged with a different subvolid.
if optstring_has_option "$varname" subvol; then if optstring_match_one_option _optstring subvol; then
optstring_remove_option "$varname" subvolid optstring_remove_options _optstring subvolid
fi fi
;; ;;
f2fs) f2fs)
# These are Kconfig options for f2fs. Kernels supporting the options will # These are Kconfig options for f2fs. Kernels supporting the options will
# only provide the negative versions of these (e.g. noacl), and vice versa # only provide the negative versions of these (e.g. noacl), and vice versa
# for kernels without support. # for kernels without support.
optstring_remove_option "$varname" noacl,acl,nouser_xattr,user_xattr optstring_remove_options _optstring noacl,acl,nouser_xattr,user_xattr
;; ;;
esac esac
} }