#!/bin/sh
#
# MBR/partition table backup script for rsnapshot
# Copyright (c) 2006 Pieter Hollants <suserpms@hollants.com>
# This file is free software licensed under the GNU Public License (GPL) v2.
#
# This script tries to determine all hard disks that are involved in a
# system (through /etc/fstab) and saves their MBRs (incl. partition table) into
# individual files in the current directory.

DEVS=""
MDDEVS=""
LVMDEVS=""

# Function that processes a given list of devices, looking up the physical devices behind
# them. Recursively called for MD and LVM devices.
function process_devs()
{
	local PHYSDEVS
	local FOUND

	for FILESYSTEM in $@ ; do
		# Physical device on either IDE or SCSI/SATA bus?
		if [ -z "${FILESYSTEM##/dev/hd??}" -o -z "${FILESYSTEM##/dev/sd??}" ] ; then
			FOUND=0
			for DEV in ${DEVS}; do
				if [ "${DEV}" == "${FILESYSTEM%?}" ] ; then
					FOUND=1
					break
				fi
			done
			if [ ${FOUND} == 0 ] ; then    
				DEVS="${DEVS} ${FILESYSTEM%?}"
			fi

		# MD device?
		elif [ -z "${FILESYSTEM##/dev/md?}" ]; then
			PHYSDEVS=`mdadm --detail ${FILESYSTEM} | sed -n '/.*active sync.*/{s/.* //;p}' | tr '\n' ' '`
			FOUND=0
			for MDDEV in ${MDDEVS}; do
				for PHYSDEV in ${PHYSDEVS}; do
					if [ "${PHYSDEV}" == "${MDDEV}" ] ; then
						FOUND=1
						break
					fi
				done
			done
			if [ ${FOUND} == 0 ] ; then 
				process_devs "${PHYSDEVS}"
				MDDEVS="${MDDEVS} ${PHYSDEVS}"
			fi

		# LVM device?
		else
			VGGROUP=`lvdisplay ${FILESYSTEM} 2>/dev/null | sed -n '/VG Name/ s/.* //p'`
			if [ -n "${VGGROUP}" ] ; then
				PHYSDEVS=`vgdisplay -v ${VGGROUP} 2>/dev/null | sed -n '/PV Name/{s/ *$//;s/^.* //;p}' | tr '\n' ' '`
				FOUND=0
				for LVMDEV in ${LVMDEVS}; do
					for PHYSDEV in ${PHYSDEVS}; do
						if [ "${PHYSDEV}" == "${LVMDEV}" ] ; then
							FOUND=1
							break
						fi
					done
				done
				if [ ${FOUND} == 0 ] ; then 
					process_devs "${PHYSDEVS}"
					LVMDEVS="${LVMDEVS} ${PHYSDEVS}"
				fi
			fi
		fi
	done
}

# Fetch interesting filesystems from /etc/fstab
TMPFILE=`mktemp fstab.XXXXX`
sed -f- /etc/fstab >$TMPFILE <<EOT
  s/\t/ /g
  s/ \{1,\}/ /g
  /^$/d
  /^.* \/.* \(ext2\|ext3\|reiserfs\|xfs\|jfs\)/! d
  /.* .* .* .*noauto.*/d
  s/ .*$//
EOT

# Determine actual physical devices
process_devs `cat $TMPFILE`

# Backup MBR and partition table information for those devices
for DEV in ${DEVS}; do
	DISK=`echo ${DEV} | sed 's/\/dev\///'`
	dd if=${DEV} of=${DISK}.mbr bs=512 count=1 2>/dev/null
done

# Clean up
rm ${TMPFILE}
