mkimage revision 1.4
1#! /bin/sh 2 3# $NetBSD: mkimage,v 1.4 2013/01/13 20:57:18 christos Exp $ 4 5# Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org> 6# All rights reserved. 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27# 28 29# find next available vnd, from kre 30next_avail () 31{ 32 local dev="$1" 33 local N=$(( ${#dev} + 1 )) 34 local unit units 35 36 units=$( 37 sysctl -n hw.disknames | 38 tr ' ' '\012' | 39 grep '^'"${dev}"'[0-9]' | 40 sort -n -k 1.$N ) 41 42 test -z "${units}" && { 43 test -e "/dev/${dev}0a" || { 44 echo >&2 "No ${dev}s available!" 45 return 1 46 } 47 echo "${dev}0" 48 return 49 } 50 51 N=0 52 for unit in ${units} 53 do 54 if [ "${unit}" = "${dev}${N}" ] 55 then 56 N=$(( N + 1 )) 57 else 58 echo "${dev}${N}" 59 return 60 fi 61 done 62 63 test -e /dev/"${dev}${N}a" || { 64 echo >&2 "All ${dev}s in use" 65 return 1 66 } 67 68 echo "${dev}${N}" 69} 70 71# find the size of the gzipped files in a .tgz archive 72sizeone() { 73 if [ ! -f "$1" ] 74 then 75 echo "$PROG: Missing set $1" 1>&2 76 echo 0 77 return; 78 fi 79 case "$1" in 80 *.tgz|*.tar.gz) 81 tar tvzf "$1" | awk '{ tot += $5 } END { print tot }' 82 ;; 83 *.tbz|*.tar.bz2) 84 tar tvjf "$1" | awk '{ tot += $5 } END { print tot }' 85 ;; 86 *) 87 echo 0 88 ;; 89 esac 90} 91 92usage() { 93 cat << EOF 1>&2 94Usage: $PROG [-S <setsdir>] [-c <custom-files-dir>] [-h <host-arch>] [-s <size>] 95EOF 96exit 1 97} 98 99finish() { 100 cleanup 101 ${sudo} umount ${mnt} 102 ${sudo} vnconfig -u ${vnddev} 103} 104 105trap finish 0 1 2 3 15 106DIR="$(dirname "$0")" 107PROG="$(basename "$0")" 108bar="===" 109sudo= 110mnt="/tmp/image.$$" 111src="/usr/src" 112obj="/usr/obj" 113 114# First pass for options to get the host 115OPTS="S:c:h:s:x" 116while getopts "$OPTS" f 117do 118 case $f in 119 h) h="$OPTARG";; 120 *) ;; 121 esac 122done 123 124if [ -z "$h" ] 125then 126 usage 127fi 128 129if [ ! -f "${DIR}/${h}.conf" ] 130then 131 echo $PROG: ${DIR}/${h}.conf is not present 1>&2 132 exit 1 133fi 134 135. "${DIR}/${h}.conf" 136 137OPTIND=1 138while getopts "$OPTS" f 139do 140 case $f in 141 S) setsdir="$OPTARG";; 142 c) custom="$OPTARG";; 143 h) ;; 144 s) size="$OPTARG";; 145 x) set -x;; 146 *) ;; 147 esac 148done 149 150shift $(( "$OPTIND" - 1 )) 151if [ -n "$1" ]; then 152 # take the next argument as being the image name 153 image="$1" 154 shift 155fi 156 157total=0 158for s in ${sets}; do 159 one="$(sizeone ${setsdir}/${s}.tgz)" 160 total=$(( ${total} + ${one} )) 161done 162# calculate size of custom files 163custsize=0 164if [ -d "${custom}" ]; then 165 custsize=$(ls -lR "${custom}" | awk 'NF == 9 { tot += $5 } END { print tot }') 166fi 167total=$(( ( ( ${total} + ${custsize} ) / 1000000 ) + ${overhead} )) 168if [ $size -eq 0 ]; then 169 # auto-size the pkgs fs 170 size=${total} 171else 172 # check that we've been given enough space 173 if [ ${total} -gt ${size} ]; then 174 echo "$PROG: Given size is ${size} MB, but we need ${total} MB" >&2 175 exit 1 176 fi 177fi 178 179echo "${bar} making a new ${size} MB image in ${image} ${bar}" 180dd if=/dev/zero of=${image} bs=1m count=${size} conv=sparse 181 182vnddev=$(next_avail vnd) 183echo "${bar} mounting image via vnd ${vnddev} ${bar}" 184${sudo} vnconfig ${vnddev} ${image} 185${sudo} mkdir -p ${mnt} 186make_filesystems 187 188${sudo} mkdir -p ${mnt}/etc ${mnt}/dev 189 190echo "${bar} installing sets ${bar}" 191(cd ${mnt} && 192 for s in ${sets}; do 193 if [ -f "${s}" ]; then 194 echo ${s} 195 ${sudo} tar xpzf ${setsdir}/${s}.tgz 196 fi 197 done 198) 199 200echo "${bar} performing customisations ${bar}" 201 202make_fstab 203 204${sudo} cat > ${mnt}/etc/rc.conf << EOF 205# 206# see rc.conf(5) for more information. 207# 208# Use program=YES to enable program, NO to disable it. program_flags are 209# passed to the program on the command line. 210# 211 212# Load the defaults in from /etc/defaults/rc.conf (if it's readable). 213# These can be overridden below. 214# 215if [ -r /etc/defaults/rc.conf ]; then 216 . /etc/defaults/rc.conf 217fi 218 219# If this is not set to YES, the system will drop into single-user mode. 220# 221rc_configured=YES 222 223hostname=${h} 224 225EOF 226 227customize 228 229for d in ${specialdirs}; do 230 ${sudo} mkdir -p ${mnt}/${d} 231done 232 233if [ \( -n "${custom}" \) -a \( -d "${custom}" \) ]; then 234 echo "${bar} user customisations from files in ${custom} ${bar}" 235 (cd ${custom} && ${sudo} pax -rwpe . ${mnt}) 236fi 237 238exit 0 239