Packages
Fostrom is an IoT Cloud Platform built for developers, to easily connect, monitor and control your fleet of devices, from microcontrollers to industrial IoT. The Elixir SDK enables you to get started with Fostrom in just a few lines of code.
Current section
Files
Jump to
Current section
Files
dl-agent.sh
#!/bin/sh
#
# dl-agent.sh - Download Fostrom Device Agent binary
#
# Usage: ./dl-agent.sh <directory>
VERSION="v0.1.0"
# CDN URLs in order of preference
CDN_PRIMARY="https://cdn.fostrom.dev/fostrom-device-agent/$VERSION"
CDN_SECONDARY="https://b.cdn.fostrom.dev/fostrom-device-agent/$VERSION"
set -e
# Print error message and exit
die() {
printf "Failed to download Fostrom Device Agent: %s\n" "$1" >&2
exit 1
}
# Check arguments
[ $# -eq 0 ] && die "Usage: $0 <directory>"
LOCATION="$1"
download_file() {
URL="$1"
OUTPUT="$2"
if command -v curl >/dev/null 2>&1; then
curl -fsSL --connect-timeout 10 --max-time 300 "$URL" -o "$OUTPUT" 2>/dev/null
elif command -v wget >/dev/null 2>&1; then
# BusyBox wget often lacks GNU long opts like --tries/--timeout.
if wget --help 2>&1 | grep -q -- '--tries'; then
wget -q --timeout=10 --tries=1 -O "$OUTPUT" "$URL" 2>/dev/null
else
# BusyBox-compatible fallback (fewer assumptions)
wget -q -O "$OUTPUT" "$URL" 2>/dev/null
fi
else
die "No download tool found (curl or wget required)"
fi
}
try_download() {
FILE_PATH="$1"
OUTPUT="$2"
for CDN_URL in "$CDN_PRIMARY" "$CDN_SECONDARY"; do
FULL_URL="${CDN_URL}/${FILE_PATH}"
if download_file "$FULL_URL" "$OUTPUT"; then
return 0
fi
done
return 1
}
create_temp_dir() {
if command -v mktemp >/dev/null 2>&1; then
mktemp -d -t 'fostrom.XXXXXX' 2>/dev/null \
|| mktemp -d "${TMPDIR:-/tmp}/fostrom.XXXXXX" 2>/dev/null \
|| mktemp -d 2>/dev/null
else
TEMP_DIR="/tmp/fostrom.$$"
mkdir -p "$TEMP_DIR" || die "Cannot create temporary directory"
printf "%s\n" "$TEMP_DIR"
fi
}
verify_checksum() {
CHECKSUM_FILE="$1"
TARGET_FILE="$2"
HASH_FILE="$TEMP_DIR/$TARGET_FILE.sha256"
awk -v f="$TARGET_FILE" '
{ name=$2; sub(/^\*/, "", name) }
name==f { print; found=1 }
END { exit !found }
' "$CHECKSUM_FILE" > "$HASH_FILE" || return 1
if command -v sha256sum >/dev/null 2>&1; then
sha256sum -c "$HASH_FILE" >/dev/null 2>&1
elif command -v shasum >/dev/null 2>&1; then
shasum -a 256 -c "$HASH_FILE" >/dev/null 2>&1
else
printf "Warning: No checksum verification tool found, skipping verification\n" >&2
return 0
fi
}
download_and_verify() {
FILENAME="$1"
INSTALL_DIR="$2"
TEMP_DIR="$(create_temp_dir)"
trap 'rm -rf "$TEMP_DIR"' EXIT INT TERM
TEMP_BINARY="$TEMP_DIR/$FILENAME"
TEMP_CHECKSUM="$TEMP_DIR/fostrom-device-agent.sha256"
# Download checksum file
if ! try_download "fostrom-device-agent.sha256" "$TEMP_CHECKSUM"; then
die "Failed to download checksum file"
fi
# Download binary
if ! try_download "$FILENAME" "$TEMP_BINARY"; then
die "Failed to download binary"
fi
# Verify checksum
cd "$TEMP_DIR"
if ! verify_checksum "fostrom-device-agent.sha256" "$FILENAME"; then
die "Checksum verification failed"
fi
cd - >/dev/null
install_binary "$TEMP_BINARY" "$INSTALL_DIR" "$FILENAME"
}
install_binary() {
TEMP_BINARY="$1"
INSTALL_DIR="$2"
FILENAME="$3"
# Create target directory if needed
[ ! -d "$INSTALL_DIR" ] && mkdir -p "$INSTALL_DIR"
# Install binary
FINAL_BINARY_PATH="$INSTALL_DIR/$FILENAME"
cp "$TEMP_BINARY" "$FINAL_BINARY_PATH" || die "Cannot copy binary to $FINAL_BINARY_PATH"
chmod +x "$FINAL_BINARY_PATH" || die "Cannot make binary executable"
# Create symlink
ln -sf "$FILENAME" "$INSTALL_DIR/fostrom-device-agent"
}
read_installed_version() {
BIN="$1"
[ ! -x "$BIN" ] && return 1
RAW_VERSION="$("$BIN" version 2>/dev/null || true)"
[ -z "$RAW_VERSION" ] && return 1
printf "%s\n" "$RAW_VERSION" | tr -d '[:space:]'
}
main() {
# Detect OS and architecture
OS="$(uname -s)"
ARCH="$(uname -m)"
# Normalize OS name
case "$OS" in
Linux*)
OS="linux"
case "$ARCH" in
x86_64|amd64) ARCH="amd64" ;;
aarch64|arm64) ARCH="arm64" ;;
armv6l) ARCH="armv6hf" ;;
riscv64) ARCH="riscv64" ;;
*) die "Unsupported architecture: $ARCH" ;;
esac
;;
Darwin*)
OS="macos"
case "$ARCH" in
x86_64|amd64) ARCH="amd64" ;;
aarch64|arm64) ARCH="arm64" ;;
*) die "Unsupported architecture: $ARCH" ;;
esac
;;
*) die "Unsupported OS: $OS" ;;
esac
FILENAME="fostrom-device-agent-${OS}-${ARCH}"
# Check if binary already exists and the version matches.
if [ -f "$LOCATION/$FILENAME" ]; then
INSTALLED_VERSION="$(read_installed_version "$LOCATION/$FILENAME" || true)"
if [ "$INSTALLED_VERSION" = "$VERSION" ]; then
# Ensure symlink exists even when reusing.
ln -sf "$FILENAME" "$LOCATION/fostrom-device-agent"
exit 0
fi
printf "Updating Fostrom Device Agent to %s...\n" "$VERSION"
fi
printf "Downloading Fostrom Device Agent...\n"
download_and_verify "$FILENAME" "$LOCATION"
# Remove quarantine on macOS
if [ "$OS" = "macos" ]; then
xattr -r -d com.apple.quarantine "$LOCATION/$FILENAME" 2>/dev/null || true
fi
INSTALLED_VERSION="$(read_installed_version "$LOCATION/$FILENAME" || true)"
[ "$INSTALLED_VERSION" = "$VERSION" ] || die \
"Fatal: Installed Version Mismatch (expected $VERSION, got ${INSTALLED_VERSION:-unknown})"
printf "Fostrom Device Agent downloaded successfully\n"
}
main