#!/system/bin/sh

license=<<EOF
sp - Switch user Profile. A utility to manage multiple user profiles
on an Android device. Also encrypts user profile data.

Copyright (C) 2011 Steven Dambeck

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

EOF


# Directory to store profile image files
if [[ -d /emmc ]]
then
   PROFILEDIR=/emmc/profiles
elif [[ -d /sdcard ]]
then
   PROFILEDIR=/sdcard/profiles
else
   echo "Error: Could not set profile directory"
   echo "Please set profile directory in $0"
   exit 7
fi

if [[ ! -d "$PROFILEDIR" ]]
then
   mkdir "$PROFILEDIR" || exit 7
fi


FILESYSTEMS="data cache"    # List of filesytems to include in profile
#typeset -i LOOPCOUNT=0           # Needed for bug workaround on Nook Color
LOOPCOUNT=0


getpassphrase()
{
   echo -n "Enter passphrase: "
   stty -echo
   read P1

   echo
   echo -n "Re-enter passphrase: "
   read P2

   stty echo
   echo

   if [[ -z $P1 ]]
   then
      echo "Error: Passphrase is empty."
      exit 1
   fi

   if [[ $P1 != $P2 ]]
   then
      echo "Error: Passphrase did not match."
      exit 1
   fi

   PASSPHRASE="$P1"
}


stopdisplay()
{
   echo Restarting display
   sleep 1

   setprop ctl.stop zygote
   setprop ctl.stop keystore
   setprop ctl.stop dhcpcd
   # Add more here if your device needs it.
   sleep 1
}


startdisplay()
{
   setprop ctl.start keystore
   setprop ctl.start dhcpcd
   setprop ctl.start zygote
   # Add more here if your device needs it.
}



deamonizesetup()
{
   # This script needs to keep running after we stop zygote
   if [[ ! -d "$PROFILEDIR/mnt" ]]
   then
      mkdir "$PROFILEDIR/mnt"
   fi
   
   for F in $FILESYSTEMS
   do
      mount /dev/mapper/$F.crypt $PROFILEDIR/mnt || exit 6
      cp -a /$F/* $PROFILEDIR/mnt || exit 6
      umount $PROFILEDIR/mnt || exit 6
   done

   reboot
}

newsetup()
{
   echo "Creating new profile for $PROFILE"
   echo "Pick a good passphrase. If you forget it, you won't be able to get to your data."
   echo "Sorry, but you're going to have to enter the passphrase several times. Be sure to use the same one."
   getpassphrase
   
   for F in $FILESYSTEMS
   do
      if [[ -e "$PROFILEDIR/$F.$PROFILE" ]]
      then
         echo "Error: file already exist: $PROFILEDIR/$F.$PROFILE"
         echo "I'm not going to overwrite this file. If you are sure it is not needed then delete it and try again."
         exit 3
      fi

      FREESPACE=`df $PROFILEDIR | tail -n 1 | awk '{print $3}'`
      FREESPACE=`expr $FREESPACE / 1024`
      echo "Free space left on $PROFILEDIR is $FREESPACE MB"
      echo -n "Enter size for filesystem $F in MB: "
      read FSSIZE
      
      FSSIZE=`expr $FSSIZE '*' 1024`  # dd bug?
      echo "Creating image file. This may take a few minutes..."
      dd if=/dev/zero of="$PROFILEDIR/$F.$PROFILE" bs=1024k count=$FSSIZE || exit 5
      echo
      
      nextfreeloopbackdev
      echo "Loopback mounting $PROFILEDIR/$F.$PROFILE on $NEXTLOOP"
      losetup $NEXTLOOP "$PROFILEDIR/$F.$PROFILE" || exit 5
      
      echo "Creating encrypted filesystem $F.crypt"
     # ( echo "YES"; echo "$PASSPHRASE"; echo "$PASSPHRASE" ) | cryptsetup luksFormat -c aes-plain $NEXTLOOP
      cryptsetup luksFormat -c aes-plain $NEXTLOOP || exit 5
      cryptsetup status $F.crypt
      echo "$PASSPHRASE" | cryptsetup luksOpen $NEXTLOOP $F.crypt
      echo
      
      echo "Formatting new filesystem $F.crypt"
      mke2fs -O uninit_bg,resize_inode,extent,dir_index -L $F.crypt -FF /dev/mapper/$F.crypt || exit 5
      tune2fs -j /dev/mapper/$F.crypt || exit 5

      echo
   done

   echo "OK. We have new empty encrypted file system created. I'm going to stop the display manager so that files are not in use when I copy them. Your screen will freeze or go dark for while then reboot. This may take several minutes..."
   echo "Press enter to continue."
   read X
   stopdisplay
   nohup $0 deamonizesetup "$PROFILE" "$PASSPHRASE" > /dev/null &
}



usage()
{
   cat <<EOF
Usage: $0 <profile_name>
       $0 setup <profile_name>
EOF
}


checkimages()
{
   # See if image files exist
   for F in $FILESYSTEMS
   do
      if [[ ! -e "$PROFILEDIR/$F.$PROFILE" ]]
      then 
         echo "Error: File $PROFILEDIR/$F.$PROFILE does not exist."
         echo "Did you run $0 setup?"
      exit 2
      fi
   done
}


nextfreeloopbackdev()
{
   # Nook Color running CyanogenMod 7.0.3 doesn't report proper device name
   #   it always returns /dev/loop0. We need to keep track of the next device
   #   here
   
   NEXTLOOP=/dev/block/loop$LOOPCOUNT
   #LOOPCOUNT=LOOPCOUNT+1
   LOOPCOUNT=`expr $LOOPCOUNT + 1`
}


startloopbackfs()
{
   for F in $FILESYSTEMS
   do
      echo Setting up encrypted filesystem $F
      nextfreeloopbackdev
      losetup $NEXTLOOP "$PROFILEDIR/$F.$PROFILE"
      echo $PASSPHRASE | cryptsetup luksOpen $NEXTLOOP $F.crypt
   done
}


mountimages()
{
   for F in $FILESYSTEMS
   do
      if [[ `lsof /$F | wc -l` -gt 1 ]]
      then
         echo "Error: Filesystem $F is still in use."
         lsof $F
      else
         umount /$F && mount /dev/mapper/$F.crypt /$F
      fi
   done
}

deamonize()
{
   # This script needs to keep running after we stop zygote
   stopdisplay
   mountimages
   startdisplay
}


if [[ -z $1 ]]
then 
  usage
  exit
fi

if [[ $1 = "setup" ]]
then
   if [[ -n "$2" ]] 
   then
      PROFILE="$2"
      newsetup
   else
      usage
   fi   
   exit
fi

if [[ $1 = "deamonize" ]]
then
   PROFILE="$2"
   deamonize
   exit
fi

if [[ $1 = "deamonizesetup" ]]
then
   PROFILE="$2"
   PASSPHRASE="$3"
   deamonizesetup
   exit
fi


# Main
PROFILE=$1
checkimages
getpassphrase
startloopbackfs
echo "Display will restart..."
sleep 1
nohup $0 deamonize "$PROFILE" > /dev/null &

exit


