buildfloppies.sh revision 1.17.32.1 1 #!/bin/sh
2 #
3 # $NetBSD: buildfloppies.sh,v 1.17.32.1 2017/03/20 06:52:04 pgoyette Exp $
4 #
5 # Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
6 # All rights reserved.
7 #
8 # This code is derived from software contributed to The NetBSD Foundation
9 # by Luke Mewburn of Wasabi Systems.
10 #
11 # Redistribution and use in source and binary forms, with or without
12 # modification, are permitted provided that the following conditions
13 # are met:
14 # 1. Redistributions of source code must retain the above copyright
15 # notice, this list of conditions and the following disclaimer.
16 # 2. Redistributions in binary form must reproduce the above copyright
17 # notice, this list of conditions and the following disclaimer in the
18 # documentation and/or other materials provided with the distribution.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 # POSSIBILITY OF SUCH DAMAGE.
31 #
32
33 # set defaults
34 #
35 : ${PAX=pax}
36 prog=${0##*/}
37 etcdir=/etc
38
39
40 usage()
41 {
42 cat 1>&2 << _USAGE_
43 Usage: ${prog} [options] base size file [...]
44 -i instboot eval instboot as a shell command to install a
45 bootstrap. @IMAGE@ is replaced with with the
46 file name of the floppy image.
47 -m max maximum number of floppies to build
48 -N etcdir directory in which to find passwd and group files.
49 -p pad last floppy to floppy size
50 -s suffix suffix for floppies
51 -t timestamp set timestamp for reproducible builds
52 base basename of generated floppies
53 size size of a floppy in 512 byte blocks
54 file [...] file(s) to store in the floppies
55 _USAGE_
56 exit 1
57 }
58
59 plural()
60 {
61 [ $1 -ne 1 ] && echo "s"
62 }
63
64 roundup()
65 {
66 echo $(( ( $1 + $2 - 1 ) / ( $2 ) ))
67 }
68
69
70 # parse and check arguments
71 #
72
73 while getopts i:m:N:ps:t: opt; do
74 case ${opt} in
75 i)
76 instboot=${OPTARG} ;;
77 m)
78 maxdisks=${OPTARG} ;;
79 N)
80 etcdir=${OPTARG} ;;
81 p)
82 pad=1 ;;
83 s)
84 suffix=${OPTARG} ;;
85 t)
86 timestamp="--timestamp ${OPTARG}" ;;
87 \?|*)
88 usage
89 ;;
90 esac
91 done
92
93 shift $(( ${OPTIND} - 1 ))
94 [ $# -lt 3 ] && usage
95 floppybase=$1
96 floppysize=$2
97 shift 2
98 files=$*
99
100 # setup temp file, remove existing images
101 #
102 floppy=floppy.$$.tar
103 trap "rm -f ${floppy}" 0 1 2 3 # EXIT HUP INT QUIT
104 rm -f ${floppybase}?${suffix} # XXX breaks if maxdisks > 9
105
106 # create tar file
107 #
108 dd if=/dev/zero of=${floppy} bs=8k count=1 2>/dev/null
109 (
110 echo ". type=dir optional"
111 for f in ${files}; do
112 echo "./$f type=file uname=root gname=wheel mode=0444"
113 done
114 ) | \
115 ${PAX} ${timestamp} -O -w -b8k -M -N "${etcdir}" -s,^./,, >> ${floppy} || exit 1
116
117 # install bootstrap before the image is split into multiple disks
118 #
119 if [ -n "$instboot" ]; then
120 instboot=$( echo $instboot | sed -e s/@IMAGE@/${floppy}/ )
121 echo "Running instboot: ${instboot}"
122 eval ${instboot} || exit 1
123 fi
124
125 # check size against available number of disks
126 #
127 set -- $(ls -ln $floppy)
128 bytes=$5
129 blocks=$(roundup ${bytes} 512)
130 # when calculating numdisks, take into account:
131 # a) the image already has an 8K tar header prepended
132 # b) each floppy needs an 8K tar volume header
133 numdisks=$(roundup ${blocks}-16 ${floppysize}-16)
134 if [ -z "${maxdisks}" ]; then
135 maxdisks=${numdisks}
136 fi
137
138 # Try to accurately summarise free space
139 #
140 msg=
141 # First floppy has 8k boot code, the rest an 8k 'multivolume header'.
142 # Each file has a 512 byte header and is rounded to a multiple of 512.
143 # The archive ends with two 512 byte blocks of zeros.
144 # The output file is then rounded up to a multiple of 8k.
145 # floppysize is in units of 512-byte blocks; free_space is in bytes.
146 free_space=$(($maxdisks * ($floppysize - 16) * 512 - 512 * 2))
147 for file in $files; do
148 set -- $(ls -ln $file)
149 file_bytes=$5
150 pad_bytes=$(($(roundup $file_bytes 512) * 512 - $file_bytes))
151 [ "$file_bytes" != 0 -o "$file" = "${file#USTAR.volsize.}" ] &&
152 msg="$msg $file $pad_bytes,"
153 free_space=$(($free_space - 512 - $file_bytes - $pad_bytes))
154 done
155 echo "Free space in last tar block:$msg"
156
157 if [ ${numdisks} -gt ${maxdisks} ]; then
158 # Add in the size of the last item (we really want the kernel) ...
159 excess=$(( 0 - $free_space + $pad_bytes))
160 echo 1>&2 \
161 "$prog: Image is ${excess} bytes ($(( ${excess} / 1024 )) KB)"\
162 "too big to fit on ${maxdisks} disk"$(plural ${maxdisks})
163 exit 1
164 fi
165
166 padto=$(( ${floppysize} * ${maxdisks} ))
167 if [ -n "${pad}" ]; then
168 echo \
169 "Writing $(( ${padto} * 512 )) bytes ($(( ${padto} / 2 )) KB)" \
170 "on ${numdisks} disk"$(plural ${numdisks})"," \
171 "padded by ${free_space} bytes" \
172 "($(( ${free_space} / 1024 )) KB)"
173 else
174 echo "Writing ${bytes} bytes ($(( ${blocks} / 2 )) KB)"\
175 "on ${numdisks} disk"$(plural ${numdisks})"," \
176 "free space ${free_space} bytes" \
177 "($(( ${free_space} / 1024 )) KB)"
178 fi
179
180 # write disks
181 #
182 curdisk=1
183 image=
184 seek=0
185 skip=0
186 floppysize8k=$(( ${floppysize} / 16 ))
187 while [ ${curdisk} -le ${numdisks} ]; do
188 image="${floppybase}${curdisk}${suffix}"
189 echo "Creating disk ${curdisk} to ${image}"
190 if [ ${curdisk} -eq 1 ]; then
191 : > ${image}
192 else
193 echo USTARFS ${curdisk} > ${image}
194 fi
195 count=$(( ${floppysize8k} - ${seek} ))
196 dd bs=8k conv=sync seek=${seek} skip=${skip} count=${count} \
197 if=${floppy} of=${image} 2>/dev/null
198
199 curdisk=$(( ${curdisk} + 1 ))
200 skip=$(( $skip + $count ))
201 seek=1
202 done
203
204 # pad last disk if necessary
205 #
206 if [ -n "${pad}" ]; then
207 dd if=$image of=$image conv=notrunc conv=sync bs=${floppysize}b count=1
208 fi
209
210
211 # final status
212 #
213 echo "Final result:"
214 ls -l ${floppybase}?${suffix} # XXX breaks if maxdisks > 9
215
216 exit 0
217