xref: /minix/distrib/common/buildfloppies.sh (revision 0a6a1f1d)
1#!/bin/sh
2#
3# $NetBSD: buildfloppies.sh,v 1.17 2008/11/12 14:22:16 apb 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}
36prog=${0##*/}
37etcdir=/etc
38
39
40usage()
41{
42	cat 1>&2 << _USAGE_
43Usage: ${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	base		basename of generated floppies
52	size		size of a floppy in 512 byte blocks
53	file [...]	file(s) to store in the floppies
54_USAGE_
55	exit 1
56}
57
58plural()
59{
60	[ $1 -ne 1 ] && echo "s"
61}
62
63roundup()
64{
65	echo $(( ( $1 + $2 - 1 ) / ( $2 ) ))
66}
67
68
69#	parse and check arguments
70#
71
72while getopts i:m:N:ps: opt; do
73	case ${opt} in
74	i)
75		instboot=${OPTARG} ;;
76	m)
77		maxdisks=${OPTARG} ;;
78	N)
79		etcdir=${OPTARG} ;;
80	p)
81		pad=1 ;;
82	s)
83		suffix=${OPTARG} ;;
84	\?|*)
85		usage
86		;;
87	esac
88done
89
90shift $(( ${OPTIND} - 1 ))
91[ $# -lt 3 ] && usage
92floppybase=$1
93floppysize=$2
94shift 2
95files=$*
96
97#	setup temp file, remove existing images
98#
99floppy=floppy.$$.tar
100trap "rm -f ${floppy}" 0 1 2 3			# EXIT HUP INT QUIT
101rm -f ${floppybase}?${suffix}			# XXX breaks if maxdisks > 9
102
103#	create tar file
104#
105dd if=/dev/zero of=${floppy} bs=8k count=1 2>/dev/null
106(
107	echo ". type=dir optional"
108	for f in ${files}; do
109		echo "./$f type=file uname=root gname=wheel mode=0444"
110	done
111) | \
112${PAX} -O -w -b8k -M -N "${etcdir}" -s,^./,, >> ${floppy} || exit 1
113
114#	install bootstrap before the image is split into multiple disks
115#
116if [ -n "$instboot" ]; then
117	instboot=$( echo $instboot | sed -e s/@IMAGE@/${floppy}/ )
118	echo "Running instboot: ${instboot}"
119	eval ${instboot} || exit 1
120fi
121
122#	check size against available number of disks
123#
124set -- $(ls -ln $floppy)
125bytes=$5
126blocks=$(roundup ${bytes} 512)
127	# when calculating numdisks, take into account:
128	#	a) the image already has an 8K tar header prepended
129	#	b) each floppy needs an 8K tar volume header
130numdisks=$(roundup ${blocks}-16 ${floppysize}-16)
131if [ -z "${maxdisks}" ]; then
132	maxdisks=${numdisks}
133fi
134
135#	Try to accurately summarise free space
136#
137msg=
138# First floppy has 8k boot code, the rest an 8k 'multivolume header'.
139# Each file has a 512 byte header and is rounded to a multiple of 512.
140# The archive ends with two 512 byte blocks of zeros.
141# The output file is then rounded up to a multiple of 8k.
142# floppysize is in units of 512-byte blocks; free_space is in bytes.
143free_space=$(($maxdisks * ($floppysize - 16) * 512 - 512 * 2))
144for file in $files; do
145	set -- $(ls -ln $file)
146	file_bytes=$5
147	pad_bytes=$(($(roundup $file_bytes 512) * 512 - $file_bytes))
148	[ "$file_bytes" != 0 -o "$file" = "${file#USTAR.volsize.}" ] &&
149		msg="$msg $file $pad_bytes,"
150	free_space=$(($free_space - 512 - $file_bytes - $pad_bytes))
151done
152echo "Free space in last tar block:$msg"
153
154if [ ${numdisks} -gt ${maxdisks} ]; then
155	# Add in the size of the last item (we really want the kernel) ...
156	excess=$(( 0 - $free_space + $pad_bytes))
157	echo 1>&2 \
158	    "$prog: Image is ${excess} bytes ($(( ${excess} / 1024 )) KB)"\
159	    "too big to fit on ${maxdisks} disk"$(plural ${maxdisks})
160	exit 1
161fi
162
163padto=$(( ${floppysize} * ${maxdisks} ))
164if [ -n "${pad}" ]; then
165	echo \
166	    "Writing $(( ${padto} * 512 )) bytes ($(( ${padto} / 2 )) KB)" \
167	    "on ${numdisks} disk"$(plural ${numdisks})"," \
168	    "padded by ${free_space} bytes" \
169	    "($(( ${free_space} / 1024 )) KB)"
170else
171	echo "Writing ${bytes} bytes ($(( ${blocks} / 2 )) KB)"\
172	    "on ${numdisks} disk"$(plural ${numdisks})"," \
173	    "free space ${free_space} bytes" \
174	    "($(( ${free_space} / 1024 )) KB)"
175fi
176
177#	write disks
178#
179curdisk=1
180image=
181seek=0
182skip=0
183floppysize8k=$(( ${floppysize} / 16 ))
184while [ ${curdisk} -le ${numdisks} ]; do
185	image="${floppybase}${curdisk}${suffix}"
186	echo "Creating disk ${curdisk} to ${image}"
187	if [ ${curdisk} -eq 1 ]; then
188		: > ${image}
189	else
190		echo USTARFS ${curdisk} > ${image}
191	fi
192	count=$(( ${floppysize8k} - ${seek} ))
193	dd bs=8k conv=sync seek=${seek} skip=${skip} count=${count} \
194	    if=${floppy} of=${image} 2>/dev/null
195
196	curdisk=$(( ${curdisk} + 1 ))
197	skip=$(( $skip + $count ))
198	seek=1
199done
200
201#	pad last disk if necessary
202#
203if [ -n "${pad}" ]; then
204	dd if=$image of=$image conv=notrunc conv=sync bs=${floppysize}b count=1
205fi
206
207
208#	final status
209#
210echo "Final result:"
211ls -l ${floppybase}?${suffix}			# XXX breaks if maxdisks > 9
212
213exit 0
214