#!/bin/bash # # Clear Linux -- automatic debuginfo preparation # # Copyright 2019 Intel Corporation # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, version 3 or later of the License. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . if [ $# -eq 1 ] || [ $# -gt 2 ]; then echo "Usage: $0 [SOURCEDIR] [DESTDIR]" echo "Generates automatic debuginfo tarballs in DESTDIR using content from SOURCEDIR." echo "The default SOURCEDIR and DESTDIR are /var/www/html/debuginfo.raw and" echo "/var/www/html/debuginfo, respectively." exit 0 fi >&2 if [ $# -eq 2 ]; then if [ ! -d "$1" ]; then echo "ERROR: SOURCEDIR argument must be an existing directory" exit 1 fi fi >&2 export SRC="${1:-/var/www/html/debuginfo.raw}" export DEST="${2:-/var/www/html/debuginfo}" srclist=$(mktemp -p .) destlist=$(mktemp -p .) trap "rm $srclist $destlist" EXIT set -o pipefail # First, scan the state of the SRC tree, containing all content for debuginfo RPMs. if ! find "$SRC" -mindepth 4 -printf "%p %T@ %y\n" | sed "s|$SRC||" | sort -k 1 > "$srclist"; then echo "ERROR: expected content in $SRC" exit 1 fi # Next, scan the state of the DEST tree, containing previously generated # automatic debuginfo tarballs. Will be empty on first run. mkdir -p "$DEST" find "$DEST" -mindepth 2 -name '*.tar' -printf "%p %T@ %y\n" | sed "s|$DEST||;s|\.tar | |" | sort -k 1 > "$destlist" process_one() { srcname="$1" destname="$2" filetype="$3" srcloc="$SRC/$srcname" srcdir="$SRC/$(echo "$srcname" | sed -r 's@^(/usr/(lib|share|src)/debug(/src)?).*@\1@')" tarcontent="$(echo "$srcname" | sed -r 's@^/usr/(lib|share|src)/debug(/src)?@.@')" destdir="$DEST/$(dirname "$destname")" dest="$DEST/$destname.tar" echo "Creating $destname.tar ..." mkdir -p "$destdir" if [ "$filetype" = "f" ]; then tar --no-recursion -C "$srcdir" --zstd -cf "$dest" "$tarcontent" elif [ "$filetype" = "l" ]; then # We "unsymlink" non-broken symlinks as an optimization by adding the # symlink target to the dest tarball, transforming the name as appropriate. if target=$(realpath -e "$srcloc" --relative-to="$srcdir" 2> /dev/null); then tar --no-recursion -C "$srcdir" --zstd -cf "$dest" --transform='s|.*|'"$tarcontent"'|' "$target" else tar --no-recursion -C "$srcdir" --zstd -cf "$dest" "$tarcontent" fi elif [ "$filetype" = "d" ]; then tar --no-recursion -C "$srcdir" --zstd -cf "$dest" "$tarcontent" fi } export -f process_one gawk ' BEGIN { OFS = "\t" } LIST == "src" { name = $1 srcname = name ret = sub(/^\/usr\/lib\/debug/, "/lib", name) if (ret == 0) { ret = sub(/^\/usr\/src\/debug/, "/src", name) if (ret == 0) { ret = sub(/^\/usr\/share\/debug\/src/, "/src", name) if (ret == 0) { ret = sub(/^\/usr\/share\/debug/, "/lib", name) if (ret == 0) { print "Error: unexpected debuginfo file:", name exit 1 } } } } src[name]["srcname"] = srcname src[name]["time"] = $2 src[name]["type"] = $3 src[name]["done"] = 0 } LIST == "dest" { dest_content = 1 name = $1 time = $2 type = $3 if (name in src) { # No need to recreate directory tars if they exist if (src[name]["type"] == "d") { src[name]["done"] = 1 next } else { # Only regenerate content if timestamp is newer if (time < src[name]["time"]) { print src[name]["srcname"], name, src[name]["type"] } src[name]["done"] = 1 } } } END { PROCINFO["sorted_in"] = "@ind_str_asc" if (dest_content == 0) { for (s in src) { print src[s]["srcname"], s, src[s]["type"] } } else { for (s in src) { if (src[s]["done"] == 0) { print src[s]["srcname"], s, src[s]["type"] } } } } ' LIST="src" "$srclist" LIST="dest" "$destlist" \ | parallel --colsep '\t' process_one # vi: ft=sh et sw=2 sts=2