#!/bin/sh # # chris@nmedia.net # # This is an example of how to create a new image, transfer the contents # of an old image to it, and keep the user from screwing it up too bad, by # performing some basic sanity checks. # # -t target-disk causes this script to write directly to a disk instead of # a new VND image. This may be useful if you want to write a small image # to a large flash without overwriting the unused space (which can be rather # slow). This is as fast as running flashdist, without requiring # the source files from flashdist. # # Growimg.sh might be useful if you have a stable, tested image that you want # to copy to a different media without having the source files originally used # to create the image. It's also useful if you are feeling too lazy to run # flashdist. # # This script tries to keep everything scaled to sectors, so we are less # likely to hit the 32 bit (2^32) boundary on shell variable values (amd64 # users have no such problem.) The sanity checks fail completely on i386 # if the source image is larger than 4GB (not very likely for flashdist # users) # # The previous version of this script used growfs. Unfortunately the # superblock locations change radically going from, say, 32 sec/trk to 63 s/t. # The change is too much for growfs or fsck to grok. Our new approach is to # create a new image, copy the data over with tar, and recreate the boot # blocks. A side benefit of this approach is that we can also shrink images # now. # unset alt if [ `uname -s` != "OpenBSD" ]; then echo Sorry, cowboy. This script only runs on OpenBSD. exit 1 fi syntax() { echo "syntax: growimg.sh [-t target-disk] " } islezero() { if [ "$1" -le "0" ]; then syntax echo -n expected a value larger than 0, got \"$1\" if [ "$2" != "" ]; then echo " for $2" else echo fi exit 1 fi } if [ "$1" == "-t" ]; then device="$2" alt=/dev/"$2"c if [ ! -b $alt ]; then echo "$device($alt) is an invalid disk device, not found or not block device" exit 1 fi shift shift fi if [ ! -f "$4" ]; then syntax exit 1 fi islezero $1 cylinders islezero $2 heads islezero $3 sectors biosboot=/usr/mdec/biosboot mbr=/usr/mdec/mbr if [ -z "$device" ]; then device=svnd0 fi device2=svnd1 image=$4 cylinders=$1 trackscylinder=$2 sectorstrack=$3 bytessec=512 totalsize=$((cylinders * trackscylinder * sectorstrack)) sectorscylinder=$((totalsize / cylinders)) # The source image must be 4GB or less, or this will break. imgbytes=`ls -l $image | awk ' { print $5 } '` imgsize=$((imgbytes / bytessec)) if [ $((imgsize * bytessec)) != "$imgbytes" ]; then cat <<-__FluxCapacitor size of image $image is not divisible by $bytessec bytes/sector without a remainder. this image may not be compatible with the media that you are installing to, or, more likely, it may not be a disk image at all. either way, run flashdist to create a new image. __FluxCapacitor exit 1 fi addon=$((totalsize - imgsize)) echo Image: $image echo Image size: $((imgbytes / 1024 / 1024))MB if [ "$bytessec" -le 1024 ]; then # The division is done like this to keep any 32 int from overflowing in ksh echo Requested size: $((totalsize / 1024 / (1024 / bytessec)))MB echo Size increase: $((addon / 1024 / (1024 / bytessec)))MB fi echo if [ -z "$alt" ]; then freespace=`df . | tail -1 | awk ' { print $4 } '` if [ $bytessec -gt 512 ]; then # df reports in 512 byte sectors, so scale freespace for comparison # to media with different bytes/sec factor=$((bytessec / 512)) freespace=$((freespace / factor)) fi # The new image will not take more disk space than the old one, in fact # it will take less. But it will appear to use more when dd reads it. # vnd will create holes in the file for the blank space so we don't have # to waste a bunch of disk space for megabytes of zeros! if [ "$imgsize" -gt "$freespace" ]; then echo imgsize: $imgsize sectors echo freespace: $freespace sectors echo echo there is not enough free disk space for the new image! exit 1 fi fi if ! vnconfig $device2 $image; then echo % vnconfig failure exit 1 fi if [ -z "$alt" ]; then NewImg=`mktemp newimg.XXXX` fi NewLabel=`mktemp growimg.XXXXXXXX` OldDir=`mktemp -d olddir.XXXXX` NewDir=`mktemp -d newdir.XXXXX` if ! mount /dev/"$device2"a $OldDir; then echo mount old image failed vnconfig -u $device2 rm -f $NewImg $NewLabel rmdir $OldDir $NewDir exit 1 fi echo Reading current disklabel... disklabel $device2 | egrep -v "^total sectors:|^bytes/sector:|^sectors/track:|^sectors/cylinder:|^tracks/cylinder:|^cylinders:|^ .:|^#|^. partitions:|^.. partitions:|^$" > $NewLabel apart=$((totalsize - sectorstrack)) cat <<-__New >>$NewLabel total sectors: $totalsize bytes/sector: $bytessec sectors/track: $sectorstrack sectors/cylinder: $sectorscylinder tracks/cylinder: $trackscylinder cylinders: $cylinders a: $apart $sectorstrack 4.2BSD 1024 8192 16 c: $totalsize 0 unused 0 0 __New if [ -z "$alt" ]; then echo echo Creating new image... dd if=/dev/zero bs=$bytessec count=32 of=$NewImg >/dev/null if ! vnconfig $device $NewImg; then echo % vnconfig failure vnconfig -u $device2 rm $NewImg $NewLabel rmdir $OldDir $NewDir exit 1 fi fi fdisk -c $cylinders -h $trackscylinder -s $sectorstrack -f $mbr \ -e $device <<-__EOC >/dev/null reinit update write quit __EOC echo echo Writing enlarged flashdist disklabel... disklabel -R $device $NewLabel echo echo Creating new filesystem... newfs -S $bytessec -q /dev/r"$device"a if ! mount -o async /dev/"$device"a $NewDir; then echo mount new image failed umount $OldDir if [ -z "$alt" ]; then vnconfig -u $device fi vnconfig -u $device2 rmdir $OldDir $NewDir rm -f $NewImg exit 1 fi UsedBlocks=`df $OldDir | tail -1 | awk ' { print $3 } '` FreeBlocks=`df $NewDir | tail -1 | awk ' { print $4 } '` if [ "$FreeBlocks" -le "$UsedBlocks" ]; then cat <<-__UsedBlocks Binaries use $((UsedBlocks / 1024 / (1024 / bytessec)))MB but only $((FreeBlocks / 1024 / (1024 / bytessec)))MB available for hip-hop verbal potential. Sorry, you must specify a larger destination size. __UsedBlocks umount $OldDir umount $NewDir if [ -z "$alt" ]; then vnconfig -u $device fi vnconfig -u $device2 rm -f $NewImg $NewLabel rmdir $OldDir $NewDir exit 1 fi echo echo Copying installation... tar cf - -C $OldDir . | tar xpf - -C $NewDir echo echo Installing boot blocks... /usr/mdec/installboot $NewDir/boot $biosboot $device echo echo Checking filesystem... fsck -f /dev/"$device"a umount /dev/"$device"a umount /dev/"$device2"a if [ -z "$alt" ]; then vnconfig -u $device fi vnconfig -u $device2 if [ "$bytessec" -le 1024 ]; then new="$((totalsize / 1024 / (1024 / bytessec)))MB " fi echo echo Grow completed. if [ -z "$alt" ]; then echo New "$new"image is located at $NewImg else echo "New image written to $device($alt)" fi echo rmdir $NewDir $OldDir rm $NewLabel exit 0