#!/bin/bash
#
PATH="/bin:/sbin:/usr/bin:/usr/sbin:$PATH"

help() {
less -M << EOF

Press 'q' to Quit, Enter to scroll!

=============================================================================
You can use this script to backup and restore the MBR. v1.7 (11-6-2007)

The (M)aster (B)oot (R)ecord is the first 512 bytes of a hard drive,
you should always have a current backup of the MBR!

To hold the MBR, you can use any media with a filesystem on it,
but the filesystem on the media must be supported by the kernel!

In addition to backing up the MBR of the hard drive you specify, it also
makes a backup of the boot sector from each partition on the hard drive.

Backup MBR from /dev/sda to directory /mbr on usb device /dev/sdb.
# backup-mbr -b -d /mbr sda sdb  "If directory doesn't exist, will create."

Restore MBR to /dev/sda from backup in directory /mbr on /dev/sdb.
# backup-mbr -r -d /mbr sda sdb

Restore boot sector to /dev/sda1 from backup in directory /mbr on /dev/sdb.
# backup-mbr -r -d /mbr sda1 sdb

If you want to backup the MBR to a multi-session CD-R/RW, do this.
# backup-mbr -cd-multi -b -d /mbr sda scd0

You can specify the cd device the old (pre kernel v2.6) way, like this.
# backup-mbr -cd-multi -b -d /mbr sda 0,0,0

You'll need 'cdrecord' and 'mkisofs' installed, and have a CD in the
drive '/dev/scd0', or 0,0,0 etc.

If it's not a multi-session CD-R/RW, do it this way.
# backup-mbr -cd -b -d /mbr sda scd0  "CD will be written multi-session."

The non multi-session CD-RW must be blank, blank it first if it's not.
cdrecord blank=fast dev=/dev/scd0  "You'll loose anything on the CD!"

Or, if you want this script to blank the CD-RW.

# backup-mbr -cd-blank -b -d /mbr sda scd0

Restore MBR to /dev/sda from backup in directory /mbr on /dev/scd0.
# backup-mbr -r -d /mbr sda scd0
=============================================================================
EOF
exit
}

fdisk_mbr() {
echo "You can restore the whole MBR (512 bytes) like this.
dd if=$1.mbr of=/dev/$1 bs=512 count=1

If you just want to restore the MBR boot sector (first 446 bytes), do this.
dd if=$1.mbr of=/dev/$1 bs=446 count=1

If you just want to restore the MBR partition table (last 64 bytes), do this.
dd if=$1.mbr of=/dev/$1 bs=1 count=64 skip=446 seek=446" >/tmp/floppy/$2/mbr-$1.txt

  fdisk -l /dev/$1 >/tmp/floppy/$2/fdisk.$1
  fdisk -ul /dev/$1 >>/tmp/floppy/$2/fdisk.$1
}

sfdisk_mbr() {
  sfdisk -d /dev/$1 >/tmp/floppy/$2/sfdisk.$1
echo "
You can also use sfdisk to restore the MBR partition table.
sfdisk /dev/$1 < sfdisk.$1

Or, you can use the backup-mbr script.

Read sfdisk.$1, but don't edit.

Read fdisk.$1 for a listing of the partition table." >>/tmp/floppy/$2/mbr-$1.txt
}

mbr_cd() {
error() {
  rm -rf /tmp/floppy
  rm -f /tmp/mbr.iso
  cat /tmp/error
  echo
  echo "ERROR! $1"
  rm -f /tmp/error
  exit
}

if ! grep -q -w $2 /proc/partitions ; then
  echo "ERROR! I can't find \`$2' listed in /proc/partitions."
  exit
elif ! echo $2 | grep -q "[a-z]$" ; then
  echo "ERROR! The device \`$2' is not a whole disk."
  exit
fi
  mkdir -p /tmp/floppy/$1
  dd if=/dev/$2 of=/tmp/floppy/$1/$2.mbr bs=512 count=1 1>/dev/null 2>/tmp/error && \
if [ ! $? = 0 ]; then
  rm -rf /tmp/floppy 
  cat /tmp/error
  echo
  echo "ERROR! There was a problem."
  rm -f /tmp/error
  exit
else
  echo
  echo "Copied MBR from \`/dev/$2' for \`$1/$2.mbr' on $3."
  if [ -x "`type -path fdisk`" ]; then
    pt=`fdisk -l /dev/$2 | grep "^/dev/$2" | awk '{print $1}'` 
  for p in $pt ; do
    dev=`echo $p | cut -b 6-10`
    dd if=/dev/$dev of=/tmp/floppy/$1/$dev.bs bs=512 count=1 1>/dev/null 2>/dev/null && \
    echo "Copied boot sector from \`/dev/$dev' for \`$1/$dev.bs' on $3."
  done
    fdisk_mbr $2 $1
  fi
    sfdisk_mbr $2 $1
fi

echo "*** Creating mbr.iso..."

if [ "$cd_multi" = "yes" ]; then
multi="`cdrecord -msinfo dev=$3 2>/tmp/error | head -n 1`"
echo $multi | grep "^[0-9]" | grep -q "[0-9]$" || error=yes 
if [ "$error" = "yes" ]; then
  echo "There's not a multi-session CD in $3."
  exit
fi 
  (cd /tmp/floppy && mkisofs -R -J -o ../mbr.iso -C $multi -M $3 . 1>/dev/null 2>/tmp/error) || error
else
  (cd /tmp/floppy && mkisofs -R -J -o ../mbr.iso . 1>/dev/null 2>/tmp/error) || error
fi

if [ "$cd_blank" = "yes" ]; then
echo "*** Blanking CD..."
cdrecord blank=fast dev=$3 1>/dev/null 2>/tmp/error || error
fi

echo "*** Writing mbr.iso multi-session to $3..."
cdrecord -multi -tao -data dev=$3 /tmp/mbr.iso 1>/dev/null 2>/tmp/error || error

  rm -rf /tmp/floppy
  rm -f /tmp/mbr.iso /tmp/error
  echo "*** Read $1/mbr-$2.txt on $3."
  echo "*** Done!"
  exit
}

if [ -z "$1" ]; then
   help
elif [ "$1" = "-cd" -o "$1" = "-cd-multi" -o "$1" = "-cd-blank" ]; then
if [ ! -x "`type -path cdrecord`" -o ! -x "`type -path mkisofs`" ]; then
   echo "ERROR! I can't find cdrecord and/or mkisofs."
   exit  
else
   if [ "$1" = "-cd-multi" ]; then
     cd_multi=yes
   elif [ "$1" = "-cd-blank" ]; then
     cd_blank=yes
   fi
     shift
     cd=yes
     if echo $5 | grep -q "," ; then
        cd_dev=$5
        dev=$4
     else
        cd_dev=/dev/$5
        dev=$5
     fi
fi
else
dev=$5
fi

if [ "$1" = "-b" -a "$2" = "-d" -a -n "$3" -a -n "$4" -a -n "$5" ]; then

if [ -b "/dev/$4" -a -b "/dev/$dev" ]; then

if [ -n "$cd" ]; then
  mbr_cd $3 $4 $cd_dev $cd_multi $cd_blank 
fi

if ! grep -q -w $4 /proc/partitions ; then
  echo "ERROR! I can't find \`$4' listed in /proc/partitions."
  exit
fi
if ! echo $4 | grep -q "[a-z]$" ; then
  echo "ERROR! The device \`$4' is not a whole disk."
  exit
fi
  umount /tmp/floppy 2>/dev/null
  umount /dev/$5 2>/dev/null
  mkdir -p /tmp/floppy
if ! mount -o rw /dev/$5 /tmp/floppy 1>/dev/null 2>/dev/null ; then 
  echo
  echo "ERROR! I can't mount device \`/dev/$5'!"
  exit
fi
if [ ! -d "/tmp/floppy/$3" ]; then
    mkdir -p /tmp/floppy/$3 || exit
fi
    dd if=/dev/$4 of=/tmp/floppy/$3/$4.mbr bs=512 count=1 1>/dev/null 2>/tmp/error && \
if [ ! $? = 0 ]; then
  umount /tmp/floppy 2>/dev/null && rmdir /tmp/floppy 
  cat /tmp/error
  echo
  echo "ERROR! There was a problem!"
  rm -f /tmp/error
  exit
else
    echo -e "\nCopied MBR from \`/dev/$4' to \`$3/$4.mbr' on /dev/$5."
  if [ -x "`type -path fdisk`" ]; then
    pt=`fdisk -l /dev/$4 | grep "^/dev/$4" | awk '{print $1}'` 
  for p in $pt ; do
    dev=`echo $p | cut -b 6-10`
    dd if=/dev/$dev of=/tmp/floppy/$3/$dev.bs bs=512 count=1 1>/dev/null 2>/dev/null && \
    echo "Copied boot sector from \`/dev/$dev' to \`$3/$dev.bs' on /dev/$5."
  done
    fdisk_mbr $4 $3
  fi
    sfdisk_mbr $4 $3
fi
  umount /tmp/floppy 2>/dev/null && rmdir /tmp/floppy
  echo
  echo "Read $3/mbr-$4.txt on /dev/$5."
  echo "Done!"
  exit
else
  echo
  echo "$0 $1 $2 $3 $4 $5"
  echo "ERROR! I can't find device \`/dev/$4' and/or \`/dev/$5'."
  exit
fi

elif [ "$1" = "-r" -a "$2" = "-d" -a -n "$3" -a -n "$4" -a -n "$5" ]; then
if [ -b "/dev/$4" -a -b "/dev/$5" ]; then
  umount /tmp/floppy 2>/dev/null
  umount /dev/$5 2>/dev/null
if echo $4 | cut -b 4 | grep -q "[1-9]" ; then
  mbr=$4.bs
else
  mbr=$4.mbr
fi
  mkdir -p /tmp/floppy 2>/dev/null
if ! mount -o ro /dev/$5 /tmp/floppy 1>/dev/null 2>/dev/null ; then 
  echo
  echo "ERROR! I can't mount device \`/dev/$5'."
  exit
fi  
if [ ! -s /tmp/floppy/$3/$mbr ]; then
  umount /tmp/floppy 2>/dev/null && rmdir /tmp/floppy 
  echo
  echo "ERROR! There's no \`$3/$mbr' on \`/dev/$5'."
  exit
fi
  if [ "$mbr" = "$4.mbr" ]; then
  echo
  echo "Restoring \`/dev/$4' from MBR backup \`$4.mbr'."
  echo
  echo "Do you just want to restore the boot sector (first 446 bytes), or the" 
  echo "partition table (last 64 bytes), or the whole MBR (512 bytes)?"
  echo
  echo "Answer 1 for boot sector (first 446 bytes)"
  echo "Answer 2 for the whole MBR (512 bytes)"
  echo "Answer 3 for just the partition table (last 64 bytes)"
  echo
  echo -n "Answer 1, 2, or 3 "
  read ans
if [ "$ans" = "1" ]; then
  dd if=/tmp/floppy/$3/$mbr of=/dev/$4 bs=446 count=1 1>/dev/null 2>/tmp/error
if [ ! $? = 0 ]; then
  umount /tmp/floppy 2>/dev/null && rmdir /tmp/floppy 
  cat /tmp/error
  echo
  echo "ERROR! There was a problem."
  rm -f /tmp/error
  exit
fi
  MBR="MBR boot sector (first 446 bytes)"
elif [ "$ans" = "2" ]; then
  dd if=/tmp/floppy/$3/$mbr of=/dev/$4 bs=512 count=1 1>/dev/null 2>/tmp/error
if [ ! $? = 0 ]; then
  umount /tmp/floppy 2>/dev/null && rmdir /tmp/floppy 
  cat /tmp/error
  echo
  echo "ERROR! There was a problem."
  rm -f /tmp/error
  exit
fi
  MBR="whole MBR (512 bytes)"
elif [ "$ans" = "3" ]; then
if [ -x "`type -path sfdisk`" -a -s "/tmp/floppy/$3/sfdisk.$4" ]; then
  sfdisk /dev/$4 < /tmp/floppy/$3/sfdisk.$4 1>/dev/null 2>/tmp/error
else
  dd if=/tmp/floppy/$3/$mbr of=/dev/$4 bs=1 count=64 skip=446 seek=446 1>/dev/null 2>/tmp/error
fi
if [ ! $? = 0 ]; then
  umount /tmp/floppy 2>/dev/null && rmdir /tmp/floppy 
  cat /tmp/error
  echo
  echo "ERROR! There was a problem!"
  rm -f /tmp/error
  exit
fi
  MBR="MBR partition table (last 64 bytes)"
else
  umount /tmp/floppy 2>/dev/null && rmdir /tmp/floppy
  echo
  echo "Cancelled!"
  exit
fi
else
  dd if=/tmp/floppy/$3/$mbr of=/dev/$4 bs=512 count=1 1>/dev/null 2>/tmp/error
if [ ! $? = 0 ]; then
  umount /tmp/floppy 2>/dev/null && rmdir /tmp/floppy 
  cat /tmp/error
  echo
  echo "ERROR! There was a problem."
  rm -f /tmp/error
  exit
fi
  MBR="boot sector ($mbr)"
fi
  umount /tmp/floppy 2>/dev/null && rmdir /tmp/floppy
  blockdev --rereadpt /dev/$4 2>/dev/null
  echo
  echo "Copied $MBR to \`/dev/$4'."
  echo "Done!"
  exit
else
  echo
  echo "$0 $1 $2 $3 $4 $5"
  echo "ERROR! I can't find device \`/dev/$4' and/or \`/dev/$5'."
  exit
fi
else
  help
fi
