Skip to content

Commit

Permalink
rustup-init.sh: Check for kernel UAPI compatibility on LoongArch
Browse files Browse the repository at this point in the history
And provide friendly diagnostics if a certain widely-deployed but
incompatible UAPI flavor (a.k.a. the "old-world" UAPI that's used by
several early and/or commercial LoongArch Linux distributions) is
detected.

The minimalistic probe was crafted by myself, checking for one of the
most prominent incompatibilities between the two UAPI flavors:
`sizeof(sigset_t)`. The probe binary is small enough to fit in 3 lines
of Base64, which is decoded into a temp file and executed for result.
The `base64(1)` command is ubiquitous (being provided by coreutils,
busybox and probably many others), and only necessary on LoongArch, so
we effectively don't lose portability.

Other irrelevant errors (e.g. /tmp being noexec) are made non-fatal,
because without the check the installer binary will instantly die
anyway on an incompatible system. A warning message is printed in case
such an error occurs.

(The installer binary, being dynamically linked, will die on a system
using the other incompatible UAPI, with a confusing error saying the
program being executed itself is not found: the actual non-existent
path is the ELF interpreter i.e. `ld.so`. Having some error messages in
case of this would hopefully reduce the technical support burden for
many.)
  • Loading branch information
xen0n committed Jul 24, 2023
1 parent 87fa15d commit db4b177
Showing 1 changed file with 62 additions and 0 deletions.
62 changes: 62 additions & 0 deletions rustup-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,67 @@ get_endianness() {
fi
}

# Detect the Linux/LoongArch UAPI flavor, with all errors being non-fatal.
# Returns 0 or 234 in case of successful detection, 1 otherwise (/tmp being
# noexec, or other causes).
check_loongarch_uapi() {
need_cmd base64

local _tmp
if ! _tmp="$(ensure mktemp)"; then
return 1
fi

# Minimal Linux/LoongArch UAPI detection, exiting with 0 in case of
# upstream ("new world") UAPI, and 234 (-EINVAL truncated) in case of
# old-world (as deployed on several early commercial Linux distributions
# for LoongArch).
#
# See https://gist.github.com/xen0n/5ee04aaa6cecc5c7794b9a0c3b65fc7f for
# source to this helper binary.
ignore base64 -d > "$_tmp" <<EOF
f0VMRgIBAQAAAAAAAAAAAAIAAgEBAAAAeAAgAAAAAABAAAAAAAAAAAAAAAAAAAAAQQAAAEAAOAAB
AAAAAAAAAAEAAAAFAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAJAAAAAAAAAAkAAAAAAAAAAAA
AQAAAAAABCiAAwUAFQAGABUAByCAAwsYggMAACsAC3iBAwAAKwAxen0n
EOF

ignore chmod u+x "$_tmp"
if [ ! -x "$_tmp" ]; then
ignore rm "$_tmp"
return 1
fi

"$_tmp"
local _retval=$?

ignore rm "$_tmp"
return "$_retval"
}

ensure_loongarch_uapi() {
check_loongarch_uapi
case $? in
0)
return 0
;;
234)
echo >&2
echo 'Your Linux kernel does not provide the ABI required by this Rust' >&2
echo 'distribution. Please check with your OS provider for how to obtain a' >&2
echo 'compatible Rust package for your system.' >&2
echo >&2
exit 1
;;
*)
echo "Warning: Cannot determine current system's ABI flavor, continuing anyway." >&2
echo >&2
echo 'Note that the official Rust distribution only works with the upstream' >&2
echo 'kernel ABI. Installation will fail if your running kernel happens to be' >&2
echo 'incompatible.' >&2
;;
esac
}

get_architecture() {
local _ostype _cputype _bitness _arch _clibtype
_ostype="$(uname -s)"
Expand Down Expand Up @@ -393,6 +454,7 @@ get_architecture() {
;;
loongarch64)
_cputype=loongarch64
ensure_loongarch_uapi
;;
*)
err "unknown CPU type: $_cputype"
Expand Down

0 comments on commit db4b177

Please sign in to comment.