Created
December 11, 2013 19:34
-
-
Save smoser/7916902 to your computer and use it in GitHub Desktop.
partition: partition a disk with a single partition using either GPT or MBR partition table format.
This is just a simple front end to 'sfdisk' or 'gpt' to put a partition on a image.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
VERBOSITY=0 | |
error() { echo "$@" 1>&2; } | |
fail() { [ $# -eq 0 ] || error "$@"; exit 1; } | |
Usage() { | |
cat <<EOF | |
Usage: ${0##*/} [ options ] target-dev | |
partition target-dev with a single partition | |
destroy any partition table that might be there already. | |
options: | |
-f | --format F use partition table format F. [mbr, gpt] | |
default gpt | |
-E | --end E end the partition at E (unit 1k bytes) | |
EOF | |
} | |
bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; return 1; } | |
debug() { | |
local level=${1}; shift; | |
[ "${level}" -gt "${VERBOSITY}" ] && return | |
error "${@}" | |
} | |
human2bytes() { | |
# converts size suitable for input to resize2fs to bytes | |
# s:512 byte sectors, K:kilobytes, M:megabytes, G:gigabytes | |
# none: block size of the image | |
local input=${1} defunit=${2:-1024} | |
local unit count; | |
case "$input" in | |
*s) count=${input%s}; unit=512;; | |
*K) count=${input%K}; unit=1024;; | |
*M) count=${input%M}; unit=$((1024*1024));; | |
*G) count=${input%G}; unit=$((1024*1024*1024));; | |
*) count=${input} ; unit=${defunit};; | |
esac | |
_RET=$((${count}*${unit})) | |
} | |
getsize() { | |
local target="$1" | |
if [ -b "$target" ]; then | |
_RET=$(blockdev --getsize64 "$target") | |
elif [ -f "$target" ]; then | |
_RET=$(stat "--format=%s" "$target") | |
else | |
return 1; | |
fi | |
} | |
wipedev() { | |
# wipe the front and end (gpt is at end also) | |
local target="$1" size="" | |
getsize "$target" || | |
{ error "failed to get size of $target"; return 1; } | |
size="$_RET" | |
dd if=/dev/zero conv=notrunc of="$target" \ | |
bs=$((1024*1024)) count=1 >/dev/null 2>&1 || | |
{ error "failed to zero beginning of $target"; return 1; } | |
out=$(dd if=/dev/zero conv=notrunc of="$target" bs=1024 \ | |
seek=$(((size/1024)-1024)) count=1024 2>&1) | |
[ $? -eq 0 ] || | |
{ error "failed to wipe end of $target [$size]: $out"; return 1; } | |
if [ -b "$target" ]; then | |
blockdev --rereadpt "$target" | |
udevadm settle | |
fi | |
} | |
pt_gpt() { | |
local target="$1" end=${2:-""} size="" s512="" ptype="L" | |
local start="2048" pt1size="" maxend="" out="" | |
getsize "$target" || | |
{ error "failed to get size of $target"; return 1; } | |
size="$_RET" | |
if [ -z "$end" ]; then | |
end=$(($size/512)) | |
else | |
end=$(($end/512)) | |
fi | |
maxend=$((($size/512)-2048)) | |
[ "$end" -gt "$maxend" ] && end="$maxend" | |
debug 1 "maxend=$maxend end=$end size=$size" | |
out=$(sgdisk --new "1:2048:$end" --typecode=1:8300 "$target") || { | |
error "$out" 1>&2; | |
error "failed sgdisk --new \"1:2048:$end\" " \ | |
"--typecode=1:8300 \"$target\"" | |
return 1 | |
} | |
return 0 | |
} | |
pt_mbr() { | |
local target="$1" end=${2:-""} size="" s512="" ptype="L" | |
local start="2048" pt1size="" maxsize="4294967296" | |
local isblk=false | |
getsize "$target" || | |
{ error "failed to get size of $target"; return 1; } | |
size="$_RET" | |
if [ "$(($size/512))" -gt "$maxsize" ]; then | |
debug 1 "disk is larger than max for mbr (2TB)" | |
s512=$maxsize | |
else | |
s512=$(($size/512)) | |
fi | |
if [ -n "$end" ]; then | |
pt1size=$(((end/512)-2048)) | |
else | |
pt1size=$((s512-2048)) | |
fi | |
[ -b "$target" ] && isblk=true | |
# interact with sfdisk in units of 512 bytes (--unit S) | |
# we start all partitions at 2048 of those (1M) | |
local sfdisk_out="" sfdisk_in="2048,$pt1size,$ptype,*" sfdisk_cmd="" | |
sfdisk_cmd=( sfdisk --no-reread --force --Linux --unit S "$target" ) | |
debug 1 "sfdisking with: echo '$sfdisk_in' | ${sfdisk_cmd[*]}" | |
sfdisk_out=$(echo "$sfdisk_in" | "${sfdisk_cmd[@]}" 2>&1) | |
ret=$? | |
[ $ret -eq 0 ] || { | |
error "failed to partition $target [${sfdisk_out}]"; | |
return 1; | |
} | |
if $isblk; then | |
blockdev --rereadpt "$target" | |
udevadm settle | |
[ -b "${target}1" ] || | |
{ error "no partition found ${target}1"; return 1; } | |
fi | |
out=$(wipefs "--offset=$(($start*512))" "$target" 2>&1) || { | |
error "$out"; | |
error "failed to wipefs first partition of $target"; | |
return 1; | |
} | |
} | |
main() { | |
local short_opts="hE:f:v" | |
local long_opts="help,end:,format:,verbose" | |
local getopt_out=$(getopt --name "${0##*/}" \ | |
--options "${short_opts}" --long "${long_opts}" -- "$@") && | |
eval set -- "${getopt_out}" || | |
{ bad_Usage; return; } | |
local cur="" next="" | |
local format="gpt" target="" end="" | |
while [ $# -ne 0 ]; do | |
cur="$1"; next="$2"; | |
case "$cur" in | |
-h|--help) Usage ; exit 0;; | |
-f|--format) format=$next; shift;; | |
-E|--end) end=$next; shift;; | |
-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; | |
--) shift; break;; | |
esac | |
shift; | |
done | |
[ $# -gt 1 ] && { bad_Usage "got $# args, expected 1"; return 1; } | |
[ $# -eq 0 ] && { bad_Usage "must provide target-dev"; return 1; } | |
target="$1" | |
if [ -n "$end" ]; then | |
human2bytes "$end" || | |
{ error "failed to convert '$end' to bytes"; return 1; } | |
end="$_RET" | |
fi | |
[ "$format" = "gpt" -o "$format" = "mbr" ] || | |
{ bad_usage "invalid format: $format"; return 1; } | |
[ -e "$target" ] || { error "$target does not exist"; return 1; } | |
[ -f "$target" -o -b "$target" ] || | |
{ error "$target not a block device"; return 1; } | |
wipedev "$target" || | |
{ error "wiping $target failed"; return 1; } | |
if [ "$format" = "mbr" ]; then | |
pt_mbr "$target" "$end" | |
elif [ "$format" = "gpt" ]; then | |
pt_gpt "$target" "$end" | |
fi | |
return 0 | |
} | |
main "$@" | |
# vi: ts=4 noexpandtab |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment