#!/bin/sh

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

# Bring in platform specific bits
. /usr/local/share/system_info

# 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='
	'

	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
}

if is_freebsd; then
	# Make text dump freebsd only until we implement saving dumps in linux
	test -e /etc/rc.conf && . /etc/rc.conf
	[ "$dumpdir" = "" ] && dumpdir="$dumpdir"
	textdump=$(get_textdump)
fi

has_ticket_info=false
dont_delete=false
print=false
limit=10000

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.
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

if [ -d "/tmp/middlewared/jobs" ]; then
	echo "** 95%: Compressing Job Logs"
	tar -chf - -C /tmp/middlewared jobs | tar -C $dir -xf -
fi
echo "** 96%: Compressing System Logs"
tar -chf - -C /var log | tar -C $dir -xf -
echo "** 97%: Compressing Debug Files"
tar -chf - -C /var/tmp fndebug | tar -C $dir -xf -
if [ "${limit}" != "-1" ] ; then
	echo "** 97%: Truncating Debug Files"
	truncate_files "${limit}"
fi

if [ -d /var/db/system/cores ]; then
	echo "** 97%: Copying Core Dumps"
	mkdir "$dir/cores"
	find /var/db/system/cores -type f -size -524288c -exec cp {} "$dir/cores/" \;
fi

if is_freebsd; then
	if ! dumpfile_to_submit_exists $dumpdir ; then
		if [ $? = 2 ] ; then
			exit 2
		fi
	else
		echo "** 97%: Compressing Textdump"
		mkdir "$dir/textdump"
		tar -xvf $textdump -C "$dir/textdump"
		cp $dumpdir/info.last "$dir/textdump"
	fi
fi
echo "** 98%: Collecting Additional Information"
if is_linux; then
	path_prefix="/usr"
else
	path_prefix="/usr/local"
	sysctl hw > "$dir/sysctl_hw"
fi
set +e
"$path_prefix"/sbin/dmidecode > "$dir/dmidecode"
"$path_prefix"/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

if is_freebsd; then
	set +e
	ls /dev/ses* 2> /dev/null | while read -r ses; do
		echo "** 98%: Collecting smp_rep_phy_err_log"
		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
fi

echo "** 99%: Compressing Archive"
tar -C $dir/.. -chzf $dir/../ixdiagnose.tgz ixdiagnose

if [ "$actualdump" != "" ] ; then
	touch $actualdump.submitted
fi
