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 # Global partition number and previous partition details. 14 15 PARTNUM=1 16 PREVSTART= 17 PREVSIZE= 18 PREVTYPE= 19 20 # Emit any previous partition details as a complete sfdisk-compatible record. 21 22 emit_partition() 23 { 24 if [ "$PREVSTART" ] || [ "$PREVSIZE" ] || [ "$PREVTYPE" ] ; then 25 echo -n "$PARTNUM : " 26 emit_partition_fields | sed 's/^ //;s/ /,/g' 27 PARTNUM=$(($PARTNUM + 1)) 28 fi 29 } 30 31 # Emit the previous partition fields. 32 33 emit_partition_fields() 34 { 35 if [ "$PREVSTART" ] ; then 36 echo -n " start=${PREVSTART}${SFDISK_UNIT_SUFFIX}" 37 fi 38 39 # Obtain any explicitly stated size. 40 # Without a size, use start details to calculate a size. 41 # Without start details, claim the rest of the device. 42 43 REMAINING=$(($DEVSIZE - $PREVSTART)) 44 45 if [ "$PREVSIZE" ] ; then 46 PREVSIZE=$(($PREVSIZE * $DEVSIZE / 100)) 47 elif [ "$START" ] ; then 48 PREVSIZE=$(($START - $PREVSTART)) 49 else 50 PREVSIZE=$REMAINING 51 fi 52 53 if [ "$PREVSIZE" -gt "$REMAINING" ] ; then 54 PREVSIZE=$REMAINING 55 fi 56 57 echo -n " size=${PREVSIZE}${SFDISK_UNIT_SUFFIX}" 58 59 if [ "$PREVTYPE" ] ; then 60 echo -n " Id=`partition_type $PREVTYPE`" 61 fi 62 echo 63 } 64 65 # Retain the current partition details. 66 67 store_partition() 68 { 69 if [ "$START" ] ; then 70 PREVSTART=$START 71 elif [ "$PREVSTART" ] && [ "$PREVSIZE" ] ; then 72 PREVSIZE=$(($PREVSIZE * $DEVSIZE / 100)) 73 PREVSTART=$(($PREVSTART + $PREVSIZE)) 74 else 75 PREVSTART=0 76 fi 77 78 PREVSIZE=$SIZE 79 PREVTYPE=$TYPE 80 } 81 82 # Reset the current partition details. 83 84 reset_partition() 85 { 86 START= 87 SIZE= 88 TYPE= 89 } 90 91 # Emit the current partition details and proceed to the next partition. 92 93 next_partition() 94 { 95 if [ "$START" ] || [ "$SIZE" ] || [ "$TYPE" ] ; then 96 emit_partition 97 store_partition 98 reset_partition 99 fi 100 } 101 102 # Convert the partition type to an sdisk-compatible identifier. 103 104 partition_type() 105 { 106 case "$1" in 107 ( ext[2-4]? ) echo "0x83" ;; 108 ( swap ) echo "0x82" ;; 109 ( fat ) echo "0x0c" ;; 110 ( * ) echo "0x83" ;; 111 esac 112 } 113 114 115 116 # device_size <device> 117 # 118 # Obtain the size of the given disk or partition in 1024-byte blocks. 119 120 device_size() 121 { 122 "$SFDISK" -s "$1" 123 } 124 125 # Test sfdisk behaviour and obtain useful information. 126 127 init_sfdisk() 128 { 129 if "$SFDISK" -uB -s "$1" > /dev/null 2>&1 ; then 130 SFDISK_UNIT_SUFFIX= 131 else 132 SFDISK_UNIT_SUFFIX="K" 133 fi 134 135 # Obtain the device size in blocks. 136 137 DEVSIZE=`device_size "$1"` 138 } 139 140 141 142 # Emit the help message if requested. 143 144 if [ "$1" = '--help' ] ; then 145 cat 1>&2 <<EOF 146 Usage: $PROGNAME ( -f <type> | -p <start> | -s <size> )... 147 148 Produce partition descriptions, indicating partition type, start position and 149 size for each partition. Each occurrence of the -f option starts a new partition 150 description. 151 152 Start positions are indicated as numbers of 1024-byte blocks. 153 154 Sizes are indicated as percentages of the entire device; if omitted, the 155 remainder of the device will be used. 156 157 Types recognised include ext, ext2, ext3, ext4, fat and swap. Other types are 158 interpreted as Linux partitions. 159 EOF 160 exit 0 161 fi 162 163 # Obtain details of the selected device. 164 165 if [ ! "$DEV" ] ; then 166 cat 1>&2 <<EOF 167 No device specified. Use the DEV environment variable to indicate a device. 168 EOF 169 exit 1 170 fi 171 172 # Initialise sfdisk usage. 173 174 init_sfdisk "$DEV" 175 176 # Process the arguments, building a partition description. 177 178 reset_partition 179 180 while [ "$1" ] ; do 181 case "$1" in 182 -f ) 183 if [ "$TYPE" ] ; then next_partition ; fi 184 TYPE="$2" 185 shift 2 186 ;; 187 -p ) 188 if [ "$START" ] ; then next_partition ; fi 189 START="$2" 190 shift 2 191 ;; 192 -s ) 193 if [ "$SIZE" ] ; then next_partition ; fi 194 SIZE="$2" 195 shift 2 196 ;; 197 * ) 198 shift 1 199 ;; 200 esac 201 done 202 203 # Terminate any unfinished partition, emitting the previous partition. 204 205 next_partition 206 207 # Emit the last partition. 208 209 emit_partition