#!/bin/sh

#
# Script to capture debug for system crash reporting.
# This script will make a temp directory and copy diagnostic information
# to it.
#

# If there is a system dataset use it
tmpdir="/var/db/system"
if [ ! -e "${tmpdir}" ]; then tmpdir="/var/tmp"; fi

mydir=`dirname $0`

# get the textdump file. On some systems this is a gzipped
# tarball, so we we check for that here.
get_textdump ()
{
	local textdump

	if [ -e $dumpdir/textdump.tar.last ] ; then
		textdump="$dumpdir/textdump.tar.last"
	elif [ -e $dumpdir/textdump.tar.last.gz ] ; then
		textdump="$dumpdir/textdump.tar.last.gz"
	fi

	echo $textdump
}

# there is a dumpfile in /var/crash
# sets "$actualdump" -> to $dumpdir/textdump.tar.N
dumpfile_to_submit_exists ()
{
	local dumpdir=$1
	local textdump=$(get_textdump)

	# no crashdump at all
	if [ -z "$textdump" -o ! -e "$textdump" ] ; then
		return 1
	fi

	actualdump=$(realpath $textdump)
	if [ $? -gt 0 ] ; then
		echo "can not realpath $textdump" >&2
		return 2
	fi

	# dump already submitted
	if [ -e "$actualdump.submitted" ] ; then
		return 1
	fi
	return 0
}

truncate_files ()
{
	local limit=$1
	local IFS=$'\n'

	for file in $(find $dir -type f -a \
		! -name '*.tar' -a \
		! -name '*.tar.gz' -a \
		! -name '*.tgz' -a \
		! -name '*.gz' -a \
		! -name '*.zip' -a \
		! -name '*.zip' -a \
		! -name '*.gzip' -a \
		! -name '*.bzip' -a \
		! -name '*.bzip2' -a \
		! -name '*.bz2' -a \
		! -name 'dump.txt' -a \
		! -name '*.compressed' -print) ; do
		tmpfile="$(env TMPDIR="${tmpdir}" mktemp /tmp/XXXXXX)"
		tail -n $limit "$file" > "$tmpfile" 2>/dev/null
		if [ $? = 0 ] ; then
			mv "$tmpfile" "$file"
		else
			rm "$tmpfile"
		fi
	done
}

test -e /etc/rc.conf && . /etc/rc.conf
[ "$dumpdir" = "" ] && dumpdir="$dumpdir"

has_ticket_info=false
dont_delete=false
print=false
limit=10000
textdump=$(get_textdump)

while getopts "Fd:psl:" opt ; do
	case "${opt}" in
	d)	topdir=$OPTARG
		;;
	s)	dont_delete=true
		;;
	l)	limit=$OPTARG
		;;
	p)	print=true
		;;
	\?)	exit 2
		;;
	esac
done

# Make our staging directory.
# We will then make a directory called ixdiagnose under it
# so that the tarball extracts nicely.
set -x
if [ -z "${topdir}" ] ; then
	topdir=`env TMPDIR="${tmpdir}" mktemp -d -t ixdiagnose`
else
	mkdir -p "${topdir}"
fi
if [ $? -gt 0 ] ; then
	echo "can't make temp directory"
	exit 1
fi

# Remove the temp directory on exit if dont_delete is false
if ! $dont_delete ; then
	trap "rm -rfx $topdir" EXIT
fi

dir=$topdir/ixdiagnose

set -e
mkdir -p $dir
if [ $? -gt 0 ] ; then
	echo "can't make ixdiagnose directory"
	exit 1
fi

if ! $print ; then
	$mydir/freenas-debug -A > /tmp/ixdiagnose.diagnose
else
	$mydir/freenas-debug -A
fi

tar -cHf - -C /var log | tar -C $dir -xf -
tar -cHf - -C /var/tmp fndebug | tar -C $dir -xf -
if [ "${limit}" != "-1" ] ; then
	truncate_files "${limit}"
fi

if ! dumpfile_to_submit_exists $dumpdir ; then
	if [ $? = 2 ] ; then
		exit 2
	fi
else
	mkdir "$dir/textdump"
	tar -xvf $textdump -C "$dir/textdump"
	cp $dumpdir/info.last "$dir/textdump"
fi

set +e
/usr/local/sbin/dmidecode > "$dir/dmidecode"
sysctl hw > "$dir/sysctl_hw"
/usr/local/bin/cpuid > "$dir/cpuid"
set -e

if [ -d /root/syslog ]; then
        cp -R /root/syslog "$dir"
fi

if [ -d /data/crash ]; then
	cp -R /data/crash "$dir"
fi

if [ -f /etc/hostid ] ; then
	cp /etc/hostid "$dir/hostid"
fi

if [ -f /etc/version ] ; then
	cp /etc/version "$dir/version"
fi

set +e
ls /dev/ses* 2> /dev/null | while read -r ses; do
	name=$(echo ${ses}|cut -d "/" -f 3)
	/sbin/camcontrol smpphylist ${ses} > "$dir/smpphylist.${name}"
	/usr/local/bin/smp_rep_phy_err_log ${ses} > "$dir/smp_rep_phy_err_log.${name}"
	cat $dir/smpphylist.${name} | tail -n +3 | while read -r num val desc; do
		if [ -n "${desc}" ]; then
			/usr/local/bin/smp_rep_phy_err_log ${ses} -p ${num} > "$dir/smp_rep_phy_err_log.${name}.${num}"
		fi
	done
done
set -e

tar -C $dir/.. -cHzf $dir/../ixdiagnose.tgz ixdiagnose
if [ "$actualdump" != "" ] ; then
	touch $actualdump.submitted
fi
