remakesd

Annotated makesd-partition-table

5:af4351d5e922
2019-05-24 Paul Boddie Introduced a summary script that takes partitioning arguments and produces a partitioning summary. This summary is then processed by the table script to generate suitable input for sfdisk.
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@1 5
paul@1 6
PROGNAME=`basename "$0"`
paul@1 7
THISDIR=`dirname "$0"`
paul@1 8
paul@1 9
SFDISK="/sbin/sfdisk"
paul@1 10
paul@1 11
paul@1 12
paul@2 13
# Cylinder size in sectors for alignment purposes.
paul@2 14
paul@2 15
HEADS=255
paul@2 16
SECTORS=63
paul@2 17
CYLINDER_SIZE=$(($HEADS * $SECTORS))
paul@2 18
paul@1 19
# Global partition number and previous partition details.
paul@1 20
paul@1 21
PARTNUM=1
paul@1 22
PREVSTART=
paul@1 23
PREVSIZE=
paul@1 24
PREVTYPE=
paul@1 25
paul@1 26
# Emit any previous partition details as a complete sfdisk-compatible record.
paul@1 27
paul@1 28
emit_partition()
paul@1 29
{
paul@1 30
    if [ "$PREVSTART" ] || [ "$PREVSIZE" ] || [ "$PREVTYPE" ] ; then
paul@1 31
        echo -n "$PARTNUM : "
paul@1 32
        emit_partition_fields | sed 's/^ //;s/ /,/g'
paul@1 33
        PARTNUM=$(($PARTNUM + 1))
paul@1 34
    fi
paul@1 35
}
paul@1 36
paul@1 37
# Emit the previous partition fields.
paul@1 38
paul@1 39
emit_partition_fields()
paul@1 40
{
paul@2 41
    echo -n " start=${PREVSTART}${SFDISK_UNIT_SUFFIX}"
paul@2 42
paul@3 43
    REMAINING=$(($DEVSIZE - $PREVSTART))
paul@3 44
paul@3 45
    # Retain any previously calculated size.
paul@1 46
    # Without a size, use start details to calculate a size.
paul@1 47
    # Without start details, claim the rest of the device.
paul@1 48
paul@1 49
    if [ "$PREVSIZE" ] ; then
paul@3 50
        :
paul@1 51
    elif [ "$START" ] ; then
paul@2 52
        PREVSIZE=$((`align_cylinder $START` - $PREVSTART))
paul@1 53
    else
paul@1 54
        PREVSIZE=$REMAINING
paul@1 55
    fi
paul@1 56
paul@1 57
    if [ "$PREVSIZE" -gt "$REMAINING" ] ; then
paul@1 58
        PREVSIZE=$REMAINING
paul@1 59
    fi
paul@1 60
paul@1 61
    echo -n " size=${PREVSIZE}${SFDISK_UNIT_SUFFIX}"
paul@1 62
paul@1 63
    if [ "$PREVTYPE" ] ; then
paul@1 64
        echo -n " Id=`partition_type $PREVTYPE`"
paul@1 65
    fi
paul@2 66
paul@1 67
    echo
paul@1 68
}
paul@1 69
paul@1 70
# Retain the current partition details.
paul@1 71
paul@1 72
store_partition()
paul@1 73
{
paul@3 74
    # Define the partition start using a specified position.
paul@3 75
    # Alternatively, use previous start and size information.
paul@3 76
    # Otherwise, the first partition is being defined.
paul@3 77
paul@5 78
    if [ "$START" ] && [ "$START" != '-' ] ; then
paul@3 79
        PREVSTART=`align_cylinder $START`
paul@1 80
    elif [ "$PREVSTART" ] && [ "$PREVSIZE" ] ; then
paul@3 81
        PREVSTART=`align_cylinder $(($PREVSTART + $PREVSIZE))`
paul@1 82
    else
paul@1 83
        PREVSTART=0
paul@1 84
    fi
paul@1 85
paul@3 86
    # Ensure that the first partition starts at sector one.
paul@3 87
paul@3 88
    if [ "$PREVSTART" = '0' ] ; then
paul@3 89
        PREVSTART=1
paul@3 90
    fi
paul@3 91
paul@3 92
    # Calculate and align the stated size.
paul@3 93
    # Otherwise, defer the calculation until emitting the details.
paul@3 94
paul@5 95
    if [ "$SIZE" ] && [ "$SIZE" != '-' ] ; then
paul@3 96
        PREVSIZE=$(($SIZE * $DEVSIZE / 100))
paul@3 97
        PREVSIZE=`align_cylinder $PREVSIZE`
paul@3 98
paul@3 99
        if [ "$PREVSTART" = '1' ] ; then
paul@3 100
            PREVSIZE=$(($PREVSIZE - 1))
paul@3 101
        fi
paul@3 102
    else
paul@3 103
        PREVSIZE=
paul@3 104
    fi
paul@3 105
paul@1 106
    PREVTYPE=$TYPE
paul@1 107
}
paul@1 108
paul@1 109
# Emit the current partition details and proceed to the next partition.
paul@1 110
paul@1 111
next_partition()
paul@1 112
{
paul@5 113
    emit_partition
paul@5 114
    store_partition
paul@1 115
}
paul@1 116
paul@1 117
# Convert the partition type to an sdisk-compatible identifier.
paul@1 118
paul@1 119
partition_type()
paul@1 120
{
paul@1 121
    case "$1" in
paul@1 122
        ( ext[2-4]? ) echo "0x83" ;;
paul@1 123
        ( swap      ) echo "0x82" ;;
paul@1 124
        ( fat       ) echo "0x0c" ;;
paul@1 125
        ( *         ) echo "0x83" ;;
paul@1 126
    esac
paul@1 127
}
paul@1 128
paul@1 129
paul@1 130
paul@1 131
# device_size <device>
paul@1 132
#
paul@1 133
# Obtain the size of the given disk or partition in 1024-byte blocks.
paul@1 134
paul@1 135
device_size()
paul@1 136
{
paul@1 137
    "$SFDISK" -s "$1"
paul@1 138
}
paul@1 139
paul@2 140
# Align to cylinders.
paul@2 141
paul@2 142
align_cylinder()
paul@2 143
{
paul@4 144
    if [ ! "$ALIGN_CYLINDER" ] ; then
paul@4 145
        echo $1
paul@4 146
        return
paul@4 147
    fi
paul@4 148
paul@2 149
    # Round up to the nearest cylinder.
paul@2 150
paul@2 151
    CYLINDER=$((($1 + $CYLINDER_SIZE - 1) / $CYLINDER_SIZE))
paul@2 152
paul@2 153
    # Emit the number of sectors.
paul@2 154
paul@2 155
    echo $(($CYLINDER * $CYLINDER_SIZE))
paul@2 156
}
paul@2 157
paul@1 158
# Test sfdisk behaviour and obtain useful information.
paul@1 159
paul@1 160
init_sfdisk()
paul@1 161
{
paul@2 162
    SFDISK_UNIT_SUFFIX=
paul@2 163
paul@2 164
    # Obtain the device size in 512-byte sectors.
paul@1 165
paul@2 166
    DEVSIZE=$((`device_size "$1"` * 2))
paul@1 167
paul@2 168
    # Find the cylinder-addressable size.
paul@2 169
paul@4 170
    if [ "$ALIGN_CYLINDER" ] ; then
paul@4 171
        CYLINDERS=$(($DEVSIZE / $CYLINDER_SIZE))
paul@4 172
        DEVSIZE=$(($CYLINDERS * $CYLINDER_SIZE))
paul@4 173
    fi
paul@1 174
}
paul@1 175
paul@1 176
paul@1 177
paul@5 178
# Process the arguments, building a partition description.
paul@5 179
paul@5 180
read_fields()
paul@5 181
{
paul@5 182
    OLDIFS=$IFS
paul@5 183
    IFS=`echo -n '\t'` read START SIZE TYPE
paul@5 184
    STATUS=$?
paul@5 185
    IFS=$OLDIFS
paul@5 186
    return $STATUS
paul@5 187
}
paul@5 188
paul@5 189
paul@5 190
paul@1 191
# Emit the help message if requested.
paul@1 192
paul@1 193
if [ "$1" = '--help' ] ; then
paul@1 194
    cat 1>&2 <<EOF
paul@4 195
Usage: $PROGNAME [ --align ] ( -f <type> | -p <start> | -s <size> )...
paul@1 196
paul@1 197
Produce partition descriptions, indicating partition type, start position and
paul@1 198
size for each partition. Each occurrence of the -f option starts a new partition
paul@1 199
description.
paul@1 200
paul@2 201
Start positions are indicated as numbers of 512-byte sectors.
paul@1 202
paul@1 203
Sizes are indicated as percentages of the entire device; if omitted, the
paul@1 204
remainder of the device will be used.
paul@1 205
paul@1 206
Types recognised include ext, ext2, ext3, ext4, fat and swap. Other types are
paul@4 207
interpreted as Linux partitions.
paul@4 208
paul@4 209
If the --align option is specified, align partitions to cylinders for the
paul@4 210
satisfaction of earlier sfdisk versions that are obsessed with cylinders, heads
paul@4 211
and sectors.
paul@1 212
EOF
paul@1 213
    exit 0
paul@1 214
fi
paul@1 215
paul@4 216
# Test for the cylinder alignment option.
paul@4 217
paul@4 218
if [ "$1" = '--align' ] ; then
paul@4 219
    ALIGN_CYLINDER="$1"
paul@4 220
    shift 1
paul@4 221
else
paul@4 222
    ALIGN_CYLINDER=
paul@4 223
fi
paul@4 224
paul@1 225
# Obtain details of the selected device.
paul@1 226
paul@1 227
if [ ! "$DEV" ] ; then
paul@1 228
    cat 1>&2 <<EOF
paul@1 229
No device specified. Use the DEV environment variable to indicate a device.
paul@1 230
EOF
paul@1 231
    exit 1
paul@1 232
fi
paul@1 233
paul@4 234
if [ ! -e "$DEV" ] ; then
paul@4 235
    cat 1>&2 <<EOF
paul@4 236
Device not found: $DEV
paul@4 237
EOF
paul@4 238
    exit 1
paul@4 239
fi
paul@4 240
paul@1 241
# Initialise sfdisk usage.
paul@1 242
paul@1 243
init_sfdisk "$DEV"
paul@1 244
paul@5 245
while read_fields ; do
paul@5 246
    next_partition
paul@1 247
done
paul@1 248
paul@1 249
# Emit the last partition.
paul@1 250
paul@1 251
emit_partition