#!/bin/bash

DBG_CMDS="/sbin/debugreiserfs -q 2>/dev/null "
DBG_CMDS="/sbin/debugreiserfs -q "
usage()
{
  echo "usage: "
}

# format int var ($1) to string in length of $2
# final string is saved into $3
Int2StrLen()
{
  local value=$1
  local length=$2

  local i=1
  local str=$3

  local tmp=""

  while [ $value -ge 10 ]
  do
    i=`expr $i + 1`
    value=`expr $value \/ 10`
  done

  while [ `expr $length - $i ` -gt 0 ]
  do
    tmp=${tmp}"0"
    i=`expr $i + 1`
  done

  eval ${str}=${tmp}"${1}"
}

# collect data including:
#   debugreiserfs output:
#     -d: blocks details of the internal tree
#     -m: bitmap blocks
#     -o: objectid map
#     -S: handle all blocks, not only used
#     -D: blocks details of all used blocks
#   block data of all data blocks (LEAF and INTERNAL node)
#
# args:
#   $1: device name
#   $2: name suffix
#   $3: sequence 
CollectData()
{
  local dev=$1
  local suffix=$2 
  local seq=$3
  local seqstr=""
  local num=0
  local numstr=""

  local block_size
  local root_node

  $DBG_CMDS $dev
  if [ $? -ne 0 ]
  then
    echo "cannot access the device of $dev using the command of $DBG_CMDS"
    exit 1
  fi

  block_size=`$DBG_CMDS $dev 2>/dev/null | grep "^Blocksize:" | cut -d" " -f2`
  root_node=`$DBG_CMDS $dev 2>/dev/null | grep "^Root block:" | cut -d" " -f3`

  Int2StrLen $seq 4 seqstr  

  for option in d m o s D
  do
    Int2StrLen $num 2 numstr

    $DBG_CMDS $dev -$option 2>/dev/null 1>${seqstr}.FS.${numstr}.-${option}.${suffix}

    num=`expr $num + 1`
  done
  
  for block in `$DBG_CMDS $dev 2>/dev/null -d | egrep  "^LEAF|^INTERNAL" | cut -d"(" -f2 | cut -d")" -f1`
  do
    grep "^${block}$" blocklist
    if [ $? -ne 0 ]
    then
      echo "${block}" >> blocklist
    fi

    dd if=${dev} bs=${block_size} count=1 skip=${block} of=${seqstr}.BLK.${block}.${suffix}
  done

  dd if=${dev} bs=${block_size} count=1 skip=${root_node} of=${seqstr}.BLK.rootblock.${suffix}

  for block in `cat blocklist`
  do
    dd if=${dev} bs=${block_size} count=1 skip=${block} of=${seqstr}.BLK.${block}.${suffix}_ALL
  done

#  for blockfile in *BLK*
#  do
#    hexdump -C $blockfile > ${blockfile}.hex
#  done
}

IsEmptyDir()
{
  lines=`ls $1 | wc -l`

  if [ "$lines" == "0" ]
  then
    return 1
  else
    return 0
  fi
}

cpfiles()
{
  local item=$1
  shift
  local dest=$1
  shift
  local entry
  local dest

  if [ ! -e $item ]
  then
    echo "error, no such $item"
    exit 1
  fi

  if [ -d $item ]
  then
    mkdir ${dest}/${item}
    touch -r $item ${dest}/${item}

    [ $1 ] && $*
    suffix=`echo $item | sed -e "s^${mount_dir}^^g" | sed -e "s^/^__^g"`".copy"
    CollectData $device $suffix $number
    number=`expr $number + 1`

    IsEmptyDir $item
    if [ $? -eq 1 ]
    then
      return 0
    fi

    for entry in ${item}/*
    do
      cpfiles $entry $dest
    done

    return 0
  fi

  if [ ! -d $item ]
  then
    cp -p $item ${dest}/${item}
    touch -r $item ${dest}/${item}

    [ $1 ] && $*
    suffix=`echo $item | sed -e "s^${mount_dir}^^g" | sed -e "s^/^__^g"`".copy"
    CollectData $device $suffix $number
    number=`expr $number + 1`

    return 0
  fi

  return 0
}

rmfiles()
{
  local item=$1
  shift
  local entry

  if [ ! -e $item ]
  then
    echo "error, no such $item"
    exit 1
  fi

  if [ ! -d $item ]
  then
    rm -f $item

    [ $1 ] && $*
    suffix=`echo $item | sed -e "s^${mount_dir}^^g" | sed -e "s^/^__^g"`".unlink"
    CollectData $device $suffix $number
    number=`expr $number + 1`

    return 0
  fi

  IsEmptyDir $item
  if [ $? -eq 1 ]
  then
    rmdir $item

    [ $1 ] && $*
    suffix=`echo $item | sed -e "s^${mount_dir}^^g" | sed -e "s^/^__^g"`".rmdir"
    CollectData $device $suffix $number
    number=`expr $number + 1`

    return 0
  fi

  for entry in ${item}/*
  do
    rmfiles $entry
  done

  rmdir $item

  [ $1 ] && $*
  suffix=`echo $item | sed -e "s^${mount_dir}^^g" | sed -e "s^/^__^g"`".rmdir"
  CollectData $device $suffix $number
  number=`expr $number + 1`

  return 0
}

device="/dev/sda4"
mount_dir="/tmp/test"
number=1
testfile=`pwd`/reiserfsprogs-3.6.19.tar.gz
file_dir=`pwd`/reiserfsprogs-3.6.19

> blocklist

if [ ! -f $testfile ]
then
  echo "Cannot find the test tarball: $testfile"
  exit 1
fi

if [ ! -e $file_dir ]
then
  mkdir -p $file_dir
fi

tar -zxf $testfile

# clean up all the data on the partition 
umount $device
dd if=/dev/zero of=$device

# make a new reiserfs and collect the data before mounting it
echo y | mkreiserfs  $device
CollectData $device "formatted" $number
number=`expr $number + 1`

# collect the data of a new mountted partition
mount $device $mount_dir
CollectData $device "mountted" $number
number=`expr $number + 1`

cpfiles `basename $file_dir` $mount_dir 

rmfiles ${mount_dir}/`basename $file_dir` 

for i in *BLK*ALL
do
  hexdump -C $i > $i.hex
done


