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 # Round up to the nearest cylinder. 157 158 CYLINDER=$((($1 + $CYLINDER_SIZE - 1) / $CYLINDER_SIZE)) 159 160 # Emit the number of sectors. 161 162 echo $(($CYLINDER * $CYLINDER_SIZE)) 163 } 164 165 # Test sfdisk behaviour and obtain useful information. 166 167 init_sfdisk() 168 { 169 SFDISK_UNIT_SUFFIX= 170 171 # Obtain the device size in 512-byte sectors. 172 173 DEVSIZE=$((`device_size "$1"` * 2)) 174 175 # Find the cylinder-addressable size. 176 177 CYLINDERS=$(($DEVSIZE / $CYLINDER_SIZE)) 178 DEVSIZE=$(($CYLINDERS * $CYLINDER_SIZE)) 179 } 180 181 182 183 # Emit the help message if requested. 184 185 if [ "$1" = '--help' ] ; then 186 cat 1>&2 <<EOF 187 Usage: $PROGNAME ( -f <type> | -p <start> | -s <size> )... 188 189 Produce partition descriptions, indicating partition type, start position and 190 size for each partition. Each occurrence of the -f option starts a new partition 191 description. 192 193 Start positions are indicated as numbers of 512-byte sectors. 194 195 Sizes are indicated as percentages of the entire device; if omitted, the 196 remainder of the device will be used. 197 198 Types recognised include ext, ext2, ext3, ext4, fat and swap. Other types are 199 interpreted as Linux partitions. 200 EOF 201 exit 0 202 fi 203 204 # Obtain details of the selected device. 205 206 if [ ! "$DEV" ] ; then 207 cat 1>&2 <<EOF 208 No device specified. Use the DEV environment variable to indicate a device. 209 EOF 210 exit 1 211 fi 212 213 # Initialise sfdisk usage. 214 215 init_sfdisk "$DEV" 216 217 # Process the arguments, building a partition description. 218 219 reset_partition 220 221 while [ "$1" ] ; do 222 case "$1" in 223 -f ) 224 if [ "$TYPE" ] ; then next_partition ; fi 225 TYPE="$2" 226 shift 2 227 ;; 228 -p ) 229 if [ "$START" ] ; then next_partition ; fi 230 START="$2" 231 shift 2 232 ;; 233 -s ) 234 if [ "$SIZE" ] ; then next_partition ; fi 235 SIZE="$2" 236 shift 2 237 ;; 238 * ) 239 shift 1 240 ;; 241 esac 242 done 243 244 # Terminate any unfinished partition, emitting the previous partition. 245 246 next_partition 247 248 # Emit the last partition. 249 250 emit_partition