diff options
Diffstat (limited to 'src/cpt-lib.in')
-rw-r--r-- | src/cpt-lib.in | 139 |
1 files changed, 109 insertions, 30 deletions
diff --git a/src/cpt-lib.in b/src/cpt-lib.in index ea00bb9..092ae0d 100644 --- a/src/cpt-lib.in +++ b/src/cpt-lib.in @@ -30,6 +30,29 @@ log() { "$colory" "${3:-->}" "$colre" "${2:+$colorb}" "$1" "$colre" "$2" >&2 } +warn() { + # Print a warning message + log "$1" "$2" "${3:-WARNING}" +} + +outv() { + # Call `out()` when CPT_VERBOSE is set. + [ "$CPT_VERBOSE" = 1 ] || return 0 + out "$@" +} + +logv() { + # Call `log()` when CPT_VERBOSE is set. + [ "$CPT_VERBOSE" = 1 ] || return 0 + log "$@" +} + +warnv() { + # Call `warn()` when CPT_VERBOSE is set. + [ "$CPT_VERBOSE" = 1 ] || return 0 + warn "$@" +} + die() { # Print a message and exit with '1' (error). log "$1" "$2" "!>" @@ -131,6 +154,22 @@ _readlinkf() ( return 1 ) +_get_digest() { + # Get digest algorithm from the given file. It looks for a header on the + # file declaring the digest algorithm. Currently only BLAKE3 is supported. + # If the file does not include a header, the function will assume that it is + # using sha256 as a digest algorithm. If the given file doesn't exist it will + # return 1. + [ -r "$1" ] || return 1 + read -r chk < "$1" + case $chk in + %BLAKE3) chk=b3sum ;; + %*) die "Unknown digest algorithm: '${chk#\%}'" ;; + *) chk=sh256 + esac + out "$chk" +} + # This is the public domain getoptions shell library. It also forms a usage # function. # URL: https://github.com/ko1nksm/getoptions (v2.5.0) @@ -381,11 +420,7 @@ global_options() { param CPT_ROOT --root init:@export -- "Use an alternate root directory" disp :usage -h --help -- "Show this help message" disp :version -v --version -- "Print version information" -} - -warn() { - # Print a warning message - log "$1" "$2" "${3:-WARNING}" + flag CPT_VERBOSE --verbose init:@export -- "Be more verbose" } contains() { @@ -400,6 +435,21 @@ regesc() { sed 's|\\|\\\\|g;s|\[|\\[|g;s|\$|\\$|g;s|\.|\\.|g;s|\*|\\*|g;s|\^|\\^|g' } +pkg_download() { + # $1: URL + # $2: Output (Optional) + set -- "$1" "${2:-${1##*/}}" + case ${dl_prog##*/} in + aria2c|axel) set -- -o "$2" "$1" ;; + curl) set -- -fLo "$2" "$1" ;; + wget|wget2) set -- -O "$2" "$1" ;; + esac + + "$dl_prog" "$@" || { + rm -f "$2" + return 1 + } +} prompt() { # If a CPT_NOPROMPT variable is set, continue. @@ -438,8 +488,10 @@ as_root() { CPT_PATH="$CPT_PATH" \ CPT_PID="$CPT_PID" \ CPT_PROMPT="$CPT_PROMPT" \ + CPT_REPO_CACHE="$CPT_REPO_CACHE" \ CPT_ROOT="$CPT_ROOT" \ CPT_TMPDIR="$CPT_TMPDIR" \ + CPT_VERBOSE="$CPT_VERBOSE" \ "$@" case ${su##*/} in @@ -472,7 +524,11 @@ run_hook() { [ -f "$CPT_HOOK" ] || { CPT_HOOK=$oldCPT_HOOK; return 0 ;} - [ "$2" ] && log "$2" "Running $1 hook" + if [ "$2" ]; then + logv "$2" "Running $1 hook" + else + logv "Running $1 hook" + fi TYPE=${1:-null} PKG=${2:-null} DEST=${3:-null} . "$CPT_HOOK" CPT_HOOK=$oldCPT_HOOK @@ -534,7 +590,7 @@ pkg_lint() { repo_dir=$(pkg_find "$1") cd "$repo_dir" || die "'$repo_dir' not accessible" - [ -f sources ] || warn "$1" "Sources file not found" + [ -f sources ] || warnv "$1" "Sources file not found" [ -x build ] || die "$1" "Build file not found or not executable" [ -s version ] || die "$1" "Version file not found or empty" @@ -663,10 +719,8 @@ pkg_sources() { # interrupt, we handle this ourselves. trap_set handle-int - curl "$src" -fLo "${src##*/}" || { - rm -f "${src##*/}" - die "$1" "Failed to download $src" - } + # Download the source + pkg_download "$src" || die "$1" "Failed to download $src" # Restore original trap value. trap_set cleanup @@ -943,10 +997,16 @@ pkg_etcsums() ( # /etc/ directory for use in "smart" handling of these files. log "$1" "Generating etcsums" + # Try to get the digest algorithm from the installed etcsums file. This + # makes sure that old packages continue to have the same digest algorithm + # and not a bunch of '.new' files are installed. It's not foolproof at all, + # but at least it keeps the /etc directory as clean as possible. + digest=$(_get_digest "$sys_db/$1/etcsums") || digest=b3sum + case $digest in b3sum) out "%BLAKE3"; esac > "$pkg_dir/$1/$pkg_db/$1/etcsums" find etc -type f | while read -r file; do - sh256 "$file" - done > "$pkg_dir/$1/$pkg_db/$1/etcsums" + "$digest" "$file" + done >> "$pkg_dir/$1/$pkg_db/$1/etcsums" ) pkg_tar() { @@ -1167,6 +1227,8 @@ pkg_checksums() { [ -f "$repo_dir/sources" ] || return 0 + case ${2:-b3sum} in b3sum) out "%BLAKE3"; esac + while read -r src _ || [ "$src" ]; do # Skip checksums if it's a comment, or a VCS repository. @@ -1185,9 +1247,9 @@ pkg_checksums() { die "$1" "Couldn't find source '$src'" fi - # An easy way to get 'sha256sum' to print with the 'basename' + # An easy way to get 'b3sum' to print with the 'basename' # of files is to 'cd' to the file's directory beforehand. - (cd "$src_path" && sh256 "${src##*/}") || + (cd "$src_path" && "${2:-b3sum}" "${src##*/}") || die "$1" "Failed to generate checksums" done < "$repo_dir/sources" } @@ -1195,13 +1257,18 @@ pkg_checksums() { pkg_verify() { # Verify all package checksums. This is achieved by generating a new set of # checksums and then comparing those with the old set. - verify_cmd="NR==FNR{a[\$1];next}/^git .*/{next}!((\$1)in a){exit 1}" + vcmd="NR==FNR{a[\$1];next}/^git .*/{next}!((\$1)in a){exit 1}" for pkg; do repo_dir=$(pkg_find "$pkg") + [ -f "$repo_dir/sources" ] || continue - pkg_checksums "$pkg" | awk "$verify_cmd" - "$repo_dir/checksums" || { + # Determine the type of digest algorithm from the checksums file to do + # verification with. + digest="$(_get_digest "$repo_dir/checksums")" + + pkg_checksums "$pkg" "$digest" | awk "$vcmd" - "$repo_dir/checksums" || { log "$pkg" "Checksum mismatch" # Instead of dying above, log it to the terminal. Also define a @@ -1380,23 +1447,25 @@ pkg_etc() { mkdir -p "$CPT_ROOT/$dir" done + digest=$(_get_digest "$mak_dir/c") || digest=b3sum + # Handle files in /etc/ based on a 3-way checksum check. find etc ! -type d | while read -r file; do - { sum_new=$(sh256 "$file") - sum_sys=$(cd "$CPT_ROOT/"; sh256 "$file") + { sum_new=$("$digest" "$file") + sum_sys=$(cd "$CPT_ROOT/"; "$digest" "$file") sum_old=$("$grep" "$file$" "$mak_dir/c"); } 2>/dev/null ||: - log "$pkg_name" "Doing 3-way handshake for $file" - printf '%s\n' "Previous: ${sum_old:-null}" - printf '%s\n' "System: ${sum_sys:-null}" - printf '%s\n' "New: ${sum_new:-null}" + logv "$pkg_name" "Doing 3-way handshake for $file" + outv "Previous: ${sum_old:-null}" + outv "System: ${sum_sys:-null}" + outv "New: ${sum_new:-null}" # Use a case statement to easily compare three strings at # the same time. Pretty nifty. case ${sum_old:-null}${sum_sys:-null}${sum_new} in # old = Y, sys = X, new = Y "${sum_new}${sum_sys}${sum_old}") - log "Skipping $file" + logv "Skipping $file" continue ;; @@ -1406,7 +1475,7 @@ pkg_etc() { "${sum_old}${sum_old}${sum_old}"|\ "${sum_old:-null}${sum_sys}${sum_sys}"|\ "${sum_sys}${sum_old}"*) - log "Installing $file" + logv "Installing $file" new= ;; @@ -1618,12 +1687,12 @@ pkg_repository_update() { # Repositories can contain a "Message of the Day" file in order to # relay important information to their users. - ! [ -r "$repo_root/motd" ] || { + ! [ -r "$repo_root/MOTD" ] || { printf '%s\n%s\n%s\n\n' \ "$(_multiply_char '=' 60)" \ "Message of the Day [$PWD]" \ "$(_multiply_char '=' 60)" - cat "$repo_root/motd" + cat "$repo_root/MOTD" printf '\n%s\n' "$(_multiply_char '=' 60)" } } @@ -1977,8 +2046,11 @@ pkg_gentree() ( pkg_query_meta() { # Query the 'meta' file of the given meta package. If there is no meta file, # or the key being queried is unavailable, the function will return with - # error. - repo_dir=$(pkg_find "$1") + # error. Full path can be specified instead of package names. + case $1 in + */*) repo_dir=$1 ;; + *) repo_dir=$(pkg_find "$1") + esac [ -f "$repo_dir/meta" ] || return while IFS=': ' read -r key val; do case $key in @@ -2089,6 +2161,13 @@ create_cache() { command -v llvm-readelf || command -v eu-readelf)"} || elf_prog=ldd + dl_prog=${CPT_DOWNLOADER:="$( + command -v curl || + command -v wget || + command -v wget2 || + command -v axel || + command -v aria2c)"} || dl_prog=curl + # Make note of the user's current ID to do root checks later on. # This is used enough to warrant a place here. uid=$(id -u) @@ -2126,7 +2205,7 @@ create_cache() { # colors. This can of course be overriden if the user specifically want # colors during piping. if { [ "$CPT_COLOR" != 0 ] && [ -t 1 ] ;} || [ "$CPT_COLOR" = 1 ]; then - colory="\033[1;33m" colorb="\033[1;36m" colre="\033[m" + colory="\033[1;33m" colorb="\033[1;34m" colre="\033[m" fi } |