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 if [ "$PREVSTART" = '0' ] ; then 42 FIRSTPART=yes 43 else 44 FIRSTPART= 45 fi 46 47 PREVSTART=`align_cylinder $PREVSTART` 48 49 if [ "$PREVSTART" = '0' ] ; then 50 PREVSTART=1 51 fi 52 53 echo -n " start=${PREVSTART}${SFDISK_UNIT_SUFFIX}" 54 55 # Obtain any explicitly stated size. 56 # Without a size, use start details to calculate a size. 57 # Without start details, claim the rest of the device. 58 59 REMAINING=$(($DEVSIZE - $PREVSTART)) 60 61 if [ "$PREVSIZE" ] ; then 62 PREVSIZE=$((($PREVSIZE * $DEVSIZE) / 100)) 63 PREVSIZE=`align_cylinder $PREVSIZE` 64 65 if [ "$FIRSTPART" ] ; then 66 PREVSIZE=$(($PREVSIZE - 1)) 67 fi 68 69 elif [ "$START" ] ; then 70 PREVSIZE=$((`align_cylinder $START` - $PREVSTART)) 71 else 72 PREVSIZE=$REMAINING 73 fi 74 75 if [ "$PREVSIZE" -gt "$REMAINING" ] ; then 76 PREVSIZE=$REMAINING 77 fi 78 79 echo -n " size=${PREVSIZE}${SFDISK_UNIT_SUFFIX}" 80 81 if [ "$PREVTYPE" ] ; then 82 echo -n " Id=`partition_type $PREVTYPE`" 83 fi 84 85 echo 86 } 87 88 # Retain the current partition details. 89 90 store_partition() 91 { 92 if [ "$START" ] ; then 93 PREVSTART=$START 94 elif [ "$PREVSTART" ] && [ "$PREVSIZE" ] ; then 95 PREVSIZE=$(($PREVSIZE * $DEVSIZE / 100)) 96 PREVSIZE=`align_cylinder $PREVSIZE` 97 PREVSTART=$(($PREVSTART + $PREVSIZE)) 98 else 99 PREVSTART=0 100 fi 101 102 PREVSIZE=$SIZE 103 PREVTYPE=$TYPE 104 } 105 106 # Reset the current partition details. 107 108 reset_partition() 109 { 110 START= 111 SIZE= 112 TYPE= 113 } 114 115 # Emit the current partition details and proceed to the next partition. 116 117 next_partition() 118 { 119 if [ "$START" ] || [ "$SIZE" ] || [ "$TYPE" ] ; then 120 emit_partition 121 store_partition 122 reset_partition 123 fi 124 } 125 126 # Convert the partition type to an sdisk-compatible identifier. 127 128 partition_type() 129 { 130 case "$1" in 131 ( ext[2-4]? ) echo "0x83" ;; 132 ( swap ) echo "0x82" ;; 133 ( fat ) echo "0x0c" ;; 134 ( * ) echo "0x83" ;; 135 esac 136 } 137 138 139 140 # device_size <device> 141 # 142 # Obtain the size of the given disk or partition in 1024-byte blocks. 143 144 device_size() 145 { 146 "$SFDISK" -s "$1" 147 } 148 149 # Align to cylinders. 150 151 align_cylinder() 152 { 153 # Round up to the nearest cylinder. 154 155 CYLINDER=$((($1 + $CYLINDER_SIZE - 1) / $CYLINDER_SIZE)) 156 157 # Emit the number of sectors. 158 159 echo $(($CYLINDER * $CYLINDER_SIZE)) 160 } 161 162 # Test sfdisk behaviour and obtain useful information. 163 164 init_sfdisk() 165 { 166 SFDISK_UNIT_SUFFIX= 167 168 # Obtain the device size in 512-byte sectors. 169 170 DEVSIZE=$((`device_size "$1"` * 2)) 171 172 # Find the cylinder-addressable size. 173 174 CYLINDERS=$(($DEVSIZE / $CYLINDER_SIZE)) 175 DEVSIZE=$(($CYLINDERS * $CYLINDER_SIZE)) 176 } 177 178 179 180 # Emit the help message if requested. 181 182 if [ "$1" = '--help' ] ; then 183 cat 1>&2 <<EOF 184 Usage: $PROGNAME ( -f <type> | -p <start> | -s <size> )... 185 186 Produce partition descriptions, indicating partition type, start position and 187 size for each partition. Each occurrence of the -f option starts a new partition 188 description. 189 190 Start positions are indicated as numbers of 512-byte sectors. 191 192 Sizes are indicated as percentages of the entire device; if omitted, the 193 remainder of the device will be used. 194 195 Types recognised include ext, ext2, ext3, ext4, fat and swap. Other types are 196 interpreted as Linux partitions. 197 EOF 198 exit 0 199 fi 200 201 # Obtain details of the selected device. 202 203 if [ ! "$DEV" ] ; then 204 cat 1>&2 <<EOF 205 No device specified. Use the DEV environment variable to indicate a device. 206 EOF 207 exit 1 208 fi 209 210 # Initialise sfdisk usage. 211 212 init_sfdisk "$DEV" 213 214 # Process the arguments, building a partition description. 215 216 reset_partition 217 218 while [ "$1" ] ; do 219 case "$1" in 220 -f ) 221 if [ "$TYPE" ] ; then next_partition ; fi 222 TYPE="$2" 223 shift 2 224 ;; 225 -p ) 226 if [ "$START" ] ; then next_partition ; fi 227 START="$2" 228 shift 2 229 ;; 230 -s ) 231 if [ "$SIZE" ] ; then next_partition ; fi 232 SIZE="$2" 233 shift 2 234 ;; 235 * ) 236 shift 1 237 ;; 238 esac 239 done 240 241 # Terminate any unfinished partition, emitting the previous partition. 242 243 next_partition 244 245 # Emit the last partition. 246 247 emit_partition