#!/bin/bash

# Input: an original name $1 and a "redirecting" directory in environment
#        variable $REDIR_DESTDIR.
# Output: Replies on stdout the "new" name, which is the redirected
#         name $REDIR_DESTDIR/$1 if it's to be redirected, else $1.
# It should redirected if it's in a place normally writable only by root
# (e.g., /usr/bin), and NOT redirected if an ordinary user can create it.
# It does NOT redirect already-redirected names, and the redirected name
# need not exist (we might need to create it).  Indeed, $1 need not exist
# (we may need to create it).

# To determine if something should be redirected, I
# once I did tests to see if it was writable, but this requires a more
# complex interface to "know" what should exist, and it fails when running as
# root or as Cygwin.  It's simpler and more reliable to just examine the name.

# Options:
# --read|--override: DO NOT redirect if the redirected name does NOT exist.
#                    In effect, "DESTDIR takes precedence", but otherwise
#                    use the original name.  This is
#                    intended for use when you're reading data/metadata
#                    from an existing file - the redirection only occurs
#                    when there's a file in DESTDIR that overrides it.
#                    It's not clear what to do if the file does not exist
#                    in either DESTDIR or its original location;
#                    for now, we'll return the original location.
# --write|--createparents: If redirecting, create matching parent directories
#                    (going up the directory tree) inside $REDIR_DESTDIR.
#                    Intended for use when you'll be writing data/metadata
#                    (by creating matching directories, it creates a
#                    ready-made place for the eventual file).
#                    This does NOT create the redirected item itself.

IFS=`printf '\n\t'`

# Helper function (recursively called)
# Given original name $1 and name of matching "redirected" directory $2,
# create $2 if $1 exists.  Presumes both are full paths.
# E.G., "/usr/bin" "/tmp/mystuff/usr/bin" might be passed.
make_matching_directories () {
  if [ -d "$1" ] ; then
    if [ -d "$2" ] ; then
      return  # Matching pair exists, do nothing.
    else
      /bin/mkdir -p "$2" || exit
    fi
  else
    # The $1 doesn't exist; recurse up.  Eventually we'll hit "/" which exists.
    original_parent=`dirname "$1"`
    redirected_parent=`dirname "$2"`
    make_matching_directories "$original_parent" "$redirected_parent"
  fi
}

# Process options.
override=0
createparents=0
while [ $# -gt 1 ] ; do
  case "$1" in
    --read|--override)       override=1      ; shift ;;
    --write|--createparents) createparents=1 ; shift ;;
    *) echo "Error, unknown option $1" ; exit 1 ;;
  esac
done

# Process our main parameters.
# Append "/" so that we don't get fooled by different dirs with = prefixes.
canonical_original=`readlink -mn "$1"`/
canonical_redir=`readlink -mn "$REDIR_DESTDIR"`/
declare -i redir_length=${#canonical_redir}

# Determine what to do.
if [ "${canonical_original::$redir_length}" = "$canonical_redir" ] ; then
  # Destination already redirected - don't redirect again.
  echo -n "$1"
else
  case "$canonical_original" in
    /[Uu]sr/tmp/*|/[Tt]mp/*|/[Hh]ome/*|/var/tmp/*|/opt/tmp/*|/[Uu]sers/*)
      # Never redirect.
      echo -n "$1" ;;
    /bin*/*|/boot/*|/dev/*|/etc/*|/lib*/*|/opt/*|/proc/*|/root/*|/sbin*/*|/selinux/*|/share/*|/srv/*|/sys/*|/usr/*|/var/*)
      # If redirection occurs, create REDIR_DESTDIR if it doesn't exist.
      /bin/mkdir -p "$REDIR_DESTDIR"
      newname="${canonical_redir%/}${canonical_original%/}"
      if [ "$override" = 1 -a ! -e "$newname" ]
      then
        # We're doing a "read"-like operation, and DESTDIR doesn't have it,
        # so use the original.  Note: Don't use the variable
        # $canonical_original, it has an extra trailing "/"!
        echo -n "$1"
      else
        if [ $createparents -eq 1 ] ; then
          make_matching_directories `dirname "$canonical_original"` \
                                    `dirname "$newname"`
        fi
        printf "%s" "$newname"
      fi ;;
    *)
      # By default, do not redirect:
      echo -n "$1" ;;
  esac 
fi


