#!/bin/sh
#
# (C) 2014-2016 SliTaz GNU/Linux - GPL2
#
# Creates a Debian package to install SliTaz on a Raspbian without
# repartitioning.
#
# AUTHORS: Pascal Bellard <pascal.bellard@slitaz.org>
#

[ $(id -u) -ne 0 ] && echo "Must be root. Abort." && exit 1

REVISION=2
DESTDIR=var/os/slitaz
DESCRIPTION="Tiny Linux distribution with multi boot features"
LONG_DESCRIPTION="SliTaz can run fully in RAM or can be installed \
on the SD card in a\nsubdirectory of your Raspbian (example /$DESTDIR)."
WEB_SITE="http://arm.slitaz.org/rpi/"
MAINTAINER="Pascal Bellard <pascal.bellard@slitaz.org>"

tazpkg()
{
	if [ -x /usr/bin/tazpkg -a "$1" == "get-install" ]; then
		/usr/bin/tazpkg "$@"
		return $?
	fi
	[ "$1" == "get-install" ] && echo "abort: can't find $2" && exit 1
	mkdir -p tazpkg$$
	cd tazpkg$$
	cpio -i < ../$2 > /dev/null 2>&1
	gunzip fs.cpio.gz 2> /dev/null
	[ -s fs.cpio ] || unlzma fs.cpio.lzma
	cpio -idmu < fs.cpio > /dev/null 2>&1
	cd ..
	sh <<EOT
. tazpkg$$/receipt
mkdir -p ${3#--root=}/var/lib/tazpkg/installed/\$PACKAGE
grep -qs ^pre_install tazpkg$$/receipt && pre_install ${3#--root=}
cp -a tazpkg$$/fs/. ${3#--root=}
grep -qs ^post_install tazpkg$$/receipt && post_install ${3#--root=}
rm -rf tazpkg$$/fs*
mv tazpkg$$/* ${3#--root=}/var/lib/tazpkg/installed/\$PACKAGE
EOT
	md5sum $2 >> ${3#--root=}/var/lib/tazpkg/installed.md5
	rm -rf tazpkg$$
}

buildfs()
{
CURDIR=$PWD
TMPDIR=/tmp/rasp$$
mkdir -p $TMPDIR
cd $TMPDIR
URL=http://mirror.slitaz.org/arm/rpi/
echo "Read $URL"
wget -O - $URL | sed '/slitaz-rpi/!d;s/.*href=.\([a-zA-Z0-9._-]*\).*/\1/' | sort -r > index
VERSION="$(sed '/rpi-desktop/!d' index | sed 's/.*-desktop-\([0-9_-]*\).*/\1/;q')"

for file in $(sed '/rpi-base/!d;q' index) $(sed '/rpi-desktop/!d;q' index); do
	echo "Get $file "
	wget -O - $URL$file | tar xjf -
done

mkdir -p fs/$DESTDIR fs/boot/slitaz fs/boot/slitaz-base fs/boot/slitaz-live \
	 fs/boot/$raspos

BOOT=$(ls -d slitaz-rpi-base-*/boot)
[ ! -d "$BOOT" ] && echo "Abort ($BOOT) !" && exit 1

# setup boot configuration 
echo "entry=SliTaz $VERSION on SD-card" > fs/boot/slitaz/menu.txt
echo "entry=SliTaz base $VERSION in RAM" > fs/boot/slitaz-base/menu.txt
echo "entry=SliTaz desktop $VERSION in RAM" > fs/boot/slitaz-live/menu.txt
cp $BOOT/config.txt fs/boot/slitaz
grep -q ^kernel= fs/boot/slitaz/config.txt ||
echo "kernel=kernel.img >> fs/boot/slitaz/config.txt"
sed -i '/^initramfs/d' fs/boot/slitaz/config.txt
cp fs/boot/slitaz/config.txt fs/boot/slitaz-base
cp fs/boot/slitaz/config.txt fs/boot/slitaz-live
echo "initramfs rootfs-base.gz" >> fs/boot/slitaz/config.txt
echo "initramfs ../slitaz/rootfs-base.gz" >> fs/boot/slitaz-base/config.txt
echo "initramfs ../slitaz/rootfs-base.gz,../slitaz/rootfs-live.gz" >> fs/boot/slitaz-live/config.txt

if [ -s $BOOT/kernel7.img ]; then
	mv $BOOT/kernel*.img fs/boot/slitaz
	sed -i 's|kernel.img|../slitaz/&|' fs/boot/slitaz-*/config.txt
else
	rm -rf	slitaz-rpi-*/boot/kernel.img \
		slitaz-rpi-*/rootfs/lib/modules/* \
		slitaz-rpi-*/rootfs/lib/firmware/*
	sed -i 's|kernel.img|../&|' fs/boot/slitaz-*/config.txt
fi

# update base package
BASE=$(ls -d slitaz-rpi-base-*/rootfs)
[ ! -d "$BASE" ] && echo "Abort ($BASE) !" && exit 1
LIVE=$(ls -d slitaz-rpi-desktop-*/rootfs)
[ ! -d "$LIVE" ] && echo "Abort ($LIVE) !" && exit 1
LIVESZ=$(du -ks $LIVE | cut -f1)
wget http://hg.slitaz.org/slitaz-arm/raw-file/tip/rpi/piboot
wget http://hg.slitaz.org/slitaz-boot-scripts/raw-file/tip/init
chmod +x piboot init
mv piboot $BASE/sbin
sed -i 's|mnt /mnt|mnt "/mnt -o noatime"|' init
sed -i 's#.*remount,ro#grep -q "tmpfs /mnt tmpfs" /proc/mounts || &#' init
mknod -m 660 $BASE/dev/mmcblk0 b 179 0
for i in $(seq 1 5); do
	mknod -m 660 $BASE/dev/mmcblk0p$i b 179 $i
done
grep /dev/pts $BASE/etc/fstab || cat >> $BASE/etc/fstab <<EOT
devpts	/dev/pts	devpts	rw,gid=5,mode=0620	0	0
EOT

[ -s slitaz-rpi-base*/boot/kernel7.img ] ||
sed -i 's#.*d /proc/sys/dev/cdrom#grep -q subroot= /proc/cmdline || for d in /dev/mmc*p[2-9]; do\n\tumount /mnt\n\tmount -r $d /mnt \&\&\n\tcp -a /mnt/lib/firmware /lib/ \&\&\n\tcp -a /mnt/lib/modules/$(uname -r) /lib/modules/ \&\& break\ndone 2> /dev/null\numount /mnt\n\n&#' init
mv init $BASE/rdinit
sed -i 's/.*mmcblk0p[2-9].*/# &/;s/noatime/noauto,&/' $BASE/etc/fstab $LIVE/etc/fstab
wget http://cook.slitaz.org/cross/arm/packages/packages.list
while read file pkg extra ; do
	[ -s boot$file ] && continue
	[ -n "$extra" ] && continue
	pkg=$(grep ^$pkg- packages.list | sort | sed q).tazpkg
	wget http://cook.slitaz.org/cross/arm/packages/$pkg
	tazpkg install $pkg --root=$BASE/
done <<EOT
/usr/lib/libz.so		zlib
/usr/sbin/kexec			kexec-tools
/usr/bin/tset			ncursesw
/usr/bin/dialog			dialog
/usr/lib/libxml2.so		libxml2			aria2
/usr/bin/gpg-error		libgpg-error		aria2
/usr/lib/libgcrypt.so		libgcrypt		aria2
/usr/lib/libgmp.so		gmp			aria2
/usr/lib/libnettle.so		nettle			aria2
/usr/lib/libreadline.so		readline		aria2
/usr/bin/p11-kit		p11-kit			aria2
/usr/lib/libgnutls.so		libgnutls		aria2
/usr/lib/libtasn1.so		libtasn1		aria2
/usr/bin/gnutls-cli		gnutls			aria2
/usr/bin/aria2c			aria2			aria2
EOT

echo "Deduplicate base & live"
( cd $BASE/ ; find ! -type d ) | while read file; do
	if [ -L $BASE/$file ]; then
		[ -L $LIVE/$file ] &&
		[ "$(readlink $BASE/$file)" == "$(readlink $LIVE/$file)" ] &&
		rm -f $LIVE/$file
	elif [ -f $BASE/$file ]; then
		[ -f $LIVE/$file ] &&
		cmp $BASE/$file $LIVE/$file > /dev/null 2>&1 &&
		rm -f $LIVE/$file
	elif [ -b $BASE/$file ]; then
		[ -b $LIVE/$file ] &&
		[ "$(stat -c '%a:%u:%g:%t:%T' $BASE/$file)" == \
		  "$(stat -c '%a:%u:%g:%t:%T' $LIVE/$file)" ] &&
		rm -f $LIVE/$file
	elif [ -c $BASE/$file ]; then
		[ -c $LIVE/$file ] &&
		[ "$(stat -c '%a:%u:%g:%t:%T' $BASE/$file)" == \
		  "$(stat -c '%a:%u:%g:%t:%T' $LIVE/$file)" ] &&
		rm -f $LIVE/$file
	fi
done
( cd $BASE/ ; find -type d ) | while read dir; do
	rmdir $LIVE/$dir 2> /dev/null
done

while read dir suffix ; do
	echo "Build $suffix archive"
	( cd $dir ; find * | cpio -o -H newc ) | if [ -x /usr/bin/zopfli ]; then
		cat > fs/boot/slitaz/rootfs-$suffix
		zopfli fs/boot/slitaz/rootfs-$suffix
		rm -f fs/boot/slitaz/rootfs-$suffix
	else
		gzip -9 > fs/boot/slitaz/rootfs-$suffix.gz
	fi
	[ -x /usr/bin/advdef ] && advdef -z4 fs/boot/slitaz/rootfs-$suffix.gz
	r=$(($(stat -c %s fs/boot/slitaz/rootfs-$suffix.gz) % 4))
	[ $r -eq 0 ] || dd if=/dev/zero bs=1 count=$((4 - $r)) \
		>> fs/boot/slitaz/rootfs-$suffix.gz 2> /dev/null
done <<EOT
$BASE	base
$LIVE	live
EOT
}

mkpostinst()
{
	cat <<EOT
RDEV=\$(sed 's/^\(\|.* \)root=\([^ ]*\).*/\2/' /boot/cmdline.txt)
FSTYPE=\$(awk '/ \/ / { if (\$1 != "rootfs") print \$3 }' < /proc/mounts)

echo "Extracting /$DESTDIR ..."
cd /$DESTDIR
zcat /boot/slitaz/rootfs-base.gz | cpio -idmu
zcat /boot/slitaz/rootfs-live.gz | cpio -idmu
EOT
	[ -s slitaz-rpi-base*/boot/kernel7.img ] || cat <<EOT
echo "Get modules & firmwares ..."
cp -a /lib/modules /lib/firmware lib
EOT
	cat <<EOT
if ! grep -qs $raspos etc/fstab ; then
	echo "Update /$DESTDIR/etc/fstab ..."
	mkdir -p mnt/$raspos
	sed -i 's/noauto,//' etc/fstab
	cat >> etc/fstab <<EOM
\$RDEV	/mnt/$raspos	\$FSTYPE	noatime	0	0
tmpfs	/mnt/$raspos/$DESTDIR	tmpfs	size=0	0	0
EOM
fi
cd - > /dev/null

if [ ! -f /boot/menu.txt ]; then

echo "Update /boot ..."
for i in keyboard locale ; do
	[ -s /etc/default/\$i ] && . /etc/default/\$i
done
KMAP=\$(find /$DESTDIR/usr/share/kbd/keymaps | grep /\$XKBLAYOUT[.-] | head -n1)
[ "\$KMAP" ] && KMAP="kmap=\$(basename \$KMAP .map.gz)"
cat > /boot/menu.txt <<EOM
title=Raspberry PI boot menu
subtitle=Select the OS with ARROW keys and hit RETURN
timeout=10
default=$raspos
\$KMAP
edittitle=Edit menu
readonly
#noedit
#nowebboot
#webpath=http://my.home.web.site/pxe/rpi/index.php http://or.this.one/rpi.txt
EOM
echo "entry=$menustr" > /boot/$raspos/menu.txt
KERNEL=\$(sed '/^kernel/!d;s/.*=//' /boot/config.txt)
cp /boot/config.txt /boot/cmdline.txt /boot/$raspos/
sed -i '/^initramfs/d' /boot/config.txt
echo "initramfs slitaz/rootfs-base.gz" >> /boot/config.txt
EOT
	[ -s slitaz-rpi-base*/boot/kernel7.img ] && cat <<EOT
mv /boot/\${KERNEL:-kernel.img} /boot/$raspos/
sed -i '/^kernel/d' /boot/config.txt
echo "kernel=slitaz/kernel.img" >> /boot/config.txt
EOT
	cat <<EOT
L=
for i in \$LANG \${LANG%.*} \${LANG%@*} \${LANG%_*} ; do
	[ -s /$DESTDIR/usr/share/i18n/locales/\$i ] && L=lang=\$i
done
TZ=\$(cat /etc/timezone 2> /dev/null || true)
X="\$L \$KMAP \${TZ:+tz=\$TZ} quiet"
echo "\$(cat /boot/cmdline.txt) \$X rdinit=/sbin/piboot" > /boot/cmdline.txt
echo "root=/dev/null \$X rdinit=/rdinit mount=\$RDEV subroot=$DESTDIR rootwait" > /boot/slitaz/cmdline.txt
echo "root=/dev/null \$X" > /boot/slitaz-base/cmdline.txt
cp /boot/slitaz-base/cmdline.txt /boot/slitaz-live/cmdline.txt
echo "The SliTaz boot menu is available for the next (re)boot."

fi
EOT
}

mkpurge()
{
	cat <<EOT
	echo "Remove /$DESTDIR & /boot/slitaz* trees..."
	rm -rf /$DESTDIR /boot/slitaz*
EOT
}

mkdisable()
{
	cat <<EOT
	if [ -d /boot/$raspos ]; then
		echo "Restore $raspos boot files..."
		rm -f /boot/$raspos/menu.txt
		mv -f /boot/$raspos/* /boot
		rmdir /boot/$raspos
	fi
	rm -f /boot/menu.txt /boot/slitaz*/cmdline.txt
EOT
}

pkgdebian()
{
	# Create raspbian package
	echo "2.0" > debian-binary
	cat > control <<EOT
Package: slitaz
Version: $VERSION-$REVISION
Architecture: armhf
Maintainer: $MAINTAINER
Installed-Size: $(($(du -ks fs | cut -f1) + $LIVESZ))
Section: miscellaneous
Priority: optional
Homepage: $WEB_SITE
Description: $DESCRIPTION
$(echo -e $LONG_DESCRIPTION | sed 's/^/ /')
EOT
	( cd fs ; find * -type f -exec md5sum {} \; ) > md5sums
	cat > postinst <<EOT
#!/bin/sh

set -e

$(mkpostinst)

exit 0
EOT
	cat > prerm <<EOT
#!/bin/sh

purge()
{
$(mkpurge)
}

disable()
{
$(mkdisable)
}

case "\$1" in
purge)
	disable
	purge
	;;
remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
	disable
	;;
*)
	echo "prerm called with unknown argument \\\`\$1'" >&2
	exit 0
esac
EOT
	chmod +x postinst prerm
	tar czf control.tar.gz md5sums control postinst prerm
	rm -rf fs/$DESTDIR/*
	cd fs ; tar czf ../data.tar.gz . ; cd ..
	ar rcs slitaz-$VERSION-${REVISION}_armhf.deb debian-binary control.tar.gz data.tar.gz
	mv slitaz-$VERSION-${REVISION}_armhf.deb $CURDIR
	cd $CURDIR
	rm -rf $TMPDIR
	ls -l slitaz-$VERSION-${REVISION}_armhf.deb
}

mkmtree()
{
	echo "#mtree"
	echo "/set type=file uid=0 gid=0 mode=644"
	find .??* * | while read file; do
		echo -n "$file $(stat -c "time=%Y.000000" "$file")"
		n="$(stat -c "%a" "$file")"; [ "$n" == "644" ] || echo -n " mode=$n"
		n="$(stat -c "%u" "$file")"; [ "$n" == "0" ] || echo -n " uid=$n"
		n="$(stat -c "%g" "$file")"; [ "$n" == "0" ] || echo -n " gid=$n"
		if [ -f "$file" ]; then
			echo -n " $(stat -c "size=%s" "$file")"
			echo -n " md5digest=$(md5sum "$file" | sed 's/ .*//')"
			echo -n " sha256digest=$(sha256sum "$file" | sed 's/ .*//')"
		fi
		[ -d "$file" ] && echo -n " type=dir"
		echo ""
	done
}

pkgarch()
{
	cd fs
	VERSION=$VERSION-$REVISION
	# Create arch package
	cat > .PKGINFO <<EOT
pkgname = slitaz
pkgver = $VERSION
pkgdesc = $DESCRIPTION
url = $WEB_SITE
builddate = $(date +%s)
packager = $MAINTAINER
size = $(du -s . | awk "{ print \$1*1024+$LIVESZ }")
arch = armv6h
license = GPL
EOT
	cat > .INSTALL <<EOT
post_install() {
$(mkpostinst)
}

post_remove() {
$(mkdisable)
$(mkpurge)
}
EOT
	mkmtree | gzip -9 > ../.MTREE
	mv ../.MTREE .
	tar cvzf ../slitaz-$VERSION-armv6h.pkg.tar.gz .??* *
	mv ../slitaz-$VERSION-armv6h.pkg.tar.gz $CURDIR
	cd $CURDIR
	rm -rf $TMPDIR
	ls -l slitaz-$VERSION-armv6h.pkg.tar.gz
}

case "$(basename $0)" in
tazarch)
	raspos=archarm
	menustr="Arch Linux ARM \$(uname -r)"
	buildfs
	pkgarch
	;;
*)
	[ -x /usr/bin/ar -o -x /bin/ar ] || tazpkg get-install binutils
	raspos=raspbian
	menustr="Raspbian \$(cat /etc/debian_version)"
	buildfs
	pkgdebian
	;;
esac
