|
#!/bin/sh |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if [ "$KSH_VERSION" = 'Version JM 93t+ 2010-03-05' ]; then |
|
|
|
|
|
|
|
echo 'rustup does not work with this ksh93 version; please try bash!' >&2 |
|
exit 1 |
|
fi |
|
|
|
|
|
set -u |
|
|
|
|
|
RUSTUP_UPDATE_ROOT="${RUSTUP_UPDATE_ROOT:-https://static.rust-lang.org/rustup}" |
|
|
|
|
|
usage() { |
|
cat <<EOF |
|
rustup-init 1.26.0 (577bf51ae 2023-04-05) |
|
The installer for rustup |
|
|
|
USAGE: |
|
rustup-init [OPTIONS] |
|
|
|
OPTIONS: |
|
-v, --verbose |
|
Enable verbose output |
|
|
|
-q, --quiet |
|
Disable progress output |
|
|
|
-y |
|
Disable confirmation prompt. |
|
|
|
--default-host <default-host> |
|
Choose a default host triple |
|
|
|
--default-toolchain <default-toolchain> |
|
Choose a default toolchain to install. Use 'none' to not install any toolchains at all |
|
|
|
--profile <profile> |
|
[default: default] [possible values: minimal, default, complete] |
|
|
|
-c, --component <components>... |
|
Component name to also install |
|
|
|
-t, --target <targets>... |
|
Target name to also install |
|
|
|
--no-update-default-toolchain |
|
Don't update any existing default toolchain after install |
|
|
|
--no-modify-path |
|
Don't configure the PATH environment variable |
|
|
|
-h, --help |
|
Print help information |
|
|
|
-V, --version |
|
Print version information |
|
EOF |
|
} |
|
|
|
main() { |
|
downloader --check |
|
need_cmd uname |
|
need_cmd mktemp |
|
need_cmd chmod |
|
need_cmd mkdir |
|
need_cmd rm |
|
need_cmd rmdir |
|
|
|
get_architecture || return 1 |
|
local _arch="$RETVAL" |
|
assert_nz "$_arch" "arch" |
|
|
|
local _ext="" |
|
case "$_arch" in |
|
*windows*) |
|
_ext=".exe" |
|
;; |
|
esac |
|
|
|
local _url="${RUSTUP_UPDATE_ROOT}/dist/${_arch}/rustup-init${_ext}" |
|
|
|
local _dir |
|
if ! _dir="$(ensure mktemp -d)"; then |
|
|
|
|
|
exit 1 |
|
fi |
|
local _file="${_dir}/rustup-init${_ext}" |
|
|
|
local _ansi_escapes_are_valid=false |
|
if [ -t 2 ]; then |
|
if [ "${TERM+set}" = 'set' ]; then |
|
case "$TERM" in |
|
xterm*|rxvt*|urxvt*|linux*|vt*) |
|
_ansi_escapes_are_valid=true |
|
;; |
|
esac |
|
fi |
|
fi |
|
|
|
|
|
local need_tty=yes |
|
for arg in "$@"; do |
|
case "$arg" in |
|
--help) |
|
usage |
|
exit 0 |
|
;; |
|
*) |
|
OPTIND=1 |
|
if [ "${arg%%--*}" = "" ]; then |
|
|
|
|
|
continue |
|
fi |
|
while getopts :hy sub_arg "$arg"; do |
|
case "$sub_arg" in |
|
h) |
|
usage |
|
exit 0 |
|
;; |
|
y) |
|
|
|
|
|
need_tty=no |
|
;; |
|
*) |
|
;; |
|
esac |
|
done |
|
;; |
|
esac |
|
done |
|
|
|
if $_ansi_escapes_are_valid; then |
|
printf "\33[1minfo:\33[0m downloading installer\n" 1>&2 |
|
else |
|
printf '%s\n' 'info: downloading installer' 1>&2 |
|
fi |
|
|
|
ensure mkdir -p "$_dir" |
|
ensure downloader "$_url" "$_file" "$_arch" |
|
ensure chmod u+x "$_file" |
|
if [ ! -x "$_file" ]; then |
|
printf '%s\n' "Cannot execute $_file (likely because of mounting /tmp as noexec)." 1>&2 |
|
printf '%s\n' "Please copy the file to a location where you can execute binaries and run ./rustup-init${_ext}." 1>&2 |
|
exit 1 |
|
fi |
|
|
|
if [ "$need_tty" = "yes" ] && [ ! -t 0 ]; then |
|
|
|
|
|
|
|
|
|
if [ ! -t 1 ]; then |
|
err "Unable to run interactively. Run with -y to accept defaults, --help for additional options" |
|
fi |
|
|
|
ignore "$_file" "$@" < /dev/tty |
|
else |
|
ignore "$_file" "$@" |
|
fi |
|
|
|
local _retval=$? |
|
|
|
ignore rm "$_file" |
|
ignore rmdir "$_dir" |
|
|
|
return "$_retval" |
|
} |
|
|
|
check_proc() { |
|
|
|
|
|
if ! test -L /proc/self/exe ; then |
|
err "fatal: Unable to find /proc/self/exe. Is /proc mounted? Installation cannot proceed without /proc." |
|
fi |
|
} |
|
|
|
get_bitness() { |
|
need_cmd head |
|
|
|
|
|
|
|
|
|
|
|
|
|
local _current_exe_head |
|
_current_exe_head=$(head -c 5 /proc/self/exe ) |
|
if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then |
|
echo 32 |
|
elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then |
|
echo 64 |
|
else |
|
err "unknown platform bitness" |
|
fi |
|
} |
|
|
|
is_host_amd64_elf() { |
|
need_cmd head |
|
need_cmd tail |
|
|
|
|
|
|
|
local _current_exe_machine |
|
_current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1) |
|
[ "$_current_exe_machine" = "$(printf '\076')" ] |
|
} |
|
|
|
get_endianness() { |
|
local cputype=$1 |
|
local suffix_eb=$2 |
|
local suffix_el=$3 |
|
|
|
|
|
need_cmd head |
|
need_cmd tail |
|
|
|
local _current_exe_endianness |
|
_current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)" |
|
if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then |
|
echo "${cputype}${suffix_el}" |
|
elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then |
|
echo "${cputype}${suffix_eb}" |
|
else |
|
err "unknown platform endianness" |
|
fi |
|
} |
|
|
|
get_architecture() { |
|
local _ostype _cputype _bitness _arch _clibtype |
|
_ostype="$(uname -s)" |
|
_cputype="$(uname -m)" |
|
_clibtype="gnu" |
|
|
|
if [ "$_ostype" = Linux ]; then |
|
if [ "$(uname -o)" = Android ]; then |
|
_ostype=Android |
|
fi |
|
if ldd --version 2>&1 | grep -q 'musl'; then |
|
_clibtype="musl" |
|
fi |
|
fi |
|
|
|
if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then |
|
|
|
if sysctl hw.optional.x86_64 | grep -q ': 1'; then |
|
_cputype=x86_64 |
|
fi |
|
fi |
|
|
|
if [ "$_ostype" = SunOS ]; then |
|
|
|
|
|
|
|
|
|
if [ "$(/usr/bin/uname -o)" = illumos ]; then |
|
_ostype=illumos |
|
fi |
|
|
|
|
|
|
|
|
|
|
|
if [ "$_cputype" = i86pc ]; then |
|
_cputype="$(isainfo -n)" |
|
fi |
|
fi |
|
|
|
case "$_ostype" in |
|
|
|
Android) |
|
_ostype=linux-android |
|
;; |
|
|
|
Linux) |
|
check_proc |
|
_ostype=unknown-linux-$_clibtype |
|
_bitness=$(get_bitness) |
|
;; |
|
|
|
FreeBSD) |
|
_ostype=unknown-freebsd |
|
;; |
|
|
|
NetBSD) |
|
_ostype=unknown-netbsd |
|
;; |
|
|
|
DragonFly) |
|
_ostype=unknown-dragonfly |
|
;; |
|
|
|
Darwin) |
|
_ostype=apple-darwin |
|
;; |
|
|
|
illumos) |
|
_ostype=unknown-illumos |
|
;; |
|
|
|
MINGW* | MSYS* | CYGWIN* | Windows_NT) |
|
_ostype=pc-windows-gnu |
|
;; |
|
|
|
*) |
|
err "unrecognized OS type: $_ostype" |
|
;; |
|
|
|
esac |
|
|
|
case "$_cputype" in |
|
|
|
i386 | i486 | i686 | i786 | x86) |
|
_cputype=i686 |
|
;; |
|
|
|
xscale | arm) |
|
_cputype=arm |
|
if [ "$_ostype" = "linux-android" ]; then |
|
_ostype=linux-androideabi |
|
fi |
|
;; |
|
|
|
armv6l) |
|
_cputype=arm |
|
if [ "$_ostype" = "linux-android" ]; then |
|
_ostype=linux-androideabi |
|
else |
|
_ostype="${_ostype}eabihf" |
|
fi |
|
;; |
|
|
|
armv7l | armv8l) |
|
_cputype=armv7 |
|
if [ "$_ostype" = "linux-android" ]; then |
|
_ostype=linux-androideabi |
|
else |
|
_ostype="${_ostype}eabihf" |
|
fi |
|
;; |
|
|
|
aarch64 | arm64) |
|
_cputype=aarch64 |
|
;; |
|
|
|
x86_64 | x86-64 | x64 | amd64) |
|
_cputype=x86_64 |
|
;; |
|
|
|
mips) |
|
_cputype=$(get_endianness mips '' el) |
|
;; |
|
|
|
mips64) |
|
if [ "$_bitness" -eq 64 ]; then |
|
|
|
_ostype="${_ostype}abi64" |
|
_cputype=$(get_endianness mips64 '' el) |
|
fi |
|
;; |
|
|
|
ppc) |
|
_cputype=powerpc |
|
;; |
|
|
|
ppc64) |
|
_cputype=powerpc64 |
|
;; |
|
|
|
ppc64le) |
|
_cputype=powerpc64le |
|
;; |
|
|
|
s390x) |
|
_cputype=s390x |
|
;; |
|
riscv64) |
|
_cputype=riscv64gc |
|
;; |
|
loongarch64) |
|
_cputype=loongarch64 |
|
;; |
|
*) |
|
err "unknown CPU type: $_cputype" |
|
|
|
esac |
|
|
|
|
|
if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then |
|
case $_cputype in |
|
x86_64) |
|
if [ -n "${RUSTUP_CPUTYPE:-}" ]; then |
|
_cputype="$RUSTUP_CPUTYPE" |
|
else { |
|
|
|
if is_host_amd64_elf; then { |
|
echo "This host is running an x32 userland; as it stands, x32 support is poor," 1>&2 |
|
echo "and there isn't a native toolchain -- you will have to install" 1>&2 |
|
echo "multiarch compatibility with i686 and/or amd64, then select one" 1>&2 |
|
echo "by re-running this script with the RUSTUP_CPUTYPE environment variable" 1>&2 |
|
echo "set to i686 or x86_64, respectively." 1>&2 |
|
echo 1>&2 |
|
echo "You will be able to add an x32 target after installation by running" 1>&2 |
|
echo " rustup target add x86_64-unknown-linux-gnux32" 1>&2 |
|
exit 1 |
|
}; else |
|
_cputype=i686 |
|
fi |
|
}; fi |
|
;; |
|
mips64) |
|
_cputype=$(get_endianness mips '' el) |
|
;; |
|
powerpc64) |
|
_cputype=powerpc |
|
;; |
|
aarch64) |
|
_cputype=armv7 |
|
if [ "$_ostype" = "linux-android" ]; then |
|
_ostype=linux-androideabi |
|
else |
|
_ostype="${_ostype}eabihf" |
|
fi |
|
;; |
|
riscv64gc) |
|
err "riscv64 with 32-bit userland unsupported" |
|
;; |
|
esac |
|
fi |
|
|
|
|
|
|
|
|
|
if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then |
|
if ensure grep '^Features' /proc/cpuinfo | grep -q -v neon; then |
|
|
|
_cputype=arm |
|
fi |
|
fi |
|
|
|
_arch="${_cputype}-${_ostype}" |
|
|
|
RETVAL="$_arch" |
|
} |
|
|
|
say() { |
|
printf 'rustup: %s\n' "$1" |
|
} |
|
|
|
err() { |
|
say "$1" >&2 |
|
exit 1 |
|
} |
|
|
|
need_cmd() { |
|
if ! check_cmd "$1"; then |
|
err "need '$1' (command not found)" |
|
fi |
|
} |
|
|
|
check_cmd() { |
|
command -v "$1" > /dev/null 2>&1 |
|
} |
|
|
|
assert_nz() { |
|
if [ -z "$1" ]; then err "assert_nz $2"; fi |
|
} |
|
|
|
|
|
|
|
|
|
ensure() { |
|
if ! "$@"; then err "command failed: $*"; fi |
|
} |
|
|
|
|
|
|
|
|
|
ignore() { |
|
"$@" |
|
} |
|
|
|
|
|
|
|
downloader() { |
|
local _dld |
|
local _ciphersuites |
|
local _err |
|
local _status |
|
local _retry |
|
if check_cmd curl; then |
|
_dld=curl |
|
elif check_cmd wget; then |
|
_dld=wget |
|
else |
|
_dld='curl or wget' |
|
fi |
|
|
|
if [ "$1" = --check ]; then |
|
need_cmd "$_dld" |
|
elif [ "$_dld" = curl ]; then |
|
check_curl_for_retry_support |
|
_retry="$RETVAL" |
|
get_ciphersuites_for_curl |
|
_ciphersuites="$RETVAL" |
|
if [ -n "$_ciphersuites" ]; then |
|
_err=$(curl $_retry --proto '=https' --tlsv1.2 --ciphers "$_ciphersuites" --silent --show-error --fail --location "$1" --output "$2" 2>&1) |
|
_status=$? |
|
else |
|
echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure" |
|
if ! check_help_for "$3" curl --proto --tlsv1.2; then |
|
echo "Warning: Not enforcing TLS v1.2, this is potentially less secure" |
|
_err=$(curl $_retry --silent --show-error --fail --location "$1" --output "$2" 2>&1) |
|
_status=$? |
|
else |
|
_err=$(curl $_retry --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2" 2>&1) |
|
_status=$? |
|
fi |
|
fi |
|
if [ -n "$_err" ]; then |
|
echo "$_err" >&2 |
|
if echo "$_err" | grep -q 404$; then |
|
err "installer for platform '$3' not found, this may be unsupported" |
|
fi |
|
fi |
|
return $_status |
|
elif [ "$_dld" = wget ]; then |
|
if [ "$(wget -V 2>&1|head -2|tail -1|cut -f1 -d" ")" = "BusyBox" ]; then |
|
echo "Warning: using the BusyBox version of wget. Not enforcing strong cipher suites for TLS or TLS v1.2, this is potentially less secure" |
|
_err=$(wget "$1" -O "$2" 2>&1) |
|
_status=$? |
|
else |
|
get_ciphersuites_for_wget |
|
_ciphersuites="$RETVAL" |
|
if [ -n "$_ciphersuites" ]; then |
|
_err=$(wget --https-only --secure-protocol=TLSv1_2 --ciphers "$_ciphersuites" "$1" -O "$2" 2>&1) |
|
_status=$? |
|
else |
|
echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure" |
|
if ! check_help_for "$3" wget --https-only --secure-protocol; then |
|
echo "Warning: Not enforcing TLS v1.2, this is potentially less secure" |
|
_err=$(wget "$1" -O "$2" 2>&1) |
|
_status=$? |
|
else |
|
_err=$(wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2" 2>&1) |
|
_status=$? |
|
fi |
|
fi |
|
fi |
|
if [ -n "$_err" ]; then |
|
echo "$_err" >&2 |
|
if echo "$_err" | grep -q ' 404 Not Found$'; then |
|
err "installer for platform '$3' not found, this may be unsupported" |
|
fi |
|
fi |
|
return $_status |
|
else |
|
err "Unknown downloader" |
|
fi |
|
} |
|
|
|
check_help_for() { |
|
local _arch |
|
local _cmd |
|
local _arg |
|
_arch="$1" |
|
shift |
|
_cmd="$1" |
|
shift |
|
|
|
local _category |
|
if "$_cmd" --help | grep -q 'For all options use the manual or "--help all".'; then |
|
_category="all" |
|
else |
|
_category="" |
|
fi |
|
|
|
case "$_arch" in |
|
|
|
*darwin*) |
|
if check_cmd sw_vers; then |
|
case $(sw_vers -productVersion) in |
|
10.*) |
|
|
|
|
|
if [ "$(sw_vers -productVersion | cut -d. -f2)" -lt 13 ]; then |
|
|
|
echo "Warning: Detected macOS platform older than 10.13" |
|
return 1 |
|
fi |
|
;; |
|
11.*) |
|
|
|
;; |
|
*) |
|
|
|
echo "Warning: Detected unknown macOS major version: $(sw_vers -productVersion)" |
|
echo "Warning TLS capabilities detection may fail" |
|
;; |
|
esac |
|
fi |
|
;; |
|
|
|
esac |
|
|
|
for _arg in "$@"; do |
|
if ! "$_cmd" --help "$_category" | grep -q -- "$_arg"; then |
|
return 1 |
|
fi |
|
done |
|
|
|
true |
|
} |
|
|
|
|
|
check_curl_for_retry_support() { |
|
local _retry_supported="" |
|
|
|
if check_help_for "notspecified" "curl" "--retry"; then |
|
_retry_supported="--retry 3" |
|
if check_help_for "notspecified" "curl" "--continue-at"; then |
|
|
|
_retry_supported="--retry 3 -C -" |
|
fi |
|
fi |
|
|
|
RETVAL="$_retry_supported" |
|
} |
|
|
|
|
|
|
|
|
|
get_ciphersuites_for_curl() { |
|
if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then |
|
|
|
RETVAL="$RUSTUP_TLS_CIPHERSUITES" |
|
return |
|
fi |
|
|
|
local _openssl_syntax="no" |
|
local _gnutls_syntax="no" |
|
local _backend_supported="yes" |
|
if curl -V | grep -q ' OpenSSL/'; then |
|
_openssl_syntax="yes" |
|
elif curl -V | grep -iq ' LibreSSL/'; then |
|
_openssl_syntax="yes" |
|
elif curl -V | grep -iq ' BoringSSL/'; then |
|
_openssl_syntax="yes" |
|
elif curl -V | grep -iq ' GnuTLS/'; then |
|
_gnutls_syntax="yes" |
|
else |
|
_backend_supported="no" |
|
fi |
|
|
|
local _args_supported="no" |
|
if [ "$_backend_supported" = "yes" ]; then |
|
|
|
if check_help_for "notspecified" "curl" "--tlsv1.2" "--ciphers" "--proto"; then |
|
_args_supported="yes" |
|
fi |
|
fi |
|
|
|
local _cs="" |
|
if [ "$_args_supported" = "yes" ]; then |
|
if [ "$_openssl_syntax" = "yes" ]; then |
|
_cs=$(get_strong_ciphersuites_for "openssl") |
|
elif [ "$_gnutls_syntax" = "yes" ]; then |
|
_cs=$(get_strong_ciphersuites_for "gnutls") |
|
fi |
|
fi |
|
|
|
RETVAL="$_cs" |
|
} |
|
|
|
|
|
|
|
|
|
get_ciphersuites_for_wget() { |
|
if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then |
|
|
|
RETVAL="$RUSTUP_TLS_CIPHERSUITES" |
|
return |
|
fi |
|
|
|
local _cs="" |
|
if wget -V | grep -q '\-DHAVE_LIBSSL'; then |
|
|
|
if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then |
|
_cs=$(get_strong_ciphersuites_for "openssl") |
|
fi |
|
elif wget -V | grep -q '\-DHAVE_LIBGNUTLS'; then |
|
|
|
if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then |
|
_cs=$(get_strong_ciphersuites_for "gnutls") |
|
fi |
|
fi |
|
|
|
RETVAL="$_cs" |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
get_strong_ciphersuites_for() { |
|
if [ "$1" = "openssl" ]; then |
|
|
|
echo "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384" |
|
elif [ "$1" = "gnutls" ]; then |
|
|
|
|
|
echo "SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS-ALL:-CIPHER-ALL:-MAC-ALL:-KX-ALL:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+AES-128-GCM:+CHACHA20-POLY1305:+AES-256-GCM" |
|
fi |
|
} |
|
|
|
main "$@" || exit 1 |
|
|