Here is a simple shell script that formats /dev/da type devices with either a UFS (Unix File System) or the good old FAT (File Allocation Table). One should note that the FAT32 implementation is buggy. That is to say that formatting it under FreeBSD works fine, however, when using a pen drive under Windows it is not possible to write to the device. Only reading is supported. For this reason, we are here formatting a disk with FAT16.
The respective man pages for the most important commands used are:
dd(1) which is used here to clear just the first megabyte of the disk.
sysctl(8) needed here to allow us to clear a portion of the disk using dd(1).
fdisk(8) create a UFS or FAT slice (or possibly even another type of slice) on the disk before formatting.
bsdlabel(8) used to write a bsdlabel to a disk.
newfs(8) with this command the disk is actually formatted with a UFS.
newfs_msdos(8) used to format a disk with FAT.
And here goes the script:
#!/bin/sh
# variables
WHO=`whoami`
DEVICE=
sanity_checks()
{
local device path
# are we root?
if [ ${WHO} != "root" ] ; then
echo "you need to be root to format the disk"
exit 1
fi
# Check wether or not the device has been specified with its full path:
# /dev/device. If not prepend it.
path=`awk -v string_to_check=$1 'BEGIN { print index(string_to_check, "/dev/") }'`
if [ $path -eq 0 ]; then
device=/dev/$1 # prepend /dev/
else
device=$1
fi
# does the device special file exist?
if [ ! -c ${device} ] ; then
echo "device ${device} does not exist"
exit 1
fi
# are we operating on a slice of a device or the device itself?
# if it is a device (e.g. /dev/da0) all is ok. if it's the slice of
# a given device extract the device and continue.
case "${device}" in
/dev/da[0-9])
echo "$device"
;;
/dev/da[0-9]s[0-9])
echo "you specified a slice, using the device instead" >&2
# extract the device part
device=`echo $device | sed s/s[0-9]//`
echo "$device"
;;
*)
echo "${device} is not a /dev/da device"
exit 1
;;
esac
}
confirm()
{
local device confirm
device=$1
echo "Do you really want to format the device: \"${device}\"?"
echo -n "All data will be lost (yes/no): "
read -t 30 confirm # we have exactly 30 seconds to make a choice
case $confirm in
[Yy][Ee][Ss])
return
;;
[Nn][Oo])
echo "aborted"
exit 0
;;
*)
echo "aborted"
exit 1
;;
esac
}
format_ufs_2()
{
local device slice
device=$1 ; slice=${device}s1
echo "### formatting ${device} with ufs 2 ###"
# enter destructive mode
sysctl kern.geom.debugflags=16
# zero the first MB using dd(1)
dd if=/dev/zero of=${device} bs=1m count=1
# leave destructive mode
sysctl kern.geom.debugflags=0
# use fdisk(8) to create a partition
fdisk -B -I ${device} # the B option makes the device bootable
# bsdlabel(8)
bsdlabel -w -B ${slice}
# use newfs(8) to format the disk via ufs2
newfs -O 2 -U ${slice} # -U enables soft updates (whatever that may mean)
}
format_msdosfs()
{
local device slice
device=$1 ; slice=${device}s1
echo "### formatting ${device} with msdosfs ###"
# enter destructive mode
sysctl kern.geom.debugflags=16
# zero the first MB using dd(1)
dd if=/dev/zero of=${device} bs=1m count=1
# leave destructive mode
sysctl kern.geom.debugflags=0
# interactive mode
fdisk -i ${device} # choose partition type 12
# create a new fat filesystem via newfs_msdos(8)
newfs_msdos -F 16 ${slice} # fat 32 is buggy
}
usage()
{
echo "usage: format_disk.sh ufs|msdosfs device"
exit 1
}
#######################################################################
### entry point
if [ $# -ne 2 ] ; then
usage
fi
if [ "$1" != "ufs" ] && [ "$1" != "msdosfs" ] ; then
usage
fi
# sanity checks
DEVICE=$(sanity_checks $2)
# confirm
confirm $DEVICE
# go
if [ "$1" = "ufs" ] ; then
format_ufs_2 ${DEVICE}
elif [ "$1" = "msdosfs" ] ; then
format_msdosfs ${DEVICE}
fi
echo "Formatting complete!"
exit 0
This shell script can only be run as root, as this requirement is checked at the beginning of the script via the sanity_checks function. To make it executable run:
# chmod +x format_disk.sh
After which you can issue:
# ./format_disk.sh ufs /dev/da1
Or even
# ./format_disk.sh ufs da1
to format the disk, connected at point "/dev/da1" with a Unix File System.
The script makes sure, the correct device specified on the command line is spoken to, even if we are indicating the slice of a device such as /dev/da0s1 in which case the sanity_checks function will extract the device itself, shortening it to /dev/da0.
This script is mainly used to format USB drives. Formatting other types of drives could be implemented, however this could be the aim of another script.