# This hook downloads the distfiles specified in a template by # the $distfiles variable and then verifies its sha256 checksum comparing # its value with the one stored in the $checksum variable. # Return the checksum of the contents of a tarball contents_cksum() { local curfile="$1" cursufx cksum case $curfile in *.tar.lzma) cursufx="txz";; *.tar.lz) cursufx="tlz";; *.tlz) cursufx="tlz";; *.tar.xz) cursufx="txz";; *.txz) cursufx="txz";; *.tar.bz2) cursufx="tbz";; *.tbz) cursufx="tbz";; *.tar.gz) cursufx="tgz";; *.tgz) cursufx="tgz";; *.gz) cursufx="gz";; *.bz2) cursufx="bz2";; *.tar) cursufx="tar";; *.zip) cursufx="zip";; *.rpm) cursufx="rpm";; *.patch) cursufx="txt";; *.diff) cursufx="txt";; *.txt) cursufx="txt";; *.7z) cursufx="7z";; *.gem) cursufx="gem";; *.crate) cursufx="crate";; *) msg_error "$pkgver: unknown distfile suffix for $curfile.\n";; esac case ${cursufx} in tar|txz|tbz|tlz|tgz|crate) cksum=$($XBPS_DIGEST_CMD <($TAR_CMD -x -O -f "$curfile")) if [ $? -ne 0 ]; then msg_error "$pkgver: extracting $curfile to pipe.\n" fi ;; gz) cksum=$($XBPS_DIGEST_CMD <(gunzip -c "$curfile")) ;; bz2) cksum=$($XBPS_DIGEST_CMD <(bunzip2 -c "$curfile")) ;; zip) if command -v unzip &>/dev/null; then cksum=$($XBPS_DIGEST_CMD <(unzip -p "$curfile")) if [ $? -ne 0 ]; then msg_error "$pkgver: extracting $curfile to pipe.\n" fi else msg_error "$pkgver: cannot find unzip bin for extraction.\n" fi ;; rpm) msg_error "$pkgver: contents checksum not support for rpm.\n" ;; txt) cksum=$($XBPS_DIGEST_CMD "$curfile") ;; 7z) if command -v 7z &>/dev/null; then cksum=$($XBPS_DIGEST_CMD <(7z x -o "$curfile")) if [ $? -ne 0 ]; then msg_error "$pkgver: extracting $curfile to pipe.\n" fi else msg_error "$pkgver: cannot find 7z bin for extraction.\n" fi ;; gem) cksum=$($XBPS_DIGEST_CMD <($TAR_CMD -x -O -f "$curfile" data.tar.gz | $TAR_CMD -xzO )) ;; *) msg_error "$pkgver: cannot guess $curfile extract suffix. ($cursufx)\n" ;; esac if [ -z "$cksum" ]; then msg_error "$pkgver: cannot find contents checksum for $curfile.\n" fi echo "$cksum" } # Verify the checksum for $curfile stored at $distfile and index $dfcount verify_cksum() { local curfile="$1" distfile="$2" cksum="$3" filesum # If the checksum starts with an commercial at (@) it is the contents checksum if [ "${cksum:0:1}" = "@" ]; then cksum=${cksum:1} msg_normal "$pkgver: verifying contents checksum for distfile '$curfile'... " filesum=$(contents_cksum "$curfile") if [ "${cksum}" != "$filesum" ]; then echo msg_red "SHA256 mismatch for '${curfile}:'\n@${filesum}\n" errors=$((errors + 1)) else msg_normal_append "OK.\n" fi else msg_normal "$pkgver: verifying checksum for distfile '$curfile'... " filesum=$(${XBPS_DIGEST_CMD} "$distfile") if [ "$cksum" != "$filesum" ]; then echo msg_red "SHA256 mismatch for '${curfile}:'\n${filesum}\n" errors=$((errors + 1)) else if [ ! -f "$XBPS_SRCDISTDIR/by_sha256/${cksum}_${curfile}" ]; then mkdir -p "$XBPS_SRCDISTDIR/by_sha256" ln -f "$distfile" "$XBPS_SRCDISTDIR/by_sha256/${cksum}_${curfile}" fi msg_normal_append "OK.\n" fi fi } # Link an existing cksum $distfile for $curfile at index $dfcount link_cksum() { local curfile="$1" distfile="$2" cksum="$3" if [ -n "$cksum" -a -f "$XBPS_SRCDISTDIR/by_sha256/${cksum}_${curfile}" ]; then ln -f "$XBPS_SRCDISTDIR/by_sha256/${cksum}_${curfile}" "$distfile" msg_normal "$pkgver: using known distfile $curfile.\n" return 0 fi return 1 } try_mirrors() { local curfile="$1" distfile="$2" cksum="$3" f="$4" local filesum basefile mirror path scheme good [ -z "$XBPS_DISTFILES_MIRROR" ] && return 1 basefile="${f##*/}" for mirror in $XBPS_DISTFILES_MIRROR; do scheme="file" if [[ $mirror == *://* ]]; then scheme="${mirror%%:/*}" path="${mirror#${scheme}://}" else path="$mirror" fi if [ "$scheme" == "file" ]; then # Skip file:// mirror locations (/some/where or file:///some/where) # where the specified directory does not exist if [ ! -d "$path" ]; then msg_warn "$pkgver: mount point $path does not exist...\n" continue fi fi if [[ "$mirror" == *voidlinux* ]]; then # For distfiles.voidlinux.* append the subdirectory mirror="$mirror/$pkgname-$version" fi msg_normal "$pkgver: fetching distfile '$curfile' from mirror '$mirror'...\n" $fetch_cmd "$mirror/$curfile" # If basefile was not found, but a curfile file may exist, try to fetch it # if [ ! -f "$distfile" -a "$basefile" != "$curfile" ]; then # msg_normal "$pkgver: fetching distfile '$basefile' from mirror '$mirror'...\n" # $fetch_cmd "$mirror/$basefile" # fi [ ! -f "$distfile" ] && continue flock -n ${distfile}.part rm -f ${distfile}.part filesum=$(${XBPS_DIGEST_CMD} "$distfile") if [ "$cksum" == "$filesum" ]; then return 0 fi msg_normal "$pkgver: checksum failed - removing '$curfile'...\n" rm -f ${distfile} done return 1 } try_urls() { local curfile="$1" local good= for i in ${_file_idxs["$curfile"]}; do local cksum=${_checksums["$i"]} local url=${_distfiles["$i"]} # If distfile does not exist, download it from the original location. if [[ "$FTP_RETRIES" && "${url}" =~ ^ftp:// ]]; then max_retries="$FTP_RETRIES" else max_retries=1 fi for retry in $(seq 1 1 $max_retries); do if [ ! -f "$distfile" ]; then if [ "$retry" == 1 ]; then msg_normal "$pkgver: fetching distfile '$curfile' from '$url'...\n" else msg_normal "$pkgver: fetch attempt $retry of $max_retries...\n" fi flock "${distfile}.part" $fetch_cmd "$url" fi done if [ ! -f "$distfile" ]; then continue fi # distfile downloaded, verify sha256 hash. flock -n "${distfile}.part" rm -f "${distfile}.part" verify_cksum "$curfile" "$distfile" "$cksum" return 0 done return 1 } hook() { local srcdir="$XBPS_SRCDISTDIR/$pkgname-$version" local dfcount=0 dfgood=0 errors=0 max_retries local -a _distfiles=($distfiles) local -a _checksums=($checksum) local -A _file_idxs # Create a map from target file to index in _distfiles/_checksums for i in ${!_distfiles[@]}; do f="${_distfiles[$i]}" curfile="${f#*>}" curfile="${curfile##*/}" _file_idxs["$curfile"]+=" $i" done if [[ ! -d "$srcdir" ]]; then mkdir -p -m775 "$srcdir" chgrp $(id -g) "$srcdir" fi cd $srcdir || msg_error "$pkgver: cannot change dir to $srcdir!\n" # Disable trap on ERR; the code is smart enough to report errors and abort. trap - ERR # Detect bsdtar and GNU tar (in that order of preference) TAR_CMD="$(command -v bsdtar)" if [[ -z "$TAR_CMD" ]]; then TAR_CMD="$(command -v tar)" fi # Detect distfiles with obsolete checksum and purge them from the cache for f in ${!_file_idxs[@]}; do distfile="$srcdir/$f" for i in ${_file_idxs["$f"]}; do if [[ -f $distfile ]]; then cksum=${_checksums["$i"]} if [[ ${cksum:0:1} = @ ]]; then cksum=${cksum:1} filesum=$(contents_cksum "$distfile") else filesum=$(${XBPS_DIGEST_CMD} "$distfile") fi if [[ $cksum = $filesum ]]; then dfgood=$((dfgood + 1)) else inode=$(stat "$distfile" --printf "%i") msg_warn "$pkgver: wrong checksum found for ${curfile} - purging\n" find ${XBPS_SRCDISTDIR} -inum ${inode} -delete -print fi fi dfcount=$((dfcount + 1)) done done # We're done, if all distfiles were found and had good checksums [[ $dfcount -eq $dfgood ]] && return # Download missing distfiles and verify their checksums for curfile in ${!_file_idxs[@]}; do distfile="$srcdir/$curfile" set -- ${_file_idxs["$curfile"]} i="$1" # If file lock cannot be acquired wait until it's available. while ! flock -w 1 "${distfile}.part" true; do msg_warn "$pkgver: ${curfile} is already being downloaded, waiting for 1s ...\n" done if [[ -f "$distfile" ]]; then continue fi # If distfile does not exist, try to link to it. if link_cksum "$curfile" "$distfile" "${_checksums[$i]}"; then continue fi # If distfile does not exist, download it from a mirror location. if try_mirrors "$curfile" "$distfile" "${_checksums[$i]}" "${_distfiles[$i]}"; then continue fi if ! try_urls "$curfile"; then msg_error "$pkgver: failed to fetch '$curfile'.\n" fi done unset TAR_CMD if [[ $errors -gt 0 ]]; then msg_error "$pkgver: couldn't verify distfiles, exiting...\n" fi }