2
# Copyright (C) 2011 Canonical Ltd.
4
# Authors: Scott Moser <smoser@canonical.com>
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, version 3 of the License.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program. If not, see <http://www.gnu.org/licenses/>.
18
# the fudge factor. if its within this many 512 byte sectors, dont bother
19
FUDGE=${GROWPART_FUDGE:-$((20*1024))}
25
error() { echo "$@" 1>&2; }
26
fail() { [ $# -eq 0 ] || echo "FAILED:" "$@"; exit 1; }
27
nochange() { echo "NOCHANGE:" "$@"; exit 0; }
28
changed() { echo "CHANGED:" "$@"; exit 0; }
30
if [ -n "${RESTORE_FROM}" ]; then
31
error "***** WARNING: Resize failed, attempting to revert ******"
32
if sfdisk "${DISK}" ${CHS} -I "${RESTORE_FROM}"; then
33
error "***** Appears to have gone OK ****"
35
error "***** FAILED! or original partition table looked like: ****"
36
cat "${RESTORE_HUMAN}" 1>&2
39
[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
42
local level=${1}; shift;
43
[ "${level}" -gt "${VERBOSITY}" ] && return
47
# just a mktemp -d that doens't need mktemp if its not there.
48
_RET=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX" 2>/dev/null) && return
49
_RET=$(umask 077 && t="${TMPDIR:-/tmp}/${0##*/}.$$" && mkdir "${t}" &&
56
${0##*/} disk partition
57
rewrite partition table so that partition takes up all the space it can
59
-h | --help print Usage an exit
60
--fudge F if part could be resized, but change would be
61
less than 'F', do not resize (default: ${FUDGE})
62
-N | --dry-run only report what would be done, show new 'sfdisk -d'
63
-v | --verbose increase verbosity / debug
67
Resize partition 1 on /dev/sda
70
bad_Usage() { Usage 1>&2; error "$@"; exit 1; }
73
#long_opts="help,dry-run,fudge:,verbose"
74
#getopt_out=$(getopt --name "${0##*/}" \
75
# --options "${short_opts}" --long "${long_opts}" -- "$@") &&
76
# eval set -- "${getopt_out}" ||
83
while [ $# -ne 0 ]; do
86
-h|--help) Usage; exit 0;;
87
--fudge) fudge=${next}; shift;;
88
--dry-run) dry_run=1;;
89
-v|--verbose) VERBOSITY=$(($VERBOSITY+1));;
91
-*) fail "unknown option ${cur}";;
93
if [ -z "${disk}" ]; then
96
[ -z "${part}" ] || fail "confused by arg ${cur}"
104
[ -n "${disk}" ] || bad_Usage "must supply disk and partition-number"
105
[ -n "${part}" ] || bad_Usage "must supply partition-number"
107
[ -e "${disk}" ] || { fail "${disk}: does not exist"; }
109
[ "${part#*[!0-9]}" = "${part}" ] || fail "partition-number must be a number"
111
mktemp_d && TEMP_D="${_RET}" || fail "failed to make temp dir"
114
change_out=${TEMP_D}/change.out
115
change_err=${TEMP_D}/change.err
116
dump_out=${TEMP_D}/dump.out
117
new_out=${TEMP_D}/new.out
118
dump_mod=${TEMP_D}/dump.mod
119
tmp="${TEMP_D}/tmp.out"
120
err="${TEMP_D}/err.out"
121
orig_bin="${TEMP_D}/orig.save"
122
RESTORE_HUMAN="${TEMP_D}/recovery"
124
# --show-pt-geometry outputs something like
125
# /dev/sda: 164352 cylinders, 4 heads, 32 sectors/track
126
sfdisk "${disk}" --show-pt-geometry > "${tmp}" 2>"${err}" &&
127
read _devc cyl _word1 heads _word2 sectors _word3 < "${tmp}" &&
128
CHS="-C $cyl -H $heads -S $sectors" ||
129
fail "failed to get CHS from ${disk}"
131
tot=$((${cyl}*${heads}*${sectors}))
133
debug 1 "geometry is $CHS. total size=${tot}"
134
sfdisk ${CHS} -uS -d "${disk}" > "${dump_out}" 2>"${err}" ||
135
fail "failed to dump sfdisk info for ${disk}"
138
echo "## sfdisk ${CHS} -uS -d ${disk}";
140
} > "${RESTORE_HUMAN}"
141
[ $? -eq 0 ] || fail "failed to save sfdisk -d output"
143
sed -e 's/,//g; s/start=/start /; s/size=/size /' "${dump_out}" > "${dump_mod}"
145
dpart="${disk}${part}" # disk and partition number
146
pt_start=$(awk '$1 == pt { print $4 }' "pt=${dpart}" < "${dump_mod}") &&
147
pt_size=$(awk '$1 == pt { print $6 }' "pt=${dpart}" < "${dump_mod}") &&
148
[ -n "${pt_start}" -a -n "${pt_size}" ] &&
149
pt_end=$((${pt_size}+${pt_start})) ||
150
fail "failed to get start and end for ${dpart} in ${disk}"
152
# find the minimal starting location that is >= pt_end
154
$3 == "start" { if($4 >= pt_end && $4 < min) { min = $4 } }
155
END { printf("%s\n",min); }' \
156
min=${tot} pt_end=${pt_end} "${dump_mod}") &&
157
[ -n "${max_end}" ] ||
158
fail "failed to get max_end for partition ${part}"
160
debug 1 "max_end=${max_end} tot=${tot} pt_end=${pt_end} pt_start=${pt_start} pt_size=${pt_size}"
161
[ $((${pt_end})) -eq ${max_end} ] &&
162
nochange "partition ${part} is size ${pt_size}. it cannot be grown"
163
[ $((${pt_end}+${fudge})) -gt ${max_end} ] &&
164
nochange "partition ${part} could only be grown by $((${max_end}-${pt_end})) [fudge=${fudge}]"
166
# now, change the size for this partition in ${dump_out} to be the
168
new_size=$((${max_end}-${pt_start}))
169
sed "\|^${dpart} |s/${pt_size},/${new_size},/" "${dump_out}" > "${new_out}" ||
170
fail "failed to change size in output"
172
change_info="partition=${part} start=${pt_start} old: size=${pt_size} end=${pt_end} new: size=${new_size},end=${max_end}"
173
if [ $dry_run -ne 0 ]; then
174
echo "CHANGE: ${change_info}"
176
echo "# === old sfdisk -d ==="
178
echo "# === new sfdisk -d ==="
184
sfdisk "${disk}" ${CHS} --force -O "${orig_bin}" \
185
< "${new_out}" > "${change_out}" 2> "${change_err}" || {
186
DISK=${disk}; RESTORE_FROM="${orig_bin}";
187
fail "failed to resize"
189
changed "${change_info}"
191
# dump_out looks something like:
192
## partition table of /tmp/out.img
195
#/tmp/out.img1 : start= 1, size= 48194, Id=83
196
#/tmp/out.img2 : start= 48195, size= 963900, Id=83
197
#/tmp/out.img3 : start= 1012095, size= 305235, Id=82
198
#/tmp/out.img4 : start= 1317330, size= 771120, Id= 5
199
#/tmp/out.img5 : start= 1317331, size= 642599, Id=83
200
#/tmp/out.img6 : start= 1959931, size= 48194, Id=83
201
#/tmp/out.img7 : start= 2008126, size= 80324, Id=83
203
# vi: ts=4 noexpandtab