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