#!/bin/sh
#
# $Id: cdroot_initdisk,v 1.6 2002/08/04 20:56:04 bsd Exp $
#
# Copyright 2001, 2002  Brian S. Dean <bsd@bsdhome.com>
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY BRIAN S. DEAN ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL BRIAN S. DEAN BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
# 
# Author : Brian Dean
# Date   : 14 April, 2001
#
# Initialize the specified disk for use as local disk space for a mostly
# diskless client system.
#
#
# $1 = disk, i.e., ad0
#
# $2 .. $N = partitions name:slice:size (in MB), i.e., var:e:128
#   if size=0, then use all remaining space (must be last entry)
#
#
# Example:
#
#    root_initdisk ad0 root:a:128 swap:b:1024 var:e:1024 usr:f:0
#


# If there is a global system configuration file, suck it in.
#
if [ -r /etc/defaults/rc.conf ]; then
	. /etc/defaults/rc.conf
	source_rc_confs
elif [ -r /etc/rc.conf ]; then
	. /etc/rc.conf
fi

usage() {
cat <<EOF

Usage: $0 [options] <DISK> <SLICE1> [<SLICE2> ... <SLICEN>]

  Where:

    <DISK>   = disk drive to operate on, e.g., ad0

    <SLICEx> = slice specification of the form:

	    mp:slice:size

        mp    = mount point, root=/, swap=swap, var=/var, etc
	slice = slice letter, e.g., "a", "b", etc.
	size  = size in MB, 0 = use all remaining space

  One option is accepted:

    -F = force disk initialization even if there is an existing
         label

  DANGER: This program is intended to be run by the '/etc/inst' script
          that is installed by 'mkcdroot' onto a live CD-Rom bootable
          FreeBSD CD for the purposes of installing FreeBSD.  It DOES
          NOT ask for confirmation before wiping out the specified
          disk.

          Use this program with EXTREME CAUTION.

  Example:

    $0 -F ad0 root:a:128 swap:b:1024 var:e:1024 usr:f:0

EOF
}

args=`getopt F $*`
if [ "$?" -ne 0 ]; then
  usage
  exit 1
fi

set -- $args
for i; do
  case "$i" in
    -F)
      cdroot_force_diskinit=YES
      shift
      ;;
    --)
      shift;
      break;
      ;;
  esac
done

#while [[ "$1" = +(-*) ]]; do
#  case $1 in
#    -force)
#      cdroot_force_diskinit=YES;
#      shift
#      ;;
#    *)
#      echo "$0: unknown option $1"
#      usage
#      exit 1
#      ;;
#  esac
#done

if [ "$#" -lt 2 ]; then
  echo
  echo "$0: must specify a disk and at least one slice specification."
  usage
  exit 1
fi

DISK=$1
shift

#
# make sure the needed device nodes are in /dev
#
if [ ! -c /dev/${DISK} ]; then
  (cd /dev && sh MAKEDEV ${DISK})
fi

if [ ! -c /dev/${DISK}s1 ]; then
  (cd /dev && sh MAKEDEV ${DISK}s1)
fi

if [ ! -c /dev/${DISK}s1a ]; then
  (cd /dev && sh MAKEDEV ${DISK}s1a)
fi

if [ ! -c /dev/$DISK ]; then
  echo
  echo "$0: /dev/$DISK does not exist or is not a disk device"
  echo
  exit 1
fi


n=$#
i=0
while [ "$i" -ne "$n" ]; do
  sln=`echo $1 | cut -f1 -d:`
  sla=`echo $1 | cut -f2 -d:`
  slz=`echo $1 | cut -f3 -d:`
  eval slname_${i}="$sln"
  eval slsize_${i}="$slz"
  eval slslic_${i}="$sla"
  shift;
  i=`expr $i + 1`
done

N_SLICES=$n
i=0
while [ $i -ne $N_SLICES ]; do
  eval echo "\${slname_${i}} \${slsize_${i}} MB on /dev/${DISK}s1\${slslic_${i}}"
  i=`expr $i + 1`
done

if [ -z "$DISK" ]; then
  echo "Usage: $0 Disk"
  exit 1
fi


if [ "$cdroot_force_diskinit" != "YES" ]; then
  /sbin/disklabel -r ${DISK}s1 > /dev/null 2>&1
  if [ "$?" -eq 0 ]; then
    echo "Disk already has a label"
    exit 0
  fi
fi

echo "Preparing to operate on /dev/$DISK"

case "$DISK" in
  ar*)
    echo "Disk is IDE raid, not zeroing"
    ;;
  *)
    echo "Zero front of disk"
    /bin/dd if=/dev/zero of=/dev/$DISK count=128
    ;;
esac


echo "Install partition"
/sbin/fdisk -I $DISK

echo "Initialize label"
/sbin/disklabel -rw ${DISK}s1 auto

echo "Install boot0 boot manager"
/usr/sbin/boot0cfg -B ${DISK}

echo "Compute slice sizes"

DISK_S=`/sbin/disklabel -r ${DISK}s1 | /usr/bin/tr -s ' ' | \
          /usr/bin/sed 's/^ //g' | /usr/bin/grep '^c: ' | \
          /usr/bin/cut -f2 -d' '`

echo "Disk size = $DISK_S blocks"

NEXT_OFFSET=0
REMAINING=$DISK_S
i=0
while [ "$i" -lt $N_SLICES ]; do
  eval s="\${slsize_${i}}"
  if [ "$s" -eq 0 ]; then
    eval slblks_${i}=$REMAINING
  else
    eval slblks_${i}=`expr ${s} \* 1024 \* 2`
  fi
  eval echo "next size = \${slblks_${i}}, remaining is $REMAINING"
  eval b="\${slblks_${i}}"
  if [ "${b}" -gt "$REMAINING" ]; then
    echo
    echo "$0: ERROR: disk size exceeded, must abort"
    echo
    exit 1
  fi
  REMAINING=`expr $REMAINING - ${b}`
  eval sloffs_${i}=$NEXT_OFFSET
  NEXT_OFFSET=`expr $NEXT_OFFSET + ${b}`
  eval echo "$i: \${slslic_${i}}: \${slblks_${i}} \${sloffs_${i}} \${slname_${i}}"
  i=`expr $i + 1`
done


echo "Generate prototype label"
PROTO=/tmp/label.proto
/sbin/disklabel -r ${DISK}s1 > $PROTO
i=0
while [ "$i" -lt $N_SLICES ]; do
  eval n="\${slname_${i}}"
  if [ "${n}" = "swap" ]; then
    fstype="swap"
  else
    fstype="4.2BSD 0 0 0"
  fi
  eval echo "\${slslic_${i}}: \${slblks_${i}} \${sloffs_${i}} $fstype" >> $PROTO
  i=`expr $i + 1`
done

echo "Install new label"
/sbin/disklabel -R -B ${DISK}s1 $PROTO

echo "Initialize disk filesystems"
i=0
while [ "$i" -lt $N_SLICES ]; do
  eval n="\${slname_${i}}"
  if [ "${n}" != "swap" ]; then
    eval /sbin/newfs /dev/${DISK}s1\${slslic_${i}}
    if [ "${n}" != "root" ]; then
      eval /sbin/tunefs -n enable /dev/${DISK}s1\${slslic_${i}}
    fi
  fi
  i=`expr $i + 1`
done

echo "Done initializing disk"



syntax highlighted by Code2HTML, v. 0.9.1