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 ] ( -f <type> | -p <start> | -s <size> )... 186 187 Produce partition descriptions, indicating partition type, start position and 188 size for each partition. Each occurrence of the -f option starts a new partition 189 description. 190 191 Start positions are indicated as numbers of 512-byte sectors. 192 193 Sizes are indicated as percentages of the entire device; if omitted, the 194 remainder of the device will be used. 195 196 Types recognised include ext, ext2, ext3, ext4, fat and swap. Other types are 197 interpreted as Linux partitions. 198 199 If the --align option is specified, align partitions to cylinders for the 200 satisfaction of earlier sfdisk versions that are obsessed with cylinders, heads 201 and sectors. 202 EOF 203 exit 0 204 fi 205 206 # Test for the cylinder alignment option. 207 208 if test_align_cylinder $* ; then shift 1 ; fi 209 210 # Obtain details of the selected device. 211 212 check_device 213 214 # Initialise sfdisk usage. 215 216 init_sfdisk "$DEV" 217 218 while read_fields ; do 219 next_partition 220 done 221 222 # Emit the last partition. 223 224 emit_partition