#!/bin/sh # $FreeBSD$ # client-side script to actually build a package. intended to be run in a jail. # usage: $0 DIRNAME PHASE # PHASE is 1 (checksum) or 2 (package) cleanup() { status=$1 # Don't keep distfiles if 'make checksum' failed keep_distfiles=$(make -V ALWAYS_KEEP_DISTFILES) if [ ${status} -eq 1 -o -z "${keep_distfiles}" ]; then cd ${dir} distdir=$(make -V DISTDIR) if [ ! -z "${distdir}" ]; then rm -rf ${distdir}/* fi fi if [ -e ${dir}/.keep ]; then cd ${dir} objdir=$(make -V WRKDIR) tar cfjC /tmp/work.tbz ${objdir}/.. work fi if [ ${status} -gt 0 ]; then cat /tmp/make.log${status} fi echo 1 > /tmp/status touch /.dirty echo "================================================================" echo -n "build of ${dir} ended at " date exit 0 } add_pkg() { pkgs=$* echo add_pkg $pkgs cd /tmp/depends # XXX TODO more hard-coding export PKG_PATH=/tmp/depends if [ ! -z "${pkgs}" ]; then arch=$(uname -m) echo "adding dependencies" for i in $pkgs; do echo "adding package $i" base=$(basename $i ${pkg_sufx}) if [ $use_pkgng = "no" ]; then pkg_cmd_info="pkg_info -qe" pkg_cmd_add="pkg_add" else pkg_cmd_info="pkg info -e" pkg_cmd_add="pkg add" fi if [ $use_pkgng = "yes" -a ${i%-*} = "pkg" ]; then tar xf $i -C . -s ",/.*/,,g" "*/pkg-static" pkg_cmd_add="./pkg-static add" pkg_cmd_info="./pkg-static info" fi eval $pkg_cmd_info $base if [ $? -eq 0 ]; then echo "skipping $base, already added" else eval $pkg_cmd_add $i if [ $? -ne 0 ]; then # XXX MCL this is where the truncated packages kill us. # echo "begin debug block" # echo # echo "remember, you are in a chroot, with dir ${dir}" # echo # echo "PKG_PATH is $PKG_PATH and contains" # ls -al $PKG_PATH # echo # df -g # echo # ps axwwl # echo # echo "end debug block" # XXX MCL this is where the truncated packages kill us. echo "error in dependency $i, exiting" cleanup 0 fi fi done fi } del_pkg() { pkgs=$* cd /tmp/depends # XXX TODO more hard-coding export PKG_PATH=/tmp/depends if [ ! -z "${pkgs}" ]; then recursion=1 dellist="" while [ $recursion -eq 1 ]; do unset delpkg nextpkg recursion=0 for i in $pkgs; do base=$(basename $i ${pkg_sufx}) if [ $use_pkgng = "no" ]; then dependents=$(cat /var/db/pkg/${base}/+REQUIRED_BY 2>/dev/null) pkg_cmd_check="cd /var/db/pkg && test -d" else dependents=$(pkg query "%ro" $base) pkg_cmd_check="pkg info -qe" fi if [ -n "$dependents" ]; then recursion=1 nextpkg="${base} ${nextpkg}" else eval $pkg_cmd_check $base >/dev/null 2>&1 if [ $? -eq 0 ]; then delpkg="${base} ${delpkg}" fi fi done pkgs="${nextpkg}" if [ "$dellist" != "" -a "$dellist" = "$delpkg" ]; then if [ $use_pkgng = "no" ]; then leftover=$(cd /var/db/pkg && find * -type d -maxdepth 1) else leftover=$(pkg info -qa | grep -vw "${PKGD}") fi echo "deleted list =\""$dellist"\", packages to delete ="\"$delpkg\" echo "The following packages were left behind (perhaps your dependency list is incomplete):" echo $leftover echo "error while removing package, exiting" cleanup 0 else for j in ${delpkg}; do echo "Deleting ${j}" if [ $use_pkgng = "no" ]; then pkg_cmd_delete="pkg_delete -f" else pkg_cmd_delete="pkg delete -y -f" fi eval $pkg_cmd_delete $j if [ $? -ne 0 ]; then echo "--> error in pkg_delete, exiting" cleanup 0 fi done dellist=$delpkg fi done fi } dir=$1 phase=$2 ED=$3 PD=$4 FD=$5 BD=$6 RD=$7 PKGD=$8 #export PATH=/ccache/libexec/ccache/:$PATH #export CCACHE_PATH=/usr/bin:/usr/local/bin # pick up value from environment set up in portbuild script L=`echo ${LOCALBASE} | sed 's,^/,,'` Z=`ident ${dir}/Makefile | grep 'FreeBSD:' | sed 's/^[ \t]*//'` cd $dir || exit 1 restr=$(make -V RESTRICTED) # Inherit from environment set by portbuild. pkg_sufx=${PKG_SUFX} # Use pkgng if available. #if [ -x /usr/sbin/pkg ]; then use_pkgng="no" make -f /usr/ports/Mk/bsd.port.mk -V WITH_PKGNG | grep -q "[Yy][Ee][Ss]$" && use_pkgng="yes" # Keep restricted distfiles in a subdirectory for extra protection # against leakage if [ ! -z "$restr" ]; then # pick up value from environment set up in portbuild script echo "DISTDIR=${DISTDIR}" export DISTDIR=${DISTDIR}/RESTRICTED echo "DISTDIR=${DISTDIR}" mkdir -p ${DISTDIR} fi if [ $phase = 1 ]; then # note: if you change this header, also change processonelog and processlogs2 cd $dir || exit 1 echo "building for: $(uname -mr)" echo "maintained by: $(make maintainer)" echo "port directory: ${dir}" echo "Makefile ident: ${Z}" echo "build started at $(date)" echo "FETCH_DEPENDS=${FD}" echo "PATCH_DEPENDS=${PD}" echo "EXTRACT_DEPENDS=${ED}" echo "BUILD_DEPENDS=${BD}" echo "RUN_DEPENDS=${RD}" echo "PKG_DEPENDS=${PKGD}" echo "prefixes: LOCALBASE=${L}" # Stash a copy of /etc/master.passwd and /etc/group to detect whether someone modifies it cp /etc/master.passwd /etc/master.passwd-save cp /etc/group /etc/group-save # Files we do not care about changing between pre-build and post-cleanup cat > /tmp/mtree.preexclude < /tmp/mtree.pristine add_pkg $FD cd $dir || exit 1 pkgname=$(make package-name) echo "================================================================" echo "========================================" # pick up value from environment set up in portbuild script if /pnohang ${BUILD_TIMEOUT} /tmp/make.log1 ${pkgname} make checksum; then cat /tmp/make.log1 echo "0" > /tmp/status else cleanup 1 fi else cd $dir || exit 1 pkgname=$(make package-name) echo "================================================================" echo "========================================" add_pkg ${ED} cd $dir /pnohang ${BUILD_TIMEOUT} /tmp/make.log2 ${pkgname} make extract || cleanup 2 cat /tmp/make.log2 del_pkg ${ED} # Fetch depends still need to be here for 'make extract' since that target # always reruns 'make fetch' due to the lack of fetch cookie (and no place # to put it since WRKDIR isn't created by 'make fetch') del_pkg $FD echo "================================================================" echo "========================================" add_pkg ${PD} cd $dir /pnohang ${BUILD_TIMEOUT} /tmp/make.log3 ${pkgname} make patch || cleanup 3 cat /tmp/make.log3 del_pkg ${PD} echo "================================================================" echo "========================================" # XXX MCL this is where the truncated packages kill us. add_pkg ${BD} # Files we do not care about changing between pre-build and post-cleanup cat > /tmp/mtree.buildexclude < /tmp/mtree.prebuild xvfb=0 if which -s Xvfb; then xvfb=1 pid=$(echo $$ % 32768 | bc) # XXX MCL HUH? X11BASE=$(which Xvfb | sed -e 's./bin/Xvfb..') Xvfb :${pid} -fp ${X11BASE}/lib/X11/fonts/misc & # pick up value from environment set up in portbuild script DISPLAY=${JAIL_ADDR}:${pid} export DISPLAY fi cd $dir /pnohang ${BUILD_TIMEOUT} /tmp/make.log4 ${pkgname} make build || cleanup 4 cat /tmp/make.log4 echo "================================================================" echo "========================================" cd $dir /pnohang ${BUILD_TIMEOUT} /tmp/make.log5 ${pkgname} make -k regression-test cat /tmp/make.log5 mtree -X /tmp/mtree.buildexclude -x -f /tmp/mtree.prebuild -p / | egrep -v "^(${L}/var|${L}/lib/X11/xserver/SecurityPolicy|${L}/share/nls/POSIX|${L}/share/nls/en_US.US-ASCII|etc/services|compat |usr/X11R6 |etc/manpath.config|etc/.*.bak|${L}/info/dir|${L}/lib/X11/fonts/.*/fonts\.|usr/local/man/..( |/man. )|${L}/lib/X11/fonts/TrueType|${L}/etc/gconf/gconf.xml.defaults/%gconf-tree.*.xml|var/db/fontconfig/* )" > /tmp/list.preinstall if [ -s /tmp/list.preinstall ]; then echo "================================================================" echo "Fatal error: filesystem was touched prior to 'make install' phase" cat /tmp/list.preinstall echo "================================================================" cleanup 0 fi echo "================================================================" echo "========================================" add_pkg ${RD} cat > /tmp/mtree.exclude < /tmp/mtree cd $dir if /pnohang ${BUILD_TIMEOUT} /tmp/make.log6 ${pkgname} make install; then cat /tmp/make.log6 echo "0" > /tmp/status else cleanup 6 fi echo "================================================================" echo "========================================" cd $dir if /pnohang ${BUILD_TIMEOUT} /tmp/make.log7 ${pkgname} make package; then cat /tmp/make.log7 echo "0" > /tmp/status prefix=$(make -V PREFIX) del_pkg ${pkgname} else cleanup 7 fi mtree -X /tmp/mtree.exclude -x -f /tmp/mtree -p / | egrep -v "^(${L}/var|${L}/lib/X11/xserver/SecurityPolicy|${L}/share/nls/POSIX|${L}/share/nls/en_US.US-ASCII|etc/services|compat |usr/X11R6 |etc/manpath.config|etc/.*.bak|${L}/info/dir|${L}/lib/X11/fonts/.*/fonts\.|usr/local/man/..( |/man. )|${L}/lib/X11/fonts/TrueType|${L}/etc/gconf/gconf.xml.defaults/%gconf-tree.*.xml|var/db/fontconfig/* )" > /tmp/list3 # Compare the state of the filesystem now to before the 'make install' phase dirty=0 if [ -s /tmp/list3 ]; then cd / grep ' extra$' /tmp/list3 | awk '{print $1}' | xargs -J % find % -ls > /tmp/list4 grep ' missing$' /tmp/list3 > /tmp/list5 grep -vE ' (extra|missing)$' /tmp/list3 > /tmp/list6 # pick up value from environment set up in portbuild script if [ "x${NOPLISTCHECK}" = "x" ]; then if grep -vq "$L/etc/" /tmp/list4; then echo "1" > /tmp/status dirty=1 fi if [ -s /tmp/list5 -o -s /tmp/list6 ]; then echo "1" > /tmp/status dirty=1 fi fi echo "================================================================" fi echo echo "=== Checking filesystem state" if [ -s /tmp/list4 ]; then echo "list of extra files and directories in / (not present before this port was installed but present after it was deinstalled)" cat /tmp/list4 fi if [ -s /tmp/list5 ]; then echo "list of files present before this port was installed but missing after it was deinstalled)" cat /tmp/list5 fi if [ -s /tmp/list6 ]; then echo "list of filesystem changes from before and after port installation and deinstallation" cat /tmp/list6 fi if [ "${dirty}" = 1 ]; then cleanup 0 fi # BUILD_DEPENDS and RUN_DEPENDS are both present at install-time (e.g. gmake) # Concatenate and remove duplicates BRD=$(echo $BD $RD | tr ' ' '\n' | sort -u | tr '\n' ' ') del_pkg ${BRD} if [ $use_pkgng = "no" ]; then cd /var/db/pkg leftover=$(find * -type d -maxdepth 1 2> /dev/null) else leftover=$(pkg info -qa | grep -vw "${PKGD}") fi # if [ -n "$leftover" -a "$leftover" != "${PKGD}" ]; then # echo "leftover packages:" $leftover # del_pkg $leftover # echo "1" > /tmp/status # cleanup 0 # fi # Compare the state of the filesystem now to clean system (should again be clean) mtree -X /tmp/mtree.preexclude -x -f /tmp/mtree.pristine -p / | egrep -v "^(${L}/var|${L}/lib/X11/xserver/SecurityPolicy|${L}/share/nls/POSIX|${L}/share/nls/en_US.US-ASCII|etc/services|compat |usr/X11R6 |etc/manpath.config|etc/.*.bak|${L}/info/dir|${L}/lib/X11/fonts/.*/fonts\.|usr/local/man/..( |/man. )|${L}/lib/X11/fonts/TrueType )" > /tmp/list3 echo echo "=== Checking filesystem state after all packages deleted" if [ -s /tmp/list3 ]; then cd / grep ' extra$' /tmp/list3 | awk '{print $1}' | xargs -J % find % -ls > /tmp/list4 grep ' missing$' /tmp/list3 > /tmp/list5 grep -vE ' (extra|missing)$' /tmp/list3 > /tmp/list6 if [ "x${NOPLISTCHECK}" = "x" ]; then if grep -vq "$L/etc/" /tmp/list4; then echo "1" > /tmp/status fi if [ -s /tmp/list5 ]; then echo "1" > /tmp/status fi fi echo "================================================================" if [ -s /tmp/list4 ]; then echo "list of extra files and directories in / (not present on clean system but present after everything was deinstalled)" cat /tmp/list4 touch /.dirty fi if [ -s /tmp/list5 ]; then echo "list of files present on clean system but missing after everything was deinstalled)" cat /tmp/list5 touch /.dirty fi if [ -s /tmp/list6 ]; then echo "list of filesystem changes from before and after all port installation/deinstallation" cat /tmp/list6 touch /.dirty fi fi cmp /etc/group /etc/group-save || (echo "=== /etc/group was modified:"; diff -du /etc/group-save /etc/group) cmp /etc/master.passwd /etc/master.passwd-save || (echo "=== /etc/master.passwd was modified:"; diff -du /etc/master.passwd-save /etc/master.passwd) if [ ${xvfb} = 1 ]; then kill $(jobid %1) fi # XXX Don't keep distfiles if checksum mismatches cd ${dir} keep_distfiles=$(make -V ALWAYS_KEEP_DISTFILES) distdir=$(make -V DISTDIR) if [ -z "${keep_distfiles}" -a ! -z "${distdir}" ]; then rm -rf ${distdir}/* fi if [ -e ${dir}/.keep ]; then cd ${dir} objdir=$(make -V WRKDIR) tar cfjC /tmp/work.tbz ${objdir}/.. work fi echo "================================================================" echo -n "build of ${dir} ended at " date fi exit 0