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