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