← Files Cloud EnvironmentARCHIVED FILE

scripts/ensure-socat.sh

2.89 KB · Sep 30, 2026 · 23:11 UTC

↓ Download file

#!/usr/bin/env bash
set -euo pipefail

fail() {
  printf 'cloud-environment socat: %s\n' "$*" >&2
  exit 1
}

case "$(uname -s):$(uname -m)" in
  Linux:x86_64) ;;
  *) fail "The bundled socat runtime requires Linux x86_64; use a maintained socat installation for this platform." ;;
esac

umask 077
cache_base="${XDG_CACHE_HOME:-${HOME}/.cache}/cloud-environment"
mkdir -p -- "$cache_base"
cache_base="$(cd -- "$cache_base" && pwd -P)"
install_root="$cache_base/socat-1.8.0.3-1+deb13u1-libwrap0-7.6.q-36-amd64"

check_runtime() {
  local features
  if ! features="$("$1" -V)"; then
    fail "The bundled socat cannot run. It requires glibc 2.38 or newer, libssl.so.3, and libcrypto.so.3; use a maintained system socat on other images."
  fi
  [[ "$features" == *'#define WITH_PROXY 1'* && "$features" == *'#define WITH_TCP 1'* ]] ||
    fail "The socat runtime does not support TCP and HTTP CONNECT."
}

if [[ -d "$install_root" ]]; then
  check_runtime "$install_root/socat"
  printf '%s\n' "$install_root/socat"
  exit 0
fi

for command in curl sha256sum dpkg-deb mktemp; do
  command -v "$command" >/dev/null || fail "Required command is unavailable: $command"
done

staging="$(mktemp -d "$cache_base/.socat-XXXXXX")"
trap 'rm -rf -- "$staging"' EXIT

download() {
  local name="$1" url="$2" sha256="$3"
  if ! curl --fail --location --silent --show-error --retry 2 \
    --connect-timeout 10 --max-time 60 --proto '=https' --proto-redir '=https' \
    --output "$staging/$name.deb" "$url"; then
    fail "Could not download $name. The environment HTTP policy must permit deb.debian.org."
  fi
  if ! (cd -- "$staging" && printf '%s  %s.deb\n' "$sha256" "$name" | sha256sum --check --status); then
    fail "Checksum verification failed for $name."
  fi
  dpkg-deb --extract "$staging/$name.deb" "$staging/runtime"
}

# These pins include the Debian security fix absent from the base image's APT snapshot.
download socat \
  'https://deb.debian.org/debian/pool/main/s/socat/socat_1.8.0.3-1+deb13u1_amd64.deb' \
  'c87c1e6eccc6d5828138dda794d28a7f283fe4e4010074fffbe4dc8354eef08d'
download libwrap0 \
  'https://deb.debian.org/debian/pool/main/t/tcp-wrappers/libwrap0_7.6.q-36_amd64.deb' \
  'cde12afa15d6b1556c5e0564d22edf3b99e6b8fa94c59ccd8b8eebbb62dc19ec'

cat > "$staging/runtime/socat" <<'WRAPPER'
#!/usr/bin/env bash
set -euo pipefail
runtime="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
export LD_LIBRARY_PATH="$runtime/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
exec "$runtime/usr/bin/socat1" "$@"
WRAPPER
chmod 0700 "$staging/runtime" "$staging/runtime/socat"
check_runtime "$staging/runtime/socat"

# Rename within the cache filesystem so concurrent callers only see complete runtimes.
if ! mv -T -- "$staging/runtime" "$install_root" 2>/dev/null; then
  [[ -d "$install_root" ]] || fail "Could not publish the socat runtime in $cache_base."
  check_runtime "$install_root/socat"
fi
printf '%s\n' "$install_root/socat"

SHA-256: 5d978e9230c4363dc84e2169e0385efaff2f1b5259da8fb15ed57924fdcd13f0