Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 78 additions & 18 deletions download.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ cd "$(dirname "$0")"
cd archives || exit 1

ARCHIVE="archives.txt"
WGET="wget --tries=5 --timeout=15 --quiet --show-progress"
# 15s was aborting slow Sourceware transfers. Keep the partial file and resume.
WGET_OPTS=(--continue --tries=20 --timeout=60 --waitretry=5 --retry-connrefused --quiet --show-progress)

# -----------------------------------------------------------------------------
# verify_sha256 <file> <expected_sha>
Expand All @@ -29,17 +30,67 @@ verify_sha256() {
return 0
}

file_size() {
wc -c "$1" | awk '{print $1}'
}

# -----------------------------------------------------------------------------
# fetch <url> <dest>
# mirror_urls <url>
# Prints the primary URL plus GNU/kernel.org fallbacks.
# -----------------------------------------------------------------------------
fetch() {
mirror_urls() {
url="$1"
dest="$2"
$WGET -O "$dest" "$url" || {
echo " !! Download failed: $url" >&2
rm -f "$dest"
return 1
}
file="$(basename "$url")"
printf '%s\n' "$url"

case "$url" in
*/binutils/releases/*|*/gnu/binutils/*)
printf '%s\n' \
"https://ftpmirror.gnu.org/gnu/binutils/${file}" \
"https://ftp.gnu.org/gnu/binutils/${file}" \
"https://sourceware.org/pub/binutils/releases/${file}" \
"https://mirrors.kernel.org/sourceware/binutils/releases/${file}"
;;
*/gcc/releases/*|*/gnu/gcc/*)
ver="${file%.tar.*}"
printf '%s\n' \
"https://ftpmirror.gnu.org/gnu/gcc/${ver}/${file}" \
"https://ftp.gnu.org/gnu/gcc/${ver}/${file}" \
"https://sourceware.org/pub/gcc/releases/${ver}/${file}" \
"https://gcc.gnu.org/pub/gcc/releases/${ver}/${file}"
;;
*/gdb/releases/*|*/gnu/gdb/*)
printf '%s\n' \
"https://ftpmirror.gnu.org/gnu/gdb/${file}" \
"https://ftp.gnu.org/gnu/gdb/${file}" \
"https://sourceware.org/pub/gdb/releases/${file}"
;;
*/newlib/*)
printf '%s\n' \
"https://sourceware.org/pub/newlib/${file}" \
"https://mirrors.kernel.org/sourceware/newlib/${file}"
;;
esac
}

# -----------------------------------------------------------------------------
# fetch <dest> <url> [url...]
# Resumes into dest; does not delete a partial file on failure.
# -----------------------------------------------------------------------------
fetch() {
dest="$1"
shift
url=""
for url in "$@"; do
[ -n "$url" ] || continue
echo " -> $url"
if wget "${WGET_OPTS[@]}" -O "$dest" "$url"; then
return 0
fi
echo " !! failed, trying next mirror..." >&2
done
echo " !! Download failed: ${1:-$url}" >&2
return 1
}

# -----------------------------------------------------------------------------
Expand All @@ -54,7 +105,6 @@ download() {

printf '==> %s\n' "$file"

# If already present, verify immediately — size alone is not enough.
if [ -f "$file" ]; then
if [ "$sha" = "-" ]; then
echo " -- no checksum, skipping re-download of existing file"
Expand All @@ -64,19 +114,27 @@ download() {
echo " -- already good"
return 0
fi
echo " -- existing file failed verification, re-downloading..."
rm -f "$file"
actual=$(file_size "$file")
if [ "$size" != "-" ] && [ "$actual" -lt "$size" ]; then
echo " -- incomplete (${actual}/${size} bytes), resuming..."
else
echo " -- existing file failed verification, re-downloading..."
rm -f "$file"
fi
fi

# First attempt
fetch "$url" "$file"
# Unique mirror list, primary URL first.
urls=$(mirror_urls "$url" | awk 'NF && !seen[$0]++')

# shellcheck disable=SC2086
fetch "$file" $urls

# Verify, with one retry on mismatch
if [ "$sha" != "-" ]; then
if ! verify_sha256 "$file" "$sha"; then
echo " -- retrying download..."
echo " -- checksum failed, retrying from another mirror..."
rm -f "$file"
fetch "$url" "$file"
# shellcheck disable=SC2086
fetch "$file" $urls
verify_sha256 "$file" "$sha" || {
rm -f "$file"
echo " !! Giving up on $file" >&2
Expand Down Expand Up @@ -125,6 +183,7 @@ run_one() {
found=0
while IFS= read -r line; do
case "$line" in
\#*|"") continue ;;
*"$target"*) ;;
*) continue ;;
esac
Expand All @@ -138,6 +197,7 @@ EOF
done < "$ARCHIVE"
[ "$found" -eq 1 ] || {
echo "Not found: $target" >&2
echo "Add a line to archives/archives.txt, including the SHA256." >&2
exit 1
}
}
Expand All @@ -147,4 +207,4 @@ if [ "$#" -eq 0 ]; then
run_all
else
run_one "$1"
fi
fi
Loading