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

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

SFS_TO_BUILD=${SFS_TO_BUILD:-multi} # means "base", "devx", and "nls", but not "base32"
OUTPUT_DIR=${OUTPUT_DIR:-/tmp/output}
BUILD_CONFIG=${BUILD_CONF:-./build-multi.conf}
#KEEP_ROOTFS=1   # don't delete rootfs after building
#NOPAD=1         # don't pad SFS output
#SQUASHFS_PARAM= # inherit # -comp xz -Xbcj x86

# 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.$$}
BASE32_ROOTFS_DIR=${BASE32_ROOTFS_DIR:-/tmp/rootfs.base32.$$}

# 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}
BASE32_PKG_LIST=${BASE32_PKG_LIST:-sfs-base32list}

# output (override SFS_OUTPUT)
BASE_SFS=${BASE_SFS:-fd64.sfs}
DEVX_SFS=${DEVX_SFS:-fd64-devx.sfs}
NLS_SFS=${NLS_SFS:-fd64-nls.sfs}
BASE32_SFS=${BASE32_SFS:-32bit-fd64.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")
BASE32_ROOTFS_DIR=$(readlink -f "$BASE32_ROOTFS_DIR")

####### generic helpers #######

# cleanup
trap 'cleanup; exit' INT QUIT TERM 0
cleanup() {
	[ -z "$KEEP_ROOTFS" ] && 
	rm -rf "$BASE_ROOTFS_DIR" "$DEVX_ROOTFS_DIR" "$NLS_ROOTFS_DIR" "$BASE32_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
}

# check whether we need to build an SFS
# $1 - sfs to check
shall_we_build() {
	local p
	case $SFS_TO_BUILD in
		multi) SFS_TO_BUILD="base devx nls" ;;
		all)   SFS_TO_BUILD="base devx nls base32" ;;
	esac
	
	for p in $SFS_TO_BUILD; do
		[ $p = $1 ] && return 0
	done
	return 1
}

# prepare base and devx rootfs
prepare_dirs() {
	mkdir -p "$OUTPUT_DIR" \
		"$BASE_ROOTFS_DIR" "$DEVX_ROOTFS_DIR" "$NLS_ROOTFS_DIR" "$BASE32_ROOTFS_DIR"
}


####### splitters #######

### move nls from base to nls
# leave /usr/locale/share/en as it is.
split_nls_from_base() {
	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" 
	
	# 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, i18n_ctype, 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
	
	# LibreOffice, move some of the localization files
	if [ -e $BASE_ROOTFS_DIR/usr/lib64/libreoffice ]; then
	mkdir -p "$NLS_ROOTFS_DIR"/usr/lib64/libreoffice/program/resource
	for FILE in $(ls $BASE_ROOTFS_DIR/usr/lib64/libreoffice/program/resource/ | grep -E -v 'US|GB') ; do
	mv "$BASE_ROOTFS_DIR"/usr/lib64/libreoffice/program/resource/$FILE "$NLS_ROOTFS_DIR"/usr/lib64/libreoffice/program/resource/
	done
	fi
	#mv "$BASE_ROOTFS_DIR"/usr/share/icu "$NLS_ROOTFS_DIR"/usr/share/ #move libicu data
	
	# large non-English bitmap fonts
	if [ -e $BASE_ROOTFS_DIR/usr/share/fonts/X11/misc ]; then
		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
		sed -i -e 's/iso8859/iso10646/' $BASE_ROOTFS_DIR/usr/share/fonts/X11/misc/fonts.alias
	fi
	
	# ROX-Filer messages
	for p in ROX-Filer ROX-Filer-jun7; do
		if [ -e "$BASE_ROOTFS_DIR"/usr/local/apps/$p/Messages ]; then
			mkdir -p "$NLS_ROOTFS_DIR"/usr/local/apps/$p/Messages
			mv "$BASE_ROOTFS_DIR"/usr/local/apps/$p/Messages/* "$NLS_ROOTFS_DIR"/usr/local/apps/$p/Messages
		fi
	done
	
	# lxqt translations
	if [ -e "$BASE_ROOTFS_DIR"/usr/share/lxqt/translations ]; then
		mkdir -p "$NLS_ROOTFS_DIR"/usr/share/lxqt
		mv "$BASE_ROOTFS_DIR"/usr/share/lxqt/translations "$NLS_ROOTFS_DIR"/usr/share/lxqt
	fi

	# avidemux translations
	if [ -e "$BASE_ROOTFS_DIR"/usr/share/avidemux6/qt5/i18n ]; then
		mkdir -p "$NLS_ROOTFS_DIR"/usr/share/avidemux6/qt5
		mv "$BASE_ROOTFS_DIR"/usr/share/avidemux6/qt5/i18n "$NLS_ROOTFS_DIR"/usr/share/avidemux6/qt5
	fi
	
	# install our mkfontscale/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
mkfontscale /usr/share/fonts/X11/TTF
mkfontdir   /usr/share/fonts/X11/TTF
xset fp rehash
EOF
	chmod +x "$NLS_ROOTFS_DIR"/tmp/sfs/autorun.sh
	
	} 2> /dev/null # don't want to see error
}


### move nls from devx to nls
# leave /usr/locale/share/en as it is.
split_nls_from_devx() {
	local p
	LOCALEDIR=/usr/share/locale
	{
	
	# move /usr/share/locales out of base and devx to nls
	mkdir -p "$NLS_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 

	# remove /home dirs, nls should not include this (with very rare exceptions)
	rm -rf "$NLS_ROOTFS_DIR"/home
		
	} 2> /dev/null # don't want to see error
}


### move header files, static libs, pkgconfigs, gtk-docs from base to devx
split_devx_from_base() {
	{	
	# 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 findnrun; 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"
	cp -a "$BASE_ROOTFS_DIR/usr/lib/pkgconfig" "$DEVX_ROOTFS_DIR/usr/lib"	
	rm -r "$BASE_ROOTFS_DIR/usr/lib64/pkgconfig" "$BASE_ROOTFS_DIR/usr/lib/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
	
	# extraneous python libs - assuming python in dex, no python in base
	if [ -e "$BASE_ROOTFS_DIR"/usr/lib64/python2.7 ]; then
		cp -a "$BASE_ROOTFS_DIR"/usr/lib64/python2.7/* "$DEVX_ROOTFS_DIR"/usr/lib64/python2.7
		rm -r "$BASE_ROOTFS_DIR"/usr/lib64/python2.7
	fi
	
	# 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" -o -name "*-config-64"
	} | sed "s|^$BASE_ROOTFS_DIR/||" | while read -r p; do
		[ -z "$p" ] && continue
		mv "$BASE_ROOTFS_DIR/$p" "$DEVX_ROOTFS_DIR/$p"
	done

	# move known .dbg debug symbol files
	mv "$BASE_ROOTFS_DIR"/lib64/*.dbg "$DEVX_ROOTFS_DIR"/lib64
	mv "$BASE_ROOTFS_DIR"/usr/lib64/*.dbg "$DEVX_ROOTFS_DIR"/usr/lib64

	# remove all empty dirs
	find "$DEVX_ROOTFS_DIR" -type d -empty | sort -r | tr '\n' '\0' | 
	xargs -0 rmdir 2>/dev/null

	# remove /home dirs, devx should not include this (with very rare exceptions)
	rm -rf "$DEVX_ROOTFS_DIR"/home
			
	} 2> /dev/null # don't want to see error		
}



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

# build base sfs
build_base_sfs() {
	[ -e "$BASE_PKG_LIST" ] || return 
	
	# install and process base if we are building nls and devx
	if shall_we_build base || shall_we_build devx || shall_we_build nls; then
		PKG_LIST="$BASE_PKG_LIST" SFS_OUTPUT=$BASE_SFS ROOTFS_DIR="$BASE_ROOTFS_DIR" \
		./build-sfs.sh install
		split_nls_from_base
		split_devx_from_base
	fi
		
	# further processing is done only if we are really building it
	if ! shall_we_build base; then
		rm -rf "$BASE_ROOTFS_DIR"
		return
	fi
	
	# 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
	
	# add os-release
	cat > "$BASE_ROOTFS_DIR"/etc/os-release << EOF
NAME="Fatdog64 Linux"
VERSION="$FATDOG_VERSION"
ID="fatdog64"
VERSION_ID="$FATDOG_VERSION"
PRETTY_NAME="Fatdog64 Linux $FATDOG_VERSION"
BUILD_ID="$(get_fossil_stamp)"
HOME_URL="http://distro.ibiblio.org/fatdog/web/"
SUPPORT_URL="http://murga-linux.com/puppy/"
BUG_REPORT_URL="http://murga-linux.com/puppy/"
EOF
	
	# done, build sfs
	make_sfs "$BASE_ROOTFS_DIR" $BASE_SFS version
}

# build devx sfs
build_devx_sfs() {
	[ -e "$DEVX_PKG_LIST" ] || return
	
	# install and process devx if we are building nls
	if shall_we_build devx || shall_we_build nls; then
		PKG_LIST="$DEVX_PKG_LIST" SFS_OUTPUT=$DEVX_SFS ROOTFS_DIR="$DEVX_ROOTFS_DIR" \
		./build-sfs.sh install	
		split_nls_from_devx
	fi
	
	if ! shall_we_build devx; then
		rm -rf "$DEVX_ROOTFS_DIR"
		return
	fi	
		
	# delete these - they make devx un-removeable (they're already included in base)
	rm -f "$DEVX_ROOTFS_DIR"/usr/lib64/libgcc*so* \
	      "$DEVX_ROOTFS_DIR"/usr/lib64/libstdc++*so* \
	      "$DEVX_ROOTFS_DIR"/usr/lib64/libelf*so* \
	      "$DEVX_ROOTFS_DIR"/usr/lib64/libssp*so* \
	      "$DEVX_ROOTFS_DIR"/usr/lib64/libltdl*so* \
	      "$DEVX_ROOTFS_DIR"/usr/lib64/libdw[-.]*so*
	
	make_sfs "$DEVX_ROOTFS_DIR" $DEVX_SFS devx-version
}

# build nls sfs
build_nls_sfs() {	
	[ -e "$NLS_PKG_LIST" ] || return

	if ! shall_we_build nls; then
		rm -rf "$NLS_ROOTFS_DIR"
		return
	fi	
	
	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
}

# build the 32-bit libraries
build_base32_sfs() {
	[ -e "$BASE32_PKG_LIST" ] || return
	shall_we_build base32 || return
	
	PKG_LIST="$BASE32_PKG_LIST" SFS_OUTPUT=$BASE32_SFS ROOTFS_DIR="$BASE32_ROOTFS_DIR" \
	./build-sfs.sh install
	
	# remove extraneous dirs/files
	(
		cd "$BASE32_ROOTFS_DIR"
		rm -f etc/rpc            # from glibc32
		rmdir lib64 root
	)
	make_sfs "$BASE32_ROOTFS_DIR" $BASE32_SFS base32-version
}

### main
prepare_dirs
build_base_sfs
build_devx_sfs
build_nls_sfs
build_base32_sfs
