#!/bin/sh
#cmptree: compare directory trees recursively and report the differences.
#this script from: http://www.drdobbs.com/the-shell-corner-cmptree/199103123
#written by Ives Aerts, February 2001.
#Executing the following: cmptree /tmp/dir1 /tmp/dir2
#performs a valid search, but executing: cmptree linkdir1 linkdir2
#displays a "different link targets" message.
#131229 BK: change bash to ash, remove function keyword so will work with busybox sh.
#161029 BK: removed awk, as busybox in /sbin/init snapshot recovery might not have it.

export LANG=C

gettype() {
  if [ -L $1 ]; then
    echo "softlink"
  elif [ -f $1 ]; then
    echo "file"
  elif [ -d $1 ]; then
    echo "directory"
  else
    echo "unknown"
  fi
}

exists() {
  if [ -e $1 -o -L $1 ]; then
    return 0;
  else
    echo "$1 does not exist."
    return 1;
  fi
}

comparefile() {
  cmp -s $1 $2
  if [ $? -gt 0 ]; then
    echo "$1 different from $2"
#  else
#    echo "$1 same as $2"
  fi
  return
}

comparedirectory() {
  local result=0
  for i in `(ls -A $1 && ls -A $2) | sort | uniq`; do
    compare $1/$i $2/$i || result=1
  done
  return $result
}

comparesoftlink() {
  local dest1=`ls -l $1 | tr -s ' ' | cut -f 11 -d ' '`
  local dest2=`ls -l $2 | tr -s ' ' | cut -f 11 -d ' '`
  #161029 removed awk, as busybox in /sbin/init snapshot recovery might not have it.
  #local dest1=`ls -l $1 | awk '{ print $11 }'`
  #local dest2=`ls -l $2 | awk '{ print $11 }'`

  if [ $dest1 = $dest2 ]; then
    return 0
  else
    echo "different link targets $1 -> $dest1, $2 -> $dest2"
    return 1
  fi
}

# compare a file, directory, or softlink
compare() {
  (exists $1 && exists $2) || return 1;

  local type1=$(gettype $1)
  local type2=$(gettype $2)

  if [ $type1 = $type2 ]; then
    case $type1 in
      file)
        comparefile $1 $2
        ;;
      directory)
        comparedirectory $1 $2
        ;;
      softlink)
        comparesoftlink $1 $2
        ;;
      *)
        echo "$1 of unknown type"
        false
        ;;
    esac
  else
    echo "type mismatch: $type1 ($1) and $type2 ($2)."
    false
  fi

  return
}

if [ 2 -ne $# ]; then
cat << EOU
Usage: $0 dir1 dir2
Compare directory trees:
  files are binary compared (cmp)
  directories are checked for identical content
  soft links are checked for identical targets
EOU
  exit 10
fi

compare $1 $2
exit $?
