#! /bin/bash # Copyright (C) 2011 GRNET S.A. # # 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; either version 2 of the License, or # (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. ### BEGIN TASK INFO # Provides: FixPartitionTable # RunBefore: FilesystemResizeUnmounted # Short-Description: Enlarge last partition to use all the available space ### END TASK INFO set -e . "@commondir@/common.sh" trap task_cleanup EXIT report_task_start # Check if the task should be prevented from running. check_if_excluded if [ ! -b "$SNF_IMAGE_DEV" ]; then log_error "Device file:\`${SNF_IMAGE_DEV}' is not a block device" fi if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = openbsd ]; then @scriptsdir@/disklabel.py -d "$($BLOCKDEV --getsz "$SNF_IMAGE_DEV")" -p "$SNF_IMAGE_DEV" # Tell the kernel to recreate the disk partitions. # We cannot use partprobe to do this because partprobe uses BLKPG ioctl # to create the partitions device files by itself one by one. Since parted # does not support disklabels, the partitions with id larger than 4 will # not be created. # We need to tell the kernel to read the partition table by itself. $BLOCKDEV --rereadpt "$SNF_IMAGE_DEV" exit 0 fi if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = netbsd ]; then warn "Partition resizing currently not supported for NetBSD" exit 0 fi table=$(get_partition_table "$SNF_IMAGE_DEV") if [ $(get_partition_count "$table") -eq 0 ]; then log_error "Device: \`${SNF_IMAGE_DEV}' does not contain any partition" fi table_type=$(get_partition_table_type "$table") if [ "$SNF_IMAGE_PROPERTY_OSFAMILY" = "freebsd" -a "$table_type" != "gpt" ]; then log_error "The image contains a(n) $table_type partition table. " \ "For FreeBSD images only GUID Partition Tables are supported." fi if [ "$table_type" == "gpt" ]; then "$SGDISK" --move-second-header "$SNF_IMAGE_DEV" elif [ "$table_type" != "msdos" ]; then log_error "Device: \'${SNF_IMAGE_DEV}' contains unsupported partition " \ "table type: \`$table_type'. Only msdos & gpt partitions are" \ "supported." fi last_part=$(get_last_partition "$table") last_part_id=$(cut -d':' -f1 <<< "$last_part") # Check if swap is defined... if [ -n "$SNF_IMAGE_PROPERTY_SWAP" ]; then if [[ "$SNF_IMAGE_PROPERTY_SWAP" =~ ^([0-9]+):([0-9]+)$ ]]; then swap_num=${BASH_REMATCH[1]} swap_size=${BASH_REMATCH[2]} swap_unit="MB" else log_error "SWAP property \`$SNF_IMAGE_PROPERTY_SWAP' is not valid" fi fi if [ -z "$swap_num" ]; then swap_num=0 fi # Most partition setups leave 2048s in the end. For GPT partitions you need at # least 34s for the secondary GPT header. new_end="-2049" if [ $swap_num -ne 0 ]; then free=$(get_last_free_sector "$SNF_IMAGE_DEV" "$swap_unit") free_size=$(cut -d: -f4 <<< "$free") free_size_val=${free_size/$swap_unit/} if [ $free_size_val -le $swap_size ]; then log_error "Not enough space for swap partition" fi swap_end="$new_end" swap_start=$((new_end - (swap_size * 2048) + 1)) # in sectors new_end=$((swap_start - 1)) fi extended="" if [ "$table_type" != "msdos" ]; then # For gpt partitions, get the partition GUID code as partition type last_part_type="$($SGDISK -i "$last_part_id" "$SNF_IMAGE_DEV" | grep "^Partition GUID code:" | cut -d"(" -f1 | cut -d: -f2 | xargs echo)" elif [ $last_part_id -gt 4 ]; then last_part_type="logical" extended=$(get_extended_partition "$table") last_primary=$(get_last_primary_partition "$table") ext_id=$(cut -d':' -f1 <<< "$extended") last_prim_id=$(cut -d':' -f1 <<< "$last_primary") if [ "$ext_id" != "$last_prim_id" ]; then # Mark last primary as the last partition last_part="$extended" last_part_id="$ext_id" last_part_type="primary" else # Enlarge the extended partition if [ $swap_num -ge 5 ]; then # This is needed because logical partitions need to have at least # 1 sector gap between them. We make the gap 2048 sectors to # properly align them. new_end=$((new_end - 2048)) enlarge_partition "$SNF_IMAGE_DEV" "$extended" "extended" "${swap_end}s" else enlarge_partition "$SNF_IMAGE_DEV" "$extended" "extended" "${new_end}s" fi fi elif [ $(is_extended_partition "$SNF_IMAGE_DEV" "$last_part_id") = "yes" ]; then last_part_type="extended" extended="$last_part" if [ $swap_num -ge 5]; then new_end=$swap_end fi else last_part_type="primary" if [ $swap_num -ge 5 ]; then # This is needed because the swap partition should be added inside a # new extended partition. In order to align the swap partition, we # need to create some extra space between the (aligned) primary and # the swap. new_end=$((new_end - 2048)) fi fi enlarge_partition "$SNF_IMAGE_DEV" "$last_part" "$last_part_type" "${new_end}s" if [ $swap_num -gt 0 ]; then swap_part="$swap_num:${swap_start}s:${swap_end}s:0:linux-swap(v1)::;" if [ "$table_type" != "msdos" ]; then swap_ptype="swap" # in gpt this is used as a partition name elif [ $swap_num -ge 5 ]; then if [ -z "$extended" ]; then extended="0:$((swap_start - 2))s:${swap_end}s:0:::;" create_partition "$SNF_IMAGE_DEV" "$extended" "extended" fi swap_ptype="logical" else swap_ptype="primary" fi create_partition "$SNF_IMAGE_DEV" "$swap_part" "$swap_ptype" fi # Inform the kernel about the changes partprobe "$SNF_IMAGE_DEV" exit 0 # vim: set sta sts=4 shiftwidth=4 sw=4 et ai :