Skip to content

Commit

Permalink
Merge branch 'dev-single-existing-partition' into develop. Fixes #24.
Browse files Browse the repository at this point in the history
  • Loading branch information
JElchison committed Feb 20, 2016
2 parents ccc3226 + c436043 commit 921c04b
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 36 deletions.
32 changes: 17 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
format-udf
==========

Bash script to format a block drive (hard drive or Flash drive) in UDF. The output is a drive that can be used for reading/writing across multiple operating system families: Windows, OS X, and Linux. This script should be capable of running in OS X or in Linux.
Bash script to format a block device (hard drive or Flash drive) in UDF. The output is a drive that can be used for reading/writing across multiple operating system families: Windows, OS X, and Linux. This script should be capable of running in OS X or in Linux.


# Features
* Formats a block drive (hard drive or Flash drive) in <a href="https://en.wikipedia.org/wiki/Universal_Disk_Format">Universal Disk Format (UDF)</a>
* Formats a block device (hard drive or Flash drive) in <a href="https://en.wikipedia.org/wiki/Universal_Disk_Format">Universal Disk Format (UDF)</a>
* UDF revision 2.01 used for maximal compatibility (see note on Linux support below)
* Resulting file system can be read/written across multiple operating system families (Windows, OS X, and Linux)
* Runs on any OS having a Bash environment
* Ability to override detected device block size
* Option to force non-interactive mode (useful for scripting)
* Optionally wipes drive before formatting
* Optionally wipes device before formatting
* Writes a fake MBR for added compatibility on Windows (optionally disabled)

For the advanced user, this script is also capable of formatting a single existing partition, without modifying the partition table. Beware that using this method will render the newly formatted UDF partition unusable on OS X (but still usable on Linux and Windows). Because of this limitation, the recommendation is to format the entire device.


# OS Support
Following tables detail operating system support for UDF. Data was adapted from https://en.wikipedia.org/wiki/Universal_Disk_Format#Compatibility (as retrieved on 2015-Feb-20).
Expand Down Expand Up @@ -74,7 +76,7 @@ Simply copy format-udf.sh to a directory of your choosing. Don't forget to make

# Usage
```
Usage: ./format-udf.sh [-b BLOCK_SIZE] [-f] [-p PARTITION_TYPE] [-w WIPE_METHOD] drive label
Usage: ./format-udf.sh [-b BLOCK_SIZE] [-f] [-p PARTITION_TYPE] [-w WIPE_METHOD] device label
-b BLOCK_SIZE
Block size to be used during format operation.
Expand All @@ -101,21 +103,21 @@ Usage: ./format-udf.sh [-b BLOCK_SIZE] [-f] [-p PARTITION_TYPE] [-w WIPE_METHOD
Wipe method to be used before format operation.
Currently supported types include: quick, zero, scrub
quick - Quick method (default)
zero - Write zeros to the entire drive
scrub - Iteratively writes patterns on drive
zero - Write zeros to the entire device
scrub - Iteratively writes patterns on device
to make retrieving the data more difficult.
Requires 'scrub' to be executable and in the PATH.
See also http://linux.die.net/man/1/scrub
If absent, defaults to 'quick'.
Note: 'zero' and 'scrub' methods will take a long time.
drive
Drive to format. Should be of the form:
device
Device to format. Should be of the form:
* sdx (Linux, where 'x' is a letter) or
* diskN (OS X, where 'N' is a number)
label
Label to apply to formatted drive.
Label to apply to formatted device.
Example: ./format-udf.sh sdg "My External Drive"
```
Expand All @@ -137,17 +139,17 @@ user@computer:~$ ./format-udf.sh sdg "My UDF External Drive"
HTS721010G9SA00
RO RA SSZ BSZ StartSec Size Device
rw 256 512 4096 0 100030242816 /dev/sdg
The above-listed drive (and partitions, if any) will be completely erased.
The above-listed device (and partitions, if any) will be completely erased.
Type 'yes' if this is what you intend: yes
[+] Detecting total size...
[*] Using total size of 100030242816
[+] Validating detected total size...
[+] Detecting physical block size...
[*] Using block size of 512
[+] Validating detected block size...
[+] Unmounting drive...
[+] Unmounting device...
umount: /dev/sdg: not mounted
[+] Zeroing out any existing partition table on drive...
[+] Zeroing out first chunk of device...
4096+0 records in
4096+0 records out
2097152 bytes (2.1 MB) copied, 0.531167 s, 3.9 MB/s
Expand Down Expand Up @@ -187,18 +189,18 @@ computer:~ user$ ./format-udf.sh disk2 "My UDF External Drive"
/dev/disk2
#: TYPE NAME SIZE IDENTIFIER
0: Old Drive *100.0 GB disk2
The above-listed drive (and partitions, if any) will be completely erased.
The above-listed device (and partitions, if any) will be completely erased.
Type 'yes' if this is what you intend: yes
[+] Detecting total size...
[*] Using total size of 100030242816
[+] Validating detected total size...
[+] Detecting physical block size...
[*] Using block size of 512
[+] Validating detected block size...
[+] Unmounting drive...
[+] Unmounting device...
Password:
Unmount of all volumes on disk2 was successful
[+] Zeroing out any existing partition table on drive...
[+] Zeroing out first chunk of device...
4096+0 records in
4096+0 records out
2097152 bytes transferred in 0.592766 secs (3537908 bytes/sec)
Expand Down
81 changes: 60 additions & 21 deletions format-udf.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# format-udf.sh
#
# Bash script to format a block drive (hard drive or Flash drive) in UDF. The output is a drive that can be used for reading/writing across multiple operating system families: Windows, OS X, and Linux. This script should be capable of running in OS X or in Linux.
# Bash script to format a block device (hard drive or Flash drive) in UDF. The output is a drive that can be used for reading/writing across multiple operating system families: Windows, OS X, and Linux. This script should be capable of running in OS X or in Linux.
#
# Version 1.2.0
#
Expand Down Expand Up @@ -50,7 +50,7 @@ OPTIND=1
# None
print_usage() {
cat <<EOF >&2
Usage: $0 [-b BLOCK_SIZE] [-f] [-p PARTITION_TYPE] [-w WIPE_METHOD] drive label
Usage: $0 [-b BLOCK_SIZE] [-f] [-p PARTITION_TYPE] [-w WIPE_METHOD] device label
-b BLOCK_SIZE
Block size to be used during format operation.
Expand All @@ -77,21 +77,21 @@ Usage: $0 [-b BLOCK_SIZE] [-f] [-p PARTITION_TYPE] [-w WIPE_METHOD] drive label
Wipe method to be used before format operation.
Currently supported types include: quick, zero, scrub
quick - Quick method (default)
zero - Write zeros to the entire drive
scrub - Iteratively writes patterns on drive
zero - Write zeros to the entire device
scrub - Iteratively writes patterns on device
to make retrieving the data more difficult.
Requires 'scrub' to be executable and in the PATH.
See also http://linux.die.net/man/1/scrub
If absent, defaults to 'quick'.
Note: 'zero' and 'scrub' methods will take a long time.
drive
Drive to format. Should be of the form:
device
Device to format. Should be of the form:
* sdx (Linux, where 'x' is a letter) or
* diskN (OS X, where 'N' is a number)
label
Label to apply to formatted drive.
Label to apply to formatted device.
Example: $0 sdg "My External Drive"
EOF
Expand Down Expand Up @@ -346,8 +346,8 @@ fi
DEVICE=$1
LABEL=$2

# verify that DEVICE doesn't have partition number on end, or that it's in OS X format
(echo "$DEVICE" | egrep -q '^([hs]d[a-z]|disk[0-9]+)$') || (echo "[-] <device> is of invalid form" >&2; false)
# validate device identifier (may be partition)
(echo "$DEVICE" | egrep -q '^(([hs]d[a-z])([1-9][0-9]*)?|(disk[0-9]+)(s[1-9][0-9]*)?)$') || (echo "[-] <device> is of invalid form" >&2; false)

# verify this is a device, not just a file
# `true` is so that a failure here doesn't cause entire script to exit prematurely
Expand All @@ -358,14 +358,42 @@ mount /dev/$DEVICE 2>/dev/null || true
trap exit_with_no_changes EXIT


###############################################################################
# validate parent device
###############################################################################

# extract parent device identifier
if sed --version &> /dev/null; then
# this box has GNU sed ('-r' for extended regex)
PARENT_DEVICE=$(echo "$DEVICE" | sed -r 's/^(([hs]d[a-z])([1-9][0-9]*)?|(disk[0-9]+)(s[1-9][0-9]*)?)$/\2\4/')
else
# this machine must have BSD sed ('-E' for extended regex)
PARENT_DEVICE=$(echo "$DEVICE" | sed -E 's/^(([hs]d[a-z])([1-9][0-9]*)?|(disk[0-9]+)(s[1-9][0-9]*)?)$/\2\4/')
fi

# validate parent device identifier (must be entire device)
(echo "$PARENT_DEVICE" | egrep -q '^([hs]d[a-z]|disk[0-9]+)$') || (echo "[-] <device> is of invalid form (invalid parent device)" >&2; false)

# verify parent is a device, not just a file
[[ -b /dev/$PARENT_DEVICE ]] || (echo "[-] /dev/$PARENT_DEVICE either doesn't exist or is not block special" >&2; false)

# validate configuration
if [[ "$PARENT_DEVICE" != "$DEVICE" ]] && [[ "$PARTITION_TYPE" != "none" ]]; then
echo "[-] You are attempting to format a single partition (as opposed to entire device)." >&2
echo "[-] Partition type '$PARTITION_TYPE' incompatible with single partition formatting." >&2
echo "[-] Please specify an entire device or partition type of 'none'." >&2
exit 1
fi


###############################################################################
# print drive information
###############################################################################

echo "[+] Gathering drive information..."
if [[ $TOOL_DRIVE_LISTING = $TOOL_BLOCKDEV ]]; then
sudo blkid -c /dev/null /dev/$DEVICE || true
cat /sys/block/$DEVICE/device/model
cat /sys/block/$PARENT_DEVICE/device/model
sudo blockdev --report | egrep "(Device|$DEVICE)"
elif [[ $TOOL_DRIVE_LISTING = $TOOL_DISKUTIL ]]; then
diskutil list $DEVICE
Expand All @@ -380,8 +408,19 @@ fi
###############################################################################

if [[ -z $FORCE ]]; then
if [[ "$PARENT_DEVICE" != "$DEVICE" ]]; then
echo "You are attempting to format a single partition (as opposed to entire device)."
echo "For maximal compatibility, the recommendation is to format the entire device."
echo "If you continue, the resultant UDF partition will not be recognized on OS X."
read -p "Type 'yes' if this is what you intend: " YES_CASE
YES=$(echo $YES_CASE | tr '[:upper:]' '[:lower:]')
if [[ $YES != "yes" ]]; then
exit 1
fi
fi

# give the user a chance to realize his/her mistake
echo "The above-listed drive (and partitions, if any) will be completely erased."
echo "The above-listed device (and partitions, if any) will be completely erased."
read -p "Type 'yes' if this is what you intend: " YES_CASE
YES=$(echo $YES_CASE | tr '[:upper:]' '[:lower:]')
if [[ $YES != "yes" ]]; then
Expand Down Expand Up @@ -438,10 +477,10 @@ echo "[+] Validating detected block size..."


###############################################################################
# unmount drive (if mounted)
# unmount device (if mounted)
###############################################################################

echo "[+] Unmounting drive..."
echo "[+] Unmounting device..."
if [[ $TOOL_UNMOUNT = $TOOL_UMOUNT ]]; then
# `true` is so that a failure here doesn't cause entire script to exit prematurely
sudo umount /dev/$DEVICE || true
Expand All @@ -455,22 +494,22 @@ fi


###############################################################################
# optionally wipe drive
# optionally wipe device
###############################################################################

# this is where we start making changes to the drive
# this is where we start making changes to the device
trap - EXIT

case $WIPE_METHOD in
quick)
# nothing to do
;;
zero)
echo "[+] Overwriting drive with zeros. This will likely take a LONG time..."
echo "[+] Overwriting device with zeros. This will likely take a LONG time..."
sudo dd if=/dev/zero of=/dev/$DEVICE bs=$BLOCK_SIZE || true
;;
scrub)
echo "[+] Scrubbing drive with random patterns. This will likely take a LONG time..."
echo "[+] Scrubbing device with random patterns. This will likely take a LONG time..."
sudo scrub -f /dev/$DEVICE
;;
*)
Expand All @@ -484,13 +523,13 @@ esac
# zero out partition table (required even without fake partition table)
###############################################################################

echo "[+] Zeroing out any existing partition table on drive..."
# 4096 was arbitrarily chosen to be "big enough" to delete first chunk of disk
echo "[+] Zeroing out first chunk of device..."
# 4096 was arbitrarily chosen to be "big enough" to delete first chunk of device
sudo dd if=/dev/zero of=/dev/$DEVICE bs=$BLOCK_SIZE count=4096


###############################################################################
# format drive
# format device
###############################################################################

echo "[+] Formatting /dev/$DEVICE ..."
Expand Down Expand Up @@ -542,7 +581,7 @@ esac
# report status
###############################################################################

# following call to blkid sometimes exits with failure, even though the drive is formatted properly.
# following call to blkid sometimes exits with failure, even though the device is formatted properly.
# `true` is so that a failure here doesn't cause entire script to exit prematurely
SUMMARY=$([[ -x $(which blkid) ]] && sudo blkid -c /dev/null /dev/$DEVICE 2>/dev/null) || true
echo "[+] Successfully formatted $SUMMARY"
Expand Down

0 comments on commit 921c04b

Please sign in to comment.