mkimage revision 1.8
11.1Sagc#! /bin/sh
21.1Sagc
31.8Sjmcneill# $NetBSD: mkimage,v 1.8 2013/01/14 12:12:19 jmcneill 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.1Sagc        size=${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.1Sagcfi
1791.1Sagc
1801.1Sagcecho "${bar} making a new ${size} MB image in ${image} ${bar}"
1811.4Schristosdd if=/dev/zero of=${image} bs=1m count=${size} conv=sparse
1821.1Sagc
1831.1Sagcvnddev=$(next_avail vnd)
1841.1Sagcecho "${bar} mounting image via vnd ${vnddev} ${bar}"
1851.2Sagc${sudo} vnconfig ${vnddev} ${image}
1861.4Schristos${sudo} mkdir -p ${mnt}
1871.4Schristosmake_filesystems
1881.4Schristos
1891.4Schristos${sudo} mkdir -p ${mnt}/etc ${mnt}/dev
1901.1Sagc
1911.1Sagcecho "${bar} installing sets ${bar}"
1921.4Schristos(cd ${mnt} &&
1931.1Sagc	for s in ${sets}; do
1941.4Schristos		if [ -f "${s}" ]; then
1951.4Schristos			echo ${s}
1961.4Schristos			${sudo} tar xpzf ${setsdir}/${s}.tgz
1971.4Schristos		fi
1981.1Sagc	done
1991.1Sagc)
2001.1Sagc
2011.1Sagcecho "${bar} performing customisations ${bar}"
2021.1Sagc
2031.4Schristosmake_fstab
2041.1Sagc
2051.4Schristos${sudo} cat > ${mnt}/etc/rc.conf << EOF
2061.1Sagc#
2071.1Sagc# see rc.conf(5) for more information.
2081.1Sagc#
2091.1Sagc# Use program=YES to enable program, NO to disable it. program_flags are
2101.1Sagc# passed to the program on the command line.
2111.1Sagc#
2121.1Sagc
2131.1Sagc# Load the defaults in from /etc/defaults/rc.conf (if it's readable).
2141.1Sagc# These can be overridden below.
2151.1Sagc#
2161.1Sagcif [ -r /etc/defaults/rc.conf ]; then
2171.1Sagc        . /etc/defaults/rc.conf
2181.1Sagcfi
2191.1Sagc
2201.1Sagc# If this is not set to YES, the system will drop into single-user mode.
2211.1Sagc#
2221.1Sagcrc_configured=YES
2231.1Sagc
2241.4Schristoshostname=${h}
2251.1Sagc
2261.4SchristosEOF
2271.1Sagc
2281.4Schristoscustomize
2291.1Sagc
2301.1Sagcfor d in ${specialdirs}; do
2311.4Schristos	${sudo} mkdir -p ${mnt}/${d}
2321.1Sagcdone
2331.1Sagc
2341.4Schristosif [ \( -n "${custom}" \) -a \( -d "${custom}" \) ]; then
2351.2Sagc	echo "${bar} user customisations from files in ${custom} ${bar}"
2361.4Schristos	(cd ${custom} && ${sudo} pax -rwpe . ${mnt})
2371.2Sagcfi
2381.1Sagc
2391.1Sagcexit 0
240