#!/bin/bash
# Script to build a package.  It uses init_buildsystem to setup a chroot
# building tree.  This script needs a directory as parameter.  This directory
# has to include sources and a spec file.
#
# BUILD_ROOT        here the packages will be built
#
# (c) 1997-2008 SuSE GmbH Nuernberg, Germany

test -z "$BUILD_DIR" && BUILD_DIR=/usr/lib/build
test -z "$BUILD_ROOT" && BUILD_ROOT=/var/tmp/build-root

export BUILD_ARCH BUILD_ROOT BUILD_RPMS BUILD_DIR

ccache=0
icecream=0
definesnstuff=()
repos=()

# mkreiserfs only works with qemu/uml if it is able to create a file
# system that is owned by the calling user (bnc#369006)
#xen_img_mkfs='mkreiserfs -q -f'
#xen_img_mkfs='mkfs.ext2 -m 0 -q -F'
xen_img_mkfs='mkfs.ext3 -m 0 -q -F'
qemu_kernel=/boot/vmlinuz
qemu_initrd=/boot/initrd
qemu_bin=/usr/bin/qemu
uml_kernel=/boot/vmlinux-um
uml_initrd=/boot/initrd-um

kvm_kernel=/boot/vmlinuz
kvm_initrd=/boot/initrd
kvm_bin=/usr/bin/qemu-kvm
mkinitrd_virtio_cmd=(env rootfstype=ext3 mkinitrd -d /dev/null -m "virtio_pci virtio_blk" -k $kvm_kernel -i $kvm_initrd-virtio)
# whether we have virtio support
kvm_virtio=

DO_INIT=true
DO_LINT=
DO_CHECKS=true
CLEAN_BUILD=
SPECFILES=()
SRCDIR=
BUILD_JOBS=
ABUILD_TARGET_ARCH=
CREATE_BASELIBS=
USEUSEDFORBUILD=
LIST_STATE=
VM_IMAGE=
VM_SWAP=
MEMSIZE=
RUNNING_IN_VM=
RPMLIST=
RELEASE=
REASON=
NOROOTFORBUILD=
LOGFILE=
KILL=
CHANGELOG=
BUILD_DEBUG=
PERSONALITY_SYSCALL=
INCARNATION=
DISTURL=

export PATH=$BUILD_DIR:$PATH

# This is for insserv
export YAST_IS_RUNNING=instsys

unset LANGUAGE
unset LANG
export LC_ALL=POSIX
umask 022

echo_help () {
    cat << EOT

Some comments for build
-----------------------

With build you can create rpm packages.  They will be built in a chroot
system.  This chroot system will be setup automatically.  Normally you can
simply call build with a spec file as parameter - nothing else has to be
set.

If you want to set the directory were the chroot system will be setup
(at the moment it uses $BUILD_ROOT),
simply set the the environment variable BUILD_ROOT.

Example:

  export BUILD_ROOT=/var/tmp/mybuildroot


Normally build builds the complete package including src.rpm (rpmbuild -ba).
If you want let build only make the binary package, simply set

   export BUILD_RPM_BUILD_STAGE=-bb

(or -bc, -bp, -bi, ...  see "Maximum RPM" for more details [*]).

When the build command succeeds, the rpm files can be found under
$BUILD_ROOT/usr/src/packages/RPMS/


Known Parameters:

  --help      You already got it :)

  --clean     Delete old build root before initializing it

  --no-init   Skip initialization of build root and start with build
              immediately.

  --no-checks Do not run post-build checks

  --rpms path1:path2:...
              Specify path where to find the RPMs for the build system

  --arch arch1:arch2:...
              Specify what architectures to select from the RPMs

  --useusedforbuild
              Do not expand dependencies but search the specfile for
              usedforbuild lines.

  --verify    Run verify when initializing the build root

  --extra-packs pack
              Also install package 'pack'

  --root rootdir
              Use 'rootdir' to setup chroot environment

  --oldpackages oldpackagesdir
              Define a directory with a former build

  --baselibs  Create -32bit/-64bit/-x86 rpms for other architectures

  --list-state
              List rpms that would be used to create a fresh build root.
              Does not create the build root or perform a build.

  --with X
              enable feature X for build

  --without X
              disable feature X for build

  --define 'X Y'
              define macro X with value Y

  --ccache
              use ccache to speed up rebuilds

  --icecream N
              use N parallel build jobs with icecream

  --debug
              enable creation of a debuginfo package

Remember to have fun!

[*] Maximum RPM: http://www.rpm.org/max-rpm/
EOT
}
usage () {
    echo "Usage: `basename $0` [--no-init|--clean|--rpms path|--verify|--help] [dir-to-build|spec-to-build]"
    cleanup_and_exit 1
}

#
#  cleanup_and_exit
#  return values: 0 -> success, new packages built
#                 1 -> error, build failed
#                 2 -> successfull build, but no changes to former built packages
#
cleanup_and_exit () {
    trap EXIT
    test -z "$1" && set 0
    if test -n "$RUNNING_IN_VM" ; then
	cd /
	if test -n "$VM_SWAP" -a -e "$VM_SWAP" ; then
	    swapoff "$VM_SWAP" 2>/dev/null
	    echo -n "BUILDSTATUS$1" >"$VM_SWAP"
	fi
	exec >&0 2>&0	# so that the logging tee finishes
	sleep 1		# wait till tee terminates
	kill -9 -1	# goodbye cruel world
	exec /bin/bash -c 'mount -n -o remount,ro / ; halt -f -p'
	halt -f -p
    else
	umount -n $BUILD_ROOT/proc 2>/dev/null || true
	umount -n $BUILD_ROOT/dev/pts 2>/dev/null || true
	test "$VM_IMAGE" = 1 && VM_IMAGE=
	[ -n "$VM_IMAGE" ] && umount $BUILD_ROOT 2>/dev/null || true
    fi
    exit $1
}

fail_exit()
{
  cleanup_and_exit 1
}

shellquote()
{
    for arg; do
	arg=${arg/\\/\\\\}
	arg=${arg/\$/\\\$}
	arg=${arg/\"/\\\"}
	arg=${arg/\`/\\\`}
	echo -n " \"$arg\""
    done
}

# create a shell script from command line. Used for preserving arguments
# through /bin/su -c
toshellscript()
{
	echo "#!/bin/sh -x"
	echo -n exec
	shellquote "$@"
	echo
}

setupccache()
{
    if [ "$ccache" = 1 ]; then
	if mkdir -p $BUILD_ROOT/var/lib/build/ccache/bin; then
	    for i in gcc g++ cc c++; do
#		ln -sf /usr/bin/ccache $BUILD_ROOT/var/lib/build/ccache/bin/$i
		rm -f $BUILD_ROOT/var/lib/build/ccache/bin/$i
		test -e $BUILD_ROOT/usr/bin/$i || continue
		echo '#! /bin/sh' > $BUILD_ROOT/var/lib/build/ccache/bin/$i
		echo "test -e /usr/bin/$i || exit 1" > $BUILD_ROOT/var/lib/build/ccache/bin/$i
	        echo 'export PATH=/opt/icecream/bin:/usr/bin:$PATH' >> $BUILD_ROOT/var/lib/build/ccache/bin/$i
		echo "ccache $i \"\$@\"" >> $BUILD_ROOT/var/lib/build/ccache/bin/$i
		chmod 755 $BUILD_ROOT/var/lib/build/ccache/bin/$i
		echo "Installed ccache wrapper as $BUILD_ROOT/var/lib/build/ccache/bin/$i"
	    done
	fi
	mkdir -p "$BUILD_ROOT"/.ccache
	chroot "$BUILD_ROOT" chown -R "$BUILD_USER" "/.ccache"
	echo "export CCACHE_DIR=/.ccache" > "$BUILD_ROOT"/etc/profile.d/build_ccache.sh
	echo 'export PATH=/var/lib/build/ccache/bin:$PATH' >> "$BUILD_ROOT"/etc/profile.d/build_ccache.sh
    else
	rm -f "$BUILD_ROOT$builduserhome"/bin/{gcc,g++,cc,c++}
	rm -f "$BUILD_ROOT"/var/lib/build/ccache/bin/{gcc,g++,cc,c++}
    fi
}

setupicecream()
{
    if [ "$icecream" -eq 0 ]; then
	rm -rf "$BUILD_ROOT"/var/run/icecream
	rm -f "$BUILD_ROOT"/etc/profile.d/build_icecream.sh
	return
    fi

    if ! chroot "$BUILD_ROOT" rpm -q icecream >/dev/null 2>/dev/null; then
	echo "*** icecream package not installed ***"
	false
	return
    fi

    echo "using icecream with $icecream jobs"

    if [ "$ccache" -ne 1 ]; then
	echo 'export PATH=/opt/icecream/bin:$PATH' > "$BUILD_ROOT"/etc/profile.d/build_icecream.sh
    else
	echo 'export CCACHE_PATH=/opt/icecream/bin' > "$BUILD_ROOT"/etc/profile.d/build_icecream.sh
    fi

    local icecc_vers=(`shopt -s nullglob; echo $BUILD_ROOT/var/run/icecream/*.tar.{bz2,gz}`)
    icecc_vers=${icecc_vers//$BUILD_ROOT/}

    # XXX use changelog like autobuild does instead?
    # only run create-env if compiler or glibc changed
    if [ -z "$icecc_vers" \
	-o ! -e "$BUILD_ROOT/$icecc_vers" \
	-o "$BUILD_ROOT/usr/bin/gcc" -nt "$BUILD_ROOT/$icecc_vers" \
	-o "$BUILD_ROOT/usr/bin/g++" -nt "$BUILD_ROOT/$icecc_vers" \
	-o "$BUILD_ROOT/usr/bin/as" -nt "$BUILD_ROOT/$icecc_vers" \
	-o "$BUILD_ROOT/lib/libc.so.6" -nt "$BUILD_ROOT/$icecc_vers" ]
    then
	rm -rf $BUILD_ROOT/var/run/icecream
	mkdir -p $BUILD_ROOT/var/run/icecream
	if [ -e "$BUILD_ROOT"/usr/bin/create-env ]; then
	  createenv=/usr/bin/create-env
	elif [ -e "$BUILD_ROOT"/usr/lib/icecc/icecc-create-env ]; then
	  createenv="/usr/lib/icecc/icecc-create-env /usr/bin/gcc /usr/bin/g++" # XXX
	else
	  echo "create-env not found"
	  false
	  return
	fi
	chroot $BUILD_ROOT bash -c "cd /var/run/icecream; $createenv"
	icecc_vers=(`shopt -s nullglob; echo $BUILD_ROOT/var/run/icecream/*.tar.{bz2,gz}`)
	icecc_vers=${icecc_vers//$BUILD_ROOT/}
    else
	echo "reusing existing icecream environment $icecc_vers"
    fi
    if [ -n "$icecc_vers" ]; then
      echo "export ICECC_VERSION=$icecc_vers" >> "$BUILD_ROOT"/etc/profile.d/build_icecream.sh
    fi
}

setmemorylimit()
{
    if [ -n "$VM_IMAGE" -o -n "$RUNNING_IN_VM" ]; then
	return
    fi
    local mem
    while read mem; do
	case "$mem" in
	    MemTotal:*)
		set -- $mem
                eval "mem=\$(($2/3*4))"
		ulimit -v $mem
		echo "Memory limit set to ${mem}KB"
		break;
	    ;;
	esac
    done < <(cat /proc/meminfo) # cat for proc stuff
}

function create_baselibs {
    echo "... creating baselibs"
    BRPMS=
    for RPM in $BUILD_ROOT$TOPDIR/RPMS/*/*.rpm ; do
        BRPMS="$BRPMS ${RPM#$BUILD_ROOT}"
    done
    BASELIBS_CFG=
    if test -e $BUILD_ROOT$TOPDIR/SOURCES/baselibs.conf ; then
	BASELIBS_CFG="-c $TOPDIR/SOURCES/baselibs.conf"
    fi
    if test -f $BUILD_ROOT/usr/lib/build/mkbaselibs ; then
	if test -z "$BASELIBS_CFG" -a -e $BUILD_ROOT/usr/lib/build/baselibs.conf ; then
	    BASELIBS_CFG="-c /usr/lib/build/baselibs.conf"
	fi
	chroot $BUILD_ROOT /usr/lib/build/mkbaselibs -c /usr/lib/build/baselibs_global.conf $BASELIBS_CFG $BRPMS || cleanup_and_exit 1
    else
	# use external version
	rm -rf $BUILD_ROOT/.mkbaselibs
	mkdir -p $BUILD_ROOT/.mkbaselibs
	cp -f $BUILD_DIR/mkbaselibs $BUILD_ROOT/.mkbaselibs
	cp -f $BUILD_DIR/baselibs_global.conf $BUILD_ROOT/.mkbaselibs
	if test -z "$BASELIBS_CFG" -a -e $BUILD_DIR/baselibs.conf ; then
	    cp -f $BUILD_DIR/baselibs.conf $BUILD_ROOT/.mkbaselibs/baselibs.conf
	    BASELIBS_CFG="-c /.mkbaselibs/baselibs.conf"
	fi
	chroot $BUILD_ROOT /.mkbaselibs/mkbaselibs -c /.mkbaselibs/baselibs_global.conf $BASELIBS_CFG $BRPMS || cleanup_and_exit 1
	rm -rf $BUILD_ROOT/.mkbaselibs
    fi
}

detect_vm_2nd_stage()
{
    if ! test "$0" = "/.build/build" ; then
	return 1
    fi
    echo "2nd stage started in virtual machine"
    BUILD_ROOT=/
    BUILD_DIR=/.build
    . $BUILD_DIR/build.data
    echo "machine type: `uname -m`"
    if test "$PERSONALITY" != 0 -a -z "$PERSONALITY_SET" ; then
	export PERSONALITY_SET=true
	echo "switching personality to $PERSONALITY..."
	# this is 32bit perl/glibc, thus the 32bit syscall number
	exec perl -e 'syscall(136, '$PERSONALITY') == -1 && warn("personality: $!\n");exec "/.build/build" || die("/.build/build: $!\n")'
    fi
    PATH=$BUILD_DIR:$PATH
    RUNNING_IN_VM=true
    mount -orw -n -tproc none /proc
    mount -n -o remount,rw /
    if test -n "$VM_SWAP" ; then
	for i in 1 2 3 4 5 6 7 8 9 10 ; do
	    test -e "$VM_SWAP" && break
	    test $i = 1 && echo "waiting for $VM_SWAP to appear"
	    echo -n .
	    sleep 1
	done
	test $i = 1 || echo
	# recreate the swap device manually if it didn't exist for some
	# reason, hardcoded to hda2 atm
	if ! test -b "$VM_SWAP" ; then
	    rm -f "$VM_SWAP"
	    umask 027
	    mknod "$VM_SWAP" b 3 2
	    umask 022
	fi
	swapon -v "$VM_SWAP" || exit 1
    fi
    HOST="$MYHOSTNAME"

    return 0
}

set_build_arch()
{
    if [ -z "$BUILD_ARCH" ]; then
	BUILD_ARCH=`uname -m`
	test i686 = "$BUILD_ARCH" && BUILD_ARCH=i586 # XXX: why?
    fi

    case $BUILD_ARCH in
      i686) BUILD_ARCH="i686:i586:i486:i386" ;;
      i586) BUILD_ARCH="i586:i486:i386" ;;
      i486) BUILD_ARCH="i486:i386" ;;
      x86_64) BUILD_ARCH="x86_64:i686:i586:i486:i386" ;;
    esac
    if test "$BUILD_ARCH" != "${BUILD_ARCH#i686}" ; then
	cpuflags=`grep ^flags /proc/cpuinfo`
	cpuflags="$cpuflags "
	test "$cpuflags" = "${cpuflags/ cx8 /}" -o "$cpuflags" = "${cpuflags/ cmov /}" && {
	    echo "Your cpu doesn't support i686 rpms. Exit."
	    exit 1
	}
    fi
}

find_spec_files()
{
    local spec files
    if [ -z "$SPECFILES" ]; then
	set -- "`pwd`"
    else
	set -- "${SPECFILES[@]}"
    fi
    SPECFILES=()
    for spec in "$@"; do
	if [ "$spec" = "${spec#/}" ]; then
	    spec="`pwd`/$spec"
	fi

	if [ -d "$spec" ]; then
	    specs=("$spec"/*.spec)
	    if [ -n "$specs" ]; then
		SPECFILES=("${SPECFILES[@]}" "${specs[@]}")
	    else
		specs=("$spec"/*.spec)
		if [ -n "$specs" ]; then
		    SPECFILES=("${SPECFILES[@]}" "${specs[@]}")
		fi
	    fi
	else
	    SPECFILES[${#SPECFILES[@]}]="$spec";
	fi
    done

    if test -z "$SPECFILES"; then
	echo no spec files or src rpms found in $@. exit...
	cleanup_and_exit 1
    fi
}

become_root_or_fail()
{
    if [ ! -w /root ]; then
	echo "You have to be root to use $0" >&2
	exit 1
    fi
    cleanup_and_exit 1
}

mkdir_build_root()
{
    if [ -d "$BUILD_ROOT" ]; then
	# check if it is owned by root
	if [ -z "$RUNNING_IN_VM" -a \! -O "$BUILD_ROOT" -a "`stat -c %u $BUILD_ROOT`" -ne 0 ]; then
	    echo "BUILD_ROOT=$BUILD_ROOT must be owned by $USER. Exit..."
	    cleanup_and_exit 1
	fi
    else
	test "$BUILD_ROOT" != "${BUILD_ROOT%/*}" && mkdir -p "${BUILD_ROOT%/*}"
	if ! mkdir $BUILD_ROOT; then
	    echo "can not create BUILD_ROOT=$BUILD_ROOT. Exit..."
	    cleanup_and_exit 1
	fi
    fi
    
    rm -rf "$BUILD_ROOT"/.build.packages
}

linux64()
{
	perl -e 'syscall('$PERSONALITY_SYSCALL', 0); exec(@ARGV) || die("$ARGV[0]: $!\n")' "$@"
}

#### main ####

trap fail_exit EXIT

case `perl -V:archname` in
    *x86_64*) PERSONALITY_SYSCALL=135 ;;
    *i?86*)   PERSONALITY_SYSCALL=136 ;;
esac

shopt -s nullglob

if detect_vm_2nd_stage ; then
    set "/.build-srcdir/$SPECFILE"
fi
export HOST

while test -n "$1"; do
  PARAM="$1"
  ARG="$2"
  shift
  case $PARAM in
    *-*=*)
      ARG=${PARAM#*=}
      PARAM=${PARAM%%=*}
      set -- "----noarg=$PARAM" "$@"
  esac
  case $PARAM in
      *-help|-h)
        echo_help
        cleanup_and_exit
      ;;
      *-no*init)
        DO_INIT=false
      ;;
      *-no*checks)
        DO_CHECKS=false
      ;;
      *-clean)
        CLEAN_BUILD='--clean'
      ;;
      *-kill)
        KILL=true
      ;;
      *-rpms)
        BUILD_RPMS="$ARG"
	if [ -z "$BUILD_RPMS" ] ; then
	  echo_help
	  cleanup_and_exit
	fi
        shift
      ;;
      *-arch)
        BUILD_ARCH="$ARG"
        shift
      ;;
      *-verify)
        export VERIFY_BUILD_SYSTEM=true
      ;;
      *-target)
	ABUILD_TARGET_ARCH="$ARG"
	shift
      ;;
      *-jobs) 
	BUILD_JOBS="$ARG"
	shift
      ;;
      *-extra*packs|-X)
        BUILD_EXTRA_PACKS="$BUILD_EXTRA_PACKS $ARG"
        shift
      ;;
      *-lint)
        DO_LINT=true
        ;;
      *-baselibs)
        CREATE_BASELIBS=true
        ;;
      *-baselibs-internal)
        CREATE_BASELIBS=internal
        ;;
      *-root)
        BUILD_ROOT="$ARG"
        shift
      ;;
      *-oldpackages)
        OLD_PACKAGES="$ARG"
        shift
      ;;
      *-dist) 
	BUILD_DIST="$ARG"
	export BUILD_DIST
	shift
      ;;
      *-xen|*-kvm|--uml|--qemu)
	VM_TYPE=${PARAM##*-}
	if [ -n "$ARG" -a "$ARG" = "${ARG#-}" ]; then
	    VM_IMAGE="$ARG"
	    shift
	else
	    VM_IMAGE=1
	fi
      ;;
      *-xenswap|*-swap)
        VM_SWAP="$ARG"
        shift
      ;;
      *-xenmemory|*-memory)
        MEMSIZE="$ARG"
        shift
      ;;
      *-rpmlist)
        RPMLIST="--rpmlist $ARG"
	BUILD_RPMS=
        shift
      ;;
      *-release)
        RELEASE="$ARG"
        shift
      ;;
      *-logfile)
        LOGFILE="$ARG"
        shift
      ;;
      *-reason)
        REASON="$ARG"
        shift
      ;;
      *-norootforbuild)
        NOROOTFORBUILD=true
      ;;
      *-stage)
        BUILD_RPM_BUILD_STAGE="$ARG"
        shift
      ;;
      *-useusedforbuild)
        USEUSEDFORBUILD="--useusedforbuild"
      ;;
      *-list*state)
	LIST_STATE=true
      ;;
      --define|--with|--without)
        definesnstuff[${#definesnstuff[@]}]="$PARAM";
        definesnstuff[${#definesnstuff[@]}]="$ARG";
	shift
      ;;
      --repository|--repo)
        if [ -z "$ARG" ] ; then
          echo_help
          cleanup_and_exit
        fi
        repos[${#repos[@]}]="$PARAM";
        repos[${#repos[@]}]="$ARG";
        shift
      ;;
      --icecream)
        if [ -z "$ARG" ] ; then
          echo "--icecream needs an argument" >&2
          echo_help
          cleanup_and_exit 1
        fi
        icecream="$ARG"
        BUILD_JOBS="$ARG"
        shift
      ;;
      --ccache)
        ccache=1
      ;;
      --debug)
        BUILD_DEBUG=1
      ;;
      --incarnation)
        INCARNATION=$ARG
	shift
      ;;
      --disturl)
        DISTURL=$ARG
	shift
      ;;
      ----noarg)
        echo "$ARG does not take an argument"
        cleanup_and_exit
      ;;
      *-changelog)
        CHANGELOG=true
      ;;
      -*)
        echo Unknown Option "$PARAM". Exit.
        cleanup_and_exit 1
      ;;
      *)
        SPECFILES[${#SPECFILES[@]}]="$PARAM";
      ;;
    esac
done

# XXX: doesn't kill vm if in prepare stage (because there is none)
if test -n "$KILL" ; then
    test -z "$SRCDIR" || usage
    if test -z "$VM_IMAGE" ; then
	if ! $BUILD_DIR/killchroot -s 9 $BUILD_ROOT ; then
	    echo "could not kill build in $BUILD_ROOT"
	    cleanup_and_exit 1
	fi
    elif test "$VM_TYPE" = 'xen'; then
	XENID="${VM_IMAGE%/root}"
	XENID="${XENID##*/}"
	if xm list "build:$XENID" >/dev/null 2>&1 ; then
	    if ! xm destroy "build:$XENID" ; then
		echo "could not kill xen build $XENID"
		cleanup_and_exit 1
	    fi
	fi
    elif test -n "$VM_TYPE"; then
	if ! fuser -k -TERM "$VM_IMAGE"; then
	    echo "could not kill build in $VM_IMAGE"
	    cleanup_and_exit 1
	fi
    else
	echo "don't know how to kill this build job"
	cleanup_and_exit 1
    fi
    cleanup_and_exit 0
fi

if [ "$VM_TYPE" = 'kvm' ]; then
    if [ ! -r /dev/kvm -o ! -x "$qemu_bin"-kvm ]; then
	echo ""
    fi
    qemu_bin="$kvm_bin"
    qemu_kernel="$kvm_kernel"
    qemu_initrd="$kvm_initrd"
    if [ ! -e $qemu_initrd-virtio -o $qemu_kernel -nt $qemu_initrd-virtio ]; then
	if [ ! -w /root ]; then
	    echo "No initrd that provides virtio support found. virtio accelleration disabled."
	    echo "Run the following command as root to enable virtio:"
	    shellquote "${mkinitrd_virtio_cmd[@]}"
	    echo
	elif /sbin/modinfo virtio_pci >/dev/null 2>&1; then
	    echo "creating $qemu_initrd-virtio"
	    "${mkinitrd_virtio_cmd[@]}" || cleanup_and_exit 1
	    kvm_virtio=1
	fi
    else
	kvm_virtio=1
    fi

    if [ "$kvm_virtio" = 1 ]; then
	qemu_initrd="$qemu_initrd-virtio"
	VM_SWAPDEV=/dev/vdb
	qemu_rootdev=/dev/vda
    else
	VM_SWAPDEV=/dev/sdb
	qemu_rootdev=/dev/sda
    fi
fi

if [ "$VM_TYPE" = 'qemu' ]; then
    VM_SWAPDEV=/dev/sdb
    qemu_rootdev=/dev/sda
fi

if [ -z "$RPMLIST" ]; then
    if [ -z "$repos" -a -z "$BUILD_RPMS" ]; then
	BUILD_RPMS="/media/dvd/suse"
    fi
else
    repos=()
fi

set_build_arch

if [ -n "$CLEAN_BUILD" ]; then
    DO_INIT=true
fi

find_spec_files

if test -n "$LIST_STATE" ; then
    BUILD_ROOT=`mktemp -d /var/tmp/build-list-state-XXXXXX`
    test -d "$BUILD_ROOT" || cleanup_and_exit 1
    SPECFILE=$SPECFILES # only one specified anyways
    if test "$SPECFILE" != "${SPECFILE%.src.rpm}" ; then
       rm -rf $BUILD_ROOT/usr/src/packages
       mkdir -p $BUILD_ROOT/usr/src/packages/SOURCES $BUILD_ROOT/usr/src/packages/SPECS
       rpm -i --nodigest --nosignature --root $BUILD_ROOT $SPECFILE || {
	   echo "could not install $SPECFILE." 2>&1
	   rm -rf $BUILD_ROOT
	   cleanup_and_exit 1
       }
       for SPECFILE in $BUILD_ROOT/usr/src/packages/SPECS/*.spec ; do : ; done
    fi
    init_buildsystem --list-state "${definesnstuff[@]}" "${repos[@]}" $USEUSEDFORBUILD $SPECFILE $BUILD_EXTRA_PACKS
    ERR=$?
    rm -rf $BUILD_ROOT
    cleanup_and_exit $ERR
fi

if test -z "$RUNNING_IN_VM" ; then
    if test -n "$VM_IMAGE" ; then
	if test "$VM_IMAGE" = 1 ; then
	    VM_IMAGE="$BUILD_ROOT.img"
	fi
	if test ! -e "$VM_IMAGE" ; then
	    echo "you need to create a file system on $VM_IMAGE first"
	    cleanup_and_exit 1
	fi
    fi
    if test -n "$VM_IMAGE" ; then
	if test -n "$CLEAN_BUILD" ; then
	    echo "Creating filesystem on $VM_IMAGE"
	    $xen_img_mkfs $VM_IMAGE || become_root_or_fail
	fi
	mkdir_build_root
	if [ -w /root ]; then
	    mount -o loop $VM_IMAGE $BUILD_ROOT || cleanup_and_exit 1
	else
	    mount $BUILD_ROOT || become_root_or_fail
	fi
    else
	test -w /root || become_root_or_fail
    fi
    if test -n "$VM_SWAP" ; then
	dd if=/dev/zero of="$VM_SWAP" bs=12 count=1 conv=notrunc 2>/dev/null
	mkswap "$VM_SWAP"
    fi
fi

mkdir_build_root

rm -f $BUILD_ROOT/exit

if [ -w /root ]; then
    mkdir -p $BUILD_ROOT/proc
    mkdir -p $BUILD_ROOT/dev/pts
    mount -n -tproc none $BUILD_ROOT/proc || true
    mount -n -tdevpts none $BUILD_ROOT/dev/pts
fi

if test -z "$VM_IMAGE" -a -z "$LOGFILE"; then
    LOGFILE="$BUILD_ROOT/.build.log"
fi

if test -n "$LOGFILE" ; then
    echo  logging output to $LOGFILE...
    rm -f $LOGFILE
    touch $LOGFILE
    if test -n "$VM_IMAGE" ; then
	exec 1> >(exec -a 'build logging tee' perl -e 'open(F,">>",$ARGV[0])||die("$ARGV[0]: $!\n");$|=1;select(F);$|=1;while(<STDIN>){print STDOUT;s/^\r//s;s/\r\n/\n/gs;print F}' $LOGFILE) 2>&1
    else
	exec 1> >(exec -a 'build logging tee' tee -a $LOGFILE) 2>&1
    fi
fi

setmemorylimit

#
# say hello
#
test -z "$HOST" && HOST=`hostname`

if [ -z "$RUNNING_IN_VM" ]; then
    echo Using BUILD_ROOT=$BUILD_ROOT
    test -n "$BUILD_RPMS" && echo Using BUILD_RPMS=$BUILD_RPMS
    echo Using BUILD_ARCH=$BUILD_ARCH
    test -n "$VM_TYPE" && echo "Doing $VM_TYPE build in $VM_IMAGE"
    echo
fi

test "$BUILD_ARCH" = all && BUILD_ARCH=
BUILD_USER_ABUILD_USED=

for SPECFILE in "${SPECFILES[@]}" ; do

    SRCDIR="${SPECFILE%/*}"
    SPECFILE="${SPECFILE##*/}"

    BUILDTYPE=
    case $SPECFILE in
      *.spec|*.src.rpm) BUILDTYPE=spec ;;
      *.dsc) BUILDTYPE=dsc ;;
      *.kiwi) BUILDTYPE=kiwi ;;
    esac
    if test -z "$BUILDTYPE" ; then
       echo "don't know how to build $SPECFILE"
       cleanup_and_exit 1
    fi

    cd "$SRCDIR"

    if [ -z "$RUNNING_IN_VM" ]; then
	echo
	echo "$HOST started \"build $SPECFILE\" at `date`."
	echo
	test -n "$REASON" && echo "$REASON"
	echo
    fi

    #
    # first setup building directory...
    #
    test -s "$SPECFILE" || {
       echo "$SPECFILE" is empty.  This should not happen...
       cleanup_and_exit 1
    }

    if test "$SPECFILE" != "${SPECFILE%.src.rpm}" ; then
	echo processing src rpm `pwd`/$SPECFILE...
	TOPDIR=`rpm --eval '%_topdir'`
	rm -rf $BUILD_ROOT$TOPDIR
	mkdir -p $BUILD_ROOT$TOPDIR/SOURCES $BUILD_ROOT$TOPDIR/SPECS
	rpm -i --nodigest --nosignature --root $BUILD_ROOT $SPECFILE || {
	    echo "could not install $SPECFILE."
	    cleanup_and_exit 1
	}
	rm -rf $BUILD_ROOT/.build-srcdir
	mkdir -p $BUILD_ROOT/.build-srcdir
	mv $BUILD_ROOT$TOPDIR/SOURCES/* $BUILD_ROOT/.build-srcdir
	mv $BUILD_ROOT$TOPDIR/SPECS/* $BUILD_ROOT/.build-srcdir
	MYSRCDIR=$BUILD_ROOT/.build-srcdir
	cd $MYSRCDIR || cleanup_and_exit 1
	for SPECFILE in *.spec ; do : ; done
    else
	echo processing specfile `pwd`/$SPECFILE...
	MYSRCDIR="$SRCDIR"
    fi

    ADDITIONAL_PACKS=""
    test -n "$BUILD_EXTRA_PACKS" && ADDITIONAL_PACKS="$ADDITIONAL_PACKS $BUILD_EXTRA_PACKS"
    test -n "$CREATE_BASELIBS" && ADDITIONAL_PACKS="$ADDITIONAL_PACKS build"
    test "$ccache" = '1' && ADDITIONAL_PACKS="$ADDITIONAL_PACKS ccache"
    test "$icecream" -gt 1 && ADDITIONAL_PACKS="$ADDITIONAL_PACKS icecream gcc-c++"
    test -n "$DO_LINT" && ADDITIONAL_PACKS="$ADDITIONAL_PACKS rpmlint-Factory"

    if test -n "$CHANGELOG" -a -z "$RUNNING_IN_VM" ; then
	rm -f $BUILD_ROOT/.build-changelog
	case $SPECFILE in
	  *.dsc) CFFORMAT=debian ;;
	  *) CFFORMAT=rpm ;;
	esac
	echo "running changelog2spec --target $CFFORMAT --file $MYSRCDIR/$SPECFILE"
	if ! $BUILD_DIR/changelog2spec --target $CFFORMAT --file "$MYSRCDIR/$SPECFILE" > $BUILD_ROOT/.build-changelog ; then
	    rm -f $BUILD_ROOT/.build-changelog
	fi
    fi

    if test -n "$VM_TYPE"; then
	rm -rf $BUILD_ROOT/.build
	mkdir -p $BUILD_ROOT/.build
	if test "$DO_INIT" = true ; then
	    # do fist stage of init_buildsystem
	    rm -f $BUILD_ROOT/.build.success
	    set -- init_buildsystem --prepare "${definesnstuff[@]}" "${repos[@]}" $CLEAN_BUILD $USEUSEDFORBUILD $RPMLIST "$MYSRCDIR/$SPECFILE" $ADDITIONAL_PACKS
	    echo "$* ..."
	    "$@" || cleanup_and_exit 1
	    if [ ! -w /root ]; then
		# remove setuid bit if files belong to user to make e.g. mount work
		find $BUILD_ROOT/{bin,sbin,usr/bin,usr/sbin} -type f -uid $UID -perm +4000 -print0 | xargs -0 --no-run-if-empty chmod -s
	    fi
            if [ -d "$OLD_PACKAGES" ]; then
               rm -rf $BUILD_ROOT/.build.oldpackages
               cp -a $OLD_PACKAGES $BUILD_ROOT/.build.oldpackages
            fi
	fi
	# start up xen, rerun ourself
	cp -a $BUILD_DIR/. $BUILD_ROOT/.build
	if ! test "$MYSRCDIR" = $BUILD_ROOT/.build-srcdir ; then
	    rm -rf $BUILD_ROOT/.build-srcdir
	    mkdir $BUILD_ROOT/.build-srcdir
	    if test "$BUILDTYPE" = kiwi ; then
		cp -pRL "$MYSRCDIR"/* $BUILD_ROOT/.build-srcdir
	    else
		cp -p "$MYSRCDIR"/* $BUILD_ROOT/.build-srcdir
	    fi
	    MYSRCDIR=$BUILD_ROOT/.build-srcdir
	fi
	Q="'\''"
	echo "SPECFILE='${SPECFILE//"'"/$Q}'" > $BUILD_ROOT/.build/build.data
	echo "BUILD_JOBS='${BUILD_JOBS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "BUILD_ARCH='${BUILD_ARCH//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "BUILD_RPMS='${BUILD_RPMS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	case $BUILD_DIST in
	    */*)
		cp $BUILD_DIST $BUILD_ROOT/.build/build.dist
		BUILD_DIST=/.build/build.dist
		;;
	esac
	echo "BUILD_DIST='${BUILD_DIST//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "RELEASE='${RELEASE//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "BUILD_DEBUG='${BUILD_DEBUG//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "DO_LINT='${DO_LINT//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "DO_CHECKS='${DO_CHECKS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "NOROOTFORBUILD='${NOROOTFORBUILD//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "CREATE_BASELIBS='$CREATE_BASELIBS'" >> $BUILD_ROOT/.build/build.data
	echo "REASON='${REASON//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "CHANGELOG='${CHANGELOG//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "INCARNATION='${INCARNATION//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	echo "DISTURL='${DISTURL//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
	# FIXME: this depends on the kernel and vm.
	# could be hda2, sda2 for xen or hdb/sdb for qemu
	test -n "$VM_SWAP" && echo "VM_SWAP='${VM_SWAPDEV:-/dev/hda2}'" >> $BUILD_ROOT/.build/build.data
	PERSONALITY=0
	test -n "$PERSONALITY_SYSCALL" && PERSONALITY=`perl -e 'print syscall('$PERSONALITY_SYSCALL', 0)."\n"'`
	echo "OLD_PACKAGES='$OLD_PACKAGES'" >> $BUILD_ROOT/.build/build.data
	echo "PERSONALITY='$PERSONALITY'" >> $BUILD_ROOT/.build/build.data
	echo "MYHOSTNAME='`hostname`'" >> $BUILD_ROOT/.build/build.data
	echo -n "definesnstuff=(" >> $BUILD_ROOT/.build/build.data
	shellquote "${definesnstuff[@]}" >> $BUILD_ROOT/.build/build.data
	echo ")" >> $BUILD_ROOT/.build/build.data
	echo -n "repos=(" >> $BUILD_ROOT/.build/build.data
	shellquote "${repos[@]}" >> $BUILD_ROOT/.build/build.data
	echo ")" >> $BUILD_ROOT/.build/build.data
	umount -n $BUILD_ROOT/proc 2> /dev/null || true
	umount -n $BUILD_ROOT/dev/pts 2> /dev/null || true
	umount -n $BUILD_ROOT/mnt 2> /dev/null || true

	# needs to work otherwise we have a corrupted file system
	umount $BUILD_ROOT || cleanup_and_exit 1

	if [ "$VM_TYPE" = 'xen' ]; then
		XMROOT=file:$VM_IMAGE
		XMROOT=${XMROOT/#file:\/dev/phy:/dev}
		XMROOT="disk=$XMROOT,hda1,w"
		XMSWAP=
		if test -n "$VM_SWAP" ; then
		    XMSWAP=file:$VM_SWAP
		    XMSWAP=${XMSWAP/#file:\/dev/phy:/dev}
		    XMSWAP="disk=$XMSWAP,hda2,w"
		fi
		XENID="${VM_IMAGE%/root}"
		XENID="${XENID##*/}"
		echo "booting XEN kernel ..."
		set -- xm create -c $BUILD_DIR/xen.conf name="build:$XENID" ${MEMSIZE:+memory=$MEMSIZE} $XMROOT $XMSWAP extra="quiet init=/.build/build panic=1 console=ttyS0"
		if test "$PERSONALITY" != 0 ; then
		    # have to switch back to PER_LINUX to make xm work
		    set -- linux64 "$@"
		fi
		echo "$@"
		"$@" || true # somehow this is always false
	elif [ "$VM_TYPE" = 'uml' ]; then
		echo "booting UML kernel ..."
		set -- $uml_kernel initrd=$uml_initrd root=/ubda init=/.build/build panic=1 quiet ubd0=$VM_IMAGE ${MEMSIZE:+mem=$MEMSIZE}
		echo "$@"
		"$@"
	elif [ "$VM_TYPE" = 'qemu' -o "$VM_TYPE" = 'kvm' ]; then
		echo "booting $VM_TYPE ..."
		if [ "$kvm_virtio" = 1 ]; then
		    qemu_disks=(-drive file="$VM_IMAGE",if=virtio -hda "$VM_IMAGE")
		    if [ -n "$VM_SWAP" ]; then
			qemu_disks[${#qemu_disks[@]}]="-drive"
			qemu_disks[${#qemu_disks[@]}]="file=$VM_SWAP,if=virtio"
		    fi
		else
		    qemu_disks=(-hda "$VM_IMAGE")
		    if [ -n "$VM_SWAP" ]; then
			qemu_disks[${#qemu_disks[@]}]="-hdb"
			qemu_disks[${#qemu_disks[@]}]="$VM_SWAP"
		    fi
		fi
		set -- $qemu_bin -no-reboot -nographic -net none -serial stdio \
		    -kernel $qemu_kernel \
		    -initrd $qemu_initrd \
		    -append "root=$qemu_rootdev panic=1 quiet noapic rw console=ttyS0 init=/.build/build" \
		    ${MEMSIZE:+-m $MEMSIZE} \
		    "${qemu_disks[@]}"

		if test "$PERSONALITY" != 0 ; then
		    # have to switch back to PER_LINUX to make qemu work
		    set -- linux64 "$@"
		fi
		echo "$@"
		"$@"
	fi
	if test -n "$VM_SWAP" ; then
	    BUILDSTATUS=`dd if="$VM_SWAP" bs=12 count=1 2>/dev/null`
	    case $BUILDSTATUS in
	      BUILDSTATUS[02])
		mkdir -p $BUILD_ROOT/.build.packages 
		cd $BUILD_ROOT/.build.packages || cleanup_and_exit 1
		echo "build: extracting built packages..."
		dd if=$VM_SWAP bs=512 skip=1 | cpio --extract --no-absolute-filenames -v
		cleanup_and_exit ${BUILDSTATUS#BUILDSTATUS}
		;;
	      *)
		cleanup_and_exit ${BUILDSTATUS#BUILDSTATUS}
		;;
	    esac
	    cleanup_and_exit 1
	fi
	cleanup_and_exit 0
    fi

    if test "$DO_INIT" = true ; then
	#
	# create legacy .buildenv file
	#
	test -z "$INCARNATION" && INCARNATION=0
	echo "BUILD_INCARNATION=$INCARNATION" > $BUILD_ROOT/.buildenv
	CREATE_BUILD_BINARIES=
	egrep '^#[       ]*needsbinariesforbuild[       ]*$' >/dev/null <$MYSRCDIR/$SPECFILE && CREATE_BUILD_BINARIES=--create-build-binaries
        set -- init_buildsystem "${definesnstuff[@]}" "${repos[@]}" $CLEAN_BUILD $USEUSEDFORBUILD $CREATE_BUILD_BINARIES $RPMLIST "$MYSRCDIR/$SPECFILE" $ADDITIONAL_PACKS
	echo "$* ..."
	"$@" || cleanup_and_exit 1
	mount -n -tproc none $BUILD_ROOT/proc || true
	mount -n -tdevpts none $BUILD_ROOT/dev/pts
        if [ -d "$OLD_PACKAGES" ]; then
           [ -d "$BUILD_ROOT/.build.oldpackages" ] || cp -r $OLD_PACKAGES $BUILD_ROOT/.build.oldpackages
        fi
    fi

    if test -z "$BUILD_DIST" -a -e "$BUILD_ROOT/.guessed_dist" ; then
	BUILD_DIST=`cat $BUILD_ROOT/.guessed_dist`
	echo "assuming dist $BUILD_DIST"
    fi

    #
    # fix rpmrc if we are compiling for i686
    #
    test -f $BUILD_ROOT/usr/lib/rpm/rpmrc_i586 && mv $BUILD_ROOT/usr/lib/rpm/rpmrc_i586 $BUILD_ROOT/usr/lib/rpm/rpmrc
    if test -e $BUILD_ROOT/usr/lib/rpm/rpmrc -a "$BUILD_ARCH" != "${BUILD_ARCH#i686}" ; then
	mv $BUILD_ROOT/usr/lib/rpm/rpmrc $BUILD_ROOT/usr/lib/rpm/rpmrc_i586
	sed -e 's/^buildarchtranslate: athlon.*/buildarchtranslate: athlon: i686/' -e 's/^buildarchtranslate: i686.*/buildarchtranslate: i686: i686/' < $BUILD_ROOT/usr/lib/rpm/rpmrc_i586 > $BUILD_ROOT/usr/lib/rpm/rpmrc
    fi

    #
    # check if we want to build with the abuild user
    #
    BUILD_USER=abuild
    if test -x $BUILD_ROOT/bin/rpm ; then
	SUSE_VERSION=`chroot $BUILD_ROOT /bin/rpm --eval '%{?suse_version}' 2>/dev/null`
	if test -n "$SUSE_VERSION" && test "$SUSE_VERSION" -le 1020 ; then
	    BUILD_USER=root
	fi
    fi
    if test "$BUILD_USER" = abuild ; then
	egrep '^#[       ]*needsrootforbuild[       ]*$' >/dev/null <$SPECFILE && BUILD_USER=root
    else
	egrep '^#[       ]*norootforbuild[       ]*$' >/dev/null <$SPECFILE && BUILD_USER=abuild
    fi
    test -n "$NOROOTFORBUILD" && BUILD_USER=abuild
    test "$BUILDTYPE" = kiwi && BUILD_USER=root

    if test $BUILD_USER = abuild ; then
        if ! egrep '^abuild:' >/dev/null <$BUILD_ROOT/etc/passwd ; then
            echo 'abuild::399:399:Autobuild:/home/abuild:/bin/bash' >>$BUILD_ROOT/etc/passwd
            echo 'abuild:*:::::::' >>$BUILD_ROOT/etc/shadow # This is needed on Mandriva 2009
            echo 'abuild::399:' >>$BUILD_ROOT/etc/group
            mkdir -p $BUILD_ROOT/home/abuild
            chown 399:399 $BUILD_ROOT/home/abuild
        fi
	if test -f $BUILD_ROOT/etc/shadow ; then
	    sed -e "s@^root::@root:*:@" < $BUILD_ROOT/etc/shadow > $BUILD_ROOT/etc/shadow.t && mv $BUILD_ROOT/etc/shadow.t $BUILD_ROOT/etc/shadow
	fi
	BUILD_USER_ABUILD_USED=true
    else
        if egrep '^abuild:' >/dev/null <$BUILD_ROOT/etc/passwd ; then
            egrep -v '^abuild:' <$BUILD_ROOT/etc/passwd >$BUILD_ROOT/etc/passwd.new
            mv $BUILD_ROOT/etc/passwd.new $BUILD_ROOT/etc/passwd
            egrep -v '^abuild:' <$BUILD_ROOT/etc/shadow >$BUILD_ROOT/etc/shadow.new
            mv $BUILD_ROOT/etc/shadow.new $BUILD_ROOT/etc/shadow
            egrep -v '^abuild:' <$BUILD_ROOT/etc/group >$BUILD_ROOT/etc/group.new
            mv $BUILD_ROOT/etc/group.new $BUILD_ROOT/etc/group
            rm -rf $BUILD_ROOT/home/abuild
        fi
    fi

    if test "$BUILDTYPE" = spec ; then
	TOPDIR=`chroot $BUILD_ROOT su -c "rpm --eval '%_topdir'" - $BUILD_USER`
    else
	TOPDIR=/usr/src/packages
	mkdir -p $BUILD_ROOT$TOPDIR
    fi

    rm -f $BUILD_ROOT/.build.packages
    ln -s ${TOPDIR#/} $BUILD_ROOT/.build.packages

    mount -n -tproc none $BUILD_ROOT/proc 2> /dev/null
    mount -n -tdevpts none $BUILD_ROOT/dev/pts 2> /dev/null
 
    setupicecream

    setupccache

    # nasty hack to prevent rpath on known paths
    # FIXME: do this only for suse
    if test -d "$BUILD_ROOT/etc/profile.d" ; then
	echo "export SUSE_IGNORED_RPATHS=/etc/ld.so.conf" > "$BUILD_ROOT/etc/profile.d/buildsystem.sh"
    fi

    #
    # now clean up RPM building directories
    #
    rm -rf $BUILD_ROOT$TOPDIR
    for i in BUILD RPMS/`uname -m` RPMS/i386 RPMS/noarch SOURCES SPECS SRPMS BUILDROOT; do
        mkdir -p $BUILD_ROOT$TOPDIR/$i
	test $BUILD_USER = abuild && chown 399:399 $BUILD_ROOT$TOPDIR/$i
    done
    test -e $BUILD_ROOT/exit && cleanup_and_exit

    mkdir -p $BUILD_ROOT$TOPDIR/SOURCES
    if test "$BUILDTYPE" = kiwi ; then
	mkdir -p $BUILD_ROOT$TOPDIR/KIWI
	if test "$MYSRCDIR" = $BUILD_ROOT/.build-srcdir ; then
	    mv "$MYSRCDIR"/* $BUILD_ROOT$TOPDIR/SOURCES/
	else
	    cp -dLR "$MYSRCDIR"/* $BUILD_ROOT$TOPDIR/SOURCES/
	fi
    else
	cp -p "$MYSRCDIR"/* $BUILD_ROOT$TOPDIR/SOURCES/
    fi
    test "$MYSRCDIR" = $BUILD_ROOT/.build-srcdir && rm -rf "$MYSRCDIR"

    CHANGELOGARGS=
    test -n "$CHANGELOG" -a -f "$BUILD_ROOT/.build-changelog" && CHANGELOGARGS="--changelog $BUILD_ROOT/.build-changelog"

    if test "$BUILDTYPE" = spec ; then
	# do buildrequires/release substitution
	args=()
	if test -n "$RELEASE"; then
		args=(--release "$RELEASE")
	fi
	substitutedeps "${args[@]}" --dist "$BUILD_DIST" --archpath "$BUILD_ARCH" --configdir "$BUILD_DIR/configs" $CHANGELOGARGS "$BUILD_ROOT$TOPDIR/SOURCES/$SPECFILE" "$BUILD_ROOT/.spec.new" || cleanup_and_exit 1
	# extract macros from configuration
	getmacros --dist "$BUILD_DIST" --archpath "$BUILD_ARCH" --configdir "$BUILD_DIR/configs" > $BUILD_ROOT/root/.rpmmacros
	if test -n "$BUILD_DEBUG" ; then
	    echo '
%prep %?_suse_insert_debug_package%%prep
%package %?_suse_insert_debug_package%%package
%suse_insert_debug_package \
  %global _suse_insert_debug_package \\\
    %%undefine _suse_insert_debug_package \\\
    %%debug_package

' >> $BUILD_ROOT/root/.rpmmacros
	fi
	test $BUILD_USER = abuild && cp -p $BUILD_ROOT/root/.rpmmacros $BUILD_ROOT/home/abuild/.rpmmacros
	# extract optflags from configuration
	getoptflags --dist "$BUILD_DIST" --configdir "$BUILD_DIR/configs" --archpath "$BUILD_ARCH" ${BUILD_DEBUG:+--debug} > $BUILD_ROOT/root/.rpmrc
	test $BUILD_USER = abuild && cp -p $BUILD_ROOT/root/.rpmrc $BUILD_ROOT/home/abuild/.rpmrc
    fi
    if test -f $BUILD_ROOT/.spec.new ; then
	if ! cmp -s $BUILD_ROOT$TOPDIR/SOURCES/$SPECFILE $BUILD_ROOT/.spec.new ; then
	    echo -----------------------------------------------------------------
	    echo I have the following modifications for $SPECFILE:
	    diff $BUILD_ROOT$TOPDIR/SOURCES/$SPECFILE $BUILD_ROOT/.spec.new
	    mv $BUILD_ROOT/.spec.new $BUILD_ROOT$TOPDIR/SOURCES/$SPECFILE
	else
	    rm -f $BUILD_ROOT/.spec.new
	fi
    fi

    if test "$BUILDTYPE" = dsc ; then
	rm -rf $BUILD_ROOT$TOPDIR/BUILD
	test $BUILD_USER = abuild && chown 399:399 $BUILD_ROOT$TOPDIR
	DEB_TRANSFORM=
	DEB_SOURCEDIR=$TOPDIR/SOURCES
	DEB_DSCFILE=$SPECFILE
	for f in $BUILD_ROOT$TOPDIR/SOURCES/debian.* ; do
	    test -f $f && DEB_TRANSFORM=true
	done
	if test -n "$DEB_TRANSFORM" ; then
	    echo "running debian transformer..."
	    mkdir -p $BUILD_ROOT$TOPDIR/SOURCES.DEB
            if ! debtransform $CHANGELOGARGS $BUILD_ROOT$TOPDIR/SOURCES $BUILD_ROOT$TOPDIR/SOURCES/$SPECFILE $BUILD_ROOT$TOPDIR/SOURCES.DEB ; then
		echo "debian transforming failed."
		cleanup_and_exit 1
	    fi
	    DEB_SOURCEDIR=$TOPDIR/SOURCES.DEB
	    for DEB_DSCFILE in $BUILD_ROOT/$DEB_SOURCEDIR/*.dsc ; do : ; done
	    DEB_DSCFILE="${DEB_DSCFILE##*/}"
        fi
	chroot $BUILD_ROOT su -c "dpkg-source -x $DEB_SOURCEDIR/$DEB_DSCFILE $TOPDIR/BUILD" - $BUILD_USER
    fi

    if test $BUILD_USER = abuild ; then
        chown -R 399:399 $BUILD_ROOT$TOPDIR/*
    else
        chown -R root:root $BUILD_ROOT$TOPDIR/*
    fi
    cd $BUILD_ROOT$TOPDIR/SOURCES || cleanup_and_exit 1

    echo -----------------------------------------------------------------
    if test "$BUILD_USER" = root ; then
        echo ----- building $SPECFILE
    else
        echo ----- building $SPECFILE "(user $BUILD_USER)"
    fi
    echo -----------------------------------------------------------------
    echo -----------------------------------------------------------------
    test -n "$RUNNING_IN_VM" && ifconfig lo 127.0.0.1 up
    test -n "$RUNNING_IN_VM" -a -n "$MYHOSTNAME" && hostname "$MYHOSTNAME"

    BUILD_SUCCEEDED=false

    if test "$BUILDTYPE" = spec ; then
	test -z "$BUILD_RPM_BUILD_STAGE" && BUILD_RPM_BUILD_STAGE=-ba

	# XXX: move _srcdefattr to macro file?
	rpmbopts=("$BUILD_RPM_BUILD_STAGE" "--define" "_srcdefattr (-,root,root)")
	if [ -n "$ABUILD_TARGET_ARCH" ]; then
		rpmbopts[${#rpmbopts[@]}]="--target=$ABUILD_TARGET_ARCH"
	fi
	if [ -n "$BUILD_JOBS" ]; then
		rpmbopts[${#rpmbopts[@]}]='--define'
		rpmbopts[${#rpmbopts[@]}]="jobs $BUILD_JOBS"
	fi
	if [ -n "$DISTURL" ]; then
		rpmbopts[${#rpmbopts[@]}]='--define'
		rpmbopts[${#rpmbopts[@]}]="disturl $DISTURL"
	fi
	if test -s "$BUILD_ROOT/usr/lib/rpm/mandriva/macros" ; then
		rpmbopts[${#rpmbopts[@]}]='--eval'
		rpmbopts[${#rpmbopts[@]}]="%undefine _enable_debug_packages"
	fi
	if [ -n "$BUILD_DEBUG" ]; then
		rpmbopts[${#rpmbopts[@]}]='--eval'
		rpmbopts[${#rpmbopts[@]}]="%suse_insert_debug_package"
	fi
	rpmbuild=rpmbuild

	test -x $BUILD_ROOT/usr/bin/rpmbuild || rpmbuild=rpm
	# su involves a shell which would require even more
	# complicated quoting to bypass than this
	toshellscript $rpmbuild \
		"${definesnstuff[@]}" \
		"${rpmbopts[@]}" \
		"$TOPDIR/SOURCES/$SPECFILE" \
		> $BUILD_ROOT/.build.command
	chmod 755 $BUILD_ROOT/.build.command
	chroot $BUILD_ROOT su -c /.build.command - $BUILD_USER < /dev/null && BUILD_SUCCEEDED=true
    fi

    if test "$BUILDTYPE" = dsc ; then
	chroot $BUILD_ROOT su -c "cd $TOPDIR/BUILD && dpkg-buildpackage -us -uc -rfakeroot-tcp" - $BUILD_USER < /dev/null && BUILD_SUCCEEDED=true
	mkdir -p $BUILD_ROOT/$TOPDIR/DEBS
	for DEB in $BUILD_ROOT/$TOPDIR/*.deb ; do
	    test -e "$DEB" && mv "$DEB" "$BUILD_ROOT/$TOPDIR/DEBS"
	done
	# link sources over
	ln $BUILD_ROOT/$DEB_SOURCEDIR/$DEB_DSCFILE $BUILD_ROOT/$TOPDIR/DEBS/
	while read f ; do
	    ln $BUILD_ROOT/$DEB_SOURCEDIR/$f $BUILD_ROOT/$TOPDIR/DEBS/
	done < <(sed -ne '/^Files:/,$s/^ ................................ [0-9][0-9]* //p' < $BUILD_ROOT/$DEB_SOURCEDIR/$DEB_DSCFILE)
    fi

    if test "$BUILDTYPE" = kiwi ; then
	# run createrepo on the repositories
	if test -d $BUILD_ROOT/$TOPDIR/SOURCES/repos ; then
	    (
	    ln -sf $TOPDIR/SOURCES/repos $BUILD_ROOT/repos
	    cd $BUILD_ROOT/$TOPDIR/SOURCES/repos
	    for r in */* ; do
		test -L $r && continue
		test -d $r || continue
		repo="$TOPDIR/SOURCES/repos/$r/"
		# create compatibility link
		rc="${r//:/:/}"
		if test "$rc" != "$r" ; then
		    rl="${rc//[^\/]}"
		    rl="${rl//?/../}"
		    mkdir -p "${rc%/*}"
		    ln -s $rl$r "${rc%/*}/${rc##*/}"
		    repo="$TOPDIR/SOURCES/repos/${rc%/*}/${rc##*/}/"
		fi
		echo "creating repodata for $repo"
		chroot $BUILD_ROOT createrepo "$repo"
	    done
	    )
	fi
	# unpack tar files in image directories
	if test -d $BUILD_ROOT/$TOPDIR/SOURCES/images ; then
	    (
	    cd $BUILD_ROOT/$TOPDIR/SOURCES/images
	    for r in */* ; do
		test -L $r && continue
		test -d $r || continue
		for t in $r/root.tar* ; do
		    test -f $t || continue
		    mkdir -p $r/root
		    chroot $BUILD_ROOT tar -C $TOPDIR/SOURCES/images/$r/root -xf "$TOPDIR/SOURCES/images/$r/$t{##*/}"
		done
		# create compatibility link
		rc="${r//:/:/}"
		if test "$rc" != "$r" ; then
		    rl="${rc//[^\/]}"
		    rl="${rl//?/../}"
		    mkdir -p "${rc%/*}"
		    ln -s $rl$r "${rc%/*}/${rc##*/}"
		fi
	    done
	    )
	fi
	rm -f $BUILD_ROOT/$TOPDIR/SOURCES/config.xml
	ln -s $SPECFILE $BUILD_ROOT/$TOPDIR/SOURCES/config.xml
	imagetype=$(perl -I$BUILD_DIR -MBuild::Kiwi -e Build::Kiwi::show $BUILD_ROOT/$TOPDIR/SOURCES/$SPECFILE imagetype)
	imagename=$(perl -I$BUILD_DIR -MBuild::Kiwi -e Build::Kiwi::show $BUILD_ROOT/$TOPDIR/SOURCES/$SPECFILE filename)
	imageversion=$(perl -I$BUILD_DIR -MBuild::Kiwi -e Build::Kiwi::show $BUILD_ROOT/$TOPDIR/SOURCES/$SPECFILE version)
	chroot $BUILD_ROOT su -c "kiwi --version" -
	if test "$imagetype" = product ; then
	    echo "running kiwi --create-instsource..."
	    chroot $BUILD_ROOT su -c "kiwi --root $TOPDIR/KIWIROOT -v -v --instsource-local --logfile terminal -p $TOPDIR/SOURCES --create-instsource $TOPDIR/SOURCES" - $BUILD_USER < /dev/null && BUILD_SUCCEEDED=true
	    for i in $BUILD_ROOT/$TOPDIR/KIWIROOT/main/* ; do
		test -d "$i" || continue
		n="${i##*/}"
		test "$n" = scripts && continue
		test "$n" != "${n%0}" && continue
		chroot $BUILD_ROOT su -c "suse-isolinux $TOPDIR/KIWIROOT/main/$n $TOPDIR/KIWI/$n.iso" - $BUILD_USER
	    done
	else
	    BUILD_SUCCEEDED=true
	    for imgtype in $imagetype ; do
		echo "running kiwi --prepare for $imgtype..."
		if chroot $BUILD_ROOT su -c "cd $TOPDIR/SOURCES && kiwi --prepare $TOPDIR/SOURCES --logfile terminal --root $TOPDIR/KIWIROOT-$imgtype" - $BUILD_USER < /dev/null ; then
		    echo "running kiwi --create for $imgtype..."
		    mkdir -p $BUILD_ROOT/$TOPDIR/KIWI-$imgtype
		    chroot $BUILD_ROOT su -c "cd $TOPDIR/SOURCES && kiwi --create $TOPDIR/KIWIROOT-$imgtype --logfile terminal --type $imgtype -d $TOPDIR/KIWI-$imgtype" - $BUILD_USER < /dev/null || cleanup_and_exit 1
		else
                    cleanup_and_exit 1
		fi
	    done

	    # create tar.gz of images, in case it makes sense
            imagearch=`uname -m`
            for imgtype in $imagetype ; do
                case "$imgtype" in
                    oem)
            	    	pushd $BUILD_ROOT/$TOPDIR/KIWI-oem > /dev/null
                        echo "compressing images... "
                        tar cvzfS $BUILD_ROOT/$TOPDIR/KIWI/$imagename.$imagearch-$imageversion-raw.tar.gz \
                          $imagename.$imagearch-$imageversion.raw
                        popd > /dev/null
                        ;;
                    vmx)
                        pushd $BUILD_ROOT/$TOPDIR/KIWI-vmx > /dev/null
                        echo "compressing images... "
                        tar cvzfS $BUILD_ROOT/$TOPDIR/KIWI/$imagename.$imagearch-$imageversion-vmx.tar.gz \
                          $imagename.$imagearch-$imageversion.vmx \
                          $imagename.$imagearch-$imageversion.vmdk
                        
                        # don't compress ovf output
            	    	if [ -e $imagename.$imagearch-$imageversion.ovf ] ; then
            	          mv $imagename.$imagearch-$imageversion.ovf $BUILD_ROOT/$TOPDIR/KIWI/
            	          mv $imagename.$imagearch-$imageversion-disk*.vmdk $BUILD_ROOT/$TOPDIR/KIWI/
            	     	fi
            	    	popd > /dev/null
                        ;;
                    xen)
                        pushd $BUILD_ROOT/$TOPDIR/KIWI-xen > /dev/null
                        echo "compressing images... "
                        tar cvzfS $BUILD_ROOT/$TOPDIR/KIWI/$imagename.$imagearch-$imageversion-xen.tar.gz \
                          `grep ^kernel $imagename.$imagearch-$imageversion.xenconfig | cut -d'"'  -f2` \
                          `grep ^ramdisk $imagename.$imagearch-$imageversion.xenconfig | cut -d'"'  -f2` \
                          $imagename.$imagearch-$imageversion.xenconfig \
                          $imagename.$imagearch-$imageversion
            	    	popd > /dev/null
                        ;;
                    pxe)
                        pushd $BUILD_ROOT/$TOPDIR/KIWI-pxe > /dev/null
                        echo "compressing images... "
                        tar cvzfS $BUILD_ROOT/$TOPDIR/KIWI/$imagename.$imagearch-$imageversion-pxe.tar.gz \
                          $imagename.$imagearch-$imageversion.config \
                          $imagename.$imagearch-$imageversion.gz \
                          initrd-*
            	    	popd > /dev/null
                        ;;
                    *)
                        pushd $BUILD_ROOT/$TOPDIR/KIWI-$imgtype > /dev/null
                        echo "compressing unkown images... "
                        tar cvzfS $BUILD_ROOT/$TOPDIR/KIWI/$imagename.$imagearch-$imageversion-$imgtype.tar.gz \
                          *
            	    	popd > /dev/null
                        ;;
                esac
            done
	fi
    fi

    test "$BUILD_SUCCEEDED" = true || cleanup_and_exit 1
    test -d "$SRCDIR" && cd "$SRCDIR"
done

RPMS=`find $BUILD_ROOT/$TOPDIR/RPMS -type f -name "*.rpm"`

if test -n "$RPMS" -a -n "$BUILD_USER_ABUILD_USED" ; then
    echo "... checking for files with abuild user/group"
    BADFILE=
    while read un gn fn ; do
	if test "$un" = abuild -o "$gn" = abuild -o "$un" = 399 -o "$gn" = 399 ; then
	    echo "  $un $gn $fn"
	    BADFILE=true
	fi
    done < <(rpm -qp --qf '[%{FILEUSERNAME} %{FILEGROUPNAME} %{FILENAMES}\n]' $RPMS)
    if test -n "$BADFILE" ; then
	echo "please fix your filelist (e.g. add defattr)"
	cleanup_and_exit 1
    fi
fi

if test -n "$RPMS" -a -d "$BUILD_ROOT/usr/lib/build/checks" ; then
    mount -n -tproc none $BUILD_ROOT/proc 2> /dev/null
    export PNAME=""
    export DO_RPM_REMOVE=true
    for SRPM in $BUILD_ROOT/$TOPDIR/SRPMS/*src.rpm ; do
	test -f "$SRPM" && PNAME=`rpm --nodigest --nosignature -qp --qf "%{NAME}" $SRPM`
    done
    for CHECKSCRIPT in $BUILD_ROOT/usr/lib/build/checks/* ; do
	echo "... running `basename $CHECKSCRIPT`"
	$CHECKSCRIPT || cleanup_and_exit 1
    done
    umount -n $BUILD_ROOT/proc 2> /dev/null
fi

if test -n "$RPMS" -a "$DO_CHECKS" != "false" -a -x "$BUILD_ROOT/opt/testing/bin/rpmlint" -a -d "$BUILD_ROOT/$TOPDIR/RPMS" ; then
    LINT_RPM_FILE_LIST=($(find $BUILD_ROOT/$TOPDIR/RPMS \
        \( -name "*-debuginfo-*" -o -name "*-debugsource-*" \
        -o -name "*-32bit-*" -o -name "*-64bit-*" \
        -o -name "*-x86-*" -o -name "*-ia32-*" \) -prune \
        -o -type f -name '*.rpm' -print))
    SRPM_FILE_LIST=($(find $BUILD_ROOT/$TOPDIR/SRPMS -type f -name "*.rpm"))
    echo
    echo "RPMLINT report:"
    echo "==============="
    chroot $BUILD_ROOT /opt/testing/bin/rpmlint --info ${LINT_RPM_FILE_LIST[*]#$BUILD_ROOT} ${SRPM_FILE_LIST[*]#$BUILD_ROOT} || cleanup_and_exit 1
fi

if test -n "$RPMS" -a -n "$CREATE_BASELIBS" -a -d "$BUILD_ROOT/$TOPDIR/RPMS" ; then
    if test -f $BUILD_ROOT/usr/lib/build/mkbaselibs -o "$CREATE_BASELIBS" != internal ; then
	mount -n -tproc none $BUILD_ROOT/proc 2> /dev/null
	create_baselibs
	umount -n $BUILD_ROOT/proc 2> /dev/null
    fi
fi

# IMPLEMENT ME: place code for creating binary package deltas here

if test -n "$RUNNING_IN_VM" -a -n "$VM_SWAP"; then
    echo "... saving built packages"
    swapoff "$VM_SWAP"
    $BUILD_DIR/extractbuild "$VM_SWAP" || cleanup_and_exit 1
fi

if test -n "$RPMS" -a -d "$BUILD_ROOT/$TOPDIR/RPMS" -a -d "$BUILD_ROOT/.build.oldpackages" -a -x "$BUILD_ROOT/usr/lib/build/same-build-result.sh" ; then
    echo "... comparing built packages with the former built"
    # exit with 2, if packages built successfull, but have no changes to former built packages.
    chroot $BUILD_ROOT /usr/lib/build/same-build-result.sh /.build.oldpackages "$TOPDIR/RPMS" "$TOPDIR/SRPMS" && cleanup_and_exit 2
fi

echo "... build is finished"
cleanup_and_exit 0
