X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;f=cirros-testvm%2Fsrc-cirros%2Fbin%2Fpart2disk;fp=cirros-testvm%2Fsrc-cirros%2Fbin%2Fpart2disk;h=92ec42677840c3b72a0054233940212d8073d10e;hb=b0a0f15dfaa205161a7fcb20cf1b8cd4948c2ef3;hp=0000000000000000000000000000000000000000;hpb=c6ac3cd55ee2da956195eee393b0882105dfad4e;p=packages%2Ftrusty%2Fcirros-testvm.git diff --git a/cirros-testvm/src-cirros/bin/part2disk b/cirros-testvm/src-cirros/bin/part2disk new file mode 100755 index 0000000..92ec426 --- /dev/null +++ b/cirros-testvm/src-cirros/bin/part2disk @@ -0,0 +1,215 @@ +#!/bin/sh +# part2disk - wrap a partition image in a disk image +# +# Copyright (C) 2010 Canonical Ltd. +# +# Authors: Scott Moser +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +DEF_SECTOR_SIZE=512 +DEBUG=0 +base_d=$(dirname $(readlink -f "${0}")) +PATH="${PATH}:${base_d}" +error() { echo "$@" 1>&2; } +debug() { + [ "${DEBUG}" -ge "${1:-0}" ] && shift || return 0; + error "$@"; +} +fail() { [ $# -eq 0 ] || error "$@"; exit 1; } +getsize() { + local fname="$1" kname="" size="" + if [ -b "${fname}" ]; then + kname=$(readlink -f "${fname}") && + size=$(awk '$4 == kn { print $3 * 1024 }' \ + "kn=${kname##*/}" /proc/partitions) && + [ -n "${size}" ] || { + error "failed to read size of ${fname} from /proc/partitions"; + return 1; + } + else + size=$(stat --format "%s" "${fname}") || { + error "failed to get size of ${fname}" + return 1; + } + fi + _RET="$size" +} + +Usage() { + cat <&2; fail "$@"; } +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=${2:-1024};; + esac + _RET=$((${count}*${unit})) +} + +short_opts="b:c:Ghs:v" +long_opts="grub1,grub,help,size:,verbose" +getopt_out=$(getopt --name "${0##*/}" \ + --options "${short_opts}" --long "${long_opts}" -- "$@") && + eval set -- "${getopt_out}" || + bad_Usage + +ssize=${DEF_SECTOR_SIZE} +size_in="" +grub_ptnum=1 +grub=0 +grub1=0 +while [ $# -ne 0 ]; do + cur=${1}; next=${2}; + case "$cur" in + -G|--grub) grub=1;; + -G|--grub1) grub1=1;; + -h|--help) Usage; exit 0;; + -s|--size) size_in=$2; shift;; + -v|--verbose) DEBUG=$((${DEBUG}+1));; + --) shift; break;; + esac + shift; +done + +[ $# -eq 2 ] || bad_Usage "must supply partition image and output file" + +pimg=${1} +dimg=${2} + +{ [ ${grub} -eq 0 ] || phelper=$(command -v part2disk-grubhelper); } || + fail "no part2disk-grubhelper in PATH" +[ $grub1 -eq 0 ] || command -v grub >/dev/null || fail "no 'grub' in path"; + +[ -f "${pimg}" -o -b "${pimg}" ] || fail "${pimg}: not a file or block device" + +getsize "$pimg" || + fail "failed to get size of $pimg" +pimg_s="$_RET" + +# end_pad_sectors: room for secondary gpt +end_pad_sectors=33 +end_pad=$(($end_pad_sectors*$ssize)) +front_pad=$((1024*1024)) +front_pad_sectors=$(($front_pad/$ssize)) +padding=$(($front_pad+$end_pad)) +pt_sector_pad=$(($ssize-(${pimg_s}%$ssize))) +if [ $pt_sector_pad -eq $ssize ]; then + pt_sector_pad=0 +fi +pt_size=$(($pimg_s+$pt_sector_pad)) +pt_sectors=$(($pt_size/$ssize)) +tot_size=$(($front_pad+$pt_size+$end_pad)) +tot_size_sectors=$(($tot_size/$ssize)) + +if [ -n "${size_in}" ]; then + human2bytes "${size_in}" 1 || fail "failed to convert ${size_in} to bytes" + size=${_RET} +else + # no size specified, get enough to fit part_img, 1M header and 1M end. + size=$((${pimg_s}+$padding+$pt_sector_pad)) +fi + +if [ -e "$dimg" ]; then + getsize "$dimg" || + fail "failed to get size of $dimg" + dimg_s="$_RET" +else + dimg_s="$size" +fi + +if [ "${dimg_s}" -lt "$size" ]; then + fail "size of $dimg ($dimg_s) not large enough to fit $size" +fi + +debug 1 "input is ${pimg_s} bytes ($pt_sectors sectors of $ssize)." +debug 1 "target is ${tot_size} bytes ($tot_size_sectors sectors)." +debug 1 "padding $front_pad_sectors sectors at front," \ + "$end_pad_sectors sectors at end." + +debug 2 "zeroing first $front_pad_sectors sectors $dimg" +dd if=/dev/zero of="${dimg}" bs=$ssize "count=${front_pad_sectors}" \ + 2>/dev/null || + fail "failed to write to ${dimg}" + +# copy partition image. this writes $pimg bytes even if that is +# not divivisble by $ssize +debug 2 "copying ${pimg} to partition in ${dimg}" +dd if="$pimg" of="$dimg" seek=${front_pad_sectors} bs=$ssize conv=notrunc \ + 2>/dev/null || + fail "failed to write ${pimg} into ${dimg}" + +# zero any unwritten portion of the final sector +leftover=$(($ssize-(${pimg_s}%$ssize))) +if [ $pt_sector_pad -ne 0 ]; then + debug 2 "finishing final sector with $pt_sector_pad bytes of zeros" + dd if=/dev/zero of="$dimg" bs=1 seek=$((${pimg_s}+${front_pad})) \ + conv=notrunc count=$pt_sector_pad 2>/dev/null || + fail "failed to finish final sector of $pimg" +fi + +# we've now written front pad + round-sectors. now write end_pad +debug 2 "writing final $end_pad_sectors sectors" +dd if=/dev/zero "of=$dimg" bs=$ssize \ + seek=$((($size/$ssize)-${end_pad_sectors})) count=${end_pad_sectors} \ + conv=notrunc 2>/dev/null || + fail "failed to write final 1M to $pimg" + +sfdisk_in="${front_pad_sectors},$pt_sectors,L,*" +debug 2 "writing partition table to ${dimg} ($sfdisk_in)" +sfdisk_out=$(echo "$sfdisk_in" | sfdisk --force --unit=S "${dimg}" 2>&1) + +[ $? -eq 0 ] || { + error "${sfdisk_out}"; + fail "failed to create partition table"; +} + +if [ ${grub} -ne 0 ]; then + debug 2 "invoking part2disk-grubhelper ${dimg}" + sudo "${phelper}" "${dimg}" || + fail "part2disk-grubhelper ${dimg} failed" +fi + +if [ $grub1 -ne 0 ]; then + debug 2 "installing grub" + grub --no-floppy --batch <