mkimage revision 1.10
11.1Sagc#! /bin/sh
21.1Sagc
31.10Schristos# $NetBSD: mkimage,v 1.10 2013/01/15 03:26:27 christos Exp $
41.1Sagc
51.1Sagc# Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org>
61.1Sagc# All rights reserved.
71.1Sagc#
81.1Sagc# Redistribution and use in source and binary forms, with or without
91.1Sagc# modification, are permitted provided that the following conditions
101.1Sagc# are met:
111.1Sagc# 1. Redistributions of source code must retain the above copyright
121.1Sagc#    notice, this list of conditions and the following disclaimer.
131.1Sagc# 2. Redistributions in binary form must reproduce the above copyright
141.1Sagc#    notice, this list of conditions and the following disclaimer in the
151.1Sagc#    documentation and/or other materials provided with the distribution.
161.1Sagc#
171.1Sagc# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
181.1Sagc# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
191.1Sagc# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
201.1Sagc# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
211.1Sagc# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
221.1Sagc# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231.1Sagc# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241.1Sagc# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251.1Sagc# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
261.1Sagc# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271.1Sagc#
281.1Sagc
291.1Sagc# find next available vnd, from kre
301.1Sagcnext_avail ()
311.1Sagc{
321.1Sagc	local dev="$1"
331.1Sagc	local N=$(( ${#dev} + 1 ))
341.1Sagc	local unit units
351.1Sagc
361.1Sagc	units=$(
371.1Sagc		sysctl -n hw.disknames		|
381.1Sagc			tr ' ' '\012'		|
391.1Sagc			grep '^'"${dev}"'[0-9]'	|
401.1Sagc			sort -n -k 1.$N			)
411.1Sagc
421.1Sagc	test -z "${units}" && {
431.1Sagc		test -e "/dev/${dev}0a" || {
441.1Sagc			echo >&2 "No ${dev}s available!"
451.1Sagc			return 1
461.1Sagc		}
471.1Sagc		echo "${dev}0"
481.1Sagc		return
491.1Sagc	}
501.1Sagc
511.1Sagc	N=0
521.1Sagc	for unit in ${units}
531.1Sagc	do
541.1Sagc		if [ "${unit}" = "${dev}${N}" ]
551.1Sagc		then
561.1Sagc			N=$(( N + 1 ))
571.1Sagc		else
581.1Sagc			echo "${dev}${N}"
591.1Sagc			return
601.1Sagc		fi
611.1Sagc	done
621.1Sagc
631.1Sagc	test -e /dev/"${dev}${N}a" || {
641.1Sagc		echo >&2 "All ${dev}s in use"
651.1Sagc		return 1
661.1Sagc	}
671.1Sagc
681.1Sagc	echo "${dev}${N}"
691.1Sagc}
701.1Sagc
711.1Sagc# find the size of the gzipped files in a .tgz archive
721.1Sagcsizeone() {
731.4Schristos	if [ ! -f "$1" ]
741.4Schristos	then
751.4Schristos		echo "$PROG: Missing set $1" 1>&2
761.4Schristos		echo 0
771.4Schristos		return;
781.4Schristos	fi
791.1Sagc        case "$1" in 
801.1Sagc        *.tgz|*.tar.gz)
811.1Sagc                tar tvzf "$1" | awk '{ tot += $5 } END { print tot }'
821.1Sagc                ;;
831.1Sagc        *.tbz|*.tar.bz2)
841.1Sagc                tar tvjf "$1" | awk '{ tot += $5 } END { print tot }' 
851.1Sagc                ;;
861.1Sagc        *)
871.1Sagc                echo 0
881.1Sagc                ;; 
891.1Sagc        esac
901.1Sagc}
911.1Sagc
921.4Schristosusage() {
931.4Schristos	cat << EOF 1>&2
941.4SchristosUsage: $PROG [-S <setsdir>] [-c <custom-files-dir>] [-h <host-arch>] [-s <size>]
951.4SchristosEOF
961.4Schristosexit 1
971.4Schristos}
981.4Schristos
991.4Schristosfinish() {
1001.4Schristos    cleanup
1011.4Schristos    ${sudo} umount ${mnt}
1021.4Schristos    ${sudo} vnconfig -u ${vnddev}
1031.4Schristos}
1041.4Schristos
1051.4SchristosDIR="$(dirname "$0")"
1061.4SchristosPROG="$(basename "$0")"
1071.2Sagcbar="==="
1081.4Schristossudo=
1091.7Schristosmnt="${TMPDIR:-/tmp}/image.$$"
1101.4Schristossrc="/usr/src"
1111.4Schristosobj="/usr/obj"
1121.4Schristos
1131.4Schristos# First pass for options to get the host
1141.4SchristosOPTS="S:c:h:s:x"
1151.4Schristoswhile getopts "$OPTS" f
1161.4Schristosdo
1171.4Schristos	case $f in
1181.4Schristos	h)	h="$OPTARG";;
1191.4Schristos	*)	;;
1201.4Schristos	esac
1211.4Schristosdone
1221.4Schristos
1231.4Schristosif [ -z "$h" ]
1241.4Schristosthen
1251.4Schristos	usage
1261.4Schristosfi
1271.4Schristos
1281.5Schristosif [ ! -f "${DIR}/conf/${h}.conf" ]
1291.4Schristosthen
1301.5Schristos	echo $PROG: ${DIR}/conf/${h}.conf is not present 1>&2
1311.4Schristos	exit 1
1321.4Schristosfi
1331.4Schristos
1341.5Schristos. "${DIR}/conf/${h}.conf"
1351.4Schristos
1361.4SchristosOPTIND=1
1371.4Schristoswhile getopts "$OPTS" f
1381.4Schristosdo
1391.4Schristos	case $f in
1401.4Schristos	S)	setsdir="$OPTARG";;
1411.4Schristos	c)	custom="$OPTARG";;
1421.4Schristos	h)	;;
1431.4Schristos	s)	size="$OPTARG";;
1441.4Schristos	x)	set -x;;
1451.6Schristos	*)	usage;;
1461.1Sagc	esac
1471.1Sagcdone
1481.1Sagc
1491.8Sjmcneilltrap finish 0 1 2 3 15
1501.8Sjmcneill
1511.4Schristosshift $(( "$OPTIND" - 1 ))
1521.4Schristosif [ -n "$1" ]; then
1531.1Sagc	# take the next argument as being the image name
1541.1Sagc	image="$1"
1551.1Sagc	shift
1561.1Sagcfi
1571.1Sagc
1581.1Sagctotal=0
1591.1Sagcfor s in ${sets}; do
1601.4Schristos	one="$(sizeone ${setsdir}/${s}.tgz)"
1611.4Schristos	total=$(( ${total} +  ${one} ))
1621.1Sagcdone
1631.2Sagc# calculate size of custom files
1641.2Sagccustsize=0
1651.2Sagcif [ -d "${custom}" ]; then
1661.2Sagc	custsize=$(ls -lR "${custom}" | awk 'NF == 9 { tot += $5 } END { print tot }')
1671.2Sagcfi
1681.4Schristostotal=$(( ( ( ${total} + ${custsize} ) / 1000000 ) + ${overhead} ))
1691.1Sagcif [ $size -eq 0 ]; then
1701.1Sagc        # auto-size the pkgs fs
1711.10Schristos        newsize=${total}
1721.1Sagcelse
1731.1Sagc        # check that we've been given enough space
1741.1Sagc        if [ ${total} -gt ${size} ]; then
1751.4Schristos                echo "$PROG: Given size is ${size} MB, but we need ${total} MB" >&2
1761.1Sagc                exit 1
1771.1Sagc        fi
1781.10Schristos	newsize=${size}
1791.1Sagcfi
1801.1Sagc
1811.10Schristosecho "${bar} making a new ${newsize} MB image in ${image} ${bar}"
1821.10Schristosdd if=/dev/zero of=${image} bs=1m count=${newsize} conv=sparse
1831.1Sagc
1841.1Sagcvnddev=$(next_avail vnd)
1851.1Sagcecho "${bar} mounting image via vnd ${vnddev} ${bar}"
1861.2Sagc${sudo} vnconfig ${vnddev} ${image}
1871.4Schristos${sudo} mkdir -p ${mnt}
1881.4Schristosmake_filesystems
1891.4Schristos
1901.4Schristos${sudo} mkdir -p ${mnt}/etc ${mnt}/dev
1911.1Sagc
1921.10Schristosecho -n "${bar} installing sets:"
1931.4Schristos(cd ${mnt} &&
1941.1Sagc	for s in ${sets}; do
1951.10Schristos		ss="${setsdir}/${s}.tgz"
1961.10Schristos		if [ -f "${ss}" ]; then
1971.10Schristos			echo -n " ${s}"
1981.10Schristos			${sudo} tar xpzf "${ss}"
1991.4Schristos		fi
2001.1Sagc	done
2011.1Sagc)
2021.10Schristosecho " ${bar}"
2031.1Sagc
2041.1Sagcecho "${bar} performing customisations ${bar}"
2051.1Sagc
2061.4Schristosmake_fstab
2071.1Sagc
2081.4Schristos${sudo} cat > ${mnt}/etc/rc.conf << EOF
2091.1Sagc#
2101.1Sagc# see rc.conf(5) for more information.
2111.1Sagc#
2121.1Sagc# Use program=YES to enable program, NO to disable it. program_flags are
2131.1Sagc# passed to the program on the command line.
2141.1Sagc#
2151.1Sagc
2161.1Sagc# Load the defaults in from /etc/defaults/rc.conf (if it's readable).
2171.1Sagc# These can be overridden below.
2181.1Sagc#
2191.1Sagcif [ -r /etc/defaults/rc.conf ]; then
2201.1Sagc        . /etc/defaults/rc.conf
2211.1Sagcfi
2221.1Sagc
2231.1Sagc# If this is not set to YES, the system will drop into single-user mode.
2241.1Sagc#
2251.1Sagcrc_configured=YES
2261.1Sagc
2271.4Schristoshostname=${h}
2281.1Sagc
2291.4SchristosEOF
2301.1Sagc
2311.4Schristoscustomize
2321.1Sagc
2331.1Sagcfor d in ${specialdirs}; do
2341.4Schristos	${sudo} mkdir -p ${mnt}/${d}
2351.1Sagcdone
2361.1Sagc
2371.4Schristosif [ \( -n "${custom}" \) -a \( -d "${custom}" \) ]; then
2381.2Sagc	echo "${bar} user customisations from files in ${custom} ${bar}"
2391.4Schristos	(cd ${custom} && ${sudo} pax -rwpe . ${mnt})
2401.2Sagcfi
2411.1Sagc
2421.1Sagcexit 0
243