#!/bin/sh -e
#$Id: mkmar,v 1.1.2.8 2005/07/08 08:19:56 mouse Exp $

[ -x /usr/bin/mar ]
[ -x /usr/bin/getpciids ]

#parse command line options
TEMP=`getopt -n "$0" -o k:,o:,p:,r:,w: -l kernel:,output:,pattern:,root:,in-chroot,workdir: -- "$@"` || exit 1
eval set -- "$TEMP"

kernel=
output=
pattern=
root=
work_dir=
in_chroot=

MODLIST=

while :; do
        case "$1" in
                -k|--kernel-version)
                        shift
                        kernel="$1"
                	;;
                -o|--output)
                        shift
                        output="$1"
                	;;
                -p|--pattern*)
                        shift
                        pattern="$1"
                	;;
                -r|--root)
                        shift
                        root="$1"
                	;;
		--in-chroot)
			in_chroot=1
			;;
		-w|--workdir)
			shift
			work_dir="$1"
			;;
                --) shift; break
                	;;
                *) "Unrecognized option: $1"
                	exit 1
                	;;
        esac
	shift
done

[ -n "$output" ]
[ -n "$pattern" ]
[ -n "$root" ] || [ `id -u` -eq 0 ] || [ -n "$in_chroot" ]
[ -n "$root" ] || root="/"
[ -n "$kernel" ] || kernel=`uname -r`

if [ -n "$in_chroot" ]; then
    hsh=/usr/share/hasher/functions
    . $hsh

    root="/"
    [ -n "$work_dir" ] || Fatal 'You must pass workdir option.'
    set_workdir "$work_dir"
    check_helpers

    kernel=$(chrootuid1 /.host/find /lib/modules/ -maxdepth 1 -mindepth 1 -type d -printf "%f\n")
    modpath=/lib/modules/$kernel
fi

exit_handler()
{
    local rc=$?
    trap - EXIT
    [ -z "$MODLIST" ] || rm -f -- "$MODLIST"
    [ $rc -eq 0 ] || {
	rm -f -- "$output.mar" "$output.dep" "$output.map"
	[ -z "$in_chroot" ] || chrootuid1 /bin/rm -rf "/.modules"
    }
    exit $rc
}

trap exit_handler HUP PIPE INT TERM QUIT EXIT

root=`realpath $root`
modpath=${modpath:-$(realpath $root/lib/modules/$kernel)}
deps="$modpath/modules.dep"

modules_list()
{
    > "$output.dep"
    find $modpath/ -type f | grep -w -f $pattern | \
    while read; do
	echo $REPLY
	if grep -qw "${REPLY##*$root}: " $deps; then
	    mod="${REPLY##*/}"
	    mod="${mod%.*}"
	    echo -n "$mod:" >> "$output.dep"
	    for dep in `grep -w "${REPLY##*$root}: " $deps | sed 's|^[^:]\+:||'`; do
		dep=`realpath $root/$dep`
		echo $dep
		dep=${dep##*/}
		dep=${dep%.*}
		echo -n " $dep" >> "$output.dep"
	    done
	    echo >> "$output.dep"
	fi
    done | sort -u
}

modules_map()
{
    > "$output.map"

    mar -l "$output.mar" |sed 's|^[[:space:]]\+\([^\.]\+\)\.ko|\1|g' > "$MODLIST"
    getpciids -f "$MODLIST" |\
    while read vendor device subv subd module; do
	[ -n "$module" ] || module="$subv"
	echo $module $vendor $device
    done |sort -u |while read module vendor device; do
	printf '0x%s 0x%s %s\n' $vendor $device $module >> "$output.map"
    done
}

export TMPDIR=/tmp
MODLIST=`mktemp -t modlist.XXXXXXXXXX`

if [ -n "$in_chroot" ]; then
    cp -a /usr/bin/mar $chroot/.host/mar
    create_entry_fakeroot_header
    cat >>"$entry" <<__EOF__
rm -rf /.modules
mkdir -p /.modules
output=/.modules/modules
pattern=/.host/modules

modules_list()
{
    > "\$output.dep"
    find $modpath/ -type f | grep -w -f \$pattern | \\
    while read; do
	echo \$REPLY
	if grep -qw "\${REPLY##*$root}: " $deps; then
	    mod="\${REPLY##*/}"
	    mod="\${mod%.*}"
	    echo -n "\$mod:" >> "\$output.dep"
	    for dep in \$(grep -w "\${REPLY##*$root}: " $deps | sed 's|^[^:]\+:||'); do
		dep=\$(realpath $root/\$dep)
		echo \$dep
		dep=\${dep##*/}
		dep=\${dep%.*}
		echo -n " \$dep" >> "\$output.dep"
	    done
	    echo >> "\$output.dep"
	fi
    done | sort -u
}
/.host/mar -c "/.modules/modules.mar" \$(modules_list)
__EOF__
    chrootuid1 || Fatal 'Could not create mar archive.'
    rm -f $entry
    cp -a $chroot/.modules/modules.mar $output.mar || exit 1
    cp -a $chroot/.modules/modules.dep $output.dep || exit 1
    chrootuid1 /bin/rm -rf /.modules
else
    mar -c "$output.mar" `modules_list`
fi
modules_map
