#!/bin/bash
# This script is run by rpmbuild at the end of the brp checks. It computes
# hashes of files listed in the BRP_PESIGN_FILES environment and stores them in
# %_topdir/OTHER/%name.cpio.rsasign. It also puts a specfile there, that
# is later used to repackage the RPMs.
#
# Copyright (c) 2013 SUSE Linux Products GmbH, Nuernberg, Germany.
#
# 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; either version 2 of the License, or
# (at your option) any later version.
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA

set -e

files="*.ko"
if test -n "${BRP_PESIGN_FILES+x}"; then
	files=${BRP_PESIGN_FILES}
fi
output=
while test $# -gt 0; do
	case "$1" in
	--files)
		files=$2
		shift 2
		;;
	--output)
		output=$2
		shift 2
		;;
	*)
		echo "$0: Unknown option: $1" >&2
		exit 1
	esac
done
if test -z "$files"; then
	exit 0
fi
if test -z "$output"; then
	output=`rpm --eval %_topdir/OTHER`
fi
if test -z "$RPM_BUILD_ROOT"; then
	echo "$0: warning: \$RPM_BUILD_ROOT not set, using the root directory" >&2
	RPM_BUILD_ROOT=/
fi

if ! mkdir -p "$output"; then
	echo "$0: warning: $output cannot be created, giving up" >&2
	exit 0
fi

case "$BRP_PESIGN_GRUB_RESERVATION" in
	'')
		pesign_grub_reservation="0"
		;;
	*[!0-9]*)
		echo "$0: warning: non-numerc value '$BRP_PESIGN_GRUB_RESERVATION' of BRP_PESIGN_GRUB_RESERVATION" >&2
		pesign_grub_reservation="0"
		;;
	*)
	pesign_grub_reservation="${BRP_PESIGN_GRUB_RESERVATION}"
	;;
esac

if test "${BRP_PESIGN_COMPRESS_MODULE}" = "xz"; then
	pesign_repackage_compress="--compress xz"
elif test "${BRP_PESIGN_COMPRESS_MODULE}" = "gzip"; then
	pesign_repackage_compress="--compress gzip"
elif test "${BRP_PESIGN_COMPRESS_MODULE}" = "zstd"; then
	pesign_repackage_compress="--compress zstd"
else
	pesign_repackage_compress=""
fi

cert=$RPM_SOURCE_DIR/_projectcert.crt
if test -e "$cert"; then
	echo "Using signing certificate $cert"
else
	echo "No buildservice signing certificate"
	cert=/dev/null
fi

if test -e $RPM_SOURCE_DIR/pesign-spec-macros; then
	sed "
		s:%{name}:$RPM_PACKAGE_NAME:g
		s:%{version}:$RPM_PACKAGE_VERSION:g
	" $RPM_SOURCE_DIR/pesign-spec-macros > $output/pesign-spec-macros
	spec_macros="--macros pesign-spec-macros"
fi
if test -e $RPM_SOURCE_DIR/pesign-copy-sources; then
	sed "
		s:%{name}:$RPM_PACKAGE_NAME:g
		s:%{version}:$RPM_PACKAGE_VERSION:g
	" $RPM_SOURCE_DIR/pesign-copy-sources > $output/pesign-copy-sources
	while read -r line; do
		if [ -n "${line}" ]; then
			source_files="${source_files}${RPM_SOURCE_DIR}/${line}\n"
		fi
	done < $output/pesign-copy-sources
	echo -e "$source_files" | head -c -1 | cpio -o > $output/source_files.cpio
	rm $output/pesign-copy-sources
fi


sed "
	s:@NAME@:$RPM_PACKAGE_NAME:g
	s:@PESIGN_GRUB_RESERVATION@:$pesign_grub_reservation:g
	s:@PESIGN_REPACKAGE_COMPRESS@:$pesign_repackage_compress:g
	s:@PESIGN_LOAD_SPEC_MACROS@:$spec_macros:g
	/@CERT@/ {
		r $cert
		d
	}
" /usr/lib/rpm/pesign/pesign-repackage.spec.in >"$output/pesign-repackage.spec"

for rpmlintrc in $RPM_SOURCE_DIR/*rpmlintrc; do
	if test -e "$rpmlintrc"; then
		cp "$rpmlintrc" "$output/"
	fi
done

cd "$RPM_BUILD_ROOT"
args=()
for pattern in $files; do
	pattern=${pattern#/}
	if test "${pattern:0:2}" != "./"; then
		pattern="./$pattern"
	fi
	if test -d "$pattern"; then
		pattern="$pattern/*"
	fi
	args=("${args[@]}" -o -path "$pattern")
done
# delete the leading -o
unset args[0]

archive=$output/$RPM_PACKAGE_NAME.cpio.rsasign
archive_dir=$output/$RPM_PACKAGE_NAME
mkdir -p "$archive_dir"
# create an empty nss database to make pesign happy
nss_db=$(mktemp -d)
trap 'rm -rf "$nss_db"' EXIT
echo foofoofoo > "$nss_db/passwd"
certutil -N -d "$nss_db" -f "$nss_db/passwd"

echo "Creating $archive"
files=($(find . -type f \( "${args[@]}" \)))
for f in "${files[@]}"; do
	dest="$archive_dir/$f"
	mkdir -p "${dest%/*}"
	case "$f" in
	./boot/* | *.efi | */lib/modules/*/vmlinu[xz] | */lib/modules/*/[Ii]mage | */lib/modules/*/z[Ii]mage)
		if [ -f /usr/bin/pesign ]; then
			pesign --certdir="$nss_db" -i "$f" -E $dest
		else
			# Non PE architectures like s390x
			cp "$f" "$dest"
		fi
		;;
	*)
		cp "$f" "$dest"
	esac
done
cd "$archive_dir"
find . -type f | cpio -H newc -o >"$archive"
rm -rf "$archive_dir"

