remakesd

makesd-partition-table

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