#!/bin/sh

rd()
{
	echo $(od -j $(($1)) -N ${2:-4} -t u${2:-4} -An ${3:-kernel})
}

ds()
{
	set -- $1 ${2:-512}
	dd count=$((($1*$2)/512)) bs=512 2>/dev/null
	dd count=$(((($1*$2)%512)/$2)) bs=$2 2>/dev/null
}

ds_rootfs()
{
	echo 'Write rootfs'
	ds $@ >rootfs
}

extract_slitaz()
{
	( ds $(($(rd 0x1F1 1)-1))
	[ $(rd 0x229 1) -le 128 ] || ds 1
	[ $(rd 0x228) -ne 0 ] && ds 1 >cmd$$
	ds $(( ($(rd 0x1F4) +31) /32)) ) >>kernel
	echo 'Write kernel'
	[ $(rd 0x21C) -ne 0 ] && ds_rootfs $(( ($(rd 0x21C) +3) /4)) 4 ||
	if [ $(rd 0x218) -ne 0 ]; then
		n=$(($(rd 0x1EE 2)%512))
		i=0
		[ $(rd $n 4 cmd$$) -eq 0 ] && ds_rootfs 5000 ||
		while [ $(($n % 256)) -lt $(rd 0x1F0 1) ]; do
			ds $(( ($(rd $n 4 cmd$$) +3) /4)) 4 >rootfs$i
			n=$(($n+4))
			i=$(($i+1))
		done
	fi
	[ -s cmd$$ ] && echo 'Write cmdline' && strings <cmd$$ | sed q >cmdline
	rm -f cmd$$
}

getname()
{
	name="$(dd if=kernel bs=1 skip=$pos 2> /dev/null | strings | sed q)"
	pos=$((pos+${#name}+1))
}

case "$1" in
extract) 
	ds 1 > kernel
	pos="$(rd 0x1f2 2)"
	if [ $pos -lt 500 -a $pos -gt 256 ] &&
           [ $(rd $((pos-5))) -eq $((0x61696465)) ]; then
		getname
		echo "Read $name menu ..."
		start=$(rd $pos 2); pos=$((pos+2))
		data="slitaz"
		cmds="/tmp/floppies$$"
		while [ $start -ne 0 ]; do
			getname
			len=$(rd $((pos+2)) 2)
			echo "$start $len $data $name"
			start=$(rd $((pos+4)) 2); pos=$((pos+6))
			data="data"
		done | sort | while read start len type name; do
			if [ "$type" = "data" ]; then
				echo "echo 'Write $name'"
				echo "ds $len > '$name'"
			else
				echo "echo 'Extract $name ...'"
				echo 'ds 1 > kernel; extract_slitaz'
			fi
		done > $cmds
		. $cmds
		rm $cmds
	else
		extract_slitaz
        fi
	;;
*)	cat <<EOT
usage: cat fd*.img | $0 extract  or
# cat fd0*.img | $0 extract
	creates kernel, rootfs(es) and cmdline files
EOT
	for i in 1 2 3; do
		j=" cat fd$i*.img |"
		echo "#$j cpio -i 2>/dev/null ||$j unlzma | cpio -idmu"
	done
esac
