3 # Copyright (c) 1994-2009 Poul-Henning Kamp.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 if [ `uname -m` = "i386" -o `uname -m` = "amd64" ] ; then
35 TARGET_PART=`df / | sed '
44 FREEBSD_PART=`sed -n \
46 -e '/[ ]\/freebsd[ ]/!d' \
50 # Calculate a suggested gpart command
51 TARGET_DISK=`expr ${TARGET_PART} : '\(.*\)s[12]a$' || true`
52 TARGET_SLICE=`expr ${TARGET_PART} : '.*s\([12]\)a$' || true`
53 GPART_SUGGESTION="gpart set -a active -i $TARGET_SLICE /dev/$TARGET_DISK"
54 unset TARGET_DISK TARGET_SLICE
58 GPART_SUGGESTION=unknown
62 # Relative to /freebsd
71 #SRCCONF="SRCCONF=/usr/src/src.conf"
75 ncpu=`sysctl -n kern.smp.cpus`
76 if [ $ncpu -gt 1 ] ; then
83 PKG_DIR=/usr/ports/packages/All
85 # Remotely mounted distfiles
86 # REMOTEDISTFILES=fs:/rdonly/distfiles
89 #FTP_PROXY=http://127.0.0.1:3128/
90 #HTTP_PROXY=http://127.0.0.1:3128/
91 #export FTP_PROXY HTTP_PROXY
96 PORTS_OPTS="BATCH=YES A4=yes"
104 SBMNT="/mnt.sysbuild"
112 before_ports_chroot() (
121 #######################################################################
122 # -P is a pretty neat way to clean junk out from your ports dist-files:
124 # mkdir /freebsd/ports/distfiles.old
125 # mv /freebsd/ports/distfiles/* /freebsd/ports/distfiles.old
126 # sh sysbuild.sh -c $yourconfig -P /freebsd/ports/distfiles.old
127 # rm -rf /freebsd/ports/distfiles.old
129 # Unfortunately bsd.ports.mk does not attempt to use a hard-link so
130 # while this runs you need diskspace for both your old and your "new"
133 #######################################################################
137 echo "Usage: $0 [-b/-k/-w] [-c config_file]"
138 echo " -b suppress builds (both kernel and world)"
139 echo " -k suppress buildkernel"
140 echo " -w suppress buildworld"
141 echo " -p used cached packages"
142 echo " -P <dir> prefetch ports"
143 echo " -c specify config file"
148 #######################################################################
149 #######################################################################
151 if [ ! -f $0 ] ; then
152 echo "Must be able to access self ($0)" 1>&2
156 if grep -q 'Magic String: 0`0nQT40W%l,CX&' $0 ; then
159 echo "self ($0) does not contain magic string" 1>&2
163 #######################################################################
169 set `cat /tmp/_sb_log`
171 echo "$1 $TX" > /tmp/_sb_log
172 DT=`expr $TX - $1 || true`
173 DL=`expr $TX - $2 || true`
174 echo -n "### `date +%H:%M:%S`"
175 printf " ### %5d ### %5d ### %s\n" $DT $DL "$a"
178 #######################################################################
181 make $* WITH="${PORTS_WITH}" WITHOUT="${PORTS_WITHOUT}" ${PORTS_OPTS}
188 if [ "x$t" = "x." ] ; then
190 true > /tmp/_.plist.tdone
191 echo 'digraph {' > /tmp/_.plist.dot
193 if grep -q "^$t\$" /tmp/_.plist.tdone ; then
196 echo "$t" >> /tmp/_.plist.tdone
199 if [ "x$d" == "xpatch" ] ; then
203 if [ ! -d $d ] ; then
204 fl=FLAVOR=`expr $d : '.*@\(.*\)'`
205 bd=`expr $d : '\(.*\)@.*'`
206 if [ ! -d "$bd" ] ; then
207 echo "Missing port $d ($t) (fl $fl) (bd $bd)" 1>&2
210 # echo "Flavored port $d ($t) (fl $fl) (bd $bd)" 1>&2
213 d=`cd /usr/ports && cd $d && /bin/pwd`
214 if [ ! -f $d/Makefile ] ; then
215 echo "Missing port (Makefile) $d" 1>&2
218 if [ "x$t" != "x." ] ; then
219 echo "\"$t\" -> \"$d\"" >> /tmp/_.plist.dot
221 if grep -q "^$d\$" /tmp/_.plist ; then
223 elif grep -q "^$d\$" /tmp/_.plist.tdone ; then
229 for a in `ports_make -V _UNIFIED_DEPENDS $fl`
231 x=`expr "$a" : '.*:\(.*\)'`
236 echo "$d" >> /tmp/_.plist
239 if [ "x$t" = "x." ] ; then
240 echo '}' >> /tmp/_.plist.dot
246 ports_recurse . $PORTS_WE_WANT
248 if [ "x${PKG_DIR}" != "x" ] ; then
252 pd=`cd /usr/ports && /bin/pwd`
253 # Now build & install them
254 for p in `cat /tmp/_.plist`
257 t=`echo $p | sed "s,${pd},,"`
258 pn=`cd $p && ports_make package-name`
260 if [ "x`basename $p`" == "xpkg" ] ; then
261 log_it "Very Special: $t ($pn)"
265 ports_make clean all install
266 ) > _.$b 2>&1 < /dev/null
270 if pkg info $pn > /dev/null 2>&1 ; then
271 log_it "Already installed: $t ($pn)"
275 if [ "x${PKG_DIR}" != "x" -a -f ${PKG_DIR}/$pn.txz ] ; then
276 if [ "x$use_pkg" = "x-p" ] ; then
277 log_it "Install $t ($pn)"
280 pkg add ${PKG_DIR}/$pn.txz || true
281 ) > _.$b 2>&1 < /dev/null
286 miss=`(cd $p ; ports_make missing) || true`
288 if [ "x${miss}" != "x" ] ; then
289 log_it "NB: MISSING for $p:" $miss
292 log_it "build $pn ($p)"
297 if ports_make install ; then
298 if [ "x${PKG_DIR}" != "x" ] ; then
306 ) > _.$b 2>&1 < /dev/null
314 true > /${ldir}/_.prefetch
315 echo "Building /tmp/_.plist" >> /${ldir}/_.prefetch
317 ports_recurse . $PORTS_WE_WANT
319 echo "Completed /tmp/_.plist" >> /${ldir}/_.prefetch
320 # Now checksump/fetch them
321 for p in `cat /tmp/_.plist`
326 if ports_make checksum ; then
327 rm -f /${ldir}/_.prefetch.$b
328 echo "OK $p" >> /${ldir}/_.prefetch
332 ports_make checksum || true
334 if ports_make checksum > /dev/null 2>&1 ; then
335 rm -f /${ldir}/_.prefetch.$b
336 echo "OK $p" >> /${ldir}/_.prefetch
338 echo "BAD $p" >> /${ldir}/_.prefetch
340 ) > /${ldir}/_.prefetch.$b 2>&1
342 echo "Done" >> /${ldir}/_.prefetch
346 #######################################################################
355 args=`getopt bc:hkpP:w $*`
356 if [ $? -ne 0 ] ; then
373 if [ ! -f "$c_arg" ] ; then
374 echo "Cannot read $c_arg" 1>&2
409 #######################################################################
411 if [ "x$1" = "xchroot_script" ] ; then
423 if [ "x$1" = "xfinal_chroot" ] ; then
428 if [ $# -gt 0 ] ; then
429 echo "$0: Extraneous arguments supplied"
433 #######################################################################
436 echo $T0 $T0 > /tmp/_sb_log
438 [ ! -d ${SBMNT} ] && mkdir -p ${SBMNT}
440 if $do_prefetch ; then
441 rm -rf /tmp/sysbuild/ports
442 mkdir -p /tmp/sysbuild/ports
443 ln -s ${distfile_cache} /tmp/sysbuild/ports/distfiles
444 export PORTS_OPTS=CD_MOUNTPTS=/tmp/sysbuild
449 log_it Unmount everything
452 umount /freebsd/distfiles || true
453 umount ${SBMNT}/freebsd/distfiles || true
454 umount ${FREEBSD_PART} || true
455 umount ${SBMNT}/freebsd || true
456 umount ${SBMNT}/dev || true
457 umount ${SBMNT} || true
458 umount /dev/${TARGET_PART} || true
461 log_it Prepare running image
463 mount ${FREEBSD_PART} /freebsd
465 #######################################################################
467 if [ ! -d /freebsd/${PORTS_PATH} ] ; then
468 echo PORTS_PATH does not exist 1>&2
472 if [ ! -d /freebsd/${SRC_PATH} ] ; then
473 echo SRC_PATH does not exist 1>&2
477 log_it TARGET_PART $TARGET_PART
481 ln -s /freebsd/${PORTS_PATH} /usr/ports
484 ln -s /freebsd/${SRC_PATH} /usr/src
487 if [ "x${OBJ_PATH}" != "x" ] ; then
489 (cd /freebsd && mkdir -p ${OBJ_PATH} && ln -s ${OBJ_PATH} /usr/obj)
496 #######################################################################
498 for i in ${PORTS_WE_WANT}
502 if [ ! -d $i ] ; then
503 fl=FLAVOR=`expr $i : '.*@\(.*\)'`
504 i=`expr $i : '\(.*\)@.*'`
506 if [ ! -d $i ] ; then
507 echo "Port $i not found" 1>&2
513 #export PORTS_WE_WANT
516 #######################################################################
518 log_it Prepare destination partition
519 newfs -t -E -O2 -U /dev/${TARGET_PART} > /dev/null
520 mount /dev/${TARGET_PART} ${SBMNT}
521 mkdir -p ${SBMNT}/dev
522 mount -t devfs devfs ${SBMNT}/dev
524 if [ "x${REMOTEDISTFILES}" != "x" ] ; then
525 rm -rf /freebsd/${PORTS_PATH}/distfiles
526 ln -s /freebsd/distfiles /freebsd/${PORTS_PATH}/distfiles
527 mkdir -p /freebsd/distfiles
528 mount ${REMOTEDISTFILES} /freebsd/distfiles
531 log_it copy ports config files
532 (cd / ; find var/db/ports -print | cpio -dumpv ${SBMNT} > /dev/null 2>&1)
534 log_it "Start prefetch of ports distfiles"
535 ports_prefetch ${SBMNT} &
541 make ${JARG} -s buildworld ${SRCCONF} > ${SBMNT}/_.bw 2>&1
549 make ${JARG} -s buildkernel KERNCONF=$KERNCONF > ${SBMNT}/_.bk 2>&1
555 (cd /usr/src && make ${JARG} installworld DESTDIR=${SBMNT} ${SRCCONF} ) \
559 (cd /usr/src && make -m /usr/src/share/mk distribution DESTDIR=${SBMNT} ${SRCCONF} ) \
560 > ${SBMNT}/_.dist 2>&1
563 (cd /usr/src && make ${JARG} installkernel DESTDIR=${SBMNT} KERNCONF=$KERNCONF ) \
566 if [ "x${OBJ_PATH}" != "x" ] ; then
567 rmdir ${SBMNT}/usr/obj
568 ( cd /freebsd && mkdir -p ${OBJ_PATH} && ln -s ${OBJ_PATH} ${SBMNT}/usr/obj )
571 log_it Wait for ports prefetch
572 log_it "(Tail ${SBMNT}/_.prefetch for progress)"
575 log_it Move filesystems
577 if [ "x${REMOTEDISTFILES}" != "x" ] ; then
578 umount /freebsd/distfiles
580 umount ${FREEBSD_PART} || true
581 mkdir -p ${SBMNT}/freebsd
582 mount ${FREEBSD_PART} ${SBMNT}/freebsd
583 if [ "x${REMOTEDISTFILES}" != "x" ] ; then
584 mount ${REMOTEDISTFILES} ${SBMNT}/freebsd/distfiles
587 rm -rf ${SBMNT}/usr/ports || true
588 ln -s /freebsd/${PORTS_PATH} ${SBMNT}/usr/ports
590 rm -rf ${SBMNT}/usr/src || true
591 ln -s /freebsd/${SRC_PATH} ${SBMNT}/usr/src
593 log_it Build and install ports
595 # Make sure fetching will work in the chroot
596 if [ -f /etc/resolv.conf ] ; then
597 log_it copy resolv.conf
598 cp /etc/resolv.conf ${SBMNT}/etc
599 chflags schg ${SBMNT}/etc/resolv.conf
602 if [ -f /etc/localtime ] ; then
603 log_it copy localtime
604 cp /etc/localtime ${SBMNT}/etc
605 if [ -f /var/db/zoneinfo ] ; then
607 cp /var/db/zoneinfo ${SBMNT}/var/db
611 log_it ldconfig in chroot
612 chroot ${SBMNT} sh /etc/rc.d/ldconfig start
620 sed "/[ ]\/[ ]/s;^[^ ]*[ ];/dev/${TARGET_PART} ;" \
621 /etc/fstab > ${SBMNT}/etc/fstab
626 cp /tmp/_sb_log ${SBMNT}/tmp
628 if [ "x$c_arg" != "x" ] ; then
629 cp $c_arg ${SBMNT}/root
630 chroot ${SBMNT} sh /root/$0 -c /root/`basename $c_arg` $use_pkg chroot_script
632 chroot ${SBMNT} sh /root/$0 $use_pkg chroot_script
634 cp ${SBMNT}/tmp/_sb_log /tmp
636 log_it create all mountpoints
637 grep -v '^[ ]*#' ${SBMNT}/etc/fstab |
643 if [ "x$SERCONS" != "xfalse" ] ; then
644 log_it serial console
645 echo " -h" > ${SBMNT}/boot.config
646 sed -i "" -e /ttyd0/s/off/on/ ${SBMNT}/etc/ttys
647 sed -i "" -e /ttyu0/s/off/on/ ${SBMNT}/etc/ttys
648 sed -i "" -e '/^ttyv[0-8]/s/ on/ off/' ${SBMNT}/etc/ttys
651 log_it move dist config files "(expect warnings)"
654 mkdir root/configfiles_dist
655 find ${CONFIGFILES} -print | cpio -dumpv root/configfiles_dist
658 log_it copy live config files
659 (cd / && find ${CONFIGFILES} -print | cpio -dumpv ${SBMNT})
664 cp /tmp/_sb_log ${SBMNT}/tmp
665 if [ "x$c_arg" != "x" ] ; then
666 chroot ${SBMNT} sh /root/$0 -c /root/`basename $c_arg` final_chroot
668 chroot ${SBMNT} sh /root/$0 final_chroot
670 cp ${SBMNT}/tmp/_sb_log /tmp
671 log_it "Check these messages (if any):"
672 grep '^Stop' ${SBMNT}/_* || true
674 echo "Now you probably want to:"
675 echo " $GPART_SUGGESTION"
676 echo " shutdown -r now"