mkimage revision 1.10 1 #! /bin/sh
2
3 # $NetBSD: mkimage,v 1.10 2013/01/15 03:26:27 christos Exp $
4
5 # Copyright (c) 2012 Alistair Crooks <agc (at] 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
30 next_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
72 sizeone() {
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
92 usage() {
93 cat << EOF 1>&2
94 Usage: $PROG [-S <setsdir>] [-c <custom-files-dir>] [-h <host-arch>] [-s <size>]
95 EOF
96 exit 1
97 }
98
99 finish() {
100 cleanup
101 ${sudo} umount ${mnt}
102 ${sudo} vnconfig -u ${vnddev}
103 }
104
105 DIR="$(dirname "$0")"
106 PROG="$(basename "$0")"
107 bar="==="
108 sudo=
109 mnt="${TMPDIR:-/tmp}/image.$$"
110 src="/usr/src"
111 obj="/usr/obj"
112
113 # First pass for options to get the host
114 OPTS="S:c:h:s:x"
115 while getopts "$OPTS" f
116 do
117 case $f in
118 h) h="$OPTARG";;
119 *) ;;
120 esac
121 done
122
123 if [ -z "$h" ]
124 then
125 usage
126 fi
127
128 if [ ! -f "${DIR}/conf/${h}.conf" ]
129 then
130 echo $PROG: ${DIR}/conf/${h}.conf is not present 1>&2
131 exit 1
132 fi
133
134 . "${DIR}/conf/${h}.conf"
135
136 OPTIND=1
137 while getopts "$OPTS" f
138 do
139 case $f in
140 S) setsdir="$OPTARG";;
141 c) custom="$OPTARG";;
142 h) ;;
143 s) size="$OPTARG";;
144 x) set -x;;
145 *) usage;;
146 esac
147 done
148
149 trap finish 0 1 2 3 15
150
151 shift $(( "$OPTIND" - 1 ))
152 if [ -n "$1" ]; then
153 # take the next argument as being the image name
154 image="$1"
155 shift
156 fi
157
158 total=0
159 for s in ${sets}; do
160 one="$(sizeone ${setsdir}/${s}.tgz)"
161 total=$(( ${total} + ${one} ))
162 done
163 # calculate size of custom files
164 custsize=0
165 if [ -d "${custom}" ]; then
166 custsize=$(ls -lR "${custom}" | awk 'NF == 9 { tot += $5 } END { print tot }')
167 fi
168 total=$(( ( ( ${total} + ${custsize} ) / 1000000 ) + ${overhead} ))
169 if [ $size -eq 0 ]; then
170 # auto-size the pkgs fs
171 newsize=${total}
172 else
173 # check that we've been given enough space
174 if [ ${total} -gt ${size} ]; then
175 echo "$PROG: Given size is ${size} MB, but we need ${total} MB" >&2
176 exit 1
177 fi
178 newsize=${size}
179 fi
180
181 echo "${bar} making a new ${newsize} MB image in ${image} ${bar}"
182 dd if=/dev/zero of=${image} bs=1m count=${newsize} conv=sparse
183
184 vnddev=$(next_avail vnd)
185 echo "${bar} mounting image via vnd ${vnddev} ${bar}"
186 ${sudo} vnconfig ${vnddev} ${image}
187 ${sudo} mkdir -p ${mnt}
188 make_filesystems
189
190 ${sudo} mkdir -p ${mnt}/etc ${mnt}/dev
191
192 echo -n "${bar} installing sets:"
193 (cd ${mnt} &&
194 for s in ${sets}; do
195 ss="${setsdir}/${s}.tgz"
196 if [ -f "${ss}" ]; then
197 echo -n " ${s}"
198 ${sudo} tar xpzf "${ss}"
199 fi
200 done
201 )
202 echo " ${bar}"
203
204 echo "${bar} performing customisations ${bar}"
205
206 make_fstab
207
208 ${sudo} cat > ${mnt}/etc/rc.conf << EOF
209 #
210 # see rc.conf(5) for more information.
211 #
212 # Use program=YES to enable program, NO to disable it. program_flags are
213 # passed to the program on the command line.
214 #
215
216 # Load the defaults in from /etc/defaults/rc.conf (if it's readable).
217 # These can be overridden below.
218 #
219 if [ -r /etc/defaults/rc.conf ]; then
220 . /etc/defaults/rc.conf
221 fi
222
223 # If this is not set to YES, the system will drop into single-user mode.
224 #
225 rc_configured=YES
226
227 hostname=${h}
228
229 EOF
230
231 customize
232
233 for d in ${specialdirs}; do
234 ${sudo} mkdir -p ${mnt}/${d}
235 done
236
237 if [ \( -n "${custom}" \) -a \( -d "${custom}" \) ]; then
238 echo "${bar} user customisations from files in ${custom} ${bar}"
239 (cd ${custom} && ${sudo} pax -rwpe . ${mnt})
240 fi
241
242 exit 0
243