remakesd

Annotated makesd-partition-table

15:8d9e0eca8425
2019-05-27 Paul Boddie Added copyright and licensing details.
paul@1 1
#!/bin/sh
paul@1 2
paul@1 3
# Emit a partition table for a device employing parameters such as the start,
paul@1 4
# size, and type.
paul@15 5
#
paul@15 6
# Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
paul@15 7
#
paul@15 8
# This program is free software; you can redistribute it and/or modify it under
paul@15 9
# the terms of the GNU General Public License as published by the Free Software
paul@15 10
# Foundation; either version 3 of the License, or (at your option) any later
paul@15 11
# version.
paul@15 12
#
paul@15 13
# This program is distributed in the hope that it will be useful, but WITHOUT
paul@15 14
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
paul@15 15
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
paul@15 16
# details.
paul@15 17
#
paul@15 18
# You should have received a copy of the GNU General Public License along with
paul@15 19
# this program.  If not, see <http://www.gnu.org/licenses/>.
paul@1 20
paul@1 21
PROGNAME=`basename "$0"`
paul@1 22
THISDIR=`dirname "$0"`
paul@1 23
paul@7 24
COMMON="$THISDIR/makesd-common"
paul@1 25
SFDISK="/sbin/sfdisk"
paul@1 26
paul@7 27
. "$COMMON"
paul@7 28
paul@1 29
paul@1 30
paul@2 31
# Cylinder size in sectors for alignment purposes.
paul@2 32
paul@2 33
HEADS=255
paul@2 34
SECTORS=63
paul@2 35
CYLINDER_SIZE=$(($HEADS * $SECTORS))
paul@2 36
paul@1 37
# Global partition number and previous partition details.
paul@1 38
paul@1 39
PARTNUM=1
paul@1 40
PREVSTART=
paul@1 41
PREVSIZE=
paul@1 42
PREVTYPE=
paul@1 43
paul@1 44
# Emit any previous partition details as a complete sfdisk-compatible record.
paul@1 45
paul@1 46
emit_partition()
paul@1 47
{
paul@1 48
    if [ "$PREVSTART" ] || [ "$PREVSIZE" ] || [ "$PREVTYPE" ] ; then
paul@1 49
        echo -n "$PARTNUM : "
paul@1 50
        emit_partition_fields | sed 's/^ //;s/ /,/g'
paul@1 51
        PARTNUM=$(($PARTNUM + 1))
paul@1 52
    fi
paul@1 53
}
paul@1 54
paul@1 55
# Emit the previous partition fields.
paul@1 56
paul@1 57
emit_partition_fields()
paul@1 58
{
paul@2 59
    echo -n " start=${PREVSTART}${SFDISK_UNIT_SUFFIX}"
paul@2 60
paul@3 61
    REMAINING=$(($DEVSIZE - $PREVSTART))
paul@3 62
paul@3 63
    # Retain any previously calculated size.
paul@1 64
    # Without a size, use start details to calculate a size.
paul@1 65
    # Without start details, claim the rest of the device.
paul@1 66
paul@1 67
    if [ "$PREVSIZE" ] ; then
paul@3 68
        :
paul@1 69
    elif [ "$START" ] ; then
paul@2 70
        PREVSIZE=$((`align_cylinder $START` - $PREVSTART))
paul@1 71
    else
paul@1 72
        PREVSIZE=$REMAINING
paul@1 73
    fi
paul@1 74
paul@1 75
    if [ "$PREVSIZE" -gt "$REMAINING" ] ; then
paul@1 76
        PREVSIZE=$REMAINING
paul@1 77
    fi
paul@1 78
paul@1 79
    echo -n " size=${PREVSIZE}${SFDISK_UNIT_SUFFIX}"
paul@1 80
paul@1 81
    if [ "$PREVTYPE" ] ; then
paul@1 82
        echo -n " Id=`partition_type $PREVTYPE`"
paul@1 83
    fi
paul@2 84
paul@1 85
    echo
paul@1 86
}
paul@1 87
paul@1 88
# Retain the current partition details.
paul@1 89
paul@1 90
store_partition()
paul@1 91
{
paul@3 92
    # Define the partition start using a specified position.
paul@3 93
    # Alternatively, use previous start and size information.
paul@3 94
    # Otherwise, the first partition is being defined.
paul@3 95
paul@5 96
    if [ "$START" ] && [ "$START" != '-' ] ; then
paul@3 97
        PREVSTART=`align_cylinder $START`
paul@1 98
    elif [ "$PREVSTART" ] && [ "$PREVSIZE" ] ; then
paul@3 99
        PREVSTART=`align_cylinder $(($PREVSTART + $PREVSIZE))`
paul@1 100
    else
paul@1 101
        PREVSTART=0
paul@1 102
    fi
paul@1 103
paul@3 104
    # Ensure that the first partition starts at sector one.
paul@3 105
paul@3 106
    if [ "$PREVSTART" = '0' ] ; then
paul@3 107
        PREVSTART=1
paul@3 108
    fi
paul@3 109
paul@3 110
    # Calculate and align the stated size.
paul@3 111
    # Otherwise, defer the calculation until emitting the details.
paul@3 112
paul@5 113
    if [ "$SIZE" ] && [ "$SIZE" != '-' ] ; then
paul@3 114
        PREVSIZE=$(($SIZE * $DEVSIZE / 100))
paul@3 115
        PREVSIZE=`align_cylinder $PREVSIZE`
paul@3 116
paul@3 117
        if [ "$PREVSTART" = '1' ] ; then
paul@3 118
            PREVSIZE=$(($PREVSIZE - 1))
paul@3 119
        fi
paul@3 120
    else
paul@3 121
        PREVSIZE=
paul@3 122
    fi
paul@3 123
paul@1 124
    PREVTYPE=$TYPE
paul@1 125
}
paul@1 126
paul@1 127
# Emit the current partition details and proceed to the next partition.
paul@1 128
paul@1 129
next_partition()
paul@1 130
{
paul@5 131
    emit_partition
paul@5 132
    store_partition
paul@1 133
}
paul@1 134
paul@1 135
# Convert the partition type to an sdisk-compatible identifier.
paul@1 136
paul@1 137
partition_type()
paul@1 138
{
paul@1 139
    case "$1" in
paul@7 140
        ( ext* ) echo "0x83" ;;
paul@7 141
        ( swap ) echo "0x82" ;;
paul@7 142
        ( fat  ) echo "0x0c" ;;
paul@7 143
        ( *    ) echo "0x83" ;;
paul@1 144
    esac
paul@1 145
}
paul@1 146
paul@1 147
paul@1 148
paul@1 149
# device_size <device>
paul@1 150
#
paul@1 151
# Obtain the size of the given disk or partition in 1024-byte blocks.
paul@1 152
paul@1 153
device_size()
paul@1 154
{
paul@1 155
    "$SFDISK" -s "$1"
paul@1 156
}
paul@1 157
paul@2 158
# Align to cylinders.
paul@2 159
paul@2 160
align_cylinder()
paul@2 161
{
paul@4 162
    if [ ! "$ALIGN_CYLINDER" ] ; then
paul@4 163
        echo $1
paul@4 164
        return
paul@4 165
    fi
paul@4 166
paul@2 167
    # Round up to the nearest cylinder.
paul@2 168
paul@2 169
    CYLINDER=$((($1 + $CYLINDER_SIZE - 1) / $CYLINDER_SIZE))
paul@2 170
paul@2 171
    # Emit the number of sectors.
paul@2 172
paul@2 173
    echo $(($CYLINDER * $CYLINDER_SIZE))
paul@2 174
}
paul@2 175
paul@1 176
# Test sfdisk behaviour and obtain useful information.
paul@1 177
paul@1 178
init_sfdisk()
paul@1 179
{
paul@2 180
    SFDISK_UNIT_SUFFIX=
paul@2 181
paul@2 182
    # Obtain the device size in 512-byte sectors.
paul@1 183
paul@2 184
    DEVSIZE=$((`device_size "$1"` * 2))
paul@1 185
paul@2 186
    # Find the cylinder-addressable size.
paul@2 187
paul@4 188
    if [ "$ALIGN_CYLINDER" ] ; then
paul@4 189
        CYLINDERS=$(($DEVSIZE / $CYLINDER_SIZE))
paul@4 190
        DEVSIZE=$(($CYLINDERS * $CYLINDER_SIZE))
paul@4 191
    fi
paul@1 192
}
paul@1 193
paul@1 194
paul@1 195
paul@1 196
# Emit the help message if requested.
paul@1 197
paul@1 198
if [ "$1" = '--help' ] ; then
paul@1 199
    cat 1>&2 <<EOF
paul@13 200
Usage: $PROGNAME [ --align ]
paul@1 201
paul@1 202
Produce partition descriptions, indicating partition type, start position and
paul@13 203
size for each partition.
paul@13 204
paul@13 205
The input for this program is supplied via standard input as a partitioning
paul@13 206
summary with each line providing a collection of tab-separated values. These
paul@13 207
values appear in the following order:
paul@13 208
paul@13 209
<start> <size> <type>
paul@1 210
paul@2 211
Start positions are indicated as numbers of 512-byte sectors.
paul@1 212
paul@1 213
Sizes are indicated as percentages of the entire device; if omitted, the
paul@1 214
remainder of the device will be used.
paul@1 215
paul@1 216
Types recognised include ext, ext2, ext3, ext4, fat and swap. Other types are
paul@4 217
interpreted as Linux partitions.
paul@4 218
paul@13 219
$(align_cylinder_description)
paul@1 220
EOF
paul@1 221
    exit 0
paul@1 222
fi
paul@1 223
paul@4 224
# Test for the cylinder alignment option.
paul@4 225
paul@11 226
if test_align_cylinder $* ; then shift 1 ; fi
paul@4 227
paul@1 228
# Obtain details of the selected device.
paul@1 229
paul@7 230
check_device
paul@4 231
paul@1 232
# Initialise sfdisk usage.
paul@1 233
paul@1 234
init_sfdisk "$DEV"
paul@1 235
paul@5 236
while read_fields ; do
paul@5 237
    next_partition
paul@1 238
done
paul@1 239
paul@1 240
# Emit the last partition.
paul@1 241
paul@1 242
emit_partition