mkimage revision 1.6
11.1Sagc#! /bin/sh
21.1Sagc
31.6Schristos# $NetBSD: mkimage,v 1.6 2013/01/13 20:59:22 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.4Schristostrap finish 0 1 2 3 15
1061.4SchristosDIR="$(dirname "$0")"
1071.4SchristosPROG="$(basename "$0")"
1081.2Sagcbar="==="
1091.4Schristossudo=
1101.4Schristosmnt="/tmp/image.$$"
1111.4Schristossrc="/usr/src"
1121.4Schristosobj="/usr/obj"
1131.4Schristos
1141.4Schristos# First pass for options to get the host
1151.4SchristosOPTS="S:c:h:s:x"
1161.4Schristoswhile getopts "$OPTS" f
1171.4Schristosdo
1181.4Schristos	case $f in
1191.4Schristos	h)	h="$OPTARG";;
1201.4Schristos	*)	;;
1211.4Schristos	esac
1221.4Schristosdone
1231.4Schristos
1241.4Schristosif [ -z "$h" ]
1251.4Schristosthen
1261.4Schristos	usage
1271.4Schristosfi
1281.4Schristos
1291.5Schristosif [ ! -f "${DIR}/conf/${h}.conf" ]
1301.4Schristosthen
1311.5Schristos	echo $PROG: ${DIR}/conf/${h}.conf is not present 1>&2
1321.4Schristos	exit 1
1331.4Schristosfi
1341.4Schristos
1351.5Schristos. "${DIR}/conf/${h}.conf"
1361.4Schristos
1371.4SchristosOPTIND=1
1381.4Schristoswhile getopts "$OPTS" f
1391.4Schristosdo
1401.4Schristos	case $f in
1411.4Schristos	S)	setsdir="$OPTARG";;
1421.4Schristos	c)	custom="$OPTARG";;
1431.4Schristos	h)	;;
1441.4Schristos	s)	size="$OPTARG";;
1451.4Schristos	x)	set -x;;
1461.6Schristos	*)	usage;;
1471.1Sagc	esac
1481.1Sagcdone
1491.1Sagc
1501.4Schristosshift $(( "$OPTIND" - 1 ))
1511.4Schristosif [ -n "$1" ]; then
1521.1Sagc	# take the next argument as being the image name
1531.1Sagc	image="$1"
1541.1Sagc	shift
1551.1Sagcfi
1561.1Sagc
1571.1Sagctotal=0
1581.1Sagcfor s in ${sets}; do
1591.4Schristos	one="$(sizeone ${setsdir}/${s}.tgz)"
1601.4Schristos	total=$(( ${total} +  ${one} ))
1611.1Sagcdone
1621.2Sagc# calculate size of custom files
1631.2Sagccustsize=0
1641.2Sagcif [ -d "${custom}" ]; then
1651.2Sagc	custsize=$(ls -lR "${custom}" | awk 'NF == 9 { tot += $5 } END { print tot }')
1661.2Sagcfi
1671.4Schristostotal=$(( ( ( ${total} + ${custsize} ) / 1000000 ) + ${overhead} ))
1681.1Sagcif [ $size -eq 0 ]; then
1691.1Sagc        # auto-size the pkgs fs
1701.1Sagc        size=${total}
1711.1Sagcelse
1721.1Sagc        # check that we've been given enough space
1731.1Sagc        if [ ${total} -gt ${size} ]; then
1741.4Schristos                echo "$PROG: Given size is ${size} MB, but we need ${total} MB" >&2
1751.1Sagc                exit 1
1761.1Sagc        fi
1771.1Sagcfi
1781.1Sagc
1791.1Sagcecho "${bar} making a new ${size} MB image in ${image} ${bar}"
1801.4Schristosdd if=/dev/zero of=${image} bs=1m count=${size} conv=sparse
1811.1Sagc
1821.1Sagcvnddev=$(next_avail vnd)
1831.1Sagcecho "${bar} mounting image via vnd ${vnddev} ${bar}"
1841.2Sagc${sudo} vnconfig ${vnddev} ${image}
1851.4Schristos${sudo} mkdir -p ${mnt}
1861.4Schristosmake_filesystems
1871.4Schristos
1881.4Schristos${sudo} mkdir -p ${mnt}/etc ${mnt}/dev
1891.1Sagc
1901.1Sagcecho "${bar} installing sets ${bar}"
1911.4Schristos(cd ${mnt} &&
1921.1Sagc	for s in ${sets}; do
1931.4Schristos		if [ -f "${s}" ]; then
1941.4Schristos			echo ${s}
1951.4Schristos			${sudo} tar xpzf ${setsdir}/${s}.tgz
1961.4Schristos		fi
1971.1Sagc	done
1981.1Sagc)
1991.1Sagc
2001.1Sagcecho "${bar} performing customisations ${bar}"
2011.1Sagc
2021.4Schristosmake_fstab
2031.1Sagc
2041.4Schristos${sudo} cat > ${mnt}/etc/rc.conf << EOF
2051.1Sagc#
2061.1Sagc# see rc.conf(5) for more information.
2071.1Sagc#
2081.1Sagc# Use program=YES to enable program, NO to disable it. program_flags are
2091.1Sagc# passed to the program on the command line.
2101.1Sagc#
2111.1Sagc
2121.1Sagc# Load the defaults in from /etc/defaults/rc.conf (if it's readable).
2131.1Sagc# These can be overridden below.
2141.1Sagc#
2151.1Sagcif [ -r /etc/defaults/rc.conf ]; then
2161.1Sagc        . /etc/defaults/rc.conf
2171.1Sagcfi
2181.1Sagc
2191.1Sagc# If this is not set to YES, the system will drop into single-user mode.
2201.1Sagc#
2211.1Sagcrc_configured=YES
2221.1Sagc
2231.4Schristoshostname=${h}
2241.1Sagc
2251.4SchristosEOF
2261.1Sagc
2271.4Schristoscustomize
2281.1Sagc
2291.1Sagcfor d in ${specialdirs}; do
2301.4Schristos	${sudo} mkdir -p ${mnt}/${d}
2311.1Sagcdone
2321.1Sagc
2331.4Schristosif [ \( -n "${custom}" \) -a \( -d "${custom}" \) ]; then
2341.2Sagc	echo "${bar} user customisations from files in ${custom} ${bar}"
2351.4Schristos	(cd ${custom} && ${sudo} pax -rwpe . ${mnt})
2361.2Sagcfi
2371.1Sagc
2381.1Sagcexit 0
239