Subject: Re: Automatically disklabel entire disk
To: Hubert Feyrer <hubert@feyrer.de>
From: Douglas Wade Needham <cinnion@ka8zrt.com>
List: tech-embed
Date: 06/27/2005 21:40:47
	version=3.0.3
Sender: tech-embed-owner@NetBSD.org


--6TrnltStXW4iwmi0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

See the attached script, which I use to setup disks.  Nothing too
fancy, but it does allow me to specify the format of the single
partition (h: RAID or 4.2BSD), along with an optional swap.  It even
tries to prevent clobbering the root disk or any other disk which has
been partitioned.  Note, however, that I make no guarentees that it
works.  I think it did last time I used it, but...

- Doug

Quoting Hubert Feyrer (hubert@feyrer.de):
> On Tue, 28 Jun 2005, Marcin Jessa wrote:
> >Is it possible to autmatically, non.interactively disklabel entire blank 
> >disk not knowing what size it has?
> >I am stucked with disklabel..
> >I am trying to create an install script which executes on MFS mounted 
> >partition, disklabels a CF/HD, creates file system on it and installs disk 
> >bootstrap soft on it.
> 
> Read the disklabel(8) manpage!
> 
> You can use something like "disklabel disk0 >file", then read stuff for 
> partitioning out of the file, then put the disklabel back with "disklabel 
> disk0 file" or so. Untested, but it should work. May need some attention 
> to get the on-disk label in sync with the in-core disklabel.
> 
> 
>  - Hubert

-- 
Douglas Wade Needham - KA8ZRT        UN*X Consultant & UW/BSD kernel programmer
Email:  cinnion @ ka8zrt . com       http://cinnion.ka8zrt.com
Disclaimer: My opinions are my own.  Since I don't want them, why
            should my employer, or anybody else for that matter! 

--6TrnltStXW4iwmi0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=disk_size

#!/bin/ksh -x

#
#  Setup the program name for use in error messages, without the path.
#
prog=${0##*/}

usage ()
{
    printf "Usage: %s [-R|-B [-S swapsize ]] [-r]\n" ${prog}			>&2
    printf "    -B\tMake a single 4.2BSD slice\n"				>&2
    printf "    -R\tMake a single RAID slice\n"					>&2
    printf "    -S\tMake a swap slice of the given size\n"			>&2
    printf "    -r\tRestrict the FDISK partition size by the FDISK geometry\n"	>&2

    exit $0
}

#
#  Determine the root disk
#
ROOTDSK=`df -k / | tail -1 | cut -f1 -d' '`
ROOTDSK=${ROOTDSK##/dev/}
ROOTDSK=${ROOTDSK%[a-z]}

#
#  Defaults for arguments
#
restrict=0
part_raid=0
part_bsd=0
swap_size_mb=0

#
#  Parse our options
#
while getopts ":BRS:[Swap size in MB required]r" opt
do
    case ${opt} in
    B)
	part_bsd=1
	;;
    R)
	part_raid=1
        ;;
    S)
	swap_size_mb=${OPTARG}
        ;;
    r)
	restrict=1
        ;;
    :)
	printf "${prog}: ${OPTARG} requries a value\n"					>&2
        usage 2
        ;;
    *)
    	printf "${prog}: unknown option ${OPTARG}\n"					>&2
        usage 22
        ;;
    esac
done
shift OPTIND-1

#
#  Validate the arguments
#
if [ $# -ne 1 ]
then
    usage 22
fi
if [ ${part_bsd} -ne 0 -a ${part_raid} -ne 0 ]
then
    printf "%s: Make up your mind...either you want a RAID or BSD4.4 partition\n" ${prog}	>&2
    usage 22
fi

#
# Get the disk from the command line, stripping off the leading /dev and trailing letter.
#
DSK=${1##/dev/}
DSK=${DSK%[a-z]}

#
#  Validate the pattern.
#
case "${DSK}" in
[sw]d[0-9])
    if [ "${DSK}" == "${ROOTDSK}" ]
    then
        printf "${prog}: Cannot use this on the root disk (${ROOTDSK})!!!  ABORTING!!!"	>&2
        return 22
    fi
    ;;
*)
    printf "${prog}: %s is not in the form of [sw]d[0-9]!\n" ${DSK}			>&2
    ;;
esac

#
#  Get the size of the disk via the report in dmesg.boot
#
SZ=`grep ^${DSK} /var/run/dmesg.boot | sed -n -e's/.* \([0-9][0-9]*\) sectors$/\1/p'`
SZ0=$((SZ-63))

#
#  Get the size of the disk and the partitions via fdisk.
#
eval `fdisk -S ${DSK} 2>/dev/null`

echo "${DSK}: ${SZ}"
echo "DLCYL=${DLCYL}"
echo "DLHEAD=${DLHEAD}"
echo "DLSEC=${DLSEC}"
echo "DLSIZE=${DLSIZE}"
echo "BCYL=${BCYL}"
echo "BHEAD=${BHEAD}"
echo "BSEC=${BSEC}"
echo "PART0ID=${PART0ID}"
echo "PART0SIZE=${PART0SIZE}"
echo "PART0START=${PART0START}"
echo "PART0FLAG=${PART0FLAG}"
echo "PART0BCYL=${PART0BCYL}"
echo "PART0BHEAD=${PART0BHEAD}"
echo "PART0BSEC=${PART0BSEC}"
echo "PART0ECYL=${PART0ECYL}"
echo "PART0EHEAD=${PART0EHEAD}"
echo "PART0ESEC=${PART0ESEC}"
echo "PART1SIZE=${PART1SIZE}"
echo "PART2SIZE=${PART2SIZE}"
echo "PART3SIZE=${PART3SIZE}"

#
#  If we have any defined partitions...
#
if [ "${PART0ID}" -ne 0 -o "${PART1ID}" -ne 0 -o "${PART2ID}" -ne 0 -o "${PART3ID}" -ne 0 ]
then
    printf "${prog}: Partitions already exist on ${DSK}...ABORTING!!!\n"			>&2
    return 17
fi

#
#  If we are to restrict the FDISK partition by the FDISK geometry.
#
if [ ${restrict} -ne 0 ]
then
 
    #
    #  Validate DLSIZE <= DLCYL*DLHEAD*DLSEC
    #
    t=$((${DLCYL}*${DLHEAD}*${DLSEC}))
    if [ ${t} -lt ${DLSIZE} ]
    then
        printf "DLSIZE (%d) is larger than DLCYL*DLHEAD*DLSEC (%d)\n" ${DLSIZE} ${t}
        printf "Overriding DLSIZE with %d\n" ${t}
        DLSIZE=${t}
    fi
fi

#
#  Compute the size of a partition occupying the entire disk.
#
PART0START=${BSEC}
PART0SIZE=$((${DLSIZE}-${PART0START}))
PART0ID=169

echo "${DSK}.0: ${SZ0}"

#
#  Create the fdisk partition table.
#
fdisk -a -i -u -0 -s ${PART0ID}/${PART0START}/${PART0SIZE} ${DSK} <<EOF
n




n
y
y
EOF
fdisk ${DSK}

#
#  Dump the disk label.
#
disklabel ${DSK} > /tmp/dsklabel.$$ 2>/dev/null

#
#  Print out the head of the new disk label.
#
sed -n -e 's/[1234567] partitions:/8 partitions:/' -e'1,/^#        size/p' /tmp/dsklabel.$$ 			> /tmp/ndsklabel.$$

#
#  Find out the number of total sectors, sectors/track and the 
#  sectors/cylinder values.
#
sec=`grep 'total sectors:' /tmp/dsklabel.$$ | cut -f2 -d:`
spt=`grep 'sectors/track:' /tmp/dsklabel.$$ | cut -f2 -d:`
spc=`grep 'sectors/cylinder:' /tmp/dsklabel.$$ | cut -f2 -d:`

#
#  We will figure on a hog partition, and it will not include track 0.
#
hog=${sec}-${spt}
start=${spt}

#
#  Do we want a swap partition?
#
if [ ${swap_size_mb} -gt 0 ]
then

    #
    #  Compute the size of the swap partition in sectors.  It will be
    #  at the beginning of the disk, starting at track 1 and will end
    #  on a cylinder boundary.
    #
    swap_cyl=$(((${swap_size_mb}*2048)%${spc}))
    swap_size=$((${swap_cyl}*${spc}-${spt}))
    swap_start=${start}

    #
    #  Add the entry for the swap partition.
    #
    printf " b: %9d %9d %10s\n" ${swap_size} ${swap_start} "swap"	>>/tmp/ndsklabel.$$

    #
    #  Account for the usage by the swap partition.
    #
    start=$((${start}+${swap_size}))
    hog=$((${hog}-${swap_size}))
fi

#
#  Print out the c and d partitions.
#
printf " c: %9d %9d %10s  %5d %5d\n" $((${sec}-${spt})) ${spt} "unused"	0 0	>>/tmp/ndsklabel.$$
printf " d: %9d %9d %10s  %5d %5d\n" ${sec} 0 "unused" 0 0			>>/tmp/ndsklabel.$$

#
#  Print out the hog partition.
#
if [ ${part_bsd} -ne 0 -o ${part_raid} -ne 0 ]
then

    #
    #  
    #
    if [ ${part_bsd} -ne 0 ]
    then

        #
        #  Compute the block size.
        #
        bsize=0

        #
        #  Compute the fragment size
        #
        fsize=0

        #
        #  Compute the cpg
        #
        cpg=0

        #
        #  Print out the record.
        #
        printf " h: %9d %9d %10s  %5d %5d %5d\n" ${hog} ${start} "4.2BSD" ${fsize} ${bsize} ${cpg} >> /tmp/ndsklabel.$$

    elif [ ${part_raid} -ne 0 ]
    then
        printf " h: %9d %9d %10s\n" ${hog} ${start} "RAID" 		>> /tmp/ndsklabel.$$
    fi

fi

#
#  Write the new disk label.
#
disklabel -R -r ${DSK} /tmp/ndsklabel.$$ <<EOF
y
EOF

#
#  If we wanted a BSD partition...
#


#
#  Cleanup
#
#rm -f /tmp/*.$$ 

#
#  We are done
#
return 0

--6TrnltStXW4iwmi0--