#!/bin/dash
# Build multi (splitted) Fatdog64 sfs (base, devx, nls)
# Uses build-sfs.sh.
#
# Copyright (C) James Budiono, 2014, 2015
# License: GPL Version 3 or later
# 
# Note: must run as root.

### configuration
LANG=C
FATDOG_VERSION=${FATDOG_VERSION:-700}

#NOPAD=1  # don't pad SFS output
#NODEVX=1 # don't build devx sfs
#NOBASE=1 # don't buidl base sfs
#NONLS=1  # don't build nls sfs
#SQUASHFS_PARAM= # inherit # -comp xz -Xbcj x86
OUTPUT_DIR=${OUTPUT_DIR:-/tmp/output}
BUILD_CONFIG=${BUILD_CONF:-./build-multi.conf}
KEEP_ROOTFS=${KEEP_ROOTFS:-$BASE_ROOTFS_DIR} # if rootfs_dir is specified, keep it (don't delete on exit)

# rootfs dir (override ROOTFS_DIR)
BASE_ROOTFS_DIR=${BASE_ROOTFS_DIR:-/tmp/rootfs.base.$$}
DEVX_ROOTFS_DIR=${DEVX_ROOTFS_DIR:-/tmp/rootfs.devx.$$}
NLS_ROOTFS_DIR=${NLS_ROOTFS_DIR:-/tmp/rootfs.nls.$$}

# pkglist (override PKG_LIST)
BASE_PKG_LIST=${BASE_PKG_LIST:-sfs-baselist}
DEVX_PKG_LIST=${DEVX_PKG_LIST:-sfs-devxlist}
NLS_PKG_LIST=${NLS_PKG_LIST:-sfs-nlslist}

# output (override SFS_OUTPUT)
BASE_SFS=${BASE_SFS:-fd64.sfs}
DEVX_SFS=${DEVX_SFS:-fd64-devx.sfs}
NLS_SFS=${NLS_SFS:-fd64-nls.sfs}

### standard configuration items - dont change unless you know what you're doing
[ -e "$BUILD_CONFIG" ] && . "$BUILD_CONFIG"
unset BUILD_CONFIG # so it doesn't get exported to build-sfs.sh

# pass through all other build-sfs.sh options (except those overriden above)
for p in PKG_EXT PKG_URL PKG_CACHE OUTPUT_DIR INSTALLER_PKG NOPAD; do
	eval test \"\$$p\" && eval export $p
done

### make all path absolute
BASE_ROOTFS_DIR=$(readlink -f "$BASE_ROOTFS_DIR")
DEVX_ROOTFS_DIR=$(readlink -f "$DEVX_ROOTFS_DIR")
NLS_ROOTFS_DIR=$(readlink -f "$NLS_ROOTFS_DIR")

####### helpers #######

# cleanup
trap 'cleanup; exit' INT QUIT TERM 0
cleanup() {
	[ -z "$KEEP_ROOTFS" ] && 
	rm -rf "$BASE_ROOTFS_DIR" "$DEVX_ROOTFS_DIR" "$NLS_ROOTFS_DIR"
}

get_fossil_stamp() {
	which fossil > /dev/null && fossil info > /dev/null && fossil info | awk '/checkout/ {print $2}' 
}

### align sfs to 256K so they are usable by qemu directly.
# $1-path to sfs
padsfs() {
	ORIGSIZE=$(stat -c %s "$1")
	BLOCKS256K=$(( ((ORIGSIZE/1024/256)+1) ))
	dd if=/dev/zero of="$1" bs=256K seek=$BLOCKS256K count=0
}

# $1-sfs rootfs, $2-sfs name, $3-version name, $OUTPUT_DIR, $SQUASHFS_PARAM
make_sfs() {
	echo Building $2 ...
	mkdir -p "$1/etc"
	echo $FATDOG_VERSION > "$1/etc/fatdog-$3"
	get_fossil_stamp > "$1/etc/fatdog-fossil-$3"
	mksquashfs "$1" "$OUTPUT_DIR/$2" -noappend $SQUASHFS_PARAM > /dev/null
	[ -z "$NOPAD" ] && padsfs "$OUTPUT_DIR/$2"
	[ -z "$KEEP_ROOTFS" ] && rm -rf "$1" # clean it, make space for others
}


# prepare base and devx rootfs
prepare_rootfs() {
	! [ -r "$BASE_PKG_LIST" ] && echo "$BASE_PKG_LIST cannot be read." && exit
	! [ -r "$DEVX_PKG_LIST" ] && echo "$DEVX_PKG_LIST cannot be read." && exit
	
	mkdir -p "$OUTPUT_DIR" "$BASE_ROOTFS_DIR" "$DEVX_ROOTFS_DIR" "$NLS_ROOTFS_DIR"
	
	# base packages
	PKG_LIST="$BASE_PKG_LIST" SFS_OUTPUT=$BASE_SFS ROOTFS_DIR="$BASE_ROOTFS_DIR" \
	./build-sfs.sh install
	
	# devx packages
	[ -z "$NODEVX" ] && 
	PKG_LIST="$DEVX_PKG_LIST" SFS_OUTPUT=$DEVX_SFS ROOTFS_DIR="$DEVX_ROOTFS_DIR" \
	./build-sfs.sh install
	
	# remove cruft
	for p in "$BASE_ROOTFS_DIR" "$DEVX_ROOTFS_DIR"; do
		find "$p" -type f -name placeholder_for_fossil -delete
	done
}


####### builders #######

### move nls from base & devx to nls, then build sfs
# leave /usr/locale/share/en as it is.
# still have to do cleanup, even though not building devx
build_nls_sfs() {
	local p
	LOCALEDIR=/usr/share/locale
	{
	
	# move /usr/share/locales out of base and devx to nls
	mkdir -p "$NLS_ROOTFS_DIR/$LOCALEDIR"
	mv "$BASE_ROOTFS_DIR/$LOCALEDIR/"* "$NLS_ROOTFS_DIR/$LOCALEDIR"
	# keep en locale
	mv "$NLS_ROOTFS_DIR/$LOCALEDIR/en" "$BASE_ROOTFS_DIR/$LOCALEDIR" 
	cp -a "$DEVX_ROOTFS_DIR/$LOCALEDIR/"* "$NLS_ROOTFS_DIR/$LOCALEDIR"
	# delete but keep en locale
	ls -d "$DEVX_ROOTFS_DIR/$LOCALEDIR/"* | grep -v '/en$' | xargs rm -r 
	
	# other minor locale stuff (but still count)
	
	# i18n - complicated. We only want to keep en_*, but for it to work
	# we also need to keep i18n, translit_* (except hangul and cjk_variants), 
	# and iso14651_t1* except iso14651_t1_pinyin (which is huge),
	# plus some odd locales!
	mkdir -p "$NLS_ROOTFS_DIR"/usr/share/i18n
	mv "$BASE_ROOTFS_DIR"/usr/share/i18n/locales "$NLS_ROOTFS_DIR"/usr/share/i18n
	mkdir -p "$BASE_ROOTFS_DIR"/usr/share/i18n/locales
	mv "$NLS_ROOTFS_DIR"/usr/share/i18n/locales/en_* "$NLS_ROOTFS_DIR"/usr/share/i18n/locales/translit_* \
	   "$NLS_ROOTFS_DIR"/usr/share/i18n/locales/iso14651_t1* "$NLS_ROOTFS_DIR"/usr/share/i18n/locales/i18n \
	   "$BASE_ROOTFS_DIR"/usr/share/i18n/locales
	for p in iso14651_t1_pinyin translit_cjk_variants translit_hangul; do
		mv "$BASE_ROOTFS_DIR"/usr/share/i18n/locales/$p "$NLS_ROOTFS_DIR"/usr/share/i18n/locales
	done
	for p in da_DK hi_IN tl_PH dem_ZM i18n; do # odd locales required in en_*
		mv "$NLS_ROOTFS_DIR"/usr/share/i18n/locales/$p "$BASE_ROOTFS_DIR"/usr/share/i18n/locales
	done

	# ghostcript Resource/CMap/CIDFSubst
	if ls $BASE_ROOTFS_DIR/var/log/packages/ghostscript* >/dev/null 2>/dev/null; then	
		GS_DIR=$(echo "$BASE_ROOTFS_DIR"/usr/share/ghostscript/[0-9]*/Resource | sed "s|$BASE_ROOTFS_DIR/||")
		mkdir -p "$NLS_ROOTFS_DIR/$GS_DIR"
		mv "$BASE_ROOTFS_DIR/$GS_DIR"/CMap "$BASE_ROOTFS_DIR/$GS_DIR"/CIDFSubst "$NLS_ROOTFS_DIR/$GS_DIR"
	fi
	
	# abiword strings
	if ls $BASE_ROOTFS_DIR/var/log/packages/abiword* >/dev/null 2>/dev/null; then
		ABI_DIR=$(echo "$BASE_ROOTFS_DIR"/usr/share/abiword* | sed "s|$BASE_ROOTFS_DIR/||")
		mkdir -p "$NLS_ROOTFS_DIR/$ABI_DIR"
		mv "$BASE_ROOTFS_DIR/$ABI_DIR"/strings "$NLS_ROOTFS_DIR/$ABI_DIR"		
	fi
	
	# large non-English bitmap fonts
	mkdir -p "$NLS_ROOTFS_DIR"/usr/share/fonts/X11/misc
	for p in "18x18*" "12x13ja*" "k14*" "*KOI*" "*JIS*" "*ISO8859*"; do
		mv $BASE_ROOTFS_DIR/usr/share/fonts/X11/misc/$p "$NLS_ROOTFS_DIR"/usr/share/fonts/X11/misc
	done	
	
	# ROX-Filer messages
	mkdir -p "$NLS_ROOTFS_DIR"/usr/share/ROX-Filer/Messages
	mv "$BASE_ROOTFS_DIR"/usr/share/ROX-Filer/Messages/* "$NLS_ROOTFS_DIR"/usr/share/ROX-Filer/Messages
	
	# install our mkfontdir script (so that i18n fonts are made available)
	mkdir -p "$NLS_ROOTFS_DIR"/tmp/sfs
	cat << "EOF" >> "$NLS_ROOTFS_DIR"/tmp/sfs/autorun.sh
#!/bin/dash
exec 2>/dev/null
mkfontdir /usr/share/fonts/X11/misc
xset fp rehash
EOF
	chmod +x "$NLS_ROOTFS_DIR"/tmp/sfs/autorun.sh
	
	} 2> /dev/null # don't want to see error
	
	# done, build sfs if needed
	[ "$NONLS" ] && return
	
	# install extra nls packages only after all is cleaned-up
	[ -e "$NLS_PKG_LIST" ] &&
	PKG_LIST="$NLS_PKG_LIST" SFS_OUTPUT=$NLS_SFS ROOTFS_DIR="$NLS_ROOTFS_DIR" \
		./build-sfs.sh install
		
	make_sfs "$NLS_ROOTFS_DIR" $NLS_SFS nls-version
}

### move header files, static libs, pkgconfigs, gtk-docs to devx, then build devx
# still have to do cleanup, even though not building devx
build_devx_sfs() {
	{
	# store original devx dirs 
	ORIG_DIRS="$(find $DEVX_ROOTFS_DIR -type d)"
	
	# re-create basesfs dirs
	find $BASE_ROOTFS_DIR -type d | sed "s|^$BASE_ROOTFS_DIR/|$DEVX_ROOTFS_DIR/|" | 
	tr '\n' '\0' | xargs -0 mkdir -p
	
	# move headers, src
	cp -a "$BASE_ROOTFS_DIR/usr/include" "$BASE_ROOTFS_DIR/usr/src" "$DEVX_ROOTFS_DIR/usr"
	rm -r "$BASE_ROOTFS_DIR/usr/include" "$BASE_ROOTFS_DIR/usr/src"
	
	# move gtk-docs, docs, info, gir, devhelp, texinfo
	cp -a "$BASE_ROOTFS_DIR/usr/share/gtk-doc" "$BASE_ROOTFS_DIR/usr/share/doc" \
		"$BASE_ROOTFS_DIR/usr/share/man" "$BASE_ROOTFS_DIR/usr/share/info" \
		"$BASE_ROOTFS_DIR/usr/share/texinfo" "$BASE_ROOTFS_DIR/usr/share/devhelp" \
		"$BASE_ROOTFS_DIR"/usr/share/gir-* \
		"$DEVX_ROOTFS_DIR/usr/share"
	rm -r "$BASE_ROOTFS_DIR/usr/share/gtk-doc" "$BASE_ROOTFS_DIR/usr/share/doc" \
		"$BASE_ROOTFS_DIR/usr/share/man" "$BASE_ROOTFS_DIR/usr/share/info" \
		"$BASE_ROOTFS_DIR/usr/share/texinfo" "$BASE_ROOTFS_DIR/usr/share/devhelp" \
		"$BASE_ROOTFS_DIR"/usr/share/gir-*
	
	# but keep fatdog, faqs, home, fd-help, license essential dirs, and all files directly under /usr/share/doc
	mkdir -p "$BASE_ROOTFS_DIR/usr/share/doc"
	for p in fatdog faqs home essential fd-help license; do
		mv "$DEVX_ROOTFS_DIR/usr/share/doc/$p" "$BASE_ROOTFS_DIR/usr/share/doc"
	done
	find "$DEVX_ROOTFS_DIR/usr/share/doc/" -maxdepth 1 -type f -print0 | xargs -0 -I '{}' mv '{}' "$BASE_ROOTFS_DIR/usr/share/doc"
	
	# move pkgconfig
	cp -a "$BASE_ROOTFS_DIR/usr/lib64/pkgconfig" "$DEVX_ROOTFS_DIR/usr/lib64"
	rm -r "$BASE_ROOTFS_DIR/usr/lib64/pkgconfig"
	
	# trim ghostscripts
	if ls $BASE_ROOTFS_DIR/var/log/packages/ghostscript* >/dev/null 2>/dev/null; then		
		mv "$BASE_ROOTFS_DIR"/usr/share/ghostscript/[0-9]*/doc "$DEVX_ROOTFS_DIR/"usr/share/ghostscript/[0-9]*
	fi
	
	# trim cups ipptool
	if ls $BASE_ROOTFS_DIR/var/log/packages/cups* >/dev/null 2>/dev/null; then
		rm -rf "$DEVX_ROOTFS_DIR/"usr/share/cups/ipptool
		mv "$BASE_ROOTFS_DIR"/usr/share/cups/ipptool "$DEVX_ROOTFS_DIR/"usr/share/cups
	fi
	
	# trim terminfo - base only needs x (xterm), r (rxvt-unicode), l (linux) and s (screen) 
	rm -rf "$DEVX_ROOTFS_DIR/"usr/share/terminfo
	mv "$BASE_ROOTFS_DIR"/usr/share/terminfo "$DEVX_ROOTFS_DIR/"usr/share
	mkdir -p "$BASE_ROOTFS_DIR"/usr/share/terminfo
	for p in x r l s; do
		mv "$DEVX_ROOTFS_DIR/"usr/share/terminfo/$p "$BASE_ROOTFS_DIR"/usr/share/terminfo
	done
	
	# static libraries, linker scripts, and M4 files, *-config files
	{
	find $BASE_ROOTFS_DIR -name "*.a" -o -name "*.la" -o -name "*.m4" \
	     -o -name INSTALL -o -name NEWS -o -name CHANGELOG -o -name README
	find $BASE_ROOTFS_DIR/bin  $BASE_ROOTFS_DIR/usr/bin \
	     $BASE_ROOTFS_DIR/sbin $BASE_ROOTFS_DIR/usr/sbin \
	     -name "*-config"
	} | sed "s|^$BASE_ROOTFS_DIR/||" | while read -r p; do
		[ -z "$p" ] && continue
		mv "$BASE_ROOTFS_DIR/$p" "$DEVX_ROOTFS_DIR/$p"
	done
	
	# remove all empty dirs
	find "$DEVX_ROOTFS_DIR" -type d -empty | sort -r | tr '\n' '\0' | 
	xargs -0 rmdir 2>/dev/null
	
	# but keep original devx dirs
	echo "$ORIG_DIRS" | tr '\n' '\0' | xargs -0 mkdir -p
	
	} 2> /dev/null # don't want to see error
	
	# done, build sfs
	[ -z "$NODEVX" ] &&
	make_sfs "$DEVX_ROOTFS_DIR" $DEVX_SFS devx-version
}

# build the rest of what we have as base sfs
build_base_sfs() {
	# more cleanup
	{
	# useless gnumeric help
	rm -rf "$BASE_ROOTFS_DIR"/usr/share/gnome/help/gnumeric
	
	# remove hwdb.bin dead-weight, re-create it at boot instead
	rm -f "$BASE_ROOTFS_DIR"/etc/udev/hwdb.bin
	
	# make sure we don't end-up with stale fonts (because we moved the fonts to nls.sfs)
	mkfontdir $BASE_ROOTFS_DIR/usr/share/fonts/X11/misc
	} #2> /dev/null
	
	# done, build sfs
	[ -z "$NOBASE" ] &&
	make_sfs "$BASE_ROOTFS_DIR" $BASE_SFS version
}


### main
prepare_rootfs
build_nls_sfs
build_devx_sfs
build_base_sfs

