#! /bin/sh

# DIET-PC firmware conversion script

# Copyright (C) 2002-2011 Paul A. Whittaker <whitpa@users.sourceforge.net>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

# Increase these values if you need more free space at run-time.
# Values may be expressed either as a percentage or an absolute number.
BLOCK_SLACK=15%		# 0.5k blocks to allow above anticipated requirement
INODE_SLACK=2048	# inodes to allow above anticipated requirement

umask 022
# It's important that /usr/local/bin precede /usr/bin in PATH so that we use
# custom lsattr/chattr and mksquashfs binaries rather than standard ones.
path='/bin:/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/usr/local/sbin'
export PATH

if [ ! -s $HOME/diet-pc/.config ]; then
    cat 1>&2 <<EOF
$HOME/diet-pc/.config is missing - must run dpc-configure first!
EOF
elif [ "`id -u`" -ne 0 ]; then
    echo "`basename $0` must be run as root." 1>&2
    exit 2
fi

cd $HOME/diet-pc
. ./.config

# Constants
CRAMFS_MOD='cramfs.ko.gz'
JFFS2_MOD='jffs2.ko.gz'
SQUASHFS_MOD='squashfs.ko.gz'
UNIONFS_MOD='unionfs.ko.gz'
TMPFS_MOD='tmpfs.ko.gz'
EXT2FS_MOD='ext2.ko.gz'
EXT3FS_MOD='ext3.ko.gz'
EXT4FS_MOD='ext4.ko.gz'

# Global variables
KPKG=
KVER=
ARCH=
PLATFORM=
DSTFILE=
INODES=
BLOCKS=
MIN_INODES=
MIN_BLOCKS=
PRECOMPRESS=
POSTCOMPRESS=
E2COMPR_ALGO=



get_kernel_capabilities () {

    KCONFIG="/tmp/kernel-config.$$"
    cat /dev/null >$KCONFIG

    KPKG=`grep '^CONFIG_KERNEL_IMAGE_[^=]\+=y$' .config | sed -e \
	    's/^CONFIG_//' -e 's/=y$//' | tr '[_A-Z]' '[\055a-z]'`
    if [ "`echo \"$KPKG\" | wc -l`" -gt 1 ]; then
	KPKG=`echo "$KPKG" | head -n 1`
	cat 1>&2 <<EOF
WARNING: Multiple kernel images specified - this shouldn't happen!
Only examining the capabilities of the first one ($KPKG).

EOF
    fi
    if [ -e "mdcache/$KPKG" ]; then
	KVER=`grep '^Version:' mdcache/$KPKG | sed 's/^Version:\s*//'`
	ARCH=`grep '^Architecture:' mdcache/$KPKG | sed 's/^Architecture:\s*//'`
	PLATFORM=`echo "$KPKG" | cut -f3- -d-`
	ar p "$ARCH/${KPKG}_${KVER}_${ARCH}.ipk" data.tar.gz | tar xzOf - \
		"./boot/config-$KVER-$PLATFORM.gz" | gunzip -c >$KCONFIG
    fi

    if [ ! -s $KCONFIG ]; then
	cat <<EOF
Can't find your kernel's configuration file.
Automatic format recommendation will not be possible for this system.
EOF
	exit 1
    fi
    . $KCONFIG
    rm -f $KCONFIG

}



check_module_capabilities () {

    MODLIST="/tmp/modlist.$$"
    ar p "$ARCH/${KPKG}_${KVER}_${ARCH}.ipk" data.tar.gz | tar tzOf - \
	'./lib/modules/' >$MODLIST

    eval `awk -F/ '$NF == "'$CRAMFS_MOD'" {printf "CRAMFS_AVAIL=m\n"} \
		$NF == "'$JFFS2_MOD'" {printf "JFFS2_AVAIL=m\n"} \
		$NF == "'$SQUASHFS_MOD'" {printf "SQUASHFS_AVAIL=m\n"} \
		$NF == "'$UNIONFS_MOD'" {printf "UNIONFS_AVAIL=m\n"} \
		$NF == "'$TMPFS_MOD'" {printf "TMPFS_AVAIL=m\n"} \
		$NF == "'$EXT2FS_MOD'" {printf "EXT2FS_AVAIL=m\n"} \
		$NF == "'$EXT3FS_MOD'" {printf "EXT3FS_AVAIL=m\n"} \
		$NF == "'$EXT4FS_MOD'" {printf "EXT4FS_AVAIL=m\n"}' \
		$MODLIST 2>/dev/null`

    rm -f $MODLIST

}



get_recommendation () {

    # $1 is the filename of the cpio archive to be converted.

    get_kernel_capabilities
    [ "`basename $1 .cpio`" = 'root' ] && RO_OK= || RO_OK=TRUE
    if [ "$CONFIG_SQUASHFS" = 'y' -a \( "$RO_OK" -o \( -n "$CONFIG_TMPFS" -a \
	    -n "$CONFIG_UNION_FS" \) \) ]; then
	RECOMMEND='squashfs'
    elif [ "$CONFIG_CRAMFS" = 'y' -a \( "$RO_OK" -o \( -n "$CONFIG_TMPFS" -a \
	    -n "$CONFIG_UNION_FS" \) \) ]; then
	RECOMMEND='cramfs'
    elif [ "$CONFIG_ISO9660_FS" = 'y' -a -n "$CONFIG_ZISOFS" -a \( "$RO_OK" \
	    -o \( -n "$CONFIG_TMPFS" \ -a -n "$CONFIG_UNION_FS" \) \) ]; then
	RECOMMEND='ziso'
    elif [ "$CONFIG_EXT2_FS" = 'y' -a -n "$CONFIG_EXT2_COMPRESS" ]; then
	RECOMMEND='e2compr'
    elif [ ! "$RO_OK" -a "$CONFIG_BLK_DEV_INITRD" = 'y' ]; then
	RECOMMEND='cpio'
    elif [ "$CONFIG_EXT2_FS" = 'y' -o \( "$CONFIG_EXT4_FS" = 'y' -a \
	    -n "$CONFIG_EXT4_USE_FOR_EXT23" \) ]; then
	RECOMMEND='ext2'
    elif [ "$CONFIG_EXT3_FS" = 'y' -o \( "$CONFIG_EXT4_FS" = 'y' -a \
	    -n "$CONFIG_EXT4_USE_FOR_EXT23" \) ]; then
	RECOMMEND='ext3'
    elif [ "$CONFIG_EXT4_FS" = 'y' ]; then
	RECOMMEND='ext4'
    else
	echo 'Your kernel provides no usable filesystem options!' 1>&2
	exit 1
    fi

}



embedding_initrd () {

    # $1 is the filename of the cpio archive to be converted.

    BN=`basename $1 .cpio`
    test \( "$BN" = 'usr' -a "$CONFIG_USR_IS_BOOTBABLE" \) -o \( "$BN" = \
	    'usrlocal' -a "$CONFIG_USRLOCAL_IS_BOOTABLE" \)
    return $?
}



compute_sizes () {

    # $1 is the filename of the cpio archive to be converted.

    if [ -z "$MIN_INODES" -o -z "$MIN_BLOCKS" ]; then
	BCOUNT="/tmp/count.$$"
	MIN_INODES=`cpio -t 2>$BCOUNT < $1| wc -l`
	MIN_BLOCKS=`cut -f1 -d' ' $BCOUNT`
	rm -f $BCOUNT
	if embedding_initrd $1; then
	    RD_NAME="`dirname $1`/root.cpio"
	    RD_SIZE=`ls -s $RD_NAME | awk '{print int($1) * 2}'`
	    MIN_INODES=`expr $MIN_INODES + 1`
	    MIN_BLOCKS=`expr $MIN_BLOCKS + $RD_SIZE`
	fi
    fi
    INODE_PERCENT=`echo $INODE_SLACK | tr -d '%'`
    if [ "$INODE_PERCENT" = "$INODE_SLACK" ]; then
	INODES=`expr $MIN_INODES + $INODE_SLACK`
    else
	INODES=`expr $MIN_INODES + \( $MIN_INODES \* $INODE_PERCENT / 100 \)`
    fi
    BLOCK_PERCENT=`echo $BLOCK_SLACK | tr -d '%'`
    if [ "$BLOCK_PERCENT" = "$BLOCK_SLACK" ]; then
	BLOCKS=`expr $MIN_BLOCKS + $BLOCK_SLACK`
    else
	BLOCKS=`expr $MIN_BLOCKS + \( $MIN_BLOCKS \* $BLOCK_PERCENT / 100 \)`
    fi

}



convert_ext () {

    # $1 is the filename of the cpio archive to be converted.
    # $2 is the desired ext version (2, 3 or 4).
    # E2compr is attempted if $2 = 2 and both $E2COMPR_ALGO and
    # $CONFIG_EXT2_COMPRESS are set.

    DSTFILE=`echo "$1" | sed "s/\.cpio\$/.ext$2/"`
    DSTMNT="/tmp/`basename $DSTFILE`.$$"

    trap "umount $DSTMNT 2>/dev/null; rmdir $DSTMNT 2>/dev/null; rm -f $DSTFILE; exit 255" 2

    compute_sizes $1
    dd if=/dev/zero of=$DSTFILE bs=512 count=$BLOCKS 2>/dev/null
    mkfs.ext$2 -I 128 -F -N $INODES -m 0 -L "`basename $1 .cpio`" $DSTFILE \
	    >/dev/null 2>&1
    if [ $? -ne 0 ]; then
	echo "Unable to create loopback ext$2 filesystem." 1>&2
	kill -INT $$
    fi
    mkdir $DSTMNT
    mount -t ext$2 -o loop $DSTFILE $DSTMNT
    if [ $? -ne 0 ]; then
	echo "Unable to mount loopback ext$2 filesystem." 1>&2
	kill -INT $$
    fi

    # If requested and plausibly possible, test to see whether the build
    # platform can do ext2 compression.
    if [ "$2" -eq 2 -a "$CONFIG_EXT2_COMPRESS" = 'y' -a -n "$E2COMPR_ALGO" ]; \
	    then
	# Ideally chattr should either do nothing or return a non-zero exit
	# code, but unfortunately it semi-works in an unsafe fashion.  Hence
	# test on an expendable directory and watch for error messages.
	mkdir $DSTMNT/comptest.$$
	if [ "`chattr -m $E2COMPR_ALGO +c $DSTMNT/comptest.$$ 2>&1 | wc -l`" \
		-eq 0 ]; then
	    # Set the compression attribute on the root directory such that all
	    # files in the filesystem will inherit it.
	    chattr -m $E2COMPR_ALGO +c $DSTMNT
	else
	    cat 1>&2 <<EOF
The host cannot compress using the $E2COMPR_ALGO e2compr algorithm.
Disabling e2compr.
EOF
	    CONFIG_EXT2_COMPRESS=
	fi
	rmdir $DSTMNT/comptest.$$
    fi

    (cd $DSTMNT; cpio -id 2>/dev/null) < $1

    # FIXME: enable/disable initrd in conf file
    if [ "$CONFIG_EXTLINUX_RUNTIME" = 'y' ]; then
	extlinux -i $DSTMNT/boot/extlinux 2>/dev/null
    elif [ "$CONFIG_GRUB_RUNTIME" = 'y' ]; then
	# We use "fd" rather than "hd" because GRUB expects an "hd" device to
	# have a partition table.
	# FIXME: this doesn't work
	grub --batch --device-map=/dev/null >/dev/null 2>&1 <<EOF
device (fd7) $DSTFILE
root (fd7)
setup (fd7)
quit
EOF
    elif [ "$CONFIG_SILO_RUNTIME" = 'y' ]; then
	# FIXME: Lots of assumptions here; this will force an UltraSPARC
	# loader for a V2 PROM into the partition boot sector.  This might not
	# not work because it still wants to detect "hardware"(?).
	silo -r $DSTMNT -f -t -p 2 -u -C /boot/silo/silo.conf
    fi

    # FIXME
    # Copy in initrd if required

    # FIXME
    # If building a non-initrd system, a device node for the root filesystem is
    # also essential, so copy this from the host system.
    #ROOTDEV=`awk '$2 == "/" {print $1; exit}' $NV_FSTAB`
    #[ "$ROOTDEV" ] && tar -chf - "$ROOTDEV" 2>/dev/null | tar -C initrd -xf -

    # Update minimum sizes based on real-world information.  This will be
    # radically different from the initial estimates if e2compr was used.
    MIN_BLOCKS=`df --block-size=512 $DSTMNT | tail -n 1 | awk \
	    '{if ($1 ~ /^[0-9]/) print $2; else print $3}'`
    MIN_INODES=`df -i $DSTMNT | tail -n 1 | awk \
	    '{if ($1 ~ /^[0-9]/) print $2; else print $3}'`

    umount $DSTMNT
    rmdir $DSTMNT
    trap - 2
}



convert_vfat () {

    # $1 is the filename of the cpio archive to be converted.

    SRCDIR="/tmp/`basename $1`.$$"
    DSTFILE=`echo "$1" | sed 's/\.cpio\$/.vfat/'`
    DSTMNT="/tmp/`basename $DSTFILE`.$$"

    [ "`basename $1 .cpio`" != 'usrlocal' ] && cat 1>&2 <<EOF
WARNING: VFAT is case-insensitive and doesn't support onwership, permissions,
	 symlinks, or device nodes.  All files will be 0755 root:root, and
	 symlinked content in the source cpio will be duplicated in full.
	 Although bootable, VFAT will not work properly as a root filesystem,
	 and is at best a dubious proposition for /usr.  Recommended only on
	 /usr/local as a container for kernels, initrds and loopback
	 filesystems.
EOF

    trap "umount $DSTMNT 2>/dev/null; rmdir $DSTMNT 2>/dev/null; rm -f $DSTFILE; rm -rf $SRCDIR; exit 255" 2

    compute_sizes $1
    dd if=/dev/zero of=$DSTFILE bs=512 count=$BLOCKS 2>/dev/null
    mkfs.vfat -n "`basename $1 .cpio`" $DSTFILE
    if [ $? -ne 0 ]; then
	echo 'Unable to create loopback vfat filesystem.' 1>&2
	kill -INT $$
    fi
    mkdir $DSTMNT
    mount -t vfat -o loop $DSTFILE $DSTMNT
    if [ $? -ne 0 ]; then
	echo 'Unable to mount loopback vfat filesystem.' 1>&2
	kill -INT $$
    fi

    # We have to extract and then copy, because cpio doesn't support symlink
    # dereferencing in copy-out mode.
    mkdir $SRCDIR
    (cd $SRCDIR; cpio -id 2>/dev/null) < $1
    (cd $SRCDIR; find . -print | cpio -p -L $DSTMNT 2>/dev/null)

    # FIXME: enable/disable initrd in conf file
    if [ "$CONFIG_SYSLINUX_RUNTIME" = 'y' ]; then
	extlinux -i $DSTMNT/boot/extlinux 2>/dev/null
    elif [ "$CONFIG_GRUB_RUNTIME" = 'y' ]; then
	# We use "fd" rather than "hd" because GRUB expects an "hd" device to
	# have a partition table.
	# FIXME: this doesn't work
	grub --batch --device-map=/dev/null >/dev/null 2>&1 <<EOF
device (fd7) $DSTFILE
root (fd7)
setup (fd7)
quit
EOF

    # FIXME
    # Copy in initrd if required

    fi
    umount $DSTMNT
    rmdir $DSTMNT
    rm -rf $SRCDIR
    trap - 2
}



convert_hfs () {

    # $1 is the filename of the cpio archive to be converted.

    SRCDIR="/tmp/`basename $1`.$$"
    DSTFILE=`echo "$1" | sed 's/\.cpio\$/.hfs/'`

    [ "`basename $1 .cpio`" != 'usrlocal' ] && cat 1>&2 <<EOF
WARNING: HFS is case insensitive and doesn't support onwership, permissions,
	 symlinks, or device nodes.  All files will be 0755 root:root, and
	 symlinked content in the source cpio will be duplicated in full.
	 Although bootable, HFS will not work properly as a root filesystem,
	 and is at best a dubious proposition for /usr.  Recommended only on
	 /usr/local as a container for kernels, initrds and loopback
	 filesystems.
EOF

    trap "humount 2>/dev/null; rm -f $DSTFILE; rm -rf $SRCDIR; exit 255" 2

    # We must extract the CPIO archive in order to create symlink targets.
    mkdir $SRCDIR
    (cd $SRCDIR; cpio -id 2>/dev/null) < $1
    compute_sizes $1
    dd if=/dev/zero of=$DSTFILE bs=512 count=$BLOCKS 2>/dev/null
    hformat -l "`basename $1 .cpio`" $DSTFILE
    if [ $? -ne 0 ]; then
	echo 'HFS creation failed (maybe: "apt-get install hfsutils"?)' 1>&2
	kill -INT $$
    fi
    # The crude recursive copy that follows will not handle various HFS error
    # conditions, such as illegal characters (other than ":") and excessively
    # long (>32 chars) pathname components.  Symlinks will be dereferenced, but
    # anything else that isn't an ordinary file or directory will be ignored.
    find -L $SRCDIR -type d -print | tr '/:' ':/' | sort | while read DIR; do
	hmkdir $DIR 2>/dev/null
    done
    find -L $SRCDIR -type f -print | sort | while read FILE; do
	hcopy $FILE "`echo \"$FILE\" | tr '/:' ':/'`" 2>/dev/null
    done
    if [ -d $SRCDIR/boot ]; then
	# "Bless" the /boot directory.
	hattrib -b ':boot'
	if [ -f $SRCDIR/boot/ofboot.b ]; then
	    sed 's/__BOOTDEV__/hd/' $SRCDIR/boot/ofboot.b | hcopy - \
		    :boot:ofboot.b
	    # Set the type of /boot/ofboot.b to indicate that it is a bootable
	    # file.
	    hattrib -t tbxi :boot:ofboot.b
	fi
	# FIXME: enable/disable initrd in yaboot.conf
    fi
    humount
    rm -rf $SRCDIR
    trap - 2
}



convert_jffs2 () {

    # $1 is the filename of the cpio archive to be converted.
    # $2 is the erase block size (128k if not specified)

    SRCDIR="/tmp/`basename $1`.$$"
    DSTFILE=`echo "$1" | sed 's/\.cpio\$/.jffs2/'`

    trap "rm -rf $SRCDIR $DSTFILE" 2
    mkdir $SRCDIR
    (cd $SRCDIR; cpio -id 2>/dev/null) < $1
    mkfs.jffs2 -r $SRCDIR -e ${2:-'131072'} -m size -n -p -U -o $DSTFILE || {
	echo 'JFFS2 creation failed (maybe: "apt-get install mtd-tools"?)' 1>&2
	kill -INT $$
    }
    rm -rf $SRCDIR
    trap - 2
}



get_squashfs_version () {

    get_kernel_capabilities
    # Unfortunately, the kernel config file doesn't tell us what the major
    # version of Squashfs is, so we'll have to extract the System.map file
    # and make deductions based on symbols that are present and absent.
    SQUASHFS_V2=TRUE
    SQUASHFS_V4=TRUE
    SQUASHFS_3PLUS_SYM='__initcall_init_squashfs_fs6'
    SQUASHFS_3MINUS_SYM='squashfs_2_0_supported'
    SYSMAP="/tmp/sysmap.$$"
    cat /dev/null >$SYSMAP
    ar p "$ARCH/${KPKG}_${KVER}_${ARCH}.ipk" data.tar.gz | tar xzOf - \
	    "./boot/System.map-$KVER-$PLATFORM.gz" | gunzip -c >$SYSMAP
    if [ ! -s $SYSMAP ]; then
        cat 1>&2 <<EOF
Can't find your kernel's System.map file.
Don't know what version of Squashfs to use.  Assuming version 4!
EOF
	SQUASHFS_V2=
    else
	eval `awk '$NF == "'$SQUASHFS_3PLUS_SYM'" {printf "SQUASHFS_V2=\n"} \
		$NF == "'$SQUASHFS_3MINUS_SYM'" {printf "SQUASHFS_V4=\n"}' \
		$SYSMAP 2>/dev/null`
    fi

    if [ "$SQUASHFS_V2" ]; then
	echo '2'
    elif [ "$SQUASHFS_V4" ]; then
	echo '4'
    else
	echo '3'
    fi
}



convert_squashfs () {

    # $1 is the filename of the cpio archive to be converted.

    SRCDIR="/tmp/`basename $1`.$$"
    DSTFILE=`echo "$1" | sed 's/\.cpio\$/.squashfs/'`
    VERSION=`get_squashfs_version`

    trap "rm -rf $SRCDIR $DSTFILE" 2
    mkdir $SRCDIR
    (cd $SRCDIR; cpio -id 2>/dev/null) < $1
    mksquashfs$VERSION $SRCDIR $DSTFILE -root-owned >/dev/null || {
	echo "Unable to create squashfs$VERSION filesystem." 1>&2
	kill -INT $$
    }
    rm -rf $SRCDIR
    trap - 2
}



convert_cramfs () {

    # $1 is the filename of the cpio archive to be converted.

    SRCDIR="/tmp/`basename $1`.$$"
    DSTFILE=`echo "$1" | sed 's/\.cpio\$/.cramfs/'`

    trap "rm -rf $SRCDIR $DSTFILE" 2
    mkdir $SRCDIR
    (cd $SRCDIR; cpio -id 2>/dev/null) < $1
    mkfs.cramfs -n "`basename $1 .cpio`" $SRCDIR $DSTFILE >/dev/null || {
	echo 'Unable to create cramfs filesystem.' 1>&2
	kill -INT $$
    }
    rm -rf $SRCDIR
    trap - 2
}



convert_iso () {

    # $1 is the filename of the cpio archive to be converted.
    # $2 is the bootstrap scheme (eltorito, hfs, sparc)
    # Source tree will be precompressed using mkzftree if PRECOMRESS == "zf"

    SRCDIR="/tmp/`basename $1`.$$"
    DSTFILE=`echo "$1" | sed 's/\.cpio\$/.iso/'`
    BOOTPARAMS=

    # FIXME: enable/disable initrd in isolinux.conf/yaboot.conf/silo.conf
    case "$2" in
    eltorito)
	if [ "$CONFIG_ISOLINUX_RUNTIME" = 'y' ]; then
	    BOOTPARAMS="-b boot/isolinux/isolinux.bin -c \
		    boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
		    -boot-info-table -V \"`basename $1 .cpio`\""
	else
	    cat 1>&2 <<EOF
WARNING: isolinux-runtime is not installed.  ISO will not be bootable.
EOF
	fi
	;;
    hfs)
	if [ "$CONFIG_YABOOT_RUNTIME" = 'y' ]; then
	    sed -i 's/__BOOTDEV__/cd/' $SRCDIR/boot/ofboot.b
	    BOOTPARAMS="--double --netatalk --osx-double --osx-hfs -hfs -map \
		    $SRCDIR/boot/map.hfs -part -no-desktop -hfs-bless \
		    $SRCDIR/boot -hfs-volid \"`basename $1 .cpio`\""
	else
	    cat 1>&2 <<EOF
WARNING: yaboot-runtime is not installed.  ISO will not be bootable.
EOF
	fi
	;;
    sparc)
	if [ "$CONFIG_SILO_RUNTIME" = 'y' ]; then
	    BOOTPARAMS="-G $SRCDIR/boot/silo/isofs.b -sparc-boot '...' \
		    -sparc-label \"`basename $1 .cpio`\""
	else
	    cat 1>&2 <<EOF
WARNING: silo-runtime is not installed.  ISO will not be bootable.
EOF
	fi
	;;
    esac

    trap "rm -rf $SRCDIR $DSTFILE" 2
    mkdir $SRCDIR
    (cd $SRCDIR; cpio -id 2>/dev/null) < $1
    if [ "$PRECOMRESS" = "zf" ]; then
	if mkzftree -p 2 -q $SRCDIR "$SRCDIR-prime"; then
	    SRCDIR="$SRCDIR-prime"
	    BOOTPARAMS="$BOOTPARAMS -z"
	    rm -rf $SRCDIR
	else
	    echo 'mkzftree failed (missing genisoimage package?)' 1>&2
	    kill -INT $$
	fi
    fi
    mkisofs -o $DSTFILE $BOOTPARAMS -J -hide-joliet-trans-tbl -r \
	    -hide-rr-moved -A \
"DIET-PC (C) 2002-2011 Paul A. Whittaker <whitpa@users.sourceforge.net>" \
	    $SRCDIR || {
	echo 'Unable to create ISO.' 1>&2
	kill -INT $$
    }
    rm -rf $SRCDIR
    trap - 2
}



usage () {
    cat 1>&2 <<EOF
Usage: `basename $0` file format[.gz|.cloop]
Where format is one of:
	RECOMMENDED|cpio|cramfs|e2compr[-algo]|ext2|ext3|ext4|hfs|
	[h|s][z]iso|jffs2[-erasesize_in_kb]|squashfs|vfat
RECOMMENDED automatically selects a format according to layout
	and kernel capabilities
Algo (e2compr only, gzip9 if not specified) is one of:
	bzip[2]|lzo[1x1]|lzrw3a|lzv[1]|gzip[1-9]|none
EOF
    exit 1
}




if [ $1 = '--gzip' ]; then
    POSTCOMPRESS='gzip'
    shift
elif [ $1 = '--cloop' ]; then
    POSTCOMPRESS='cloop'
    shift
elif [ $1 = '--zf' ]; then
    PRECOMPRESS='zf'
    shift
fi
[ $# -ne 2 ] && usage
case "$2" in
*.gz)
    exec $0 --gzip $1 `basename $2 .gz`
    ;;
*.cloop)
    exec $0 --cloop $1 `basename $2 .cloop`
    ;;
RECOMMENDED)
    exec $0 $1 `get_recommendation $1`
    ;;
cpio)
    ;;
cramfs)
    convert_cramfs $1
    ;;
e2compr|e2compr-*)
    E2COMPR_ALGO=`echo $2 | cut -f2 -d-`
    [ -z "$E2COMPR_ALGO" ] && E2COMPR_ALGO='gzip9'
    convert_ext $1 2
    convert_ext $1 2
    ;;
ext2)
    convert_ext $1 2
    ;;
ext3)
    convert_ext $1 3
    ;;
ext4)
    convert_ext $1 4
    ;;
hfs)
    convert_hfs $1
    ;;
hiso)
    convert_iso $1 hfs
    ;;
iso)
    convert_iso $1 eltorito
    ;;
jffs2|jffs2-*)
    convert_jffs2 $1 `echo $2 | cut -f2 -d-`
    ;;
siso)
    convert_iso $1 sparc
    ;;
squashfs)
    convert_squashfs $1
    ;;
vfat)
    convert_vfat $1
    ;;
z*iso)
    exec $0 --zf $1 `echo $2 | sed 's/^z//'`
    ;;
*)
    usage
    ;;
esac
    

case "$POSTCOMPRESS" in
gzip)
    gzip -9 $DSTFILE
    DSTFILE="$DSTFILE.gz"
    ;;
cloop)
    create_compressed_fs -L -1 -B 32K $DSTFILE $DSTFILE.cloop
    if [ $? -ne 0 ]; then
	echo 'create_compressed_fs failed (missing executable?)' 1>&2
	exit 1
    fi
    DSTFILE="$DSTFILE.cloop"
    ;;
esac

SRC_SIZE=`ls -s $1 | awk '{print $1}'`
DST_SIZE=`ls -s $DSTFILE | awk '{print $1}'`
COMP_RATIO=`echo "1k $DST_SIZE 100 * $SRC_SIZE / p" | dc`
printf "\nFinal image size is %uk - %.1f%% of original size (%uk).\n" \
	$DST_SIZE $COMP_RATIO $SRC_SIZE

chown `ls -ld . | awk '{printf "%s:%s\n", $3, $4}'` $DSTFILE
sync
exit 0
