#!/bin/bash
#
# --- T2-COPYRIGHT-NOTE-BEGIN ---
# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
# 
# T2 SDE: scripts/Build-Pkg
# Copyright (C) 2004 - 2010 The T2 SDE Project
# Copyright (C) 1998 - 2003 ROCK Linux Project
# 
# More information can be found in the files COPYING and README.
# 
# 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; version 2 of the License. A copy of the
# GNU General Public License can be found in the file COPYING.
# --- T2-COPYRIGHT-NOTE-END ---

exec 2>&1

buildstart="`date "+%m/%d/%Y from %T"`"

options=''
config=default

clear_src=1
norebuild=0
update=0

make_tar=''
prefix="usr"
prefix_auto=1
verbose=0
xtrace=0
debug=0
chroot=0
root=""
id=''

stagelevel=9
this_is_the_2nd_run=0

#
# ----  Functions
#


help_msg() {
	spacer="                          "
	echo
	echo "Usage: ./scripts/Build-Pkg" \
	             "[ -0 | -1 | -2  ... | -8 | -9 ]           \\"
	echo "$spacer [ -v ]  [ -xtrace ]  [ -chroot ]          \\"
	echo "$spacer [ -root { <rootdir> | auto } ]            \\"
	echo "$spacer [ -cfg <config> ]  [ -update ]            \\"
	echo "$spacer [ -prefix <prefix-dir> ]  [ -norebuild ]  \\"
	echo "$spacer [ -noclearsrc ]                           \\"
	echo "$spacer [ -id <id> ]  [ -debug ]  pkg-name(s)"
	echo
}


#
# ---- Parse options + config and make Build-Pkg sub-calls
#

while [ "$1" ] ; do
	case "$1" in
		-this_is_the_2nd_run) this_is_the_2nd_run=1 ;;
		-[0-9])   options="$options $1"    ; stagelevel=${1#-} ;;
		-v)       options="$options $1"    ; verbose=1     ;;
		-xtrace)  options="$options $1"    ; xtrace=1      ;;
		-debug)   options="$options $1"    ; debug=1 ; clear_src=0 ;;
		-update)  options="$options $1"    ; update=1      ;;
		-chroot)  options="$options $1"    ; chroot=1      ;;
		-chr-sub) options="$options $1"    ; chroot=0      ;;
		-cfg)     options="$options $1 $2" ; config="$2"   ; shift ;;
		-root)    options="$options $1 $2" ; root="$2"     ; shift ;;
		-prefix)  options="$options $1 $2" ;
				prefix_auto=0      ; prefix="$2"   ; shift ;;
		-id)      options="$options $1 $2" ; id="$2"       ; shift ;;
		-noclearsrc) options="$options $1" ; clear_src=0   ;;
		-norebuild)  options="$options $1" ; norebuild=1   ;;
		-*) help_msg ; exit 1 ;;
		*)  break ;;
	esac
	shift
done

# check if arguments are left as package names
if [ $# = 0 ] ; then 
	help_msg ; exit 1
fi

. scripts/functions.in
. scripts/parse-config

if [ -z "$root" -a $stagelevel -le 1 ] ||
   [ -z "$root" -a $chroot -eq 1 ] ||
   [ "$root" = auto ]; then
	# stage 0 cross compiler build
	if [ $stagelevel -eq 0 ]; then root="build/$SDECFG_ID/TOOLCHAIN/$toolsdir"
	# the new systems root
	else root="build/$SDECFG_ID"; fi
fi

[ "$root" -a "${root#/}" = "$root" ] && root="$base/$root"

# remove leading and trailing / on prefix and root
prefix=${prefix%/} ; prefix=${prefix#/} ; root=${root%/}

# xroot is for internal use and always points to the new system
xroot="$root"
if [ $stagelevel -le 1 ]; then
	sysroot="$base/build/$SDECFG_ID" # always fresh sandbox
else
	root=
	sysroot=
fi


if [ -z "$id" ] ; then
	id=`get_unique`
	options="$options -id $id"
fi

# more than one package is passed
if [ $# -gt 1 ] ; then 
    for x ; do
	if ! ./scripts/Build-Pkg $options $x && \
	   [ $stagelevel -le $SDECFG_CONTINUE_ON_ERROR_AFTER ]; then
		exit 1
	fi
    done
    exit 0
fi
pkg="${1%=*}" ; xpkg="${1#*=}"
builddir="$base/src.$pkg.$config.$id"

if [ "$chroot" = 1 ] ; then

	cd "$xroot" || exit 1

	x_mknod() {
		if [ ! -c "$1" -a ! -b "$1" ]; then
			mknod "$@"
		fi
	}

	mkdir -p dev/loop
	x_mknod dev/null     c 1 3
	x_mknod dev/zero     c 1 5
	x_mknod dev/random   c 1 8
	x_mknod dev/urandom  c 1 9
	x_mknod dev/loop/0   b 7 0 
	x_mknod dev/loop/1   b 7 1 
	x_mknod dev/loop/2   b 7 2 
	x_mknod dev/loop/3   b 7 3 
	#_mknod dev/tty      c 5 0

	if [ ! -L dev/fd ]; then
		ln -s /proc/self/fd dev/fd
	fi

	realconf=$(cd $base/config; pwd -P)
	realdown=$(cd $base/download; pwd -P)
	realbase=$(dirname $(cd $base/scripts; pwd -P))

	if [ ! -e TOOLCHAIN/loop/scripts ]; then
		mkdir -p TOOLCHAIN/{loop,config,download}
		mount --bind $realbase TOOLCHAIN/loop
		mount --bind $realconf TOOLCHAIN/config
		mount --bind $realdown TOOLCHAIN/download
	fi

	if [ ! -f proc/mounts ]; then
		mount -nt proc none proc
	fi

	for x in architecture kernel misc package scripts target; do
		if [ ! -e TOOLCHAIN/$x ]; then ln -s "loop/$x" "TOOLCHAIN/$x"; fi
	done

	if [ ! -e "TOOLCHAIN/build/$SDECFG_ID" ]; then
		mkdir -p "TOOLCHAIN/build"
		ln -snf ../.. "TOOLCHAIN/build/$SDECFG_ID"
	fi

	mkdir -p "TOOLCHAIN/src.$pkg.$config.$id"
	ln -s "$PWD/TOOLCHAIN/src.$pkg.$config.$id" "$builddir"

	cat > $builddir/chroot.sh <<- EOT
		export SDE_THIS_IS_CHROOT=1; cd /TOOLCHAIN
		./scripts/Build-Pkg $options -chr-sub -root "/" "$1"
	EOT

	cat > $builddir/debug.sh <<- EOT
		#!/bin/bash
		if [ ! -f "$xroot/proc/mounts" ]; then
		    mount -nt proc none "$xroot/proc"
		fi
		if [ ! -e "$xroot/TOOLCHAIN/loop/scripts" ]; then
		    mkdir -p "$xroot/"TOOLCHAIN/{loop,config,download}
		    mount --bind $realbase "$xroot/TOOLCHAIN/loop"
		    mount --bind $realconf "$xroot/TOOLCHAIN/config"
		    mount --bind $realdown "$xroot/TOOLCHAIN/download"
		fi

		export SDE_THIS_IS_CHROOT=1
		chroot "$xroot" /bin/bash TOOLCHAIN/src.$pkg.$config.$id/debug_x.sh

		if ! fuser -s "$xroot/TOOLCHAIN/" ; then
			echo "Loop mounts appear unused - un-mounting ..."
			umount "$xroot/TOOLCHAIN/"{loop,config,download}
			umount "$xroot/proc"
		fi
	EOT
	chmod +x $builddir/debug.sh

	if [ "$TZ" ] ; then
		if [ "${TZ#/}" != "$TZ" ] ; then
			cp $TZ TOOLCHAIN/localtime
		else
			cp /usr/share/zoneinfo/$TZ TOOLCHAIN/localtime
		fi
	else
		if [ -f /etc/localtime ] ; then
			cp /etc/localtime TOOLCHAIN/localtime
		else
			ln -sf /usr/share/zoneinfo/Factory TOOLCHAIN/localtime
		fi
	fi

	if [ "$SDECFG_PKG_DISTCC_HOST_RESOLV" = "1" ]; then
	    cat /etc/resolv.conf > etc/resolv.conf
	fi

	TZ="/TOOLCHAIN/localtime" chroot . bin/bash TOOLCHAIN/src.$pkg.$config.$id/chroot.sh
	returncode=$?

	if [ ! -d "$builddir/." ]; then
		rm "$builddir"
	fi

	exit $returncode
fi

./scripts/Build-Tools -$stagelevel -cfg $config || exit 1

if [ "$SDECFG_FLIST" = "flwrapper" -a -z "$FLWRAPPER" ] ; then
	export FLWRAPPER_WLOG="$builddir/fl_wrapper.wlog"
	export FLWRAPPER_RLOG="$builddir/fl_wrapper.rlog"
	export FLWRAPPER_BASEPID=$$
	export FLWRAPPER_FILTERDIR="/tmp/:$builddir"
	[ "$LD_PRELOAD" ] && LD_PRELOAD="${LD_PRELOAD}:"
	export FLWRAPPER="$base/build/$SDECFG_ID/TOOLCHAIN/$toolsdir/lib/fl_wrapper.so"
	export LD_PRELOAD="${LD_PRELOAD}$FLWRAPPER"
fi
export INSTALL_WRAPPER_LOGFILE="$builddir/install_wrapper.log"
export CMD_WRAPPER_LOGFILE="$builddir/cmd_wrapper.log"

if [ $norebuild = 1 -a -f $root/var/adm/logs/$stagelevel-$xpkg.log ] ; then
	echo_pkg_deny $stagelevel $pkg "already built"
	exit 0
fi

# TODO: should i be pedantic and force rebuild of low stages even if $norebuild? /mnemoc
if [ "$SDECFG_RETRY_BROKEN" = 0 -a $norebuild = 1 -a \
     -f $root/var/adm/logs/$stagelevel-$xpkg.err ] ; then
	echo_pkg_deny $stagelevel $pkg "already failed"
	exit 1
fi

archdir="$builddir/archdir"

detect_confdir

if [ -z "$confdir" ] ; then
	echo_pkg_deny $stagelevel $pkg "does not exist" ; exit 1
fi

mkdir -p $root/var/adm/logs
mkdir -p $root/var/adm/flists
mkdir -p $root/var/adm/olists
mkdir -p $root/var/adm/md5sums
mkdir -p $root/var/adm/packages
mkdir -p $root/var/adm/dependencies
mkdir -p $root/var/adm/dep-debug
mkdir -p $root/var/adm/parse-config
mkdir -p $root/var/adm/cache
mkdir -p $root/var/adm/descs
[ "$root" ] && chmod 700 $root

rm -f $root/var/adm/logs/$stagelevel-$xpkg.out
rm -f $root/var/adm/logs/$stagelevel-$xpkg.log
rm -f $root/var/adm/logs/$stagelevel-$xpkg.err

if [ $this_is_the_2nd_run = 0 ] ; then
	[ $stagelevel -gt 1 ] && . /etc/profile
	options="-this_is_the_2nd_run $options $pkg=$xpkg"
	if [ "$SDECFG_CREATE_CACHE" = 1 -a $stagelevel -gt 1 ] ; then

		mkdir -p $root/var/adm/cache
		rm -f $root/var/adm/cache/$xpkg
		rm -f $root/var/adm/cache/$xpkg.tm

		/usr/bin/time -o "$root/var/adm/cache/$xpkg.tm" \
		              -f 'buildtime=$(qcalc %U + %S)' $0 $options
		returncode=$?
		[ ! -e "$root/var/adm/cache/$xpkg.tm" ] && exit $returncode

		qcalc() { gawk "BEGIN { printf(\"%d\n\", ($*)*100); }"; }
		eval "`grep -v '^Command ' < $root/var/adm/cache/$xpkg.tm`"
		rm -f $root/var/adm/cache/$xpkg.tm

		# store reference time
		if [ $pkg = binutils ]; then
			echo $buildtime > $sysroot/TOOLCHAIN/reftime
		fi
		# compute relative build time to binutils (LFS-style)
		if [ -e $root/TOOLCHAIN/reftime ]; then
			reftime=`cat $root/TOOLCHAIN/reftime`
		else
			reftime=$buildtime # so until we have a ref all will be 100%
		fi
		# quantisized to 5% steps
		buildtime=`gawk "BEGIN { printf(\"%d\n\", int($buildtime * 20 / $reftime) * 5 ); }"`

		{
			date '+%n[TIMESTAMP] %s %c'

			[ -f $root/var/adm/logs/$stagelevel-$xpkg.err ] &&
				x=" ERROR" || x=""

			echo "[BUILDTIME] $buildtime ($stagelevel)$x"

			x="$root/var/adm/packages/$xpkg"
			if [ -f $x ]; then
				echo "[SIZE] `grep "^Package Size: " \
						$x | cut -f3- -d' '`"
			fi
			echo

			x="$root/var/adm/dependencies/$xpkg"
			[ "$pkg" != "t2-debug" -a -f $x ] &&
				sed 's,^[^:]*:,[DEP],' $x
		} > $root/var/adm/cache/$xpkg

		exit $returncode
	else
		exec $0 $options
	fi
fi


#
# ----  Setting Build Variables
#

flistroot="bin boot etc lib lib64 sbin usr var opt"

# remove the obvious noise: ldconfig and our /var/adm as well as due to
# rare i18n locale directories ...
flistrfilter="ldconfig\..*:	.*|.*:	/var/adm/.*|.*:	.*/share/locale/.*"

flistdel="etc/ld.so.cache|etc/blkid.tab|var/tmp/.*|usr/tmp/.*|var/adm/logs/.*|.*\\.old"
flistvalid="$base|/tmp|/var/backups|/proc|/dev"
foodirlist="bindir sbindir libdir datadir includedir sysconfdir localstatedir docdir"

init_vars_and_hooks

#
# ---- Read various config files
#

parse_desc $pkg

echo_pkg_start $stagelevel $repository $xpkg $ver $extraver

if [ "$SDECFG_PARANOIA_CHECK" = 1 ] ; then
        x="`./scripts/Check-PkgFormat $pkg`"
	[ "$x" ] && abort "$x\nDisable the 'Paranoia Check' config `
	                  `option to ignore such errors."
fi

targetdir="$base/target/$target"

detect_patchfiles

if [ $stagelevel -eq 0 ]; then
	var_append patchfiles ' ' "`ls $confdir/*.patch.cross0{,.$arch} \
	                            2>/dev/null | tr '\n' ' '`"
fi

if [ $stagelevel -le 1 ]; then
	var_append patchfiles ' ' "`ls $confdir/*.patch.cross{,.$arch} \
	                            2>/dev/null | tr '\n' ' '`"
fi

if [ $stagelevel -gt 1 ]; then
	for pc_file in $xroot/var/adm/parse-config/* ; do
		if [ -s "$pc_file" -a "${pc_file##*/}" != "$xpkg" ]
		then . "$pc_file" ; fi
	done
	unset pc_file
fi
. $base/build/$SDECFG_ID/TOOLCHAIN/$toolsdir/lib/parse-config

set_confopt

# Erase positional parameters to prevent unintended parameter
# passing. We do not want to pass the current positional parameters
# to the loaded script.
set --
eval "$desc_O"

# include package pre config - if any
if [ -f $base/build/$SDECFG_ID/TOOLCHAIN/$toolsdir/lib/pkg_${pkg}_pre.conf ] ; then
	echo_status "Reading build/.../$toolsdir/lib/pkg_${pkg}_pre.conf"
	. $base/build/$SDECFG_ID/TOOLCHAIN/$toolsdir/lib/pkg_${pkg}_pre.conf
fi

# read the package configuration, $confdir might differ from package/*/$pkg ...
for x in $( get_expanded $base/target/%/pkg_$pkg.conf $targetchain ) \
	$targetdir/package/$pkg/$pkg.conf \
	architecture/$arch/package/$pkg/$pkg.conf \
	$confdir/$pkg.conf \
	$base/package/*/$pkg/$pkg.conf; do
	if [ -f $x ]; then
		echo_status "Reading package config: ${x#$base/}"
		. $x
		break
	fi
done

# include package post config - if any
if [ -f $base/build/$SDECFG_ID/TOOLCHAIN/$toolsdir/lib/pkg_${pkg}_post.conf ] ; then
	echo_status "Reading build/.../$toolsdir/lib/pkg_${pkg}_post.conf"
	. $base/build/$SDECFG_ID/TOOLCHAIN/$toolsdir/lib/pkg_${pkg}_post.conf
fi

if [ -f $base/architecture/$arch/pkg-header ] ; then
	echo_status "Reading overwrites from architecture/$arch/pkg-header."
	. $base/architecture/$arch/pkg-header
fi

for x in $( get_expanded $base/target/%/pkg-header `get_reverted $targetchain` ); do
	if [ -f $x ] ; then
		echo_status "Reading overwrites from ${x#$base/}."
		. $x
	fi
done

#
# ---- Variable updates based on the configuration files read
#

if [ -z "$prefix" -o "${prefix#usr}" != "$prefix" ] ; then
	flistdel="$flistdel|usr/share/info/(dir|standards.info)"
	if [ "$SDECFG_DISABLE_NLS" = 1 ] ; then
		flistdel="$flistdel|usr/share/locale/..[/_].*"
		flistdel="$flistdel|usr/share/man/..[/_].*"
	fi
else
	flistdel="$flistdel|$prefix/info/(dir|standards.info)"
	if [ "$SDECFG_DISABLE_NLS" = 1 ] ; then
		flistdel="$flistdel|$prefix/share/locale/..[/_].*"
		flistdel="$flistdel|$prefix/man/..[/_].*"
	fi
fi

#
# ----  Build Package
#

echo_status "Preparing build in src.$pkg.$config.$id"

if [ $clear_src = 1 ] ; then
	mkdir -p $builddir; chmod 700 $builddir
	if [ "$SDECFG_SRC_TMPFS" = 1 ]; then
		mount -n -t tmpfs -o $SDECFG_SRC_TMPFS_OPT none $builddir
	fi
else
	mkdir -p $builddir; chmod 700 $builddir
fi

if [ $update = 1 -a ! -f $xroot/var/adm/md5sums/$xpkg ] ; then
	echo_status "Ignoring update mode since package isn't installed already."
	update=0
fi

if [ $update = 1 ] ; then
	echo_status "Creating backup of old package data."
	(
		cd $xroot/
		md5sum --check var/adm/md5sums/$xpkg 2>&1 < /dev/null |
			grep ': FAILED$' | cut -f1 -d:
	) > $builddir/backup_files.txt
	if [ -s $builddir/backup_files.txt ] ; then
		mkdir -p "$xroot/var/adm/backup"
		chmod 700 "$xroot/var/adm/backup"
		backup_tar="$xroot/var/adm/backup/$(
			date '+%Y%m%d%H%M%S')_$xpkg.tar.bz2"
		( cd $xroot/; tar --no-recursion -cf - -T $builddir/`
			`backup_files.txt || true; ) | bzip2 > $backup_tar
	else
		update=0
	fi
fi

if [ "$SDECFG_FLIST" = "flwrapper" ] ; then
	rm -f $builddir/fl_wrapper.wlog $builddir/fl_wrapper.rlog
	touch $builddir/fl_wrapper.wlog $builddir/fl_wrapper.rlog
elif [ "$SDECFG_FLIST" = "find" ] ; then
	touch $builddir/temp.time_stamp
	sleep 2
fi

hook_eval prepare

# define new abort function for errors while building
#
abort() {
	[ "$*" ] && echo "$*"; echo "--- BUILD ERROR ---"
	rm -vf $root/var/adm/logs/$stagelevel-$xpkg.log
	false
}

{
	trap 'echo "Got SIGINT (Ctrl-C). Aborting build." ; exit 1' INT
	exec < /dev/null

	# Makes debugging build problems easier
	#
	hook_dump > $builddir/debug.hooks
	#
	{
	  dump_env
	  cat <<- EOT
		PS1='\\[\\e[00m\\e[01;31m\\]debug-`
					`$xpkg\\[\\e[00m\\]:[\\W]\\\$ '
		alias cp="cp -i" ; alias mv="mv -i"
		alias rm="rm -i" ; alias ls="ls --color=auto -a"
		alias ..="cd .." ; alias ...="cd ../.."
		fixfile () {
		  # we use .vanilla to not rediff backup .orig from patch
		  [ -f \$1.vanilla ] || cp \$1 \$1.vanilla
		  # maybe we do not have the editor yet?
		  which \$EDITOR > /dev/null || EDITOR=nvi
		  \$EDITOR \$1
		}
		fixfilediff() {
		  find -name '*.vanilla' -printf '%P\n' | while read x ; do
		    diff -u \$x \${x/.vanilla/}
		  done
		}
		EOT
	} > $builddir/debug.buildenv
	#
	cat > $builddir/debug_x.sh <<- EOT
		#!/bin/bash
		cd $builddir; exec bash --rcfile debug.buildenv 200>> build.pid
	EOT
	#
	if [ "$SDE_THIS_IS_CHROOT" != 1 ]; then
		mv $builddir/debug_x.sh $builddir/debug.sh
		chmod +x $builddir/debug.sh
	fi

	# Create PID file
	#
	# The builtin-variable '$$' is not this pid because this proc
	# is just a sub-proc of $$. That's why the $builddir/strace.tmp
	# hack is required to get the right pid to trace.
	#
	# We also conntect filedescriptor 3 with the pid file. So the command
	# 'fuser' can be used to create a list of all processes which are part
	# of this build process.
	#
	sh -c 'echo $PPID' > $builddir/build.pid
	exec 200>> $builddir/build.pid

	echo "Command Wrapper Debug: running '${CC} --version' .."
	type ${CC}; CMD_WRAPPER_DEBUG=1 ${CC} --version
	echo "[ writing debug log to $builddir/cmd_wrapper.log ]"

	if [ "$debug" = 1 ] ; then
		echo "Everything is set up." \
		     "We are in debug mode - so exit now."
		exit
	fi

	if [ "$SDECFG_FLIST" = "strace" ] ; then
		strace -o $builddir/strace.out -F -f -q -e open,creat,mkdir,`
		       `mknod,link,symlink,rename,utime,chdir,execve,fork,`
                       `vfork,_exit,exit_group -p `cat $builddir/build.pid` &
                 strace_pid=$! ; sleep 1 ; cd $base
	fi

	(
		set -e

		mkdir -p "$builddir/archdir"
		populate_archdir

		echo "Running main build function '$mainfunction' ..."
		if [ $xtrace -eq 1 -o $SDECFG_XTRACE -eq 1 ] ;	then
			PS4=$'=[$FUNCNAME:$LINENO (last \\\$?=$?)> ' ; set -o xtrace
			cd $builddir ; eval "$mainfunction"
			set +o xtrace
		else
			cd $builddir ; eval "$mainfunction"
		fi
		touch $root/var/adm/logs/$stagelevel-$xpkg.log
	)
	[ -f $root/var/adm/logs/$stagelevel-$xpkg.log ] ||
	  abort "Due to previous errors, no $stagelevel-$xpkg.log file!
(Try enabling xtrace in the config to track an error inside the build system.)"

	hook_eval postinstall

	echo "Creating file list and doing final adaptions ... "
	#
	cd $xroot/
	[ -s "var/adm/parse-config/$xpkg" ] &&
		echo "var/adm/parse-config/$xpkg" >> $builddir/flist.txt
	for x in var/adm/flists/$xpkg var/adm/md5sums/$xpkg \
	         var/adm/packages/$xpkg \
	         var/adm/descs/$xpkg var/adm/dependencies/$xpkg ; do
			touch $x ; echo "$x" >> $builddir/flist.txt
	done
	#
	if [ "$SDECFG_FLIST" = "strace" ] ; then
		sleep 1 ; kill -INT $strace_pid ; sleep 1
		fl_stparse -w $builddir/fl_wrapper.wlog \
			   -r $builddir/fl_wrapper.rlog < $builddir/strace.out
		
	fi
	if [ "$SDECFG_FLIST" = "flwrapper" -o \
	     "$SDECFG_FLIST" = "strace" ] ; then
		if [ "$stagelevel" -le 1 ]
		then
			xbase="$( cd $xroot/ 2> /dev/null ; pwd -P )"
			flistvalid="$xbase|$flistvalid"
			
			if egrep -qv "	($flistvalid)/" $builddir/fl_wrapper.wlog
			then
				while read file ; do
					if [ -e "$file" ] ; then
						echo "Created file outside basedir: $file"
						abort_soon=1
					else # non fatal for now (configure junk)
						echo "Created (vanished) file outside basedir (ignored): $file"
					fi
				done < <( egrep -v "	($flistvalid)/" \
				          $builddir/fl_wrapper.wlog |
				          cut -f2- | sort -u )

				echo "base #1: $base"
				echo "base #2: $xbase"
				[ "$abort_soon" = 1 ] && abort
			fi
		fi

		fl_wrparse -D -s -r "$xroot/" < $builddir/fl_wrapper.wlog > \
			$builddir/flist.txt.tmp

		# check for file creation beside the allowed top-level
		# directories - allow root since qt, wxwidgets, ... create some
		# profile there ... - on stage 0 we have an ugly symlink hack
		# so we get doc, $arch_machine, ... in the top level dir :-(
		if [ $stagelevel -gt 0 ]; then
		  fr="$flistroot root TOOLCHAIN"

		  while read file; do
			echo "Created file outside allowed top-level dir: $file"
			abort_soon=1
		  done < <( egrep -v "^(${fr// /|})(/|$)" \
		         $builddir/flist.txt.tmp )
		  [ "$abort_soon" = 1 ] && abort
		fi

		egrep "^(${flistroot// /|})(/|$)" $builddir/flist.txt.tmp >> \
			 $builddir/flist.txt

	elif [ "$SDECFG_FLIST" = "find" ] ; then
		find $flistroot \
			\( -not -type d -or -type d -empty \) \
			-and \( -newer $builddir/temp.time_stamp -or \
			-cnewer $builddir/temp.time_stamp \) -printf "%p\n" >> \
			$builddir/flist.txt
	fi

	# evaluate flistdel
	egrep -v "^($flistdel)\$" $builddir/flist.txt > $builddir/flist.txt.new
	mv $builddir/flist.txt{.new,}

	hook_eval postflist

	# save the old flist for later orphaned file check
	[ -e var/adm/flists/$xpkg ] &&
        	cp -f var/adm/flists/$xpkg $builddir/flist.txt.old

	fl_wrparse -D -p "$xpkg" -r "$xroot/" < $builddir/flist.txt |
			sort -u > $builddir/flist.txt.new

        # analyze which files have not been reinstalled and thus are (normally)
        # no longer needed (orphaned)
	if [ -e $builddir/flist.txt.old ]; then
		echo "Searching for orphaned files ..."
		diff --normal $builddir/flist.txt.{old,new} |
		grep '^<' | cut -d ' ' -f 2- > $builddir/olist.txt.new
		[ -e var/adm/olists/$xpkg ] &&
			cp -f var/adm/olists/$xpkg $builddir/olist.txt.old ||
			touch $builddir/olist.txt.old
		cat $builddir/olist.txt.{old,new} | sort -u > \
			var/adm/olists/$xpkg
	fi

	# until all olist regressions are fixed merge the two lists ... :-(
	touch  $builddir/flist.txt.old
	cat $builddir/flist.txt.{old,new} | egrep -v "^$xpkg: ($flistdel)\$" |
		sort -u > var/adm/flists/$xpkg
	echo Found `wc -l < var/adm/flists/$xpkg` "files for this package."
	echo Found `wc -l < var/adm/olists/$xpkg` "orphaned files for this package."

	echo "Clear (old) md5sums ..."
	echo -n > var/adm/md5sums/$xpkg

	if [ "$SDECFG_FLIST" = "flwrapper" -o \
	     "$SDECFG_FLIST" = "strace" ] && [ $stagelevel -gt 1 ] ; then
		echo "Calculating package dependencies ..."

		! egrep -v "^($flistrfilter)\$" $builddir/fl_wrapper.[rw]log |
		sort -u | fl_wrparse -D -s -r "$xroot/" -p '' | sort -u |
		grep -v ' var/adm/' | awk '
			# read the var/adm/... file content in
			ARGIND < ARGC-1 {
			    if ( $1 != "'$xpkg':" )
				f[$2] = $1 " " f[$2];
			}
			# iterate over the read file list streamed to stdin
			ARGIND == ARGC-1 {
			    file = $2;
				if ( f[file] ) {
				    print f[file] " " file;
				}
			}
		' var/adm/flists/* - >> $builddir/dependencies.debug

		awk 'BEGIN { FS=": "; } { print "'$xpkg': " $1; }' \
			<  $builddir/dependencies.debug \
			>> $builddir/dependencies.txt

		sort -u $builddir/dependencies.debug > var/adm/dep-debug/$xpkg

		# merge the dependencies defined by the package
		for x in `echo "$desc_E" | egrep '^add ' | sed 's/^add //' ` ; do
			echo "Adding dependency: $x ..."
			echo "$xpkg: $x" >> $builddir/dependencies.txt
		done

		# remove dependencies as requested by the package
		# TODO: goups are not used yet (and it is not easy here)
		del_pattern=""
		for x in `echo "$desc_E" | egrep '^del ' | sed 's/^del //' ` ; do
			del_pattern="$del_pattern -e \".*: $x\$\""  
		done
		if [ -n "$del_pattern" ] ; then
			echo "Deleting dependencies, pattern: $del_pattern ..."
			eval egrep -v $del_pattern \
			  $builddir/dependencies.txt > \
			  $builddir/dependencies.txt.new
			mv $builddir/dependencies.txt{.new,}
		fi

		sort -u $builddir/dependencies.txt > var/adm/dependencies/$xpkg
	fi

	echo -n "Creating md5sum files ..."
	getfiles < var/adm/flists/$xpkg > $builddir/files.lst
	if [ -s $builddir/files.lst ] ; then
		cat $builddir/files.lst |
			grep -v '^var/adm/' | sed -e 's,^.*,"\0",' |
			xargs -r md5sum > var/adm/md5sums/$xpkg
	fi
	echo ' done.'

	echo "Creating package description ..."
	#
	rocksrcck=$( pkgchksum $base/package/*/$pkg )
	buildlist="$( grep "^Build \[.\] at " var/adm/packages/$xpkg || true
		echo "Build [$stagelevel] at $buildstart to `date "+%T %Z"`")"
	#
	cat > var/adm/packages/$xpkg << EOT
Package Name and Version: $xpkg $ver $extraver
Package Size: `getdu $root/ < var/adm/flists/$xpkg`, `
				wc -l < var/adm/flists/$xpkg | tr -d ' '` files
T2 Package Source Checksum: $rocksrcck
T2 Version and Architecture: $sdever $arch
$buildlist
Prefix: $prefix
EOT

	# Location libdir: /opt/openldap/lib
	for x in $foodirlist; do
		if [ "`eval echo \\$$x`" != "`pkggetdir $x`" ]; then
			echo "Location $x: `eval echo \\$$x`" \
				>> var/adm/packages/$xpkg
		fi
	done

	cat >> var/adm/packages/$xpkg << EOT
Status: ${desc_S:-ALPHA},  License: ${desc_L:-Unknown}

  ${desc_I:-$xpkg}

$( echo "${desc_T:-No description available.}" | sed 's,^,  ,' )

URL(s):
$( echo "${desc_U:-http://www.t2-project.org/packages/$pkg.html}" | sed 's,^,  ,' )

Original Author(s):
$( echo "${desc_A:-Unknown}" | sed 's,^,  ,' )

Package Maintainer(s):
$( echo "${desc_M:-Unknown}" | sed 's,^,  ,' )

Download URL(s):
$( echo "${desc_D:-None}" | awk '{ print "  " $3 $2; }' )
EOT
	(
	    echo "[CONFIG] ${SDECFG_ID#*-}"
	    descfile=$base/package/*/$pkg/$pkg.desc
	    while read x ; do
		if [ "${x#\[}" != "$x" ] ; then
		    x="`echo ${x// */} | tr -d '[]'`"
		    y="${x/-/_}"
		    IFS='
'
		    eval lines=\"\${desc_$y}\"
		    for line in $lines; do
		    	echo "[$x] $line"
		    done
		fi
	    done < $base/misc/share/PKG-DESC-FORMAT
	) > var/adm/descs/$xpkg

	echo "Making post-install adaptions."

	if [ "$SDECFG_PARANOIA_CHECK" = 1 ] ; then
		found_errors=0
		found_dups=0

		# check for files which are 'shared' with other packages
		if [ "$check_shared" != "0" ]; then
			while read dummy file; do
				if [ $found_dups = 0 ] ; then
					echo "Found shared files with other packages:"
					found_errors=1; found_dups=1
				fi
				echo "$file:" $( cd $root/var/adm/flists
						 grep -l " $file\$" * )
			done < <( echo $root/var/adm/flists/* | xargs -n 128 cat | sed "s,^$xpkg:,.," | \
				  sort -k2 | uniq -d -f1 | grep '^\. ' )
		fi

		found_local=0

		# check for files in /usr/local
		if [ "$check_usrlocal" != "0" ]; then
			while read file ; do
				if [ $found_local = 0 ] ; then
					echo "Found files in /usr/local:"
					found_errors=1; found_local=1
				fi
				echo $file
			done < <( sed "s,^$xpkg: ,/," $root/var/adm/flists/$xpkg | \
				    egrep "^/usr/local" )
		fi

		found_bad=0

		# check for registered 'bad files'
		if [ "$check_badfiles" != "0"  -a -n "$badfiles" ]; then
			echo "$badfiles" > $builddir/badfiles.txt
			while read x file; do
				if [ $found_bad = 0 ]; then
					echo "Found registered 'bad files' in package:"
					found_errors=1; found_bad=1
				fi
				desc="No description found!"
				for ((x=0; x<badfiles_nr; x++)); do
					if echo " $file" | grep -q "${badfiles_desc[x]%%$'\n'*}" 
					then desc="${badfiles_desc[x]#*$'\n'}"; fi
				done
				echo "$file: $desc"
			done < <( grep -f $builddir/badfiles.txt $root/var/adm/flists/$xpkg )
		fi

		[ $found_errors != 0 ] && abort "Due to previous errors."
	fi

} 2>&1 | {

	trap '' INT

	echo_status "Building. Writing output to" \
	            "\$root/var/adm/logs/$stagelevel-$xpkg.out"

	if [ "$SDECFG_VERBOSE" = 1 -o "$verbose" = 1 ] ; then
		tee $root/var/adm/logs/$stagelevel-$xpkg.out
	else
		cat > $root/var/adm/logs/$stagelevel-$xpkg.out
	fi
}

hook_eval finish

if [ $update = 1 ] ; then
	echo_status "Restoring backup of old package data."

	while read fn ; do
		[ -f $xroot/$fn ] && mv $xroot/$fn $xroot/$fn.new
	done < $builddir/backup_files.txt

	tar --use-compress-program=bzip2 -C $xroot/ -xpf $backup_tar

	while read fn ; do
		cmp -s $fn $fn.new && rm -f $fn.new
	done < $builddir/backup_files.txt
fi

cd $base

umount -r -d -f    $builddir/* 2> /dev/null
umount -r -d -f -l $builddir/* 2> /dev/null

if [ "$SDECFG_SRC_TMPFS_LOG" = 1 -a -n "$( type -p df )" ]; then
	mkdir -p $root/var/adm/t2-debug
	if [ ! -f $root/var/adm/t2-debug/tmpfslog.txt ] ; then
		echo -e "# Config\tPackage\tInodes\tKB" | \
			expand -t20 > $root/var/adm/t2-debug/tmpfslog.txt
	fi
	echo -e "$config\t$stagelevel-$xpkg\t$(
		df 2> /dev/null -Pi $builddir | tail -n 1 | tr -s ' ' | cut -f3 -d' '
	)\t$(
		df 2> /dev/null -Pk $builddir | tail -n 1 | tr -s ' ' | cut -f3 -d' ')" | \
	expand -t20 >> $root/var/adm/t2-debug/tmpfslog.txt
fi

umount -r -d -f    $builddir   2> /dev/null
umount -r -d -f -l $builddir   2> /dev/null

# cleanup_src <error code>
# Cleanup the src.* directory the way configured.
# 
cleanup_src () {
	# cleaning the src disabled manually
	[ $clear_src = 0 ] && return

	case "$SDECFG_KEEP_SRC" in
		0)	: # always clean, just fall-thru
			;;
		1)	[ $1 != 0 ] && return # keep on error, just return
			;;
		2|3)	# on error or if in the list
			[ "$SDECFG_KEEP_SRC" = 3 -a $1 != 0 ] && return

			local list=" $SDECFG_KEEP_SRC_LIST "
			list="${list//:/ }"
			list="${list//,/ }"

			# if package is in the list, just return
			[ "${list/ $pkg /}" != "$list" ] && return
			;;
        esac

	rm -rf $builddir/* $builddir
}

if [ -f $root/var/adm/logs/$stagelevel-$xpkg.log ] ; then
	cp $root/var/adm/logs/$stagelevel-$xpkg.out $builddir/BUILD-LOG
	cleanup_src 0
	echo_status "\$root/var/adm/logs/$stagelevel-$xpkg.out" \
	            "-> $stagelevel-$xpkg.log"
	mv $root/var/adm/logs/$stagelevel-$xpkg.out \
		$root/var/adm/logs/$stagelevel-$xpkg.log
	echo_pkg_finish $stagelevel $repository $xpkg
	exit 0
else
	cp $root/var/adm/logs/$stagelevel-$xpkg.out $builddir/ERROR-LOG
	cleanup_src 1
	if [ "$SDECFG_VERBOSE" != 1 -a "$verbose" != 1 ] ; then
		echo_errorquote "$( grep -v 'make[^ ]*:' \
			$root/var/adm/logs/$stagelevel-$xpkg.out |
			grep -B8 -- '--- BUILD ERROR ---' |
			sed '/--- BUILD ERROR ---/d' )"
	fi
	echo_status "\$root/var/adm/logs/$stagelevel-$xpkg.out" \
	            "-> $stagelevel-$xpkg.err"
	mv $root/var/adm/logs/$stagelevel-$xpkg.out \
		$root/var/adm/logs/$stagelevel-$xpkg.err
	echo_pkg_abort $stagelevel $repository $xpkg
	exit 1
fi

# ----  EOF
