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