#!/bin/sh

DIRLIST="/etc /usr/syno/etc /tmp/space"
SZF_MSG="/var/log/messages* /var/log/*.result /var/log/syno*.log /var/log/memtester.log /var/run/dmesg.boot /etc.defaults/VERSION /var/log/cstn/* /var/log/log.* /var/log/surveillance.log* /var/log/rsync.error* /var/log/*.state /var/log/ddnsd.* /etc/firewall/* /etc/tc/* /etc/fw_security/* /etc/firewall_* /etc/tc_* /tmp/ddns.* /var/lib/nfs/*tab /tmp/usbdebug /var/lib/bluetooth/*"
# copy synolog file
f=`get_key_value /etc/synolog.conf syslogfile`
if [ $? -eq 1 -a "$f" != "/var/log/synosys.log" ]; then
	SZF_MSG="$SZF_MSG $f"
fi

PROCFILES="/proc/usb/devices /proc/scsi/scsi /proc/partitions /proc/mdstat /proc/mtd /sys/class/scsi_host/host*/syno_pm_info /proc/net/dev /proc/net/route /proc/mounts /proc/meminfo /proc/swaps /proc/vmstat /proc/cpuinfo /proc/interrupts /proc/uptime /proc/cmdline /proc/bus/usb/devices"

# File list to exclude. This list is FILE base, if you want to exclude a whole
# dir, add '*' to match all in the dir.
EXCLUDE_LIST=/tmp/.synomsg_exclude.list.$$
exclude_dir_but_add() { # <exclude dir> <include pattern>
	local dir=$1 pattern=$2
	/usr/bin/find $dir | /bin/grep -v "$pattern"
}
create_exclude_list() {
	/bin/cat > $EXCLUDE_LIST <<EOF
/etc/ddns.conf
/etc/hostapd/stainfo.sh
/etc/mt-daapd.conf
/etc/portforward/router_upnp.db
/etc/portforward/routerdb/*
/etc/ppp/chap-secrets
/etc/ppp/pap-secrets
/etc/rsyncd.secrets
/etc/shadow
/etc/synoinfo.conf
/etc/myds.conf
/usr/syno/etc/.tunnel_passwd
/usr/syno/etc/audio/password.json
/usr/syno/etc/packages/AudioStation/password.json
/usr/syno/etc/ddnsreg.conf
/usr/syno/etc/download/host.conf
/usr/syno/etc/packages/DownloadStation/download/host.conf
/usr/syno/etc/packages/iTunesServer/mt-daapd.conf
/usr/syno/etc/indexdb/*
/usr/syno/etc/iscsi_acl.conf
/usr/syno/etc/iscsi_target.conf
/usr/syno/etc/openldap/data/*
/usr/syno/etc/openldap/schema/*"
/usr/syno/etc/private/ldap.secret
/usr/syno/etc/private/ldapbrowser.conf
/usr/syno/etc/private/secrets.tdb*
/usr/syno/etc/private/smbpasswd
/usr/syno/etc/ssl/*
/usr/syno/etc/synosms.conf
/usr/syno/etc/synosyslog/keys/*
/usr/syno/etc/synosyslog/client_key/*
/usr/syno/etc/synovpn/openvpn/keys/*
/usr/syno/etc/usb.map
/usr/syno/etc/wireless.conf
$(exclude_dir_but_add '/usr/syno/etc/amule/*' 'amule.conf$')
$(exclude_dir_but_add '/usr/syno/etc/packages/DownloadStation/amule/*' 'amule.conf$')
$(exclude_dir_but_add '/usr/syno/etc/audio/radio/*' '\(userdef\|favorite\).json$')
$(exclude_dir_but_add '/usr/syno/etc/packages/AudioStation/radio/*' '\(userdef\|favorite\).json$')
$(exclude_dir_but_add '/etc/ssh/*' 'sshd_config$')
EOF
}
create_exclude_list

if [ -z "$1" ]; then
	TAR_FILE="/tmp/msg.tar.gz"
else
	TAR_FILE="$1"
fi

SZD_TMP="`dirname ${TAR_FILE}`/@`date +%s`.$$"
TMP_LIST=""
copy_proc_to_tmp()
{
	local file=$1 dir=
	[ -r "$file" ] || return 1
	dir=${SZD_TMP}/`/usr/bin/dirname "$file"`
	[ -w "$dir" ] || /bin/mkdir -p "$dir"
	/bin/cp -f $file ${SZD_TMP}/$file
}
copy_and_filter_out() { # <fileter pattern> <file>
	local pattern=$1 file=$2 dir=
	[ -r "$file" ] || return 1
	dir=${SZD_TMP}/`/usr/bin/dirname "$file"`
	[ -w "$dir" ] || /bin/mkdir -p "$dir"
	/bin/grep -v "$pattern" "$file" > ${SZD_TMP}/${file}

	# concate file list for later `ls -l', because the grep command can
	# not restore original file stat like mtime.
	# FIXME if file name include white space, this list will be wrong
	TMP_LIST="$TMP_LIST $file"
}

gen_cmd_result() {
	local SZ_CMD="dmesg df free ifconfig iwconfig"
	local UPS_V_SERVER="localhost"

	/bin/rm -f /var/log/*.result

	# Runtime commands
	for cmd in $SZ_CMD; do
		`/usr/bin/which $cmd` > /var/log/$cmd.result
	done

	/bin/ps -w > /var/log/ps.result

	mv /etc/mtab /etc/mtab.$$
	/bin/ln -s /proc/mounts /etc/mtab
	/bin/df > /var/log/df2.result
	rm /etc/mtab
	mv /etc/mtab.$$ /etc/mtab

	# collect all nfs mount clients
	/usr/sbin/showmount --all > /var/log/showmount.result

	/usr/bin/top -b -n 1 > /var/log/top.result
	route -n > /var/log/route.result

	if [ -x /usr/syno/bin/spacetool ]; then
		/usr/syno/bin/spacetool --synoblock-enum > /var/log/synoblock_enum.result
	fi

	for i in $(ls /sys/class/net); do
		[ "$i" = "bonding_masters" ] && continue
		/usr/syno/bin/ethtool $i &> /var/log/ethtool.$i.result
	done

	# network and firewall related information
	/bin/netstat -neap > /var/log/netstat.result
	/sbin/iptables-save > /var/log/iptables-save.result

	# samba related information
	/usr/syno/bin/smbstatus -v > /var/log/smbstatus.result

	# core-dump file list
	/bin/ls -al /volume1/*.core > /var/log/core-files.result

	# for upnp router info
	/usr/syno/bin/synoupnp -m > /var/log/upnp-info.result
	/usr/syno/bin/synoupnp -i >> /var/log/upnp-info.result
	/usr/syno/bin/synoupnp -l >> /var/log/upnp-info.result

	# for Bluetooth info
	/usr/syno/bin/hciconfig -a > /var/log/bluetooth-hciconfig.result

	# for upsc info
	case `/usr/syno/bin/synogetkeyvalue /etc/synoinfo.conf ups_mode`  in
		slave)
		UPS_V_SERVER=`/usr/syno/bin/synogetkeyvalue /etc/synoinfo.conf upsslave_server`
		;;
	esac
	/usr/syno/bin/upsc ups@$UPS_V_SERVER > /var/log/upsc.result

	# for wireless info
	[ -f /usr/syno/sbin/rfkill ] && /usr/syno/sbin/rfkill list all > /var/log/rfkill.result
	: > /var/log/wifi_signal_antenna.result
	for wsa in `ls /proc/sys/kernel/syno_wifi_signal_antenna*` ;
	do
		/bin/cat $wsa > /var/log/wifi_signal_antenna.result
	done

}
IsMvSocDriver() {
	local KernelVersion Chip
	if [ -z "$1" ]; then
		return 255
	fi
	KernelVersion=`/bin/uname -r | cut -d'.' -f-2`
	if [ "x$KernelVersion" = "x2.4" ]; then
		return 0
	fi
	Chip=`/bin/cat /sys/block/$1/device/../../scsi*/proc_name`
	if [ "x$Chip" = "xmvSata" ]; then
		return 1
	fi
	return 0
}
gen_raid_result() {
	local SZF_RAID_RESULT="/var/log/raid_superblock_enum.result"
	local SZF_SFDISK_RESULT="/var/log/sfdisk_enum.result"

	local i D N ret

	for i in `cat /proc/partitions | awk '{print $4}'`;
	do
		if [ ! -e /dev/$i ]; then
			continue;
		fi
		if [ -x /sbin/mdadm ]; then
			echo "$i:" >> $SZF_RAID_RESULT
			/sbin/mdadm -E -b /dev/$i >> $SZF_RAID_RESULT
			echo "" >> $SZF_RAID_RESULT
		fi
		# seperate sdXXyy to D=sdXX N=yy
		D=""
		N=""

		case "$i" in
		    hd*)
		    `echo $i | sed -n 's/hd\([a-z]*\)\([0-9]*\)/eval D=hd\1; eval N=\2;/p'`
		    ;;
		    sd*)
		    `echo $i | sed -n 's/sd\([a-z]*\)\([0-9]*\)/eval D=sd\1; eval N=\2;/p'`
		    ;;
		    sas*)
		    `echo $i | sed -n 's/sas\([0-9]*\)\(p[0-9]*\)/eval D=sas\1; eval N=\2;/p'`
		    ;;
		esac

		if [ ! -z $N ]; then
			# Partition Info for sdXXyy
			/sbin/sfdisk -l -uS -N$N /dev/$D >> $SZF_SFDISK_RESULT
			if [ $? -ne 0 ]; then
				echo "/dev/$D$N error" >> $SZF_SFDISK_RESULT
			fi
		elif [ ! -z $D ]; then
			# SMART test for sdXX
			IsMvSocDriver $D
			ret=$?
			if [ $ret -eq 0 ]; then
				/usr/syno/bin/smartctl -a -d ata /dev/$D > /var/log/smart_$D.result
			elif [ $ret -eq 1 ]; then
				/usr/syno/bin/smartctl -a -d marvell /dev/$D > /var/log/smart_$D.result
			fi
		fi
	done
}

gen_tc_result()
{
	local interfaces=`ifconfig | grep "Link encap" | awk '{print $1}'`
	local tc_log="/var/log/tc.result"

	echo "" > $tc_log

	for tc_if in $interfaces ;
	do
		echo "==== $tc_if ====" >> $tc_log
		echo "qdisc:" >> $tc_log
		/usr/sbin/tc qdisc show dev $tc_if >> $tc_log

		echo "class:" >> $tc_log
		/usr/sbin/tc class show dev $tc_if >> $tc_log

		echo "filter:" >> $tc_log
		/usr/sbin/tc filter show dev $tc_if >> $tc_log
	done
}

gen_smb_dig_result()
{
	local dig_log="/var/log/smb-dig.result"

	echo "" > $dig_log

	if [ "x`synogetkeyvalue /usr/syno/etc/smb.conf security`" == "xads" ]; then
		FQDN=`synogetkeyvalue /usr/syno/etc/smb.conf realm`

		echo "==== /usr/syno/named/bin/dig ns $FQDN ====" >> $dig_log
		/usr/syno/named/bin/dig ns $FQDN >> $dig_log
		echo "==== /usr/syno/named/bin/dig srv _kerberos._tcp.$FQDN ====" >> $dig_log
		## query kerberos srv record
		/usr/syno/named/bin/dig srv _kerberos._tcp.$FQDN >> $dig_log
		echo "==== /usr/syno/named/bin/dig srv _ldap._tcp.$FQDN ====" >> $dig_log
		## query ldap srv record
		/usr/syno/named/bin/dig srv _ldap._tcp.$FQDN >> $dig_log
	fi
}

gen_asound_result()
{
	local base_dir="/proc/asound"

	if [ -d ${base_dir} ]; then
		local card_dir=`ls -d ${base_dir}/card* | sed '/[0-9]$/!d'`
		for card in ${card_dir}; do
			copy_proc_to_tmp "${card}/stream0"
			local sub_dir=`ls -d ${card}/pcm0p/sub* | sed '/[0-9]$/!d'`
			for sub in ${sub_dir}; do
				local sub_list=`ls -d ${sub}/*`
				for sub_file in ${sub_list}; do
					copy_proc_to_tmp "${sub_file}"
				done
			done
		done
	fi
}

gen_cmd_result
gen_raid_result
gen_tc_result
gen_smb_dig_result
gen_asound_result

/bin/mkdir -p "$SZD_TMP"
for f in $PROCFILES; do
	copy_proc_to_tmp "$f"
done
copy_and_filter_out "\(download_[a-z]*_password\|smspass\|eventpasscrypted\)=" /etc/synoinfo.conf
copy_and_filter_out "\(download_[a-z]*_password\)=" /usr/syno/etc/packages/DownloadStation/settings.conf
copy_and_filter_out "^\[" /usr/syno/etc/iscsi_acl.conf
copy_and_filter_out "\(username\|password\)" /usr/syno/etc/iscsi_target.conf
copy_and_filter_out "passwd=" /usr/syno/etc/synosms.conf
copy_and_filter_out "passwd=" /etc/ddns.conf
/bin/ls -l $TMP_LIST >> "$SZD_TMP/grep_files.list"

if [ -f /usr/syno/synoha/etc.defaults/rc.ha ]; then
	/usr/syno/synoha/etc.defaults/rc.ha get-ha-debug-info $SZD_TMP &> /dev/null
fi

cd "$SZD_TMP"
/bin/rm -f "$TAR_FILE"
/bin/tar cz -X "$EXCLUDE_LIST" -f "$TAR_FILE" $SZF_MSG $DIRLIST *
cd -
/bin/rm -rf "$SZD_TMP" /var/log/*.result
/bin/rm -f "$EXCLUDE_LIST"

