diff --git a/download.sh b/download.sh index 7807826d..9ec8690c 100755 --- a/download.sh +++ b/download.sh @@ -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 @@ -29,17 +30,67 @@ verify_sha256() { return 0 } +file_size() { + wc -c "$1" | awk '{print $1}' +} + # ----------------------------------------------------------------------------- -# fetch +# mirror_urls +# 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 [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 } # ----------------------------------------------------------------------------- @@ -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" @@ -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 @@ -125,6 +183,7 @@ run_one() { found=0 while IFS= read -r line; do case "$line" in + \#*|"") continue ;; *"$target"*) ;; *) continue ;; esac @@ -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 } } @@ -147,4 +207,4 @@ if [ "$#" -eq 0 ]; then run_all else run_one "$1" -fi \ No newline at end of file +fi