commit: 28cd240fb23d880b8641a058831c6762db71c3e2 Author: Sam James <sam <AT> gentoo <DOT> org> AuthorDate: Wed Mar 29 22:34:37 2023 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Sun Apr 9 06:51:35 2023 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=28cd240f
emerge-webrsync: support PGP verification via gemato Introduce PGP verification of the webrsync snapshot tarballs using app-portage/gemato - which is already a dependency of Portage for verifying normal rsync. This is the same method Portage uses (see below). Technical changes before we dive into the rationale: - Use gemato for PGP verification just like Portage does for sync-type=webrsync, sync-type=rsync (although that uses a metamanifest), and sync-type=git (although that uses gemato for gpg-wrap, so works differently). - Use gentoo-functions automagically if available for better output functions. - Be more verbose about verification and various other operations, while also respecting --quiet if passed for misc. existing & new messages. - Make --verbose a no-op. There weren't enough output messages to justify three states (--quiet, normal, --verbose). - Bail out more aggressively in the event of errors or "warnings". - Use modern terminology for repository, etc (avoid overloading the "portage" term.) - Allow disabling PGP verification with --no-pgp-verify. Technically, the fix is very straightforward, but getting to the fix was the slightly painful bit. What I've concluded happened is: - Portage starts getting reworked to gain proper sync module support; - Someone gets the idea of implementing emerge-webrsync fully in Python as a Portage sync module (which is a not-unreasonable idea); [This ultimately hasn't gone anywhere, and in fact, while working on this bug, I ended up finding a bunch of typos that meant you couldn't even test it. But it's a stub anyway.] - The idea of deprecating emerge-webrsync is floated around. The idea being Portage should call it via its new sync module with sync-type=webrsync. This is presumably with the ultimate goal of it transparently one day using the aforementioned (yet-non-existent) Python implementation as its backend, and not the shell script. [To this day, Portage's webrsync implementation shells out to the emerge-webrsync shell script, but it has the abstraction to switch that out, in theory.] - At the time, PGP verification in general of the Gentoo repository is an active topic, especially now we'd migrated to git which makes it way easier, unlike CVS. - A bug is filed for PGP verification in emerge-webrsync. People decide it doesn't matter too much, because Portage is going to Real Soon Now (TM) have its own backend (replacing the shell script) and/or Portage's sync module support obsoletes emerge-webrsync entirely. The idea here, I think, being that nobody should call emerge-webrsync and everyone should just call emerge (or emaint) to sync as appropriate. [This isn't a terrible idea in a sense, but it needs a better basis: we should probably make emerge-webrsync a wrapper which creates a temporary repo config to forcefully webrsync a repository if the user asks us to. This is what people expect from emerge-webrsync with the default sync-type=rsync in repos.conf for ::gentoo. I actually started implementing this before I realised that emerge was shelling out to emerge-webrsync, so have postponed it.] - Then nothing happens with the "replacement" ideas and the good ol' trusty emerge-webrsync ends up with the same problems sitting there because nobody saw the point in working on it if it was to be replaced soon. But that didn't happen. The fix overall for this is pretty small, but the commit is larger than I'd like because I had to rework a few things to sensibly allow disabling PGP verification as well as follow the flow. (I did start splitting up this commit but ultimately it needs -w for best review even without the output tweaks in this commit and deconstructing this for atomic commits would end up being more brittle as I couldn't be as confident in the result.) Bug: https://bugs.gentoo.org/597800 Signed-off-by: Sam James <sam <AT> gentoo.org> NEWS | 5 + bin/emerge-webrsync | 363 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 240 insertions(+), 128 deletions(-) diff --git a/NEWS b/NEWS index 3dfaf2a09..4a41fc0c6 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,11 @@ portage-3.0.47 (UNRELEASED) --------------- +Security: +* emerge-webrsync (the standalone tool) now verifies PGP signatures, see + bug #597800. Note that 'sync-type = webrsync' in repos.conf already + handled PGP verification when configured to do so (and it is by default). + Features: * install-qa-check.d: 90gcc-warnings: Add additional code quality warnings: - -Wrestrict diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync index 4b982a1c1..43ac18f46 100755 --- a/bin/emerge-webrsync +++ b/bin/emerge-webrsync @@ -24,14 +24,49 @@ # gpg --homedir /etc/portage/gnupg --edit-key ${KEY_ID} trust # -# Only echo if in verbose mode -vvecho() { [[ ${do_verbose} -eq 1 ]] && echo "$@" ; } -# Only echo if not in verbose mode -nvecho() { [[ ${do_verbose} -eq 0 ]] && echo "$@" ; } -# warning echos -wecho() { echo "${argv0##*/}: warning: $*" 1>&2 ; } -# error echos -eecho() { echo "${argv0##*/}: error: $*" 1>&2 ; } +# Opportunistically use gentoo-functions for nicer output +functions_script="${EPREFIX:-/}/lib/gentoo/functions.sh" +source "${functions_script}" || { + echo "${argv0}: Could not source ${functions_script}!" 1>&2 + + ebegin() { + printf '%s*%s %s ... ' "${GOOD}" "${NORMAL}" "$*" + } + + eend() { + local r=${1:-0} + shift + if [[ $r -eq 0 ]] ; then + printf '[ %sok%s ]\n' "${GOOD}" "${NORMAL}" + else + printf '%s [ %s!!%s ]\n' "$*" "${BAD}" "${NORMAL}" + fi + return "${r}" + } + + einfo() { + echo "${argv0##*/}: $*" + } + + ewarn() { + echo "${argv0##*/}: warning: $*" 1>&2 + } + + eerror() { + echo "${argv0##*/}: error: $*" 1>&2 + } + +} + +# Only echo if in normal mode +vvecho() { [[ ${PORTAGE_QUIET} != 1 ]] && echo "$@" ; } +# Only echo if in quiet mode +nvecho() { [[ ${PORTAGE_QUIET} == 1 ]] && echo "$@" ; } + +# Unfortunately, gentoo-functions doesn't yet have a die() (bug #878505) +die() { + eerror "$@" && exit 1 +} argv0=$0 @@ -43,8 +78,7 @@ if [[ -x "${scriptpath%/*}/portageq" ]]; then elif type -P portageq > /dev/null ; then portageq=portageq else - eecho "could not find 'portageq'; aborting" - exit 1 + die "could not find 'portageq'; aborting" fi eval "$("${portageq}" envvar -v DISTDIR EPREFIX FEATURES \ @@ -60,54 +94,74 @@ source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1 repo_name=gentoo repo_location=$(__repo_attr "${repo_name}" location) if [[ -z ${repo_location} ]]; then - eecho "Repository '${repo_name}' not found" - exit 1 + die "Repository '${repo_name}' not found" fi repo_sync_type=$(__repo_attr "${repo_name}" sync-type) # If PORTAGE_NICENESS is overriden via the env then it will # still pass through the portageq call and override properly. if [[ -n "${PORTAGE_NICENESS}" ]]; then - renice ${PORTAGE_NICENESS} $$ > /dev/null + renice "${PORTAGE_NICENESS}" $$ > /dev/null fi -do_verbose=0 do_debug=0 keep=false -has webrsync-gpg ${FEATURES} && webrsync_gpg=1 || webrsync_gpg=0 +handle_pgp_setup() { + has webrsync-gpg ${FEATURES} && webrsync_gpg=1 || webrsync_gpg=0 -if [[ ${webrsync_gpg} -eq 1 ]]; then - wecho "FEATURES=webrsync-gpg is deprecated, see the make.conf(5) man page." -fi + if [[ ${webrsync_gpg} -eq 1 ]]; then + ewarn "FEATURES=webrsync-gpg is deprecated, see the make.conf(5) man page." + fi -repo_has_webrsync_verify=$( - has $(__repo_attr "${repo_name}" sync-webrsync-verify-signature | LC_ALL=C tr '[:upper:]' '[:lower:]') true yes -) - -if [[ -n ${PORTAGE_TEMP_GPG_DIR} ]] || [[ ${repo_has_webrsync_verify} -eq 1 ]]; then - # If FEATURES=webrsync-gpg is enabled then allow direct emerge-webrsync - # calls for backward compatibility (this triggers a deprecation warning - # above). Since direct emerge-webrsync calls do not use gemato for secure - # key refresh, this behavior will not be supported in a future release. - if [[ ! ( -d ${PORTAGE_GPG_DIR} && ${webrsync_gpg} -eq 1 ) && - -z ${PORTAGE_TEMP_GPG_DIR} ]]; then - eecho "Do not call ${argv0##*/} directly, instead call emerge --sync or emaint sync." - exit 1 + repo_has_webrsync_verify=$( + has $(__repo_attr "${repo_name}" sync-webrsync-verify-signature | LC_ALL=C tr '[:upper:]' '[:lower:]') true yes + ) + + # WEBRSYNC_VERIFY_SIGNATURE=0: disable PGP verification + # WEBRSYNC_VERIFY_SIGNATURE=1: use gemato for verification, fallback to regular gpg + # WEBRSYNC_VERIFY_SIGNATURE=2: use legacy FEATURES="webrsync-gpg" + WEBRSYNC_VERIFY_SIGNATURE=1 + + if [[ -n ${PORTAGE_TEMP_GPG_DIR} ]] || [[ ${repo_has_webrsync_verify} -eq 1 ]]; then + # If FEATURES=webrsync-gpg is enabled then allow direct emerge-webrsync + # calls for backward compatibility (this triggers a deprecation warning + # above). Since direct emerge-webrsync calls do not use gemato for secure + # key refresh, this behavior will not be supported in a future release. + if [[ ! ( -d ${PORTAGE_GPG_DIR} && ${webrsync_gpg} -eq 1 ) && -z ${PORTAGE_TEMP_GPG_DIR} ]]; then + die "Do not call ${argv0##*/} directly, instead call emerge --sync or emaint sync." + fi + + WEBRSYNC_VERIFY_SIGNATURE=2 + elif has webrsync-gpg ${FEATURES}; then + WEBRSYNC_VERIFY_SIGNATURE=2 + elif [[ -n ${no_pgp_verify} ]]; then + WEBRSYNC_VERIFY_SIGNATURE=0 fi - WEBSYNC_VERIFY_SIGNATURE=1 -elif has webrsync-gpg ${FEATURES}; then - WEBSYNC_VERIFY_SIGNATURE=1 -else - WEBSYNC_VERIFY_SIGNATURE=0 -fi + case "${WEBRSYNC_VERIFY_SIGNATURE}" in + 0) + [[ ${PORTAGE_QUIET} -eq 1 ]] || ewarn "PGP verification method: disabled" + ;; + 1) + [[ ${PORTAGE_QUIET} -eq 1 ]] || einfo "PGP verification method: gemato" + ;; + 2) + ewarn "PGP verification method: legacy FEATURES=webrsync-gpg" + ;; + *) + die "Unknown WEBRSYNC_VERIFY_SIGNATURE state: \${WEBRSYNC_VERIFY_SIGNATURE}=${WEBRSYNC_VERIFY_SIGNATURE}" + ;; + esac -[[ -n ${PORTAGE_TEMP_GPG_DIR} ]] && PORTAGE_GPG_DIR=${PORTAGE_TEMP_GPG_DIR} -if [[ ${WEBSYNC_VERIFY_SIGNATURE} != 0 && -z "${PORTAGE_GPG_DIR}" ]]; then - eecho "Please set PORTAGE_GPG_DIR in make.conf!" - exit 1 -fi + if [[ -n ${PORTAGE_TEMP_GPG_DIR} ]]; then + PORTAGE_GPG_DIR=${PORTAGE_TEMP_GPG_DIR} + fi + + if [[ ${WEBRSYNC_VERIFY_SIGNATURE} == 2 && -z "${PORTAGE_GPG_DIR}" ]]; then + die "Please set PORTAGE_GPG_DIR in make.conf!" + fi +} do_tar() { local file=$1 @@ -134,9 +188,9 @@ get_date_part() { local part="$2" if [[ ${USERLAND} == BSD ]] ; then - date -r ${utc_time_in_secs} -u +"${part}" + date -r "${utc_time_in_secs}" -u +"${part}" else - date -d @${utc_time_in_secs} -u +"${part}" + date -d "@${utc_time_in_secs}" -u +"${part}" fi } @@ -152,7 +206,7 @@ get_utc_second_from_string() { fi } -get_portage_timestamp() { +get_repository_timestamp() { local portage_current_timestamp=0 if [[ -f "${repo_location}/metadata/timestamp.x" ]]; then @@ -175,7 +229,7 @@ fetch_file() { rm -f "${DISTDIR}/${FILE}" fi - __vecho "Fetching file ${FILE} ..." + [[ ${PORTAGE_QUIET} -eq 1 ]] || einfo "Fetching file ${FILE} ..." # Already set DISTDIR= eval "${FETCHCOMMAND} ${opts}" @@ -192,7 +246,7 @@ check_file_digest() { local file="$2" local r=1 - __vecho "Checking digest ..." + [[ ${PORTAGE_QUIET} -eq 1 ]] || einfo "Checking digest ..." if type -P md5sum > /dev/null; then local md5sum_output=$(md5sum "${file}") @@ -201,43 +255,85 @@ check_file_digest() { elif type -P md5 > /dev/null; then [[ "$(md5 -q "${file}")" == "$(cut -d ' ' -f 1 "${digest}")" ]] && r=0 else - eecho "cannot check digest: no suitable md5/md5sum binaries found" + die "cannot check digest: no suitable md5/md5sum binaries found" fi return "${r}" } -check_file_signature() { +check_file_signature_gemato() { local signature="$1" local file="$2" local r=1 - local gnupg_status line - if [[ ${WEBSYNC_VERIFY_SIGNATURE} != 0 ]]; then - __vecho "Checking signature ..." + if type -P gemato > /dev/null; then + local gemato_args=( + openpgp-verify-detached + -K /usr/share/openpgp-keys/gentoo-release.asc + ) - if type -P gpg > /dev/null; then - if gnupg_status=$(gpg --homedir "${PORTAGE_GPG_DIR}" --batch \ - --status-fd 1 --verify "${signature}" "${file}"); then - while read -r line; do - if [[ ${line} == "[GNUPG:] GOODSIG"* ]]; then - r=0 - break - fi - done <<< "${gnupg_status}" - fi + [[ ${PORTAGE_QUIET} == 1 ]] && gemato_args+=( --quiet ) + [[ ${do_debug} == 1 ]] && gemato_args+=( --debug ) - if [[ ${r} -ne 0 ]]; then - # Exit early since it's typically inappropriate to - # try other mirrors in this case (it may indicate - # a keyring problem). - eecho "signature verification failed" - exit 1 - fi - else - eecho "cannot check signature: gpg binary not found" - exit 1 + gemato "${gemato_args[@]}" "${signature}" "${file}" + r=$? + + if [[ ${r} -ne 0 ]]; then + # Exit early since it's typically inappropriate to + # try other mirrors in this case (it may indicate + # a keyring problem). + die "signature verification failed" + fi + fi + + return "${r}" +} + +check_file_signature_gpg_unwrapped() { + local signature="$1" + local file="$2" + + if type -P gpg > /dev/null; then + if gnupg_status=$(gpg --homedir "${PORTAGE_GPG_DIR}" --batch \ + --status-fd 1 --verify "${signature}" "${file}"); then + while read -r line; do + if [[ ${line} == "[GNUPG:] GOODSIG"* ]]; then + r=0 + break + fi + done <<< "${gnupg_status}" fi + + if [[ ${r} -ne 0 ]]; then + # Exit early since it's typically inappropriate to + # try other mirrors in this case (it may indicate + # a keyring problem). + die "signature verification failed" + fi + else + die "cannot check signature: gpg binary not found" + fi +} + +check_file_signature() { + local signature="$1" + local file="$2" + local r=1 + local gnupg_status line + + if [[ ${WEBRSYNC_VERIFY_SIGNATURE} != 0 ]]; then + [[ ${PORTAGE_QUIET} -eq 1 ]] || einfo "Checking signature ..." + + case ${WEBRSYNC_VERIFY_SIGNATURE} in + 1) + check_file_signature_gemato "${signature}" "${file}" + r=$? + ;; + 2) + check_file_signature_gpg_unwrapped "${signature}" "${file}" + r=$? + ;; + esac else r=0 fi @@ -254,7 +350,7 @@ get_snapshot_timestamp() { sync_local() { local file="$1" - __vecho "Syncing local tree ..." + [[ ${PORTAGE_QUIET} -eq 1 ]] || einfo "Syncing local repository ..." local ownership="portage:portage" if has usersync ${FEATURES} ; then @@ -275,36 +371,39 @@ sync_local() { if ! tarsync $(vvecho -v) -s 1 ${chown_opts} \ -e /distfiles -e /packages -e /local "${file}" "${repo_location}"; then - eecho "tarsync failed; tarball is corrupt? (${file})" + eerror "tarsync failed; tarball is corrupt? (${file})" return 1 fi else if ! do_tar "${file}" -x --strip-components=1 -f -; then - eecho "tar failed to extract the image. tarball is corrupt? (${file})" + eerror "tar failed to extract the image. tarball is corrupt? (${file})" return 1 fi # Free disk space ${keep} || rm -f "${file}" - local rsync_opts="${PORTAGE_RSYNC_OPTS} ${PORTAGE_RSYNC_EXTRA_OPTS}" + local rsync_opts="${PORTAGE_RSYNC_OPTS} ${PORTAGE_RSYNC_EXTRA_OPTS} $(nvecho -q)" if chown ${ownership} . > /dev/null 2>&1; then chown -R ${ownership} . rsync_opts+=" --owner --group" fi chmod 755 . - rsync ${rsync_opts} . "${repo_location%%/}" + rsync ${rsync_opts} . "${repo_location%%/}" || { + eerror "rsync failed: $?" + die "Aborting because of rsync failure" + } - __vecho "Cleaning up ..." + [[ ${PORTAGE_QUIET} == 1 ]] || einfo "Cleaning up ..." fi if has metadata-transfer ${FEATURES} ; then - __vecho "Updating cache ..." + einfo "Updating cache ..." emerge --metadata fi - local post_sync=${PORTAGE_CONFIGROOT}etc/portage/bin/post_sync + local post_sync=${PORTAGE_CONFIGROOT%/}/etc/portage/bin/post_sync [[ -x "${post_sync}" ]] && "${post_sync}" # --quiet suppresses output if there are no relevant news items @@ -327,20 +426,20 @@ do_snapshot() { type -P xzcat > /dev/null && compressions="${compressions} ${repo_name}:xz portage:xz" type -P bzcat > /dev/null && compressions="${compressions} ${repo_name}:bz2 portage:bz2" - type -P zcat > /dev/null && compressions="${compressions} ${repo_name}:gz portage:gz" - + type -P zcat > /dev/null && compressions="${compressions} ${repo_name}:gz portage:gz" if [[ -z ${compressions} ]] ; then - eecho "unable to locate any decompressors (xzcat or bzcat or zcat)" - exit 1 + die "unable to locate any decompressors (xzcat or bzcat or zcat)" fi for mirror in ${GENTOO_MIRRORS} ; do mirror=${mirror%/} - __vecho "Trying to retrieve ${date} snapshot from ${mirror} ..." + [[ ${PORTAGE_QUIET} -eq 1 ]] || einfo "Trying to retrieve ${date} snapshot from ${mirror} ..." for compression in ${compressions} ; do local name=${compression%%:*} + compression=${compression#*:} + local file="${name}-${date}.tar.${compression}" local digest="${file}.md5sum" local signature="${file}.gpgsig" @@ -353,10 +452,11 @@ do_snapshot() { if [[ ${have_files} -eq 0 ]] ; then fetch_file "${mirror}/snapshots/${digest}" "${digest}" && \ - fetch_file "${mirror}/snapshots/${signature}" "${signature}" && \ - fetch_file "${mirror}/snapshots/${file}" "${file}" && \ - check_file_digest "${DISTDIR}/${digest}" "${DISTDIR}/${file}" && \ - check_file_signature "${DISTDIR}/${signature}" "${DISTDIR}/${file}" && \ + fetch_file "${mirror}/snapshots/${signature}" "${signature}" && \ + fetch_file "${mirror}/snapshots/${file}" "${file}" && \ + check_file_digest "${DISTDIR}/${digest}" "${DISTDIR}/${file}" && \ + check_file_signature "${DISTDIR}/${signature}" "${DISTDIR}/${file}" && \ + have_files=1 fi @@ -366,25 +466,25 @@ do_snapshot() { # from a different mirror # if [[ ${have_files} -eq 1 ]]; then - __vecho "Getting snapshot timestamp ..." - local snapshot_timestamp=$(get_snapshot_timestamp "${DISTDIR}/${file}") + [[ ${PORTAGE_QUIET} -eq 1 ]] || einfo "Getting snapshot timestamp ..." + + local snapshot_timestamp + snapshot_timestamp=$(get_snapshot_timestamp "${DISTDIR}/${file}") if [[ ${ignore_timestamp} == 0 ]]; then - if [[ ${snapshot_timestamp} -lt $(get_portage_timestamp) ]]; then - wecho "portage is newer than snapshot" + if [[ ${snapshot_timestamp} -lt $(get_repository_timestamp) ]]; then + ewarn "Repository (age) is newer than fetched snapshot" have_files=0 fi else - local utc_seconds=$(get_utc_second_from_string "${date}") + local utc_seconds + utc_seconds=$(get_utc_second_from_string "${date}") - # - # Check that this snapshot - # is what it claims to be ... - # + # Check that this snapshot is what the age it claims to be if [[ ${snapshot_timestamp} -lt ${utc_seconds} || \ ${snapshot_timestamp} -gt $((${utc_seconds}+ 2*86400)) ]]; then - wecho "snapshot timestamp is not in acceptable period" + ewarn "Snapshot timestamp is not within acceptable period!" have_files=0 fi fi @@ -393,9 +493,7 @@ do_snapshot() { if [[ ${have_files} -eq 1 ]]; then break else - # # Remove files and use a different mirror - # rm -f "${DISTDIR}/${file}" "${DISTDIR}/${digest}" "${DISTDIR}/${signature}" fi done @@ -406,7 +504,7 @@ do_snapshot() { if [[ ${have_files} -eq 1 ]]; then sync_local "${DISTDIR}/${file}" && r=0 else - __vecho "${date} snapshot was not found" + ewarn "${date} snapshot was not found" fi ${keep} || rm -f "${DISTDIR}/${file}" "${DISTDIR}/${digest}" "${DISTDIR}/${signature}" @@ -417,7 +515,7 @@ do_latest_snapshot() { local attempts=0 local r=1 - __vecho "Fetching most recent snapshot ..." + [[ ${PORTAGE_QUIET} -eq 1 ]] || einfo "Fetching most recent snapshot ..." # The snapshot for a given day is generated at 00:45 UTC on the following # day, so the current day's snapshot (going by UTC time) hasn't been @@ -428,12 +526,18 @@ do_latest_snapshot() { # are considered to be approximately equal. local min_time_diff=$(( 2 * 60 * 60 )) - local existing_timestamp=$(get_portage_timestamp) + local existing_timestamp local timestamp_difference local timestamp_problem local approx_snapshot_time - local start_time=$(get_utc_date_in_seconds) - local start_hour=$(get_date_part ${start_time} "%H") + local start_time + local start_hour + local snapshot_date + local snapshot_date_seconds + + existing_timestamp=$(get_repository_timestamp) + start_time=$(get_utc_date_in_seconds) + start_hour=$(get_date_part "${start_time}" "%H") # Daily snapshots are created at 00:45 and are not # available until after 01:00. Don't waste time trying @@ -441,17 +545,19 @@ do_latest_snapshot() { if [[ ${start_hour} -lt 1 ]] ; then (( start_time -= 86400 )) fi - local snapshot_date=$(get_date_part ${start_time} "%Y%m%d") - local snapshot_date_seconds=$(get_utc_second_from_string ${snapshot_date}) - while (( ${attempts} < 40 )) ; do + snapshot_date=$(get_date_part "${start_time}" "%Y%m%d") + snapshot_date_seconds=$(get_utc_second_from_string "${snapshot_date}") + + while (( ${attempts} < 40 )) ; do (( attempts++ )) (( snapshot_date_seconds -= 86400 )) # snapshots are created at 00:45 (( approx_snapshot_time = snapshot_date_seconds + 86400 + 2700 )) (( timestamp_difference = existing_timestamp - approx_snapshot_time )) - [ ${timestamp_difference} -lt 0 ] && (( timestamp_difference = -1 * timestamp_difference )) - snapshot_date=$(get_date_part ${snapshot_date_seconds} "%Y%m%d") + + [[ ${timestamp_difference} -lt 0 ]] && (( timestamp_difference = -1 * timestamp_difference )) + snapshot_date=$(get_date_part "${snapshot_date_seconds}" "%Y%m%d") timestamp_problem="" if [[ ${timestamp_difference} -eq 0 ]]; then @@ -497,9 +603,10 @@ usage() { Options: --revert=yyyymmdd Revert to snapshot + --no-pgp-verify Disable PGP verification of snapshot -k, --keep Keep snapshots in DISTDIR (don't delete) -q, --quiet Only output errors - -v, --verbose Enable verbose output + -v, --verbose Enable verbose output (no-op) -x, --debug Enable debug output -h, --help This help screen (duh!) EOF @@ -521,24 +628,25 @@ main() { -h|--help) usage ;; -k|--keep) keep=true ;; -q|--quiet) PORTAGE_QUIET=1 ;; - -v|--verbose) do_verbose=1 ;; + -v|--verbose) unset PORTAGE_QUIET ;; -x|--debug) do_debug=1 ;; --revert=*) revert_date=${v} ;; + --no-pgp-verify) no_pgp_verify=1 ;; *) usage "Invalid option '${arg}'" ;; esac done + handle_pgp_setup + [[ -d ${repo_location} ]] || mkdir -p "${repo_location}" if [[ ! -w ${repo_location} ]] ; then - eecho "Repository '${repo_name}' is not writable: ${repo_location}" - exit 1 + die "Repository '${repo_name}' is not writable: ${repo_location}" fi [[ -d ${PORTAGE_TMPDIR}/portage ]] || mkdir -p "${PORTAGE_TMPDIR}/portage" TMPDIR=$(mktemp -d "${PORTAGE_TMPDIR}/portage/webrsync-XXXXXX") if [[ ! -w ${TMPDIR} ]] ; then - eecho "TMPDIR is not writable: ${TMPDIR}" - exit 1 + die "TMPDIR is not writable: ${TMPDIR}" fi trap 'cd / ; rm -rf "${TMPDIR}"' EXIT cd "${TMPDIR}" || exit 1 @@ -547,21 +655,20 @@ main() { [[ ! -d "${DISTDIR}" ]] && mkdir -p "${DISTDIR}" if ${keep} && [[ ! -w ${DISTDIR} ]] ; then - eecho "DISTDIR is not writable: ${DISTDIR}" - exit 1 + die "DISTDIR is not writable: ${DISTDIR}" fi # This is a sanity check to help prevent people like funtoo users # from accidentally wiping out their git tree. - if [[ -n ${repo_sync_type} && ${repo_sync_type} != rsync && ${repo_sync_type} != webrsync ]] ; then - echo "The current sync-type attribute of repository 'gentoo' is not set to 'rsync' or 'webrsync':" >&2 - echo >&2 - echo " sync-type=${repo_sync_type}" >&2 - echo >&2 - echo "If you intend to use emerge-webrsync then please" >&2 - echo "adjust sync-type and sync-uri attributes to refer to rsync." >&2 - echo "emerge-webrsync exiting due to abnormal sync-type setting." >&2 - exit 1 + if [[ -n ${repo_sync_type} && ${repo_sync_type} != rsync && ${repo_sync_type} != webrsync ]] ; then + eerror "The current sync-type attribute of repository 'gentoo' is not set to 'rsync' or 'webrsync':" + eerror + eerror " sync-type=${repo_sync_type}" + eerror + eerror "If you intend to use emerge-webrsync then please" + eerror "adjust sync-type and sync-uri attributes to refer to rsync." + eerror "emerge-webrsync exiting due to abnormal sync-type setting." + die fi [[ ${do_debug} -eq 1 ]] && set -x
