Michal Marek d1acfa
#! /bin/bash
Michal Marek d1acfa
Michal Marek 0a417c
#############################################################################
Michal Marek 0a417c
# Copyright (c) 2006-2009 Novell, Inc.
Michal Marek 0a417c
# All Rights Reserved.
Michal Marek 0a417c
#
Michal Marek 0a417c
# This program is free software; you can redistribute it and/or
Michal Marek 0a417c
# modify it under the terms of version 2 of the GNU General Public License as
Michal Marek 0a417c
# published by the Free Software Foundation.
Michal Marek 0a417c
#
Michal Marek 0a417c
# This program is distributed in the hope that it will be useful,
Michal Marek 0a417c
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Michal Marek 0a417c
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
Michal Marek 0a417c
# GNU General Public License for more details.
Michal Marek 0a417c
#
Michal Marek 0a417c
# You should have received a copy of the GNU General Public License
Michal Marek 0a417c
# along with this program; if not, contact Novell, Inc.
Michal Marek 0a417c
#
Michal Marek 0a417c
# To contact Novell about this file by physical or electronic mail,
Michal Marek 0a417c
# you may find current contact information at www.novell.com
Michal Marek 0a417c
#############################################################################
Michal Marek 0a417c
Michal Marek d1acfa
usage() {
Michal Marek d1acfa
    echo "USAGE: ${0##*/} [--(no-)symvers|--(no-)symsets|--(no-)symtypes] [--filter <filter>] rpm ..."
Michal Marek d1acfa
    echo -n "The default is"
Michal Marek d1acfa
    $do_symvers  && echo -n " --symvers"  || echo -n " --no-symvers"
Michal Marek d1acfa
    $do_symsets  && echo -n " --symsets"  || echo -n " --no-symsets"
Michal Marek d1acfa
    $do_symtypes && echo -n " --symtypes" || echo -n " --no-symtypes"
Michal Marek d1acfa
    echo
Michal Marek d1acfa
}
Michal Marek d1acfa
Michal Marek d1acfa
symsets_are_equal() {
Michal Marek d1acfa
    local a=$1 b=$2
Michal Marek d1acfa
Michal Marek d1acfa
    cmp -s <(tar tfz $a | sed -e 's:.*/::' | sort) \
Michal Marek d1acfa
	   <(tar tfz $b | sed -e 's:.*/::' | sort)
Michal Marek d1acfa
}
Michal Marek d1acfa
Michal Marek d1acfa
filters2re() {
Michal Marek 992a92
    local f tail res sep
Michal Marek d1acfa
Michal Marek 772cbc
    if test -z "$tail"; then
Michal Marek 772cbc
        tail='/[^/]*$'
Michal Marek 772cbc
    fi
Michal Marek d1acfa
    for f in "$@"; do
Michal Marek 992a92
        case "$f" in
Michal Marek 992a92
        *\*)
Michal Marek 992a92
            f="${f%\*}"
Michal Marek 992a92
            f="^\.?$f"
Michal Marek 992a92
            ;;
Michal Marek 992a92
        *)
Michal Marek 992a92
            f="^\.?$f$tail"
Michal Marek 992a92
        esac
Michal Marek 992a92
        res="$res$sep$f"
Michal Marek 992a92
        sep="|"
Michal Marek d1acfa
    done
Michal Marek d1acfa
    echo "$res"
Michal Marek d1acfa
}
Michal Marek d1acfa
Michal Marek d1acfa
merge_dirs() {
Michal Marek d1acfa
    local old=$1 new=$2
Michal Marek d1acfa
Michal Marek d1acfa
    find "$old" "$new" -type f -printf '%P\n' | sort -u \
Michal Marek d1acfa
	>"$tmpdir/all"
Michal Marek d1acfa
    while read f; do
Michal Marek d1acfa
	if cmp -s "$old/$f" "$new/$f"; then
Michal Marek d1acfa
	    continue
Michal Marek d1acfa
	fi
Michal Marek d1acfa
	if ! echo "$f" | grep -Eq "$re"; then
Michal Marek d1acfa
	    continue
Michal Marek d1acfa
	fi
Michal Marek d1acfa
	if test -e "$new/$f"; then
Michal Marek d1acfa
	    cp "$new/$f" "$old/$f"
Michal Marek d1acfa
	    echo "$f added to $target"
Michal Marek d1acfa
	else
Michal Marek d1acfa
	    rm "$old/$f"
Michal Marek d1acfa
	    echo "$f removed from $target"
Michal Marek d1acfa
	fi
Michal Marek d1acfa
    done <"$tmpdir/all"
Michal Marek d1acfa
}
Michal Marek d1acfa
Michal Marek d1acfa
add_symsets() {
Michal Marek d1acfa
    set -- $tmpdir/boot/symsets-*
Michal Marek d1acfa
    if [ $# -eq 0 ]; then
Michal Marek d1acfa
	echo "No symsets file found in $rpm" >&2
Michal Marek d1acfa
	status=1
Michal Marek d1acfa
	return
Michal Marek d1acfa
    fi
Michal Marek d1acfa
Michal Marek 42990c
    local re=$(tail='\.[0-9a-f]*(\.fake)?$' filters2re "${filters[@]//\//_}")
Michal Marek d1acfa
Michal Marek d1acfa
    for symsets in "$@"; do
Michal Marek d1acfa
	flavor=${symsets%.tar.gz}
Michal Marek d1acfa
	flavor=${flavor##*-}
Michal Marek d1acfa
Michal Marek d1acfa
	target=kabi/$arch/symsets-$flavor.tar.gz
Michal Marek d1acfa
	if [ -e $target ] && symsets_are_equal "$symsets" $target; then
Michal Marek d1acfa
	    echo "$target is unchanged"
Michal Marek d1acfa
	    continue
Michal Marek d1acfa
	fi
Michal Marek d1acfa
	if $opt_dry_run; then
Michal Marek d1acfa
	    echo "$target added"
Michal Marek d1acfa
	    continue
Michal Marek d1acfa
	fi
Michal Marek d1acfa
	mkdir -p ${target%/*}
Michal Marek d1acfa
	if test -z "${filters[*]}"; then
Michal Marek d1acfa
	    cp "$symsets" $target
Michal Marek d1acfa
	else
Michal Marek d1acfa
	    rm -rf "$tmpdir/symsets"
Michal Marek d1acfa
	    mkdir "$tmpdir/symsets"
Michal Marek d1acfa
	    tar xzf "$target" -C "$tmpdir/symsets"
Michal Marek d1acfa
	    old=$(echo "$tmpdir/symsets"/*)
Michal Marek d1acfa
	    mkdir "$tmpdir/symsets/new"
Michal Marek d1acfa
	    tar xzf "$symsets" -C "$tmpdir/symsets/new" --strip-components=1
Michal Marek d1acfa
	    new="$tmpdir/symsets/new"
Michal Marek d1acfa
	    merge_dirs "$old" "$new"
Michal Marek d1acfa
	    tar czf "$target" -C "$tmpdir/symsets" "${old##*/}"
Michal Marek d1acfa
	fi
Michal Marek d1acfa
	echo "$target added"
Michal Marek d1acfa
    done
Michal Marek d1acfa
}
Michal Marek d1acfa
Michal Marek d1acfa
unpack_symtypes() {
Michal Marek d1acfa
    local dir="$1"
Michal Marek d1acfa
Michal Marek d1acfa
    rpm/modversions --unpack "$dir"
Michal Marek d1acfa
}
Michal Marek d1acfa
Michal Marek d1acfa
pack_symtypes() {
Michal Marek d1acfa
    local dir="$1"
Michal Marek d1acfa
Michal Marek d1acfa
    rpm/modversions --pack --ext .symref "$dir"
Michal Marek d1acfa
}
Michal Marek d1acfa
Michal Marek d1acfa
unpack_symvers() {
Michal Marek d1acfa
    local dir="$1" csum sym mod rest last=
Michal Marek d1acfa
    mkdir -p "$dir"
Michal Marek d1acfa
Michal Marek d1acfa
    sort -k 3 | while read csum sym mod rest; do
Michal Marek d1acfa
	    if test "$last" != "$mod"; then
Michal Marek d1acfa
		    mkdir -p "$dir/${mod%/*}"
Michal Marek d1acfa
		    exec 3>"$dir/$mod.symvers"
Michal Marek d1acfa
		    last=$mod
Michal Marek d1acfa
	    fi
Michal Marek d1acfa
	    echo -ne "$csum\\t$sym\\t$mod" >&3
Michal Marek d1acfa
	    if test -n "$rest"; then
Michal Marek d1acfa
		    echo -ne "\\t$rest" >&3
Michal Marek d1acfa
	    fi
Michal Marek d1acfa
	    echo >&3
Michal Marek d1acfa
    done
Michal Marek d1acfa
    exec 3>&-
Michal Marek d1acfa
}
Michal Marek d1acfa
Michal Marek d1acfa
pack_symvers() {
Michal Marek d1acfa
    local dir="$1"
Michal Marek d1acfa
Michal Marek d1acfa
    find "$dir" -type f | xargs cat | sort -k 2
Michal Marek d1acfa
}
Michal Marek d1acfa
Michal Marek d1acfa
add_flat_files() {
Michal Marek d1acfa
    local type=$1
Michal Marek d1acfa
Michal Marek 5479af
    set -- $tmpdir/boot/$type-*.gz
Michal Marek 5479af
    if [ $# -eq 0 ]; then
Michal Marek 5479af
        set -- $tmpdir/usr/src/linux-*-obj/*/*/Module.$type
Michal Marek 5479af
    fi
Michal Marek d1acfa
    if [ $# -eq 0 ]; then
Michal Marek d1acfa
	echo "No $type file found in $rpm" >&2
Michal Marek d1acfa
	status=1
Michal Marek d1acfa
	return
Michal Marek d1acfa
    fi
Michal Marek d1acfa
    local file flavor target
Michal Marek d1acfa
    local re=$(filters2re "${filters[@]}")
Michal Marek d1acfa
Michal Marek d1acfa
    for file; do
Michal Marek e9d724
        case "$file" in
Michal Marek e9d724
        *.gz)
Michal Marek e9d724
            gzip -cd "$file" > "${file%.gz}"
Michal Marek e9d724
            file=${file%.gz}
Michal Marek e9d724
            ;;
Michal Marek e9d724
        esac
Michal Marek e9d724
        case "$file" in
Michal Marek e9d724
        $tmpdir/boot/*)
Michal Marek e9d724
            flavor=${file##*-}
Michal Marek e9d724
            ;;
Michal Marek e9d724
        $tmpdir/usr/src/*/Module.symvers)
Michal Marek e9d724
            flavor=${file##*-obj/}
Michal Marek e9d724
            flavor=${flavor#*/}
Michal Marek e9d724
            flavor=${flavor%/Module.symvers}
Michal Marek e9d724
            ;;
Michal Marek e9d724
        esac
Michal Marek d1acfa
Michal Marek d1acfa
	target=kabi/$arch/$type-$flavor
Michal Marek d1acfa
	if cmp -s "$file" "$target"; then
Michal Marek d1acfa
	    echo "$target is unchanged"
Michal Marek d1acfa
	    continue
Michal Marek d1acfa
	fi
Michal Marek d1acfa
	if $opt_dry_run; then
Michal Marek d1acfa
	    echo "$target added"
Michal Marek d1acfa
	    continue
Michal Marek d1acfa
	fi
Michal Marek d1acfa
	mkdir -p "${target%/*}"
Michal Marek d1acfa
	if test -z "${filters[*]}"; then
Michal Marek d1acfa
	    cp "$file" "$target"
Michal Marek d1acfa
	else
Michal Marek d1acfa
	    rm -rf "$tmpdir/$type"
Michal Marek d1acfa
	    mkdir -p "$tmpdir/$type"/{old,new}
Michal Marek d1acfa
	    old="$tmpdir/$type/old"
Michal Marek d1acfa
	    new="$tmpdir/$type/new"
Michal Marek d1acfa
	    unpack_$type "$old" <"$target" &
Michal Marek d1acfa
	    unpack_$type "$new" <"$file" &
Michal Marek d1acfa
	    wait
Michal Marek d1acfa
	    merge_dirs "$old" "$new"
Michal Marek d1acfa
	    pack_$type "$old" >"$target"
Michal Marek d1acfa
	fi
Michal Marek d1acfa
	echo "$target added"
Michal Marek d1acfa
    done
Michal Marek d1acfa
}
Michal Marek d1acfa
Michal Marek 2f6c0d
unpack_iso()
Michal Marek 2f6c0d
{
Michal Marek 2f6c0d
    local iso=$1 file name
Michal Marek 2f6c0d
Michal Marek 0745e5
    isoinfo -R -f -i "$iso" | grep -E '/kernel-[^/]*-([2-9]|[1-9][0-9]+)\.[0-9][^/]*\.rpm$' |
Michal Marek 2f6c0d
    while read file; do
Michal Marek 2f6c0d
        name=${file##*/}
Michal Marek 2f6c0d
        case "$name" in
Michal Marek 2f6c0d
        kernel-source-* | kernel-syms-* | kernel-*-debug* | kernel-*-man-*| \
Michal Marek 2f6c0d
        kernel-firmware-* | kernel-coverage-* | kernel-docs-* | \
Michal Marek 2f6c0d
        kernel-*-extra* | *src.rpm)
Michal Marek 2f6c0d
            continue
Michal Marek 2f6c0d
        esac
Michal Marek 2f6c0d
        isoinfo -R -i "$iso" -x "$file" >"$tmpdir/$name"
Michal Marek 2f6c0d
        echo "$tmpdir/$name"
Michal Marek 2f6c0d
    done
Michal Marek 2f6c0d
}
Michal Marek 2f6c0d
Michal Marek 2f6c0d
query_rpm()
Michal Marek 2f6c0d
{
Michal Marek 2f6c0d
    local rpm=$1
Michal Marek 2f6c0d
Michal Marek 2f6c0d
    exec 3< <(rpm -qp --qf '%{NAME}\n%{ARCH}\n%{VERSION}\n%{RELEASE}' "$rpm")
Michal Marek 2f6c0d
    read name <&3
Michal Marek 2f6c0d
    read arch <&3
Michal Marek 2f6c0d
    read version <&3
Michal Marek 2f6c0d
    read release <&3
Michal Marek 2f6c0d
    exec 3<&-
Michal Marek 2f6c0d
}
Michal Marek d1acfa
Michal Marek bf19c3
. rpm/config.sh
Michal Marek bf19c3
case "$IBS_PROJECT" in
Michal Marek bf19c3
SUSE:SLE-9*)
Michal Marek d1acfa
    do_symvers=true
Michal Marek d1acfa
    do_symsets=false
Michal Marek d1acfa
    do_symtypes=false
Michal Marek d1acfa
    ;;
Michal Marek bf19c3
SUSE:SLE-10-SP[012]*)
Michal Marek d1acfa
    do_symvers=true
Michal Marek d1acfa
    do_symsets=true
Michal Marek d1acfa
    do_symtypes=false
Michal Marek d1acfa
    ;;
Michal Marek bf19c3
SUSE:SLE-10* | SUSE:SLE-11*)
Michal Marek d1acfa
    do_symvers=true
Michal Marek d1acfa
    do_symsets=true
Michal Marek d1acfa
    do_symtypes=true
Michal Marek d1acfa
    ;;
Michal Marek d1acfa
*)
Michal Marek d1acfa
    do_symvers=true
Michal Marek d1acfa
    do_symsets=false
Michal Marek d1acfa
    do_symtypes=true
Michal Marek d1acfa
    ;;
Michal Marek d1acfa
esac
Michal Marek d1acfa
Michal Suchanek 2ea024
options="$(getopt -o h --long symvers,no-symvers,symsets,no-symsets,symtypes,no-symtypes,dry-run,filter:,help -- "$@")"
Michal Marek d1acfa
if [ $? -ne 0 ]; then
Michal Marek d1acfa
    usage >&2
Michal Marek d1acfa
    exit 1
Michal Marek d1acfa
fi
Michal Marek d1acfa
eval set -- "$options"
Michal Marek d1acfa
Michal Marek d1acfa
opt_dry_run=false
Michal Marek d1acfa
filters=()
Michal Marek d1acfa
while :; do
Michal Marek d1acfa
    arg=$1
Michal Marek d1acfa
    shift
Michal Marek d1acfa
    newval=true
Michal Marek d1acfa
    case "$arg" in
Michal Marek d1acfa
	--no-*)
Michal Marek d1acfa
	    newval=false
Michal Marek d1acfa
	    arg=${arg/--no-/--}
Michal Marek d1acfa
    esac
Michal Marek d1acfa
    case "$arg" in
Michal Marek d1acfa
	--symvers)
Michal Marek d1acfa
            do_symvers=$newval
Michal Marek d1acfa
	    ;;
Michal Marek d1acfa
	--symsets)
Michal Marek d1acfa
            do_symsets=$newval
Michal Marek d1acfa
	    ;;
Michal Marek d1acfa
	--symtypes)
Michal Marek d1acfa
            do_symtypes=$newval
Michal Marek d1acfa
	    ;;
Michal Marek d1acfa
	--dry-run)
Michal Marek d1acfa
	    opt_dry_run=true
Michal Marek d1acfa
	    ;;
Michal Marek d1acfa
	--filter)
Michal Marek 772cbc
	    filters[${#filters[@]}]=${1%/}
Michal Marek d1acfa
	    shift
Michal Marek d1acfa
	    ;;
Michal Marek d1acfa
	-h|--help)
Michal Marek d1acfa
	    usage
Michal Marek d1acfa
	    exit 0
Michal Marek d1acfa
	    ;;
Michal Marek d1acfa
	--)
Michal Marek d1acfa
	    break;
Michal Marek d1acfa
    esac
Michal Marek d1acfa
done
Michal Marek d1acfa
Michal Marek d1acfa
if [ $# -eq 0 ]; then
Michal Marek d1acfa
    usage >&2
Michal Marek d1acfa
    exit 1
Michal Marek d1acfa
fi
Michal Marek d1acfa
Michal Marek d1acfa
tmpdir=$(mktemp -td ${0##*/}.XXXXXX)
Michal Marek d1acfa
trap "rm -rf $tmpdir" EXIT
Michal Marek d1acfa
Michal Marek d1acfa
shopt -s nullglob
Michal Marek d1acfa
Michal Marek d1acfa
echo "Packages to process:"
Michal Marek d1acfa
unset ${!found_rmps_*}
Michal Marek 2f6c0d
while test $# -gt 0; do
Michal Marek 2f6c0d
    rpm=$1
Michal Marek 2f6c0d
    shift
Michal Marek d1acfa
    case "$rpm" in
Michal Marek d1acfa
	*.src.rpm | *.nosrc.rpm | *.noarch.rpm | *.delta.rpm)
Michal Marek d1acfa
	    continue
Michal Marek d1acfa
	    ;;
Michal Marek 2f6c0d
        *.iso)
Michal Marek 2f6c0d
            set -- $(unpack_iso "$rpm") "$@"
Michal Marek 2f6c0d
            continue
Michal Marek 2f6c0d
            ;;
Michal Marek d1acfa
    esac
Michal Marek d1acfa
Michal Marek d1acfa
    # There may be symlinks as well as regular files. Skip duplicates.
Michal Marek d1acfa
    for file in "${rpms[@]}"; do
Michal Marek d1acfa
	[ "$rpm" -ef "$file" ] && continue 2
Michal Marek d1acfa
    done
Michal Marek d1acfa
Michal Marek 2f6c0d
    query_rpm "$rpm"
Michal Marek 2f6c0d
    var=found_rmps_${arch}_${name//-/_}
Michal Marek d1acfa
    eval "$var=\"\$$var $rpm\""
Michal Marek d1acfa
Michal Marek d1acfa
    rpms[${#rpms[@]}]=$rpm
Michal Marek d1acfa
done
Michal Marek d1acfa
for rpm in ${!found_rmps_*}; do
Michal Marek d1acfa
    set -- ${!rpm}
Michal Marek d1acfa
    if [ $# -ne 1 ]; then
Michal Marek d1acfa
	echo "*** Duplicate: ${*##*/}" >&2
Michal Marek d1acfa
	failed=1
Michal Marek d1acfa
    fi
Michal Marek d1acfa
done
Michal Marek d1acfa
[ -z "$failed" ] || exit 1
Michal Marek d1acfa
for rpm in ${!found_rmps_*}; do
Michal Marek d1acfa
    set -- ${!rpm}
Michal Marek d1acfa
    echo ${1##*/}
Michal Marek d1acfa
done
Michal Marek d1acfa
echo
Michal Marek d1acfa
Michal Marek d1acfa
archs_flavors="$(scripts/guards --list < config.conf)"
Michal Marek d1acfa
for rpm in "${rpms[@]}"; do
Michal Marek 2f6c0d
    query_rpm "$rpm"
Michal Marek d1acfa
Michal Marek d1acfa
    # skip the main package if there is a base subpackage
Michal Marek d1acfa
    base=found_rmps_${arch}_${name//-/_}_base
Michal Marek d1acfa
    if [ -n "${!base}" ]; then
Michal Marek d1acfa
	continue
Michal Marek d1acfa
    fi
Michal Marek e9d724
    # ... and skip both if there is a -devel subpackage
Michal Marek e9d724
    devel=found_rmps_${arch}_${name//-/_}
Michal Marek e9d724
    devel=${devel%_base}_devel
Michal Marek e9d724
    if [ -n "${!devel}" ]; then
Michal Marek e9d724
        continue
Michal Marek e9d724
    fi
Michal Marek d1acfa
Michal Marek d1acfa
    build_arch=$arch
Michal Marek d1acfa
    case "$arch" in
Michal Marek d1acfa
	i?86)
Michal Marek d1acfa
	    arch=i386 ;;
Michal Marek d1acfa
	s390*)
Michal Marek bf19c3
            case "$IBS_PROJECT" in
Michal Marek 0ae102
            SUSE:SLE-9* | SUSE:SLE-10* | SUSE:SLE-11:*)
Michal Marek 5ad27c
                arch=s390 ;;
Michal Marek 5ad27c
            esac
Michal Marek 5ad27c
            ;;
Michal Marek c75894
        ppc*)
Michal Marek bf19c3
            case "$IBS_PROJECT" in
Michal Marek bf19c3
            SUSE:SLE-10*)
Michal Marek c75894
                arch=powerpc ;;
Michal Marek c75894
            esac
Michal Marek c75894
            ;;
Michal Marek e5ba6b
        aarch64)
Michal Marek e5ba6b
            arch=arm64
Michal Marek e5ba6b
            ;;
Michal Marek d1acfa
    esac
Michal Marek d1acfa
    flavor=${name#kernel-}
Michal Marek d1acfa
    flavor=${flavor%-base}
Michal Marek e9d724
    flavor=${flavor%-devel}
Michal Marek d1acfa
Michal Marek d1acfa
    if ! echo "$archs_flavors" | grep -q "$arch/$flavor"; then
Michal Marek d1acfa
	case "$flavor" in
Michal Marek d1acfa
	source | syms | *-extra)
Michal Marek d1acfa
	    ;;
Michal Marek d1acfa
	*)
Michal Marek d1acfa
	    echo "${rpm%%*/}: not a known arch/flavor; skipping" >&2
Michal Marek d1acfa
	    ;;
Michal Marek d1acfa
	esac
Michal Marek d1acfa
	continue
Michal Marek d1acfa
    fi
Michal Marek d1acfa
Michal Marek d1acfa
    echo "[$name-$version-$release.$build_arch.rpm]"
Michal Marek d1acfa
Michal Marek 5479af
    rm -rf $tmpdir/{boot,usr}
Michal Marek d1acfa
    rpm2cpio "$rpm" \
Michal Marek d1acfa
    | ( cd $tmpdir && cpio -dim --quiet './boot/symvers-*' './boot/symsets-*' \
Michal Marek e9d724
        './boot/symtypes-*' './usr/src/linux-*-obj/*/*/Module.symvers' )
Michal Marek d1acfa
Michal Marek d1acfa
    if $do_symvers; then
Michal Marek d1acfa
	add_flat_files symvers
Michal Marek d1acfa
    fi
Michal Marek d1acfa
    if $do_symtypes; then
Michal Marek d1acfa
	add_flat_files symtypes
Michal Marek d1acfa
    fi
Michal Marek d1acfa
    if $do_symsets; then
Michal Marek d1acfa
	add_symsets
Michal Marek d1acfa
    fi
Michal Marek d1acfa
done
Michal Marek d1acfa
Michal Marek d1acfa
exit $status
Michal Marek d1acfa
Michal Marek d1acfa
# vim:sw=4 et