#!/system/bin/sh
VERSION=0.9.1

# User configurable are of the script:

# Android has the nasty habit to "move" your mounts around. On the TF700T for example, the
# /sdcard folder apears to be mounted under /storage/sdcard but accessed via /sdcard. This
# variable is needed to take care of it:
MOUNT_PREFIX=/storage

# List of local mounts which will be bind-mounted inside the chroot:
ANDROID_TO_LINUX_MOUNTS="/sdcard /Removable/MicroSD"

# base path of the loop devices. The loop n. will be appended. Change this according to your device setup:
LOOP_DEV_BASE=/dev/block/loop

# filesystem used by the images. Must be supported natively by android:
FILESYSTEM=ext2

# Range of loop devide we will try to use:
MIN_LOOP=100
MAX_LOOP=254


# YOU SHOULD NOT CHANGE ANYTHING BELOW THIS LINE

# First of all, check for root user...
if [ "$USER" != "root" ]
then
   echo Must be root to run mount your linux installation!
   exit 0
fi

function usage()
{
   echo LinuxOnAndroid version $VERSION
   echo To use the LinuxOnAndroid script, you must specify a image folder - also called LINUX_BASE
   echo and a command which can be: start, stop, chroot, mount_root
   echo EXAMPLE: $0 gentoo start
   exit 0
}

ACTIONS=
# check parameters...
if [ "$1" = "" ]
then
   usage
elif [ "$2" = "mount_root" ]
then

   ACTIONS="mount_root"

elif [ "$2" = "start" ]
then

   ACTIONS="mount_root mount_images mount_others misc chroot"

elif [ "$2" = "chroot" ]
then

   ACTIONS="chroot"

elif [ "$2" = "stop" ]
then

   ACTIONS="umount"

else
   usage
fi


LINUX_BASE=$MOUNT_PREFIX$(pwd)/$1
MOUNT_BASE=$LINUX_BASE/mnt

if [ "$ACTIONS" = "" ]
then
   usage
fi
if [ ! -d $LINUX_BASE ]
then 
   echo Folder $LINUX_BASE missing
   usage
fi
if [ ! -d $MOUNT_BASE ]
then
   echo Folder $MOUNT_BASE missing
   usage
fi

#DUMMY=echo
#DUMMY_REDIR=\'
DUMMY=
DUMMY_REDIR=



# $1 = name of image file associated to the loop to find
function find_loop_device()
{
   FIND_IMG=$1
   N=$MIN_LOOP
   while [ $N -lt $MAX_LOOP ]
   do
      LOOP_DEVICE=$LOOP_DEV_BASE$N
      # does it exists?
      if [ -e $LOOP_DEVICE ]
      then
         IMG=$(losetup $LOOP_DEVICE | awk '{ print $3 }')                  
         if [ "$IMG" = "$FIND_IMG" ]
         then
            echo Found alredy assigned loop device for image $FIND_IMG n.$N
            return $N
         fi
      fi
      N=$(( N + 1 ))
   done
   return 0
}

# $1 = name of image file associated to the loop to find
function allocate_loop_device()
{
   IMG=$1
   N=$MIN_LOOP
   while [ $N -lt $MAX_LOOP ]
   do
      LOOP_DEVICE=$LOOP_DEV_BASE$N
      # does it exists?
      if [ ! -e $LOOP_DEVICE ]
      then
         echo Found unused loop device on n.$N
         $DUMMY mknod $LOOP_DEVICE b 7 $N
         $DUMMY losetup $LOOP_DEVICE $IMG
         return $N
      fi
      N=$(( N + 1 ))
   done
   return 0
}


# $1 = FULL PATHH to the image file to umount
function umount_image()
{
   IMAGE_FILE=$1
   IMAGE_NAME=$(basename $IMAGE_FILE .img)
   if [ "$IMAGE_NAME" = "root" ]
   then
      MOUNT_PATH=$MOUNT_BASE
   else
      MOUNT_PATH=$MOUNT_BASE/$IMAGE_NAME
   fi
   LOOP_DEVICE=$(mount | grep $MOUNT_PATH | awk '{print $1}')
   if [ -e $LOOP_DEVICE ]
   then
      echo Unmounting image $IMAGE_FILE
      umount $MOUNT_PATH
      echo Releasing loop device $LOOP_DEVICE
      losetup -d $LOOP_DEVICE
      rm -f $LOOP_DEVICE
   else
      echo Image $IMAGE_FILE not mounted
   fi
}  


# $1 = FULL PATHH to the image file to mount
function mount_image()
{
   # First of all, build the mount path:
   IMAGE_FILE=$1
   IMAGE_NAME=$(basename $IMAGE_FILE .img)
   if [ "$IMAGE_NAME" = "root" ]
   then
      MOUNT_PATH=$MOUNT_BASE
   else
      MOUNT_PATH=$MOUNT_BASE/$IMAGE_NAME
   fi

   if [ -d $MOUNT_PATH ]
   then

      # Check if there is a loop device already in place for the image:
      find_loop_device $IMAGE_FILE
      LOOP_NO=$?

      # Is this a valid loop device?
      if [ $LOOP_NO -eq 0 ]
      then
         # well, just setup a new loop device for this image...
         allocate_loop_device $IMAGE_FILE
         LOOP_NO=$?
         if [ $LOOP_NO -eq 0 ]
         then
            echo Unable to allocate loop device for $IMAGE_NAME
            return 0
         fi
         LOOP_DEVICE=$LOOP_DEV_BASE$LOOP_NO
      else
         LOOP_DEVICE=$LOOP_DEV_BASE$LOOP_NO
         # Is it already mounted?
         if [ "$(mount | grep $LOOP_DEVICE)" != "" ]
         then
            echo mount_image: \'$IMAGE_NAME\' already mounted on \'$MOUNT_PATH\'
            return 0
        fi
      fi

      $DUMMY mount -t $FILESYSTEM $LOOP_DEVICE $MOUNT_PATH
      
   else # mount path missing
      echo mount_image: mount point \'$MOUNT_PATH\' does not exist
   fi

   return 0
}




#### Start operations...

# valid actions:
# mount_root mount_images mount_others misc chroot"
for ACTION in $ACTIONS
do
   if [ "$ACTION" = "mount_root" ]
   then
   
      ROOT_IMG=$LINUX_BASE/root.img
      if [ -e $ROOT_IMG ]
      then
         echo Mounting root image...
         mount_image $ROOT_IMG
      fi

   elif [ "$ACTION" = "mount_images" ]
   then

      # First of all, collect all the available images for the $LINUX_BASE.
      IMGS=$(ls $LINUX_BASE/*.img)
      for i in $IMGS
      do
         IMG_NAME=$(basename $i .img)
         if [ "$IMG_NAME" != "root" ]
         then
            echo Setting up $IMG_NAME...
            mount_image $i
         fi
      done
      echo All disk images mounted!

   elif [ "$ACTION" = "mount_others" ]
   then
   
      if [ "$(mount | grep $MOUNT_BASE/dev/pts)" == "" ]
      then
         echo Mounting PTS filesystem...
	 $DUMMY mount -t devpts devpts $MOUNT_BASE/dev/pts
      else
         echo PTS filesystem already mounted
      fi

      if [ "$(mount | grep $MOUNT_BASE/proc)" == "" ]
      then
         echo Mounting PROC filesystem...
	 $DUMMY mount -t proc proc $MOUNT_BASE/proc
      else     
         echo PROC filesystem already mounted
      fi

      if [ "$(mount | grep $MOUNT_BASE/sys)" == "" ]
      then
         echo Mounting SYSFS filesystem...
         $DUMMY mount -t sysfs sysfs $MOUNT_BASE/sys
      else
         echo SYSFS filesystem already mounted
      fi

      echo Mouting all android-linux bridges
      for i in $ANDROID_TO_LINUX_MOUNTS
      do
         MOUNT_DEST=$(basename $i)
         if [ "$(mount | grep $MOUNT_BASE/$MOUNT_DEST)" == "" ]      
         then
            echo Mounting android-linux bind $i...
            $DUMMY mount -o bind $i $MOUNT_BASE/$MOUNT_DEST
         else
             echo Android-linux bridge $i alrready mounted
         fi
      done

   elif [ "$ACTION" = "misc" ]
   then

      if [ "$(sysctl net.ipv4.ip_forward)" != "net.ipv4.ip_forward = 1" ]
      then
         echo Enabling IPv4 forwarding...
         $DUMMY sysctl -w net.ipv4.ip_forward=1
      else
         echo IPv4 Forwarding already enabled
      fi

      if [ -d $MOUNT_BASE/dev ]
      then
         echo Copying contents of /dev to $MOUNT_BASE/dev...
         if [ "$DUMMY" = "" ]
         then
            $DUMMY cp -a /dev/* $MOUNT_BASE/dev 2> /dev/null
         else
            $DUMMY cp -a /dev/\* $MOUNT_BASE/dev 2\> /dev/null
         fi
      fi

      echo Clearing tmp...
      $DUMMY rm -rf $MOUNT_BASE/tmp/*
      $DUMMY rm -rf $MOUNT_BASE/var/tmp/*

      echo Updating mtab....
      if [ "$DUMMY" = "" ]
      then
         mount | grep $MOUNT_BASE | sed 's|'$MOUNT_BASE'||g' > $MOUNT_BASE/etc/mtab      
      else
         $DUMMY mount \| grep $MOUNT_BASE \| sed 's|'$MOUNT_BASE'||g' \> $MOUNT_BASE/etc/mtab      
      fi
      


   elif [ "$ACTION" = "chroot" ]
   then

      echo Chrooting...
      if [ -e $LINUX_BASE/mnt/login.sh ]
      then
         $DUMMY chroot $LINUX_BASE/mnt /login.sh
      else
         echo Maybe you have not installed the tools inside your linux installation?
         echo you should type immediately \"source /etc/profile\" otherwise you will not
         echo even be able to run ls...
         $DUMMY chroot $LINUX_BASE/mnt /bin/bash
      fi

   elif [ "$ACTION" = "umount" ]
   then

      if [ "$(mount | grep $MOUNT_BASE/dev/pts)" != "" ]
      then
         echo Unmounting DEV/PTS...
         $DUMMY umount $MOUNT_BASE/dev/pts
      fi
      if [ "$(mount | grep $MOUNT_BASE/proc)" != "" ]
      then
         echo Unmounting PROC...
         $DUMMY umount $MOUNT_BASE/proc
      fi
      if [ "$(mount | grep $MOUNT_BASE/sys)" != "" ]
      then
         echo Unmounting SYS...
         $DUMMY umount $MOUNT_BASE/sys
     fi
      for i in $ANDROID_TO_LINUX_MOUNTS
      do
         MOUNT_DEST=$(basename $i)
         if [ "$(mount | grep $MOUNT_BASE/$MOUNT_DEST)" != "" ]      
         then
            echo Unmounting android-linux bind $i...
            $DUMMY umount $MOUNT_BASE/$MOUNT_DEST
         fi
      done
      IMGS=$(ls $LINUX_BASE/*.img)
      for i in $IMGS
      do
         IMG_NAME=$(basename $i .img)
         if [ "$IMG_NAME" != "root" ]
         then
            umount_image $i
         fi
      done
      echo All disk images unmounted!
      umount_image $LINUX_BASE/root.img
      echo All partitions unmounted.

   fi

done


