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