#!/bin/bash
#================
# FILE          : linuxrc
#----------------
# PROJECT       : OpenSuSE KIWI Image System
# COPYRIGHT     : (c) 2006 SUSE LINUX Products GmbH. All rights reserved
#               :
# AUTHOR        : Marcus Schaefer <ms@suse.de>
#               :
# BELONGS TO    : Operating System images
#               :
# DESCRIPTION   : OEM repartition code functions. This file is used
#               : to setup the partition table according to the OEM
#               : specifications
#               :
# STATUS        : BETA
#----------------
#======================================
# OEMRepartInit 
#--------------------------------------
function OEMRepartInit {
	# /.../
	# calculate memory based swapsize amount and initialize
	# size of recovery archive
	# ----
	mem_size=`grep MemTotal: /proc/meminfo | tr -dc '[0-9]'`
	swapsize=$(( $mem_size *2 / 1024 ))
	recoMByte=0
	if [ ! -z "$OEM_SWAPSIZE" ];then
		swapsize=$OEM_SWAPSIZE
	fi
	if [ ! -z "$OEM_WITHOUTSWAP" ];then
		swapsize=0
	fi
	if [ ! -z "$OEM_RECOVERY" ];then
		mkdir -p /reco-root
		if ! mount $imageRootDevice /reco-root >/dev/null;then
			systemException "Failed to mount root device" "reboot"
		fi
		if [ ! -f /reco-root/recovery.tar.gz ];then
			systemException "Can't find recovery archive" "reboot"
		fi
		recoBytes=`du --bytes /reco-root/recovery.tar.gz | cut -f1`
		recoMByte=`expr $recoBytes / 1048576`
		recoMByte=`expr $recoMByte \* 15 / 10`
		umount /reco-root && rmdir /reco-root
	fi
}

#======================================
# OEMRepartStandard
#--------------------------------------
function OEMRepartStandard {
	# /.../
	# repartition disk with read/write root filesystem
	# ----
	#======================================
	# write new partition table
	#--------------------------------------
	# /.../
	# Explanation of the partition commands used within the
	# here document below:
	# ----
	# d              # delete xda partition [ 1 ]
	# n              # create xda partition at same place than xda1
	# p              # primary
	# 2              # [ 2 ]
	# 1              # accept old xda1 start block for xda2
	# +10240M        # accept new root device size of 10GB
	# n              # create xda swap partition
	# p              # primary
	# 1              # [ 1 ]
	#                # accept start block
	# +"$swapsize"M  # accept new swapsize
	# n              # create xda3 home partition
	# p              # primary
	# 3              # [ 3 ]
	#                # accept start block
	#                # accept end block, complete disk
	# t              # change swap system id
	# 1              # [ 1 ]
	# 82             # Linux Swap
	# w              # write partition table
	# ----
	input=/part.input
	rm -f $input
	diskXMBytes=`partitionSize $imageDiskDevice`
	diskPMBytes=`partitionSize $(ddn $imageDiskDevice 1)`
	diskPMBytes=`expr $diskPMBytes / 1024`
	diskXMBytes=`expr $diskXMBytes / 1024`
	disk1MBytes=10240
	# /.../
	# set OEM_SYSTEMSIZE if available, else try to
	# use 10GB system size
	# ----
	if [ ! -z "$OEM_SYSTEMSIZE" ];then
		disk1MBytes=$OEM_SYSTEMSIZE
	fi
	# /.../
	# prevent /home and recovery partition if requested
	# system size is bigger than the whole disk
	# ----
	if [ $disk1MBytes -gt $diskXMBytes ];then
		export OEM_WITHOUTHOME=1
		unset OEM_SYSTEMSIZE
		unset OEM_RECOVERY
		recoMByte=0
	fi
	# /.../
	# recalculate system size if no /home partition
	# will be used. size is whole disk minus swap
	# minus recovery
	# ----
	if [ ! -z "$OEM_WITHOUTHOME" ] && [ -z "$OEM_SYSTEMSIZE" ];then
		disk1MBytes=`expr $diskXMBytes - $swapsize - $recoMByte`
	fi
	# /.../
	# check if requested system size is bigger than
	# the existing system partition
	# ----
	if [ $disk1MBytes -lt $diskPMBytes ];then
		# /.../
		# Requested system partition size is smaller than
		# existing partition, will not re-partition
		# ----
		Echo "Current system partition is bigger than requested size"
		Echo "Disk won't be re-partitioned"
		OEM_WITHOUTHOME=1
		DONT_PARTITION=1
		unset OEM_RECOVERY
	fi
	if [ -z "$DONT_PARTITION" ];then
		if [ ! -z "$OEM_WITHOUTHOME" ];then
			#======================================
			# -home
			#--------------------------------------
			if [ -z "$OEM_WITHOUTSWAP" ];then
				#======================================
				# -home +swap
				#--------------------------------------
				if [ -z "$OEM_RECOVERY" ];then
					#======================================
					# -home +swap -recovery
					#--------------------------------------
					if [ ! -z "$OEM_SYSTEMSIZE" ];then
						createPartitionerInput \
							d n p 1 1 +"$disk1MBytes"M \
							n p 2 . +"$swapsize"M \
							t 2 82 w q
					else
						createPartitionerInput \
							d n p 1 1 +"$disk1MBytes"M \
							n p 2 . . \
							t 2 82 w q
					fi
					setupDeviceNames 1 2 no no 1 no
				else
					#======================================
					# -home +swap +recovery
					#--------------------------------------
					if [ ! -z "$OEM_SYSTEMSIZE" ];then
						createPartitionerInput \
							d n p 1 1 +"$disk1MBytes"M \
							n p 2 . +"$swapsize"M \
							n p 3 . +"$recoMByte"M \
							t 2 82 w q
					else
						createPartitionerInput \
							d n p 1 1 +"$disk1MBytes"M \
							n p 2 . +"$swapsize"M \
							n p 3 . . \
							t 2 82 w q
					fi
					setupDeviceNames 1 2 no 3 1 no
				fi
			else
				#======================================
				# -home -swap
				#--------------------------------------
				if [ -z "$OEM_RECOVERY" ];then
					#======================================
					# -home -swap -recovery
					#--------------------------------------
					if [ ! -z "$OEM_SYSTEMSIZE" ];then
						createPartitionerInput \
							d n p 1 . +"$disk1MBytes"M w q
					else
						createPartitionerInput \
							d n p 1 . . w q
					fi
					setupDeviceNames 1 no no no 1 no
				else
					#======================================
					# -home -swap +recovery
					#--------------------------------------
					if [ ! -z "$OEM_SYSTEMSIZE" ];then
						createPartitionerInput \
							d n p 1 1 +"$disk1MBytes"M \
							n p 2 . +"$recoMByte"M w q
					else
						createPartitionerInput \
							d n p 1 1 +"$disk1MBytes"M \
							n p 2 . . w q
					fi
					setupDeviceNames 1 no no 2 1 no
				fi
			fi
		else
			#======================================
			# +home
			#--------------------------------------
			if [ -z "$OEM_WITHOUTSWAP" ];then
				#======================================
				# +home +swap
				#--------------------------------------
				if [ -z "$OEM_RECOVERY" ];then
					#======================================
					# +home +swap -recovery
					#--------------------------------------
					createPartitionerInput \
						d n p 1 1 +"$disk1MBytes"M \
						n p 2 . +"$swapsize"M \
						n p 3 . . \
						t 2 82 w q
					setupDeviceNames 1 2 3 no 1 no
				else
					#======================================
					# +home +swap +recovery
					#--------------------------------------
					createPartitionerInput \
						d n p 1 1 +"$disk1MBytes"M \
						n p 2 . +"$swapsize"M \
						n p 3 . +"$recoMByte"M \
						n p 4 . . \
						t 2 82 w q
					setupDeviceNames 1 2 4 3 1 no
				fi
			else
				#======================================
				# +home -swap
				#--------------------------------------
				if [ -z "$OEM_RECOVERY" ];then
					#======================================
					# +home -swap -recovery
					#--------------------------------------
					createPartitionerInput \
						d n p 1 1 +"$disk1MBytes"M \
						n p 2 . . w q
					setupDeviceNames 1 no 2 no 1 no
				else
					#======================================
					# +home -swap +recovery
					#--------------------------------------
					createPartitionerInput \
						d n p 1 1 +"$disk1MBytes"M \
						n p 2 . +"$recoMByte"M \
						n p 3 . . w q
					setupDeviceNames 1 no 3 2 1 no
				fi
			fi
		fi
		callPartitioner $input
	fi
	#======================================
	# post repart actions
	#--------------------------------------
	if [ -z "$DONT_PARTITION" ];then
		#======================================
		# Activate boot partition
		#--------------------------------------
		activateBootPartition
	fi
}

#======================================
# OEMRepartOverlayed
#--------------------------------------
function OEMRepartOverlayed {
	# /.../
	# repartition disk if overlay system via overlay filesystem
	# like aufs, unionfs is used
	# ---- 
	#====================================== 
	# no recovery support in union mode
	#--------------------------------------
	unset OEM_RECOVERY
	#====================================== 
	# no homepart support for union mode
	#--------------------------------------
	export OEM_WITHOUTHOME=1
	#====================================== 
	# check for DM squash setup
	#--------------------------------------
	if mount $(ddn $imageDiskDevice 1) /mnt &>/dev/null;then
		if [ -f /mnt/fsdata.ext3 ];then
			umount /mnt
			mount $(ddn $imageDiskDevice 3) /mnt
			cp /mnt/boot/linux.vmx  /tmp
			cp /mnt/boot/initrd.vmx /tmp
			cp /mnt/boot/grub/mbrid /tmp
			umount /mnt
			export haveDMSquash=yes
		else
			umount /mnt
		fi
	fi
	#======================================
	# calculate end block - swapspace
	#--------------------------------------
	swapXMBytes=$swapsize
	bootXMBytes=0
	if [ "$haveDMSquash" = "yes" ];then
		bootXMBytes=40
	fi
	diskXMBytes=`partitionSize $imageDiskDevice`
	diskXMBytes=`expr $diskXMBytes / 1024`
	disk1MBytes=`partitionSize $(ddn $imageDiskDevice 1)`
	disk1MBytes=`expr $disk1MBytes / 1024`
	disk2MBytes=`expr $diskXMBytes - $disk1MBytes - $swapsize - $bootXMBytes`
	if [ $disk2MBytes -lt 100 ];then
		# /.../
		# Very small disk which we will not re-partition
		# ----
		Echo "Disk is too small, will not re-partition it"
		DONT_PARTITION=1
	fi
	if [ -z "$DONT_PARTITION" ];then
		#======================================
		# write new partition table
		#--------------------------------------
		# /.../
		# Explanation of the partition commands used within the
		# here document below:
		# ----
		# d               # delete xda partition
		# 2               # [ 2 ]
		# n               # create xda partition at same place than xda2
		# p               # primary
		# 2               # [ 2 ]
		#                 # accept old xda2 start block
		# +"disk2MBytes"M # accept new RW device size
		# n               # create xda swap partition
		# p               # primary
		# 3               # [ 3 ]
		#                 # accept start block
		#                 # accept end block
		# t               # change swap system id
		# 3               # [ 3 ]
		# 82              # Linux Swap
		# w               # write partition table
		# ----
		input=/part.input
		rm -f $input
		if [ $swapsize = 0 ];then
			if [ "$haveDMSquash" = "yes" ];then
				createPartitionerInput \
					d 2 n p 2 . +"$disk2MBytes"M n p 3 . . w q
				setupDeviceNames 1 no no no 3 2
			else
				createPartitionerInput \
					d 2 n p 2 . . w q
				setupDeviceNames 1 no no no 2 2
			fi
		else
			if [ "$haveDMSquash" = "yes" ];then
				createPartitionerInput \
					d 2 n p 2 . +"$disk2MBytes"M \
					n p 3 . +"$bootXMBytes"M n p 4 . . \
					t 4 82 w q
				setupDeviceNames 1 4 no no 3 2
			else
				createPartitionerInput \
					d 2 n p 2 . +"$disk2MBytes"M n p 3 . . \
					t 3 82 w q
				setupDeviceNames 1 3 no no 2 2
			fi
		fi
		callPartitioner $input
	fi
	#======================================
	# post repart actions
	#--------------------------------------
	if [ -z "$DONT_PARTITION" ];then
		#======================================
		# Activate boot partition
		#--------------------------------------
		activateBootPartition
		#======================================
		# Create bootfs if DM squash setup
		#--------------------------------------
		if [ "$haveDMSquash" = "yes" ];then
			if ! mke2fs -T ext2 -q $imageBootDevice >/dev/null 2>&1;then
				systemException "Failed to create Boot filesystem" "reboot"
			fi
		fi
	fi
}

#======================================
# OEMRepartCombined
#--------------------------------------
function OEMRepartCombined {
	# /.../
	# repartition disk if split system is used
	# ----
	#====================================== 
	# no recovery support for combined mode
	#--------------------------------------
	unset OEM_RECOVERY
	#====================================== 
	# no homepart support for combined mode
	#--------------------------------------
	export OEM_WITHOUTHOME=1
	#====================================== 
	# check for read-write partition
	#--------------------------------------
	if ! partitionSize $(ddn $imageDiskDevice 2) &>/dev/null;then
		Echo "No read-write partition in this split image"
		DONT_PARTITION=1
	fi
	#======================================
	# calculate new partition 3 size
	#--------------------------------------
	if [ -z "$DONT_PARTITION" ];then
		swapXMBytes=$swapsize
		diskXMBytes=`partitionSize $imageDiskDevice`
		diskXMBytes=`expr $diskXMBytes / 1024`
		disk1MBytes=`partitionSize $(ddn $imageDiskDevice 1)`
		disk1MBytes=`expr $disk1MBytes / 1024`
		disk2MBytes=`partitionSize $(ddn $imageDiskDevice 2)`
		disk2MBytes=`expr $disk2MBytes / 1024`
		diskXLBytes=`expr $diskXMBytes - $disk1MBytes - $disk2MBytes`
		diskXABytes=`expr $diskXLBytes - $swapXMBytes`
		if [ $diskXABytes -lt 50 ];then
			# /.../
			# Very small disk which we will not re-partition
			# ----
			Echo "Disk is too small, will not re-partition it"
			DONT_PARTITION=1
		else
			disk2MBytes=`expr $disk2MBytes + $diskXABytes`
		fi
	fi
	if [ -z "$DONT_PARTITION" ];then
		#======================================
		# write new partition table
		#--------------------------------------
		# /.../
		# Explanation of the partition commands used within the
		# here document below:
		# ----
		# d               # delete xda partition
		# 2               # [ 2 ]
		# n               # create xda partition at same place than xda2
		# p               # primary
		# 2               # [ 2 ]
		#                 # accept old xda3 start block
		# +"disk2MBytes"M # accept new RW device size of disk blocks - swap
		# n               # create xda swap partition
		# p               # primary
		# 3               # [ 3 ]
		#                 # accept start block
		#                 # accept end block
		# t               # change swap system id
		# 3               # [ 3 ]
		# 82              # Linux Swap
		# w               # write partition table
		# ----
		input=/part.input
		rm -f $input
		if [ $swapsize = 0 ];then
			createPartitionerInput \
				d 2 n p 2 . . w q
			setupDeviceNames 1 no no no 2 2
		else
			createPartitionerInput \
				d 2 n p 2 . +"$disk2MBytes"M n p 3 . . t 3 82 w q
			setupDeviceNames 1 3 no no 2 2
		fi
		callPartitioner $input
	fi
	#======================================
	# post repart actions
	#--------------------------------------
	if [ -z "$DONT_PARTITION" ];then
		#======================================
		# Activate boot partition
		#--------------------------------------
		activateBootPartition
	fi
}

#======================================
# OEMRepartLVM
#--------------------------------------
function OEMRepartLVM {
	#======================================
	# Variable setup...
	#--------------------------------------
	local VGFreeMBytes
	local VGNeedMBytes
	local VGSwapMBytes=0
	local VGRecoveryMBytes=0
	local VGSpareMBytes=100
	local VGSystemMBytes=10240
	if [ ! -z "$OEM_SYSTEMSIZE" ];then
		VGSystemMBytes=$OEM_SYSTEMSIZE
	fi
	if [ ! -z "$OEM_RECOVERY" ];then
		VGRecoveryMBytes=$recoMByte
	fi
	if [ -z "$OEM_WITHOUTSWAP" ];then
		VGSwapMBytes=$swapsize
	fi
	#======================================
	# Extend vgroup to max physical space
	#--------------------------------------
	vgchange -an
	input=/part.input
	rm -f $input
	createPartitionerInput \
		n p 3 . . t 3 8e w q
	luksClose
	callPartitioner $input
	#======================================
	# Set boot id
	#--------------------------------------
	bootid=2
	activateBootPartition
	vgchange -a y kiwiVG
	pvcreate $(ddn $imageDiskDevice 3)
	vgextend kiwiVG $(ddn $imageDiskDevice 3)
	VGFreeMBytes=`vgdisplay --short --unit B kiwiVG | cut -f2 -d/ | cut -f1 -dB`
	VGFreeMBytes=`expr $VGFreeMBytes / 1000`
	VGFreeMBytes=`expr $VGFreeMBytes / 1000`
	VGNeedMBytes=`expr $VGSwapMBytes + $VGRecoveryMBytes + $VGSystemMBytes`
	VGNeedMBytes=`expr $VGNeedMBytes + $VGSpareMBytes`
	#======================================
	# Check if we have enough space left
	#--------------------------------------
	if [ $VGNeedMBytes -gt $VGFreeMBytes ];then
		Echo "Not enough space left, will not extend logical volumes"
		export OEM_WITHOUTHOME=1
		export OEM_WITHOUTSWAP=1
		unset  OEM_RECOVERY
		DONT_PARTITION=1
	fi
	#======================================
	# Setup logical volumes for free space
	#--------------------------------------
	if [ -z "$DONT_PARTITION" ];then
		#======================================
		# Extend LVRoot to requested size
		#--------------------------------------
		lvextend --size $VGSystemMBytes"M" /dev/kiwiVG/LVRoot
		#======================================
		# Add LVSwap if requested.
		#--------------------------------------
		if [ -z "$OEM_WITHOUTSWAP" ];then
			lvcreate --size $VGSwapMBytes"M" -n LVSwap kiwiVG
			export imageSwapDevice=/dev/kiwiVG/LVSwap
		fi
		#======================================
		# Add LVRecovery if requested
		#--------------------------------------
		if [ ! -z "$OEM_RECOVERY" ];then
			lvcreate --size $VGRecoveryMBytes"M" -n LVRecovery kiwiVG
			export imageRecoveryDevice=/dev/kiwiVG/LVRecovery
		fi
		#======================================
		# Add LVHome if requested
		#--------------------------------------
		if [ -z "$OEM_WITHOUTHOME" ];then
			lvcreate -l 100%FREE -n LVHome kiwiVG
			export imageHomeDevice=/dev/kiwiVG/LVHome
		else
			lvextend -l 100%FREE /dev/kiwiVG/LVRoot
		fi
	fi
}

#======================================
# OEMRepartLuks
#--------------------------------------
function OEMRepartLuks {
	#====================================== 
	# no recovery support for LUKS mode
	#--------------------------------------
	unset OEM_RECOVERY
	#====================================== 
	# no homepart support for LUKS mode
	#--------------------------------------
	export OEM_WITHOUTHOME=1
	#====================================== 
	# Store kiwi kernel and initrd
	#--------------------------------------
	if isFSTypeReadOnly;then
		mount $(ddn $imageDiskDevice 3) /mnt
		cp /mnt/boot/linux.vmx  /tmp
		cp /mnt/boot/initrd.vmx /tmp
		cp /mnt/boot/grub/mbrid /tmp
		umount /mnt
	fi
	#======================================
	# calculate end block - swapspace
	#--------------------------------------
	swapXMBytes=$swapsize
	bootXMBytes=0
	if [ "$haveLuks" = "yes" ];then
		bootXMBytes=40
	fi
	diskXMBytes=`partitionSize $imageDiskDevice`
	diskXMBytes=`expr $diskXMBytes / 1024`
	disk1MBytes=`partitionSize $(ddn $imageDiskDevice 1)`
	disk1MBytes=`expr $disk1MBytes / 1024`
	disk2MBytes=`expr $diskXMBytes - $disk1MBytes - $swapsize - $bootXMBytes`
	if ! isFSTypeReadOnly;then
		disk1MBytes=`expr $diskXMBytes - $swapsize - $bootXMBytes`
		disk2MBytes=$disk1MBytes
	fi
	if [ ! -z "$OEM_SYSTEMSIZE" ];then
		if ! isFSTypeReadOnly && [ $OEM_SYSTEMSIZE -lt $disk1MBytes ];then
			disk1MBytes=$OEM_SYSTEMSIZE
			disk2MBytes=$disk1MBytes
		fi
	fi
	if [ $disk2MBytes -lt 100 ];then
		# /.../
		# Very small disk which we will not re-partition
		# ----
		Echo "Disk is too small, will not re-partition it"
		DONT_PARTITION=1
	fi
	if [ -z "$DONT_PARTITION" ];then
		#======================================
		# write new partition table
		#--------------------------------------
		# /.../
		# Explanation of the partition commands used within the
		# here document below:
		# ----
		# d               # delete xda partition
		# 2               # [ 2 ]
		# d               # delete xda partition
		# n               # create xda partition at same place than xda1
		# p               # primary
		# 1               # [ 1 ]
		#                 # accept old xda1 start block
		# +"disk1MBytes"M # accept new root device size - swap - boot
		# n               # create xda boot partition
		# p               # primary
		# 2               # [ 2 ]
		#                 # accept start block
		# +"bootXMBytes"M # accept bootMBytes for boot
		# n               # create xda swap partition
		# p               # primary
		# 3               # [ 3 ]
		#                 # accept start block
		#                 # accept end block
		# t               # change swap system id
		# 3               # [ 3 ]
		# 82              # Linux Swap
		# w               # write partition table
		# ----
		input=/part.input
		rm -f $input
		if [ $swapsize = 0 ];then
			if isFSTypeReadOnly;then
				createPartitionerInput \
					d 2 d 3 n p 2 . +"$disk2MBytes"M n p 3 . . w q
				setupDeviceNames 1 no no no 3 2
			else
				if [ ! -z "$OEM_SYSTEMSIZE" ];then
					createPartitionerInput \
						d 2 d n p 1 . +"$disk1MBytes"M \
						n p 2 . +"$bootXMBytes"M w q
				else
					createPartitionerInput \
						d 2 d n p 1 . +"$disk1MBytes"M n p 2 . . w q
				fi
				setupDeviceNames 1 no no no 2 no
			fi
		else
			if isFSTypeReadOnly;then
				createPartitionerInput \
					d 2 d 3 n p 2 . +"$disk2MBytes"M \
					n p 3 . +"$bootXMBytes"M \
					n p 4 . . \
					t 4 82 w q
				setupDeviceNames 1 4 no no 3 2
			else
				if [ ! -z "$OEM_SYSTEMSIZE" ];then
					createPartitionerInput \
						d 2 d n p 1 . +"$disk1MBytes"M \
						n p 2 . +"$bootXMBytes"M \
						n p 3 . +"$swapsize"M \
						t 3 82 w q
				else
					createPartitionerInput \
						d 2 d n p 1 . +"$disk1MBytes"M \
						n p 2 . +"$bootXMBytes"M \
						n p 3 . . \
						t 3 82 w q
				fi
				setupDeviceNames 1 3 no no 2 no
			fi
		fi
		luksClose
		callPartitioner $input
	fi
	#======================================
	# post repart actions
	#--------------------------------------
	if [ -z "$DONT_PARTITION" ];then
		#======================================
		# Activate boot partition
		#--------------------------------------     
		activateBootPartition
		#======================================
		# LUKS Maps
		#--------------------------------------
		export imageRootDevice=$(luksOpen $imageRootDevice)
		if isFSTypeReadOnly;then
			export imageIOWRDevice=$(luksOpen $imageIOWRDevice luksReadWrite)
			export imageRWDevice=$imageIOWRDevice
			export imageRODevice=$imageRootDevice
		fi
		#======================================
		# Create boot filesystem
		#--------------------------------------
		if ! mke2fs -T ext2 -q $imageBootDevice >/dev/null 2>&1;then
			systemException "Failed to create Boot filesystem" "reboot"
		fi
	fi
}

#======================================
# OEMRepart
#--------------------------------------
function OEMRepart {
	# /.../
	# call the appropriate repartition functions
	# ----
	if [ ! $LOCAL_BOOT = "no" ];then
		return
	fi
	#======================================
	# Initialize
	#--------------------------------------
	OEMRepartInit
	#======================================
	# Do the repartitioning
	#--------------------------------------
	if [ ! -z "$haveLVM" ];then
		OEMRepartLVM
	elif [ "$haveLuks" = "yes" ];then
		OEMRepartLuks
	elif [ ! -z "$COMBINED_IMAGE" ];then
		OEMRepartCombined
	elif isFSTypeReadOnly;then
		OEMRepartOverlayed
	else
		OEMRepartStandard
	fi
	sleep 1
	#======================================
	# Activate swap space
	#--------------------------------------
	if [ -z "$DONT_PARTITION" ] && [ $swapsize -gt 0 ]; then
		if partitionSize $imageSwapDevice &>/dev/null;then
			Echo "Activating swap space on $imageSwapDevice"
			if ! mkswap $imageSwapDevice 1>&2;then
				systemException "Failed to create swap signature" "reboot"
			fi
		fi
	fi
	#======================================
	# Create home file system
	#--------------------------------------
	if [ -z "$DONT_PARTITION" ] && [ -z "$OEM_WITHOUTHOME" ];then
		Echo "Creating Home filesystem on $imageHomeDevice"
		if ! mke2fs -T ext3 -j -q $imageHomeDevice >/dev/null 2>&1;then
			systemException "Failed to create Home filesystem" "reboot"
		fi
	fi
	#======================================
	# Create recovery file system
	#--------------------------------------
	if [ -z "$DONT_PARTITION" ] && [ ! -z "$OEM_RECOVERY" ];then
		Echo "Creating Recovery filesystem on $imageRecoveryDevice"
		if ! mke2fs -T ext3 -j -q $imageRecoveryDevice >/dev/null 2>&1;then
			systemException "Failed to create Recovery fs" "reboot"
		fi
	fi
	#======================================
	# Setup recovery contents
	#--------------------------------------
	if [ -z "$DONT_PARTITION" ] && [ ! -z "$OEM_RECOVERY" ];then
		Echo "Setting up recovery archive..."
		mkdir -p /reco-root
		if ! mount $imageRootDevice /reco-root >/dev/null;then
			systemException "Failed to mount root device" "reboot"
		fi
		mkdir -p /reco-save
		if ! mount $imageRecoveryDevice /reco-save >/dev/null;then
			systemException "Failed to mount recovery device" "reboot"
		fi
		if ! mv /reco-root/recovery.tar.gz /reco-save >/dev/null;then
			systemException "Failed to move recovery archive" "reboot"
		fi
		if ! mv /reco-root/recovery.tar.files /reco-save >/dev/null;then
			systemException "Failed to move recovery file count" "reboot"
		fi
		mkdir /reco-save/boot
		if ! cp /reco-root/boot/initrd.vmx /reco-save/boot/initrd;then
			systemException "Failed to copy recovery initrd" "reboot"
		fi
		if ! cp /reco-root/boot/linux.vmx /reco-save/boot/vmlinuz;then
			systemException "Failed to copy recovery kernel" "reboot"
		fi
		umount /reco-save && rmdir /reco-save
		umount /reco-root && rmdir /reco-root
	fi
}

#======================================
# activateBootPartition
#--------------------------------------
function activateBootPartition {
	# /.../
	# set boot flag to current value of $bootid
	# ----
	local input=/part.input
	Echo "Set boot flag to partition ID: $bootid [ $imageDiskDevice ]"
	if [ $PARTITIONER = "sfdisk" ];then
		rm -f $input
		for cmd in a $bootid w q; do
			echo $cmd >> $input
		done
		fdisk $imageDiskDevice < $input 1>&2
	else
		parted -m $imageDiskDevice set $bootid boot on
	fi
	if test $? != 0; then
		systemException "Failed to set boot flag" "reboot"
	fi
}

#======================================
# callPartitioner
#--------------------------------------
function callPartitioner {
	local input=$1
	if [ $PARTITIONER = "sfdisk" ];then
		Echo "Repartition the disk according to real geometry [ fdisk ]"
		fdisk $imageDiskDevice < $input 1>&2
		if test $? != 0; then
			systemException "Failed to create partition table" "reboot"
		fi
	else
		# /.../
		# nothing to do for parted here as we write
		# imediately with parted and don't create a
		# command input file as for fdisk
		# ----
		:
	fi
}

#======================================
# createPartitionerInput
#--------------------------------------
function createPartitionerInput {
	if [ $PARTITIONER = "sfdisk" ];then
		createFDiskInput $@
	else
		Echo "Repartition the disk according to real geometry [ parted ]"
		partedInit $imageDiskDevice
		createPartedInput $imageDiskDevice $@
    fi
}

#======================================
# createFDiskInput
#--------------------------------------
function createFDiskInput {
	local input=/part.input
	rm -f $input
	for cmd in $*;do
		if [ $cmd = "." ];then
			echo >> $input
			continue
		fi
		echo $cmd >> $input
	done
}

#======================================
# partedInit
#--------------------------------------
function partedInit {
	# /.../
	# initialize current partition table output
	# as well as the number of cylinders and the
	# cyliner size in kB for this disk
	# ----
	local device=$1
	local IFS=""
	local parted=$(parted -m $device unit cyl print)
	local header=$(echo $parted | head -n 3 | tail -n 1)
	local ccount=$(echo $header | cut -f1 -d:)
	local cksize=$(echo $header | cut -f4 -d: | cut -f1 -dk)
	export partedOutput=$parted
	export partedCylCount=$ccount
	export partedCylKSize=$cksize
}

#======================================
# partedWrite
#--------------------------------------
function partedWrite {
	# /.../
	# call parted with current command queue.
	# This will immediately change the partition table
	# ----
	local device=$1
	local cmds=$2
	if ! parted -m $device unit cyl $cmds;then
		systemException "Failed to create partition table" "reboot"
	fi
	partedInit $device
}

#======================================
# partedStartCylinder
#--------------------------------------
function partedStartCylinder {
	# /.../
	# return start cylinder of given partition.
	# lowest cylinder number is 0
	# ----
	local part=$(($1 + 3))
	local IFS=""
	local header=$(echo $partedOutput | head -n $part | tail -n 1)
	local ccount=$(echo $header | cut -f2 -d: | tr -d cyl)
	echo $ccount
}

#======================================
# partedEndCylinder
#--------------------------------------
function partedEndCylinder {
	# /.../
	# return end cylinder of given partition, next
	# partition must start at return value plus 1
	# ----
	local part=$(($1 + 3))
	local IFS=""
	local header=$(echo $partedOutput | head -n $part | tail -n 1)
	local ccount=$(echo $header | cut -f3 -d: | tr -d cyl)
	echo $ccount
}

#======================================
# partedMBToCylinder
#--------------------------------------
function partedMBToCylinder {
	# /.../
	# convert size given in MB to cylinder count
	# ----
	local sizeKB=$(($1 * 1024))
	local cylreq=$(($sizeKB / $partedCylKSize))
	echo $cylreq
}

#======================================
# createPartedInput
#--------------------------------------
function createPartedInput {
	# /.../
	# evaluate partition instructions and turn them
	# into a parted command line queue. As soon as the
	# geometry data would be changed according to the
	# last partedInit() call the command queue is processed
	# and the partedInit() will be called afterwards
	# ----
	local disk=$1
	shift
	local index=0
	local pcmds
	local partid
	local pstart
	local pstopp
	local value
	local cmdq
	#======================================
	# create list of commands
	#--------------------------------------
	for cmd in $*;do
		pcmds[$index]=$cmd
		index=$(($index + 1))
	done
	index=0
	#======================================
	# process commands
	#--------------------------------------
	for cmd in ${pcmds[*]};do
		case $cmd in
			#======================================
			# delete partition
			#--------------------------------------
			"d")
				partid=${pcmds[$index + 1]}
				partid=$(($partid / 1))
				if [ $partid -eq 0 ];then
					partid=1
				fi
				cmdq="$cmdq rm $partid"
				;;
			#======================================
			# create new partition
			#--------------------------------------
			"n")
				partid=${pcmds[$index + 2]}
				partid=$(($partid / 1))
				if [ $partid -eq 0 ];then
					partid=1
				fi
				pstart=${pcmds[$index + 3]}
				if [ "$pstart" = "1" ];then
					pstart=0
				fi
				if [ $pstart = "." ];then
					# start is next cylinder according to previous partition
					pstart=$(($partid - 1))
					if [ $pstart -gt 0 ];then
						pstart=$(partedEndCylinder $pstart)
						pstart=$(($pstart + 1))
					fi
				fi
				pstopp=${pcmds[$index + 4]}
				if [ $pstopp = "." ];then
					# use rest of the disk for partition end
					pstopp=$partedCylCount
				elif echo $pstopp | grep -qi M;then
					# calculate stopp cylinder from size
					pstopp=$(($partid - 1))
					if [ $pstopp -gt 0 ];then
						pstopp=$(partedEndCylinder $pstopp)
					fi
					value=$(echo ${pcmds[$index + 4]} | cut -f1 -dM | tr -d +)
					value=$(partedMBToCylinder $value)
					pstopp=$((1 + $pstopp + $value))
				fi
				cmdq="$cmdq mkpart primary $pstart $pstopp"
				partedWrite "$disk" "$cmdq"
				cmdq=""
				;;
			#======================================
			# change partition ID
			#--------------------------------------
			"t")
				ptypex=${pcmds[$index + 2]}
				partid=${pcmds[$index + 1]}
				cmdq="$cmdq set $partid type 0x$ptypex"
				partedWrite "$disk" "$cmdq"
				cmdq=""
				;;
		esac
		index=$(($index + 1))
	done
}

#======================================
# setupDeviceNames
#--------------------------------------
function setupDeviceNames {
	local rootID=$1
	local swapID=$2
	local homeID=$3
	local recoID=$4
	local bootID=$5
	local iorwID=$6
	#======================================
	# set root device name
	#--------------------------------------
	export imageRootDevice=$(ddn $imageDiskDevice $rootID)
	#======================================
	# set swap device name
	#--------------------------------------
	if [ ! $swapID = "no" ];then
		export imageSwapDevice=$(ddn $imageDiskDevice $swapID)
	fi
	#======================================
	# set home device name
	#--------------------------------------
	if [ ! $homeID = "no" ];then
		export imageHomeDevice=$(ddn $imageDiskDevice $homeID)
	fi
	#======================================
	# set recovery device name
	#--------------------------------------
	if [ ! $recoID = "no" ];then
		export imageRecoveryDevice=$(ddn $imageDiskDevice $recoID)
		export recoid=$recoID
	fi
	#======================================
	# set read-write device name
	#--------------------------------------
	if [ ! $iorwID = "no" ];then
		export imageIOWRDevice=$(ddn $imageDiskDevice $iorwID)
		export imageRWDevice=$imageIOWRDevice
		export imageRODevice=$imageRootDevice
	fi
	#======================================
	# set boot device name
	#--------------------------------------
	export imageBootDevice=$(ddn $imageDiskDevice $bootID)
	#======================================
	# set boot partition id
	#--------------------------------------
	export bootid=$bootID
}
