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" ] && [ "$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" ] && [ "$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 # Emit the current partition details and proceed to the next partition. 110 111 next_partition() 112 { 113 emit_partition 114 store_partition 115 } 116 117 # Convert the partition type to an sdisk-compatible identifier. 118 119 partition_type() 120 { 121 case "$1" in 122 ( ext[2-4]? ) echo "0x83" ;; 123 ( swap ) echo "0x82" ;; 124 ( fat ) echo "0x0c" ;; 125 ( * ) echo "0x83" ;; 126 esac 127 } 128 129 130 131 # device_size <device> 132 # 133 # Obtain the size of the given disk or partition in 1024-byte blocks. 134 135 device_size() 136 { 137 "$SFDISK" -s "$1" 138 } 139 140 # Align to cylinders. 141 142 align_cylinder() 143 { 144 if [ ! "$ALIGN_CYLINDER" ] ; then 145 echo $1 146 return 147 fi 148 149 # Round up to the nearest cylinder. 150 151 CYLINDER=$((($1 + $CYLINDER_SIZE - 1) / $CYLINDER_SIZE)) 152 153 # Emit the number of sectors. 154 155 echo $(($CYLINDER * $CYLINDER_SIZE)) 156 } 157 158 # Test sfdisk behaviour and obtain useful information. 159 160 init_sfdisk() 161 { 162 SFDISK_UNIT_SUFFIX= 163 164 # Obtain the device size in 512-byte sectors. 165 166 DEVSIZE=$((`device_size "$1"` * 2)) 167 168 # Find the cylinder-addressable size. 169 170 if [ "$ALIGN_CYLINDER" ] ; then 171 CYLINDERS=$(($DEVSIZE / $CYLINDER_SIZE)) 172 DEVSIZE=$(($CYLINDERS * $CYLINDER_SIZE)) 173 fi 174 } 175 176 177 178 # Process the arguments, building a partition description. 179 180 read_fields() 181 { 182 OLDIFS=$IFS 183 IFS=`echo -n '\t'` read START SIZE TYPE 184 STATUS=$? 185 IFS=$OLDIFS 186 return $STATUS 187 } 188 189 190 191 # Emit the help message if requested. 192 193 if [ "$1" = '--help' ] ; then 194 cat 1>&2 <<EOF 195 Usage: $PROGNAME [ --align ] ( -f <type> | -p <start> | -s <size> )... 196 197 Produce partition descriptions, indicating partition type, start position and 198 size for each partition. Each occurrence of the -f option starts a new partition 199 description. 200 201 Start positions are indicated as numbers of 512-byte sectors. 202 203 Sizes are indicated as percentages of the entire device; if omitted, the 204 remainder of the device will be used. 205 206 Types recognised include ext, ext2, ext3, ext4, fat and swap. Other types are 207 interpreted as Linux partitions. 208 209 If the --align option is specified, align partitions to cylinders for the 210 satisfaction of earlier sfdisk versions that are obsessed with cylinders, heads 211 and sectors. 212 EOF 213 exit 0 214 fi 215 216 # Test for the cylinder alignment option. 217 218 if [ "$1" = '--align' ] ; then 219 ALIGN_CYLINDER="$1" 220 shift 1 221 else 222 ALIGN_CYLINDER= 223 fi 224 225 # Obtain details of the selected device. 226 227 if [ ! "$DEV" ] ; then 228 cat 1>&2 <<EOF 229 No device specified. Use the DEV environment variable to indicate a device. 230 EOF 231 exit 1 232 fi 233 234 if [ ! -e "$DEV" ] ; then 235 cat 1>&2 <<EOF 236 Device not found: $DEV 237 EOF 238 exit 1 239 fi 240 241 # Initialise sfdisk usage. 242 243 init_sfdisk "$DEV" 244 245 while read_fields ; do 246 next_partition 247 done 248 249 # Emit the last partition. 250 251 emit_partition