Fix permissions updates

Also redirect stderr output on terminal commands for display in
GUI console
diff --git a/gui/action.cpp b/gui/action.cpp
index 75d6c47..1132a20 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -790,11 +790,22 @@
             LOGI("fix permissions started!\n");
 			if (simulate) {
 				simulate_progress_bar();
-			} else
-				PartitionManager.Fix_Permissions();
+			} else {
+				int op_status;
+				if (!PartitionManager.Mount_By_Path("/data", true) || !PartitionManager.Mount_By_Path("/system", true))
+					operation_end(1, simulate);
 
-			LOGI("fix permissions DONE!\n");
-			operation_end(0, simulate);
+				DataManager::SetValue("tw_terminal_command_thread", "./sbin/fix_permissions.sh");
+				DataManager::SetValue("tw_terminal_state", 1);
+				DataManager::SetValue("tw_background_thread_running", 1);
+				op_status = pthread_create(&terminal_command, NULL, command_thread, NULL);
+				if (op_status != 0) {
+					LOGE("Error starting terminal command thread, %i.\n", op_status);
+					DataManager::SetValue("tw_terminal_state", 0);
+					DataManager::SetValue("tw_background_thread_running", 0);
+					operation_end(1, simulate);
+				}
+			}
 			return 0;
 		}
         if (function == "dd")
@@ -956,10 +967,7 @@
 				simulate_progress_bar();
 				operation_end(op_status, simulate);
 			} else {
-				command = "cd \"";
-				command += cmdpath;
-				command += "\" && ";
-				command += arg;
+				command = "cd \"" + cmdpath + "\" && " + arg + " 2>&1";;
 				LOGI("Actual command is: '%s'\n", command.c_str());
 				DataManager::SetValue("tw_terminal_command_thread", command);
 				DataManager::SetValue("tw_terminal_state", 1);
@@ -1187,6 +1195,7 @@
 				keep_going = 0;
 			} else {
 				// Try to read output
+				memset(line, 0, sizeof(line));
 				bytes_read = read(fd, line, sizeof(line));
 				if (bytes_read > 0)
 					ui_print("%s", line); // Display output
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index 034b5cd..c99447f 100644
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -1473,19 +1473,6 @@
 	return 1;
 }
 
-int TWPartitionManager::Fix_Permissions(void) {
-	if (!Mount_By_Path("/data", true))
-		return false;
-
-	if (!Mount_By_Path("/system", true))
-		return false;
-
-	ui_print("Fixing Permissions\nThis may take a few minutes.\n");
-	system("./sbin/fix_permissions.sh");
-	ui_print("Done.\n\n");
-	return true;
-}
-
 //partial kangbang from system/vold
 #ifndef CUSTOM_LUN_FILE
 #define CUSTOM_LUN_FILE "/sys/devices/platform/usb_mass_storage/lun%d/file"
diff --git a/partitions.hpp b/partitions.hpp
index 5a919ae..9a700b8 100644
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -177,7 +177,6 @@
 	virtual void Refresh_Sizes();                                             // Refreshes size data of partitions
 	virtual void Update_System_Details();                                     // Updates fstab, file systems, sizes, etc.
 	virtual int Decrypt_Device(string Password);                              // Attempt to decrypt any encrypted partitions
-	virtual int Fix_Permissions();                                            // Fixes permissions in /system and /data
 	virtual int usb_storage_enable(void);                                     // Enable USB storage mode
 	virtual int usb_storage_disable(void);                                    // Disable USB storage mode
 	virtual void Mount_All_Storage(void);                                     // Mounts all storage locations
diff --git a/prebuilt/fix_permissions.sh b/prebuilt/fix_permissions.sh
index f2c8e2a..6d063f9 100755
--- a/prebuilt/fix_permissions.sh
+++ b/prebuilt/fix_permissions.sh
@@ -15,8 +15,8 @@
 #         /data/data depth recursion is tweaked;
 #         fixed single mode;
 #         functions created for modularity;
-#         logging can be disabled via CLI for more speed; 
-#         runtime computation added to end (Runtime: mins secs); 
+#         logging can be disabled via CLI for more speed;
+#         runtime computation added to end (Runtime: mins secs);
 #         progress (current # of total) added to screen;
 #         fixed CLI argument parsing, now you can have more than one option!;
 #         debug cli option;
@@ -25,13 +25,13 @@
 # v2.02 - ignore com.htc.resources.apk if it exists and minor code cleanups,
 #         fix help text, implement simulated run (-s) [farmatito]
 # v2.03 - fixed chown group ownership output [Kastro]
-
-VERSION="2.03"
+# v2.04 - replaced /system/sd with $SD_EXT_DIRECTORY [Firerat]
+VERSION="2.04"
 
 # Defaults
 DEBUG=0 # Debug off by default
-LOGGING=0 # Logging on by default
-VERBOSE=0 # Verbose on by default
+LOGGING=1 # Logging on by default
+VERBOSE=1 # Verbose on by default
 
 # Messages
 UID_MSG="Changing user ownership for:"
@@ -74,394 +74,402 @@
 SYSSDMOUNT=0
 FP_STARTTIME=$( $DATE +"%m-%d-%Y %H:%M:%S" )
 FP_STARTEPOCH=$( $DATE +%s )
-
+if $TEST "$SD_EXT_DIRECTORY" = ""; then
+    #check for mount point, /system/sd included in tests for backward compatibility
+    for MP in /sd-ext /system/sd;do
+        if $TEST -d $MP; then
+            SD_EXT_DIRECTORY=$MP
+            break
+        fi
+    done
+fi
 fp_usage()
 {
-	$ECHO "Usage $0 [OPTIONS] [APK_PATH]"
-	$ECHO "      -d         turn on debug"
-	$ECHO "      -f         fix only package APK_PATH"	
-	$ECHO "      -l         disable logging for this run (faster)"
-	$ECHO "      -r         remove stale data directories"
-	$ECHO "                 of uninstalled packages while fixing permissions"
-	$ECHO "      -s         simulate only"
-	$ECHO "      -u         check only non-system directories"
-	$ECHO "      -v         disable verbosity for this run (less output)"
-	$ECHO "      -V         print version"
-	$ECHO "      -h         this help"
+   $ECHO "Usage $0 [OPTIONS] [APK_PATH]"
+   $ECHO "      -d         turn on debug"
+   $ECHO "      -f         fix only package APK_PATH"
+   $ECHO "      -l         disable logging for this run (faster)"
+   $ECHO "      -r         remove stale data directories"
+   $ECHO "                 of uninstalled packages while fixing permissions"
+   $ECHO "      -s         simulate only"
+   $ECHO "      -u         check only non-system directories"
+   $ECHO "      -v         disable verbosity for this run (less output)"
+   $ECHO "      -V         print version"
+   $ECHO "      -h         this help"
 }
 
 fp_parseargs()
 {
-	# Parse options
-	while $TEST $# -ne 0; do
-		case "$1" in
-			-d)
-				DEBUG=1
-			;;
-			-f)
-				if $TEST $# -lt 2; then
-					$ECHO "$0: missing argument for option $1"
-					exit 1
-				else
-					if $TEST $( $ECHO $2 | $CUT -c1 ) != "-"; then
-						ONLY_ONE=$2
-						shift;
-					else
-						$ECHO "$0: missing argument for option $1"
-						exit 1
-					fi
-				fi
-			;;
-			-r)
-				REMOVE=1
-			;;
-			-s)
-				SIMULATE=1
-			;;
-			-l)
-				if $TEST $LOGGING -eq 0; then
-					LOGGING=1
-				else
-					LOGGING=0
-				fi
-			;;
-			-v)
-				if $TEST $VERBOSE -eq 0; then
-					VERBOSE=1
-				else
-					VERBOSE=0
-				fi
-			;;
-			-u)
-				NOSYSTEM=1
-			;;
-			-V)
-				$ECHO "$0 $VERSION"
-				exit 0
-			;;
-			-h)
-				fp_usage
-				exit 0
-			;;
-			-*)
-				$ECHO "$0: unknown option $1"
-				$ECHO
-				fp_usage
-				exit 1
-			;;
-		esac
-		shift;
-	done
+   # Parse options
+   while $TEST $# -ne 0; do
+      case "$1" in
+         -d)
+            DEBUG=1
+         ;;
+         -f)
+            if $TEST $# -lt 2; then
+               $ECHO "$0: missing argument for option $1"
+               exit 1
+            else
+               if $TEST $( $ECHO $2 | $CUT -c1 ) != "-"; then
+                  ONLY_ONE=$2
+                  shift;
+               else
+                  $ECHO "$0: missing argument for option $1"
+                  exit 1
+               fi
+            fi
+         ;;
+         -r)
+            REMOVE=1
+         ;;
+         -s)
+            SIMULATE=1
+         ;;
+         -l)
+            if $TEST $LOGGING -eq 0; then
+               LOGGING=1
+            else
+               LOGGING=0
+            fi
+         ;;
+         -v)
+            if $TEST $VERBOSE -eq 0; then
+               VERBOSE=1
+            else
+               VERBOSE=0
+            fi
+         ;;
+         -u)
+            NOSYSTEM=1
+         ;;
+         -V)
+            $ECHO "$0 $VERSION"
+            exit 0
+         ;;
+         -h)
+            fp_usage
+            exit 0
+         ;;
+         -*)
+            $ECHO "$0: unknown option $1"
+            $ECHO
+            fp_usage
+            exit 1
+         ;;
+      esac
+      shift;
+   done
 }
 
 fp_print()
 {
-	MSG=$@
-	if $TEST $LOGGING -eq 1; then
-		$ECHO $MSG | $TEE -a $LOG_FILE
-	else
-		$ECHO $MSG
-	fi
+   MSG=$@
+   if $TEST $LOGGING -eq 1; then
+      $ECHO $MSG | $TEE -a $LOG_FILE
+   else
+      $ECHO $MSG
+   fi
 }
 
 fp_start()
 {
-	if $TEST $SIMULATE -eq 0 ; then
-		if $TEST $( $GREP -c " /system " "/proc/mounts" ) -ne 0; then
-			DEVICE=$( $GREP " /system " "/proc/mounts" | $CUT -d ' ' -f1 )
-			if $TEST $DEBUG -eq 1; then
-				fp_print "/system mounted on $DEVICE"
-			fi
-			if $TEST $( $GREP " /system " "/proc/mounts" | $GREP -c " ro " ) -ne 0; then
-				$MOUNT -o remount,rw $DEVICE /system
-				SYSREMOUNT=1
-			fi
-		else
-			$MOUNT /system > /dev/null 2>&1
-			SYSMOUNT=1
-		fi
-	
-		if $TEST $( $GREP -c " /data " "/proc/mounts" ) -eq 0; then
-			$MOUNT /data > /dev/null 2>&1
-			DATAMOUNT=1
-		fi
-	
-		if $TEST -e /dev/block/mmcblk0p2 && $TEST $( $GREP -c " /sd-ext " "/proc/mounts" ) -eq 0; then
-				$MOUNT /sd-ext > /dev/null 2>&1
-			SYSSDMOUNT=1
-		fi
-	fi	
-	if $TEST $( $MOUNT | $GREP -c /sdcard ) -eq 0; then
-		LOG_FILE="/data/fix_permissions.log"
-	else
-		LOG_FILE="/sdcard/fix_permissions.log"
-	fi
-	if $TEST ! -e "$LOG_FILE"; then
-		> $LOG_FILE
-	fi
-
-	fp_print "$0 $VERSION started at $FP_STARTTIME"
+   if $TEST $SIMULATE -eq 0 ; then
+      if $TEST $( $GREP -c " /system " "/proc/mounts" ) -ne 0; then
+         DEVICE=$( $GREP " /system " "/proc/mounts" | $CUT -d ' ' -f1 )
+         if $TEST $DEBUG -eq 1; then
+            fp_print "/system mounted on $DEVICE"
+         fi
+         if $TEST $( $GREP " /system " "/proc/mounts" | $GREP -c " ro " ) -ne 0; then
+            $MOUNT -o remount,rw $DEVICE /system
+            SYSREMOUNT=1
+         fi
+      else
+         $MOUNT /system > /dev/null 2>&1
+         SYSMOUNT=1
+      fi
+      
+      if $TEST $( $GREP -c " /data " "/proc/mounts" ) -eq 0; then
+         $MOUNT /data > /dev/null 2>&1
+         DATAMOUNT=1
+      fi
+      
+      if $TEST -e /dev/block/mmcblk0p2 && $TEST $( $GREP -c " $SD_EXT_DIRECTORY " "/proc/mounts" ) -eq 0; then
+         $MOUNT $SD_EXT_DIRECTORY > /dev/null 2>&1
+         SYSSDMOUNT=1
+      fi
+   fi
+   if $TEST $( $MOUNT | $GREP -c /sdcard ) -eq 0; then
+      LOG_FILE="/data/fix_permissions.log"
+   else
+      LOG_FILE="/sdcard/fix_permissions.log"
+   fi
+   if $TEST ! -e "$LOG_FILE"; then
+      > $LOG_FILE
+   fi
+   
+   fp_print "$0 $VERSION started at $FP_STARTTIME"
 }
 
 fp_chown_uid()
 {
-	FP_OLDUID=$1
-	FP_UID=$2
-	FP_FILE=$3
-	
-	#if user ownership doesn't equal then change them
-	if $TEST "$FP_OLDUID" != "$FP_UID"; then
-		if $TEST $VERBOSE -ne 0; then
-			fp_print "$UID_MSG $FP_FILE from '$FP_OLDUID' to '$FP_UID'"
-		fi
-		if $TEST $SIMULATE -eq 0; then
-			$CHOWN $FP_UID "$FP_FILE"
-		fi
-	fi
+   FP_OLDUID=$1
+   FP_UID=$2
+   FP_FILE=$3
+   
+   #if user ownership doesn't equal then change them
+   if $TEST "$FP_OLDUID" != "$FP_UID"; then
+      if $TEST $VERBOSE -ne 0; then
+         fp_print "$UID_MSG $FP_FILE from '$FP_OLDUID' to '$FP_UID'"
+      fi
+      if $TEST $SIMULATE -eq 0; then
+         $CHOWN $FP_UID "$FP_FILE"
+      fi
+   fi
 }
 
 fp_chown_gid()
 {
-	FP_OLDGID=$1
-	FP_GID=$2
-	FP_FILE=$3
-	
-	#if group ownership doesn't equal then change them
-	if $TEST "$FP_OLDGID" != "$FP_GID"; then
-		if $TEST $VERBOSE -ne 0; then
-			fp_print "$GID_MSG $FP_FILE from '$FP_OLDGID' to '$FP_GID'"
-		fi
-		if $TEST $SIMULATE -eq 0; then
-			$CHOWN :$FP_GID "$FP_FILE"
-		fi
-	fi
+   FP_OLDGID=$1
+   FP_GID=$2
+   FP_FILE=$3
+   
+   #if group ownership doesn't equal then change them
+   if $TEST "$FP_OLDGID" != "$FP_GID"; then
+      if $TEST $VERBOSE -ne 0; then
+         fp_print "$GID_MSG $FP_FILE from '$FP_OLDGID' to '$FP_GID'"
+      fi
+      if $TEST $SIMULATE -eq 0; then
+         $CHOWN :$FP_GID "$FP_FILE"
+      fi
+   fi
 }
 
 fp_chmod()
 {
-	FP_OLDPER=$1
-	FP_OLDPER=$( $ECHO $FP_OLDPER | cut -c2-10 )
-	FP_PERSTR=$2
-	FP_PERNUM=$3
-	FP_FILE=$4
-	
-	#if the permissions are not equal
-	if $TEST "$FP_OLDPER" != "$FP_PERSTR"; then
-		if $TEST $VERBOSE -ne 0; then
-			fp_print "$PERM_MSG $FP_FILE from '$FP_OLDPER' to '$FP_PERSTR' ($FP_PERNUM)"
-		fi
-		#change the permissions
-		if $TEST $SIMULATE -eq 0; then	
-			$CHMOD $FP_PERNUM "$FP_FILE"
-		fi
-	fi
+   FP_OLDPER=$1
+   FP_OLDPER=$( $ECHO $FP_OLDPER | cut -c2-10 )
+   FP_PERSTR=$2
+   FP_PERNUM=$3
+   FP_FILE=$4
+   
+   #if the permissions are not equal
+   if $TEST "$FP_OLDPER" != "$FP_PERSTR"; then
+      if $TEST $VERBOSE -ne 0; then
+         fp_print "$PERM_MSG $FP_FILE from '$FP_OLDPER' to '$FP_PERSTR' ($FP_PERNUM)"
+      fi
+      #change the permissions
+      if $TEST $SIMULATE -eq 0; then
+         $CHMOD $FP_PERNUM "$FP_FILE"
+      fi
+   fi
 }
-  
+
 fp_all()
 {
-	FP_NUMS=$( $CAT /data/system/packages.xml | $EGREP "^<package.*serId" | $GREP -v framework-res.apk | $GREP -v com.htc.resources.apk | $WC -l )
-	I=0
-	$CAT /data/system/packages.xml | $EGREP "^<package.*serId" | $GREP -v framework-res.apk | $GREP -v com.htc.resources.apk | while read all_line; do
-		I=$( $EXPR $I + 1 )
-		fp_package "$all_line" $I $FP_NUMS
-	done
+   FP_NUMS=$( $CAT /data/system/packages.xml | $EGREP "^<package.*serId" | $GREP -v framework-res.apk | $GREP -v com.htc.resources.apk | $WC -l )
+   I=0
+   $CAT /data/system/packages.xml | $EGREP "^<package.*serId" | $GREP -v framework-res.apk | $GREP -v com.htc.resources.apk | while read all_line; do
+      I=$( $EXPR $I + 1 )
+      fp_package "$all_line" $I $FP_NUMS
+   done
 }
 
 fp_single()
 {
-	FP_SFOUND=$( $CAT /data/system/packages.xml | $EGREP "^<package.*serId" | $GREP -v framework-res.apk | $GREP -v com.htc.resources.apk | $GREP -i $ONLY_ONE | wc -l )
-	if $TEST $FP_SFOUND -gt 1; then
-		fp_print "Cannot perform single operation on $FP_SFOUND matched package(s)."
-	elif $TEST $FP_SFOUND = "" -o $FP_SFOUND -eq 0; then
-		fp_print "Could not find the package you specified in the packages.xml file."
-	else
-		FP_SPKG=$( $CAT /data/system/packages.xml | $EGREP "^<package.*serId" | $GREP -v framework-res.apk | $GREP -v com.htc.resources.apk | $GREP -i $ONLY_ONE )
-		fp_package "${FP_SPKG}" 1 1
-	fi
+   FP_SFOUND=$( $CAT /data/system/packages.xml | $EGREP "^<package.*serId" | $GREP -v framework-res.apk | $GREP -v com.htc.resources.apk | $GREP -i $ONLY_ONE | wc -l )
+   if $TEST $FP_SFOUND -gt 1; then
+      fp_print "Cannot perform single operation on $FP_SFOUND matched package(s)."
+      elif $TEST $FP_SFOUND = "" -o $FP_SFOUND -eq 0; then
+      fp_print "Could not find the package you specified in the packages.xml file."
+   else
+      FP_SPKG=$( $CAT /data/system/packages.xml | $EGREP "^<package.*serId" | $GREP -v framework-res.apk | $GREP -v com.htc.resources.apk | $GREP -i $ONLY_ONE )
+      fp_package "${FP_SPKG}" 1 1
+   fi
 }
 
 fp_package()
 {
-	pkgline=$1
-	curnum=$2
-	endnum=$3
-	CODEPATH=$( $ECHO $pkgline | $SED 's%.* codePath="\(.*\)".*%\1%' |  $CUT -d '"' -f1 )
-	PACKAGE=$( $ECHO $pkgline | $SED 's%.* name="\(.*\)".*%\1%' | $CUT -d '"' -f1 )
-	UID=$( $ECHO $pkgline | $SED 's%.*serId="\(.*\)".*%\1%' |  $CUT -d '"' -f1 )
-	GID=$UID
-	APPDIR=$( $ECHO $CODEPATH | $SED 's%^\(.*\)/.*%\1%' )
-	APK=$( $ECHO $CODEPATH | $SED 's%^.*/\(.*\..*\)$%\1%' )
-	
-	#debug
-	if $TEST $DEBUG -eq 1; then
-		fp_print "CODEPATH: $CODEPATH APPDIR: $APPDIR APK:$APK UID/GID:$UID:$GID"
-	fi
-	
-	#check for existence of apk
-	if $TEST -e $CODEPATH;  then
-		fp_print "Processing ($curnum of $endnum): $PACKAGE..."
-		
-		#lets get existing permissions of CODEPATH
-		OLD_UGD=$( $LS -ln "$CODEPATH" )
-		OLD_PER=$( $ECHO $OLD_UGD | $CUT -d ' ' -f1 )
-		OLD_UID=$( $ECHO $OLD_UGD | $CUT -d ' ' -f3 )
-		OLD_GID=$( $ECHO $OLD_UGD | $CUT -d ' ' -f4 )
-		
-		#apk source dirs
-		if $TEST "$APPDIR" = "/system/app"; then
-			#skip system apps if set
-			if $TEST "$NOSYSTEM" = "1"; then
-				fp_print "***SKIPPING SYSTEM APP ($PACKAGE)!"
-				return
-			fi
-			fp_chown_uid $OLD_UID 0 "$CODEPATH"
-			fp_chown_gid $OLD_GID 0 "$CODEPATH"
-			fp_chmod $OLD_PER "rw-r--r--" 644 "$CODEPATH"
-		elif $TEST "$APPDIR" = "/data/app"; then
-			fp_chown_uid $OLD_UID 1000 "$CODEPATH"
-			fp_chown_gid $OLD_GID 1000 "$CODEPATH"
-			fp_chmod $OLD_PER "rw-r--r--" 644 "$CODEPATH"
-		elif $TEST "$APPDIR" = "/data/app-private"; then
-			fp_chown_uid $OLD_UID 1000 "$CODEPATH"
-			fp_chown_gid $OLD_GID $GID "$CODEPATH"
-			fp_chmod $OLD_PER "rw-r-----" 640 "$CODEPATH"
-		fi
-	else
-		fp_print "$CODEPATH does not exist ($curnum of $endnum). Reinstall..."
-		if $TEST $REMOVE -eq 1; then
-			if $TEST -d /data/data/$PACKAGE ; then
-				fp_print "Removing stale dir /data/data/$PACKAGE"
-				if $TEST $SIMULATE -eq 0 ; then
-					$RM -R /data/data/$PACKAGE
-				fi
-			fi
-		fi
-	fi
-		
-	#the data/data for the package
-	if $TEST -d "/data/data/$PACKAGE"; then   
-		#find all directories in /data/data/$PACKAGE
-		$FIND /data/data/$PACKAGE -type d -exec $LS -ldn {} \; | while read dataline; do
-			#get existing permissions of that directory
-			OLD_PER=$( $ECHO $dataline | $CUT -d ' ' -f1 )
-			OLD_UID=$( $ECHO $dataline | $CUT -d ' ' -f3 )
-			OLD_GID=$( $ECHO $dataline | $CUT -d ' ' -f4 )
-			FILEDIR=$( $ECHO $dataline | $CUT -d ' ' -f9 )
-			FOURDIR=$( $ECHO $FILEDIR | $CUT -d '/' -f5 )
-			
-			#set defaults for iteration
-			ISLIB=0
-			REVPERM=755
-			REVPSTR="rwxr-xr-x"
-			REVUID=$UID
-			REVGID=$GID
-				
-			if $TEST "$FOURDIR" = ""; then
-				#package directory, perms:755 owner:$UID:$GID
-				fp_chmod $OLD_PER "rwxr-xr-x" 755 "$FILEDIR"
-			elif $TEST "$FOURDIR" = "lib"; then
-				#lib directory, perms:755 owner:1000:1000
-				#lib files, perms:755 owner:1000:1000
-				ISLIB=1
-				REVPERM=755
-				REVPSTR="rwxr-xr-x"
-				REVUID=1000
-				REVGID=1000
-				fp_chmod $OLD_PER "rwxr-xr-x" 755 "$FILEDIR"
-			elif $TEST "$FOURDIR" = "shared_prefs"; then
-				#shared_prefs directories, perms:771 owner:$UID:$GID
-				#shared_prefs files, perms:660 owner:$UID:$GID
-				REVPERM=660
-				REVPSTR="rw-rw----"
-				fp_chmod $OLD_PER "rwxrwx--x" 771 "$FILEDIR"
-			elif $TEST "$FOURDIR" = "databases"; then
-				#databases directories, perms:771 owner:$UID:$GID
-				#databases files, perms:660 owner:$UID:$GID
-				REVPERM=660
-				REVPSTR="rw-rw----"
-				fp_chmod $OLD_PER "rwxrwx--x" 771 "$FILEDIR"
-			elif $TEST "$FOURDIR" = "cache"; then
-				#cache directories, perms:771 owner:$UID:$GID
-				#cache files, perms:600 owner:$UID:GID
-				REVPERM=600
-				REVPSTR="rw-------"
-				fp_chmod $OLD_PER "rwxrwx--x" 771 "$FILEDIR"
-			else
-				#other directories, perms:771 owner:$UID:$GID     
-				REVPERM=771
-				REVPSTR="rwxrwx--x"
-				fp_chmod $OLD_PER "rwxrwx--x" 771 "$FILEDIR"
-			fi
-			
-			#change ownership of directories matched
-			if $TEST "$ISLIB" = "1"; then
-				fp_chown_uid $OLD_UID 1000 "$FILEDIR"
-				fp_chown_gid $OLD_GID 1000 "$FILEDIR"
-			else
-				fp_chown_uid $OLD_UID $UID "$FILEDIR"
-				fp_chown_gid $OLD_GID $GID "$FILEDIR"
-			fi
-			
-			#if any files exist in directory with improper permissions reset them
-			$FIND $FILEDIR -type f -maxdepth 1 ! -perm $REVPERM -exec $LS -ln {} \; | while read subline; do
-				OLD_PER=$( $ECHO $subline | $CUT -d ' ' -f1 )
-				SUBFILE=$( $ECHO $subline | $CUT -d ' ' -f9 )
-				fp_chmod $OLD_PER $REVPSTR $REVPERM "$SUBFILE"
-			done
-			
-			#if any files exist in directory with improper user reset them
-			$FIND $FILEDIR -type f -maxdepth 1 ! -user $REVUID -exec $LS -ln {} \; | while read subline; do
-				OLD_UID=$( $ECHO $subline | $CUT -d ' ' -f3 )
-				SUBFILE=$( $ECHO $subline | $CUT -d ' ' -f9 )
-				fp_chown_uid $OLD_UID $REVUID "$SUBFILE"
-			done
-			
-			#if any files exist in directory with improper group reset them
-			$FIND $FILEDIR -type f -maxdepth 1 ! -group $REVGID -exec $LS -ln {} \; | while read subline; do
-				OLD_GID=$( $ECHO $subline | $CUT -d ' ' -f4 )
-				SUBFILE=$( $ECHO $subline | $CUT -d ' ' -f9 )
-				fp_chown_gid $OLD_GID $REVGID "$SUBFILE"
-			done
-		done
-	fi
+   pkgline=$1
+   curnum=$2
+   endnum=$3
+   CODEPATH=$( $ECHO $pkgline | $SED 's%.* codePath="\(.*\)".*%\1%' |  $CUT -d '"' -f1 )
+   PACKAGE=$( $ECHO $pkgline | $SED 's%.* name="\(.*\)".*%\1%' | $CUT -d '"' -f1 )
+   UID=$( $ECHO $pkgline | $SED 's%.*serId="\(.*\)".*%\1%' |  $CUT -d '"' -f1 )
+   GID=$UID
+   APPDIR=$( $ECHO $CODEPATH | $SED 's%^\(.*\)/.*%\1%' )
+   APK=$( $ECHO $CODEPATH | $SED 's%^.*/\(.*\..*\)$%\1%' )
+   
+   #debug
+   if $TEST $DEBUG -eq 1; then
+      fp_print "CODEPATH: $CODEPATH APPDIR: $APPDIR APK:$APK UID/GID:$UID:$GID"
+   fi
+   
+   #check for existence of apk
+   if $TEST -e $CODEPATH;  then
+      fp_print "Processing ($curnum of $endnum): $PACKAGE..."
+      
+      #lets get existing permissions of CODEPATH
+      OLD_UGD=$( $LS -ln "$CODEPATH" )
+      OLD_PER=$( $ECHO $OLD_UGD | $CUT -d ' ' -f1 )
+      OLD_UID=$( $ECHO $OLD_UGD | $CUT -d ' ' -f3 )
+      OLD_GID=$( $ECHO $OLD_UGD | $CUT -d ' ' -f4 )
+      
+      #apk source dirs
+      if $TEST "$APPDIR" = "/system/app"; then
+         #skip system apps if set
+         if $TEST "$NOSYSTEM" = "1"; then
+            fp_print "***SKIPPING SYSTEM APP ($PACKAGE)!"
+            return
+         fi
+         fp_chown_uid $OLD_UID 0 "$CODEPATH"
+         fp_chown_gid $OLD_GID 0 "$CODEPATH"
+         fp_chmod $OLD_PER "rw-r--r--" 644 "$CODEPATH"
+         elif $TEST "$APPDIR" = "/data/app" || $TEST "$APPDIR" = "/sd-ext/app"; then
+         fp_chown_uid $OLD_UID 1000 "$CODEPATH"
+         fp_chown_gid $OLD_GID 1000 "$CODEPATH"
+         fp_chmod $OLD_PER "rw-r--r--" 644 "$CODEPATH"
+         elif $TEST "$APPDIR" = "/data/app-private" || $TEST "$APPDIR" = "/sd-ext/app-private"; then
+         fp_chown_uid $OLD_UID 1000 "$CODEPATH"
+         fp_chown_gid $OLD_GID $GID "$CODEPATH"
+         fp_chmod $OLD_PER "rw-r-----" 640 "$CODEPATH"
+      fi
+   else
+      fp_print "$CODEPATH does not exist ($curnum of $endnum). Reinstall..."
+      if $TEST $REMOVE -eq 1; then
+         if $TEST -d /data/data/$PACKAGE ; then
+            fp_print "Removing stale dir /data/data/$PACKAGE"
+            if $TEST $SIMULATE -eq 0 ; then
+               $RM -R /data/data/$PACKAGE
+            fi
+         fi
+      fi
+   fi
+   
+   #the data/data for the package
+   if $TEST -d "/data/data/$PACKAGE"; then
+      #find all directories in /data/data/$PACKAGE
+      $FIND /data/data/$PACKAGE -type d -exec $LS -ldn {} \; | while read dataline; do
+         #get existing permissions of that directory
+         OLD_PER=$( $ECHO $dataline | $CUT -d ' ' -f1 )
+         OLD_UID=$( $ECHO $dataline | $CUT -d ' ' -f3 )
+         OLD_GID=$( $ECHO $dataline | $CUT -d ' ' -f4 )
+         FILEDIR=$( $ECHO $dataline | $CUT -d ' ' -f9 )
+         FOURDIR=$( $ECHO $FILEDIR | $CUT -d '/' -f5 )
+         
+         #set defaults for iteration
+         ISLIB=0
+         REVPERM=755
+         REVPSTR="rwxr-xr-x"
+         REVUID=$UID
+         REVGID=$GID
+         
+         if $TEST "$FOURDIR" = ""; then
+            #package directory, perms:755 owner:$UID:$GID
+            fp_chmod $OLD_PER "rwxr-xr-x" 755 "$FILEDIR"
+            elif $TEST "$FOURDIR" = "lib"; then
+            #lib directory, perms:755 owner:1000:1000
+            #lib files, perms:755 owner:1000:1000
+            ISLIB=1
+            REVPERM=755
+            REVPSTR="rwxr-xr-x"
+            REVUID=1000
+            REVGID=1000
+            fp_chmod $OLD_PER "rwxr-xr-x" 755 "$FILEDIR"
+            elif $TEST "$FOURDIR" = "shared_prefs"; then
+            #shared_prefs directories, perms:771 owner:$UID:$GID
+            #shared_prefs files, perms:660 owner:$UID:$GID
+            REVPERM=660
+            REVPSTR="rw-rw----"
+            fp_chmod $OLD_PER "rwxrwx--x" 771 "$FILEDIR"
+            elif $TEST "$FOURDIR" = "databases"; then
+            #databases directories, perms:771 owner:$UID:$GID
+            #databases files, perms:660 owner:$UID:$GID
+            REVPERM=660
+            REVPSTR="rw-rw----"
+            fp_chmod $OLD_PER "rwxrwx--x" 771 "$FILEDIR"
+            elif $TEST "$FOURDIR" = "cache"; then
+            #cache directories, perms:771 owner:$UID:$GID
+            #cache files, perms:600 owner:$UID:GID
+            REVPERM=600
+            REVPSTR="rw-------"
+            fp_chmod $OLD_PER "rwxrwx--x" 771 "$FILEDIR"
+         else
+            #other directories, perms:771 owner:$UID:$GID
+            REVPERM=771
+            REVPSTR="rwxrwx--x"
+            fp_chmod $OLD_PER "rwxrwx--x" 771 "$FILEDIR"
+         fi
+         
+         #change ownership of directories matched
+         if $TEST "$ISLIB" = "1"; then
+            fp_chown_uid $OLD_UID 1000 "$FILEDIR"
+            fp_chown_gid $OLD_GID 1000 "$FILEDIR"
+         else
+            fp_chown_uid $OLD_UID $UID "$FILEDIR"
+            fp_chown_gid $OLD_GID $GID "$FILEDIR"
+         fi
+         
+         #if any files exist in directory with improper permissions reset them
+         $FIND $FILEDIR -type f -maxdepth 1 ! -perm $REVPERM -exec $LS -ln {} \; | while read subline; do
+            OLD_PER=$( $ECHO $subline | $CUT -d ' ' -f1 )
+            SUBFILE=$( $ECHO $subline | $CUT -d ' ' -f9 )
+            fp_chmod $OLD_PER $REVPSTR $REVPERM "$SUBFILE"
+         done
+         
+         #if any files exist in directory with improper user reset them
+         $FIND $FILEDIR -type f -maxdepth 1 ! -user $REVUID -exec $LS -ln {} \; | while read subline; do
+            OLD_UID=$( $ECHO $subline | $CUT -d ' ' -f3 )
+            SUBFILE=$( $ECHO $subline | $CUT -d ' ' -f9 )
+            fp_chown_uid $OLD_UID $REVUID "$SUBFILE"
+         done
+         
+         #if any files exist in directory with improper group reset them
+         $FIND $FILEDIR -type f -maxdepth 1 ! -group $REVGID -exec $LS -ln {} \; | while read subline; do
+            OLD_GID=$( $ECHO $subline | $CUT -d ' ' -f4 )
+            SUBFILE=$( $ECHO $subline | $CUT -d ' ' -f9 )
+            fp_chown_gid $OLD_GID $REVGID "$SUBFILE"
+         done
+      done
+   fi
 }
 
 date_diff()
 {
-	if $TEST $# -ne 2; then
-		FP_DDM="E"
-		FP_DDS="E"
-		return
-	fi
-	FP_DDD=$( $EXPR $2 - $1 )
-	FP_DDM=$( $EXPR $FP_DDD / 60 )
-	FP_DDS=$( $EXPR $FP_DDD % 60 )
+   if $TEST $# -ne 2; then
+      FP_DDM="E"
+      FP_DDS="E"
+      return
+   fi
+   FP_DDD=$( $EXPR $2 - $1 )
+   FP_DDM=$( $EXPR $FP_DDD / 60 )
+   FP_DDS=$( $EXPR $FP_DDD % 60 )
 }
 
 fp_end()
 {
-	if $TEST $SYSREMOUNT -eq 1; then
-		$MOUNT -o remount,ro $DEVICE /system > /dev/null 2>&1
-	fi
-	
-	if $TEST $SYSSDMOUNT -eq 1; then
-		$UMOUNT /sd-ext > /dev/null 2>&1
-	fi
-	
-	if $TEST $SYSMOUNT -eq 1; then
-		$UMOUNT /system > /dev/null 2>&1
-	fi
-	
-	if $TEST $DATAMOUNT -eq 1; then
-		$UMOUNT /data > /dev/null 2>&1
-	fi
-	
-	FP_ENDTIME=$( $DATE +"%m-%d-%Y %H:%M:%S" )
-	FP_ENDEPOCH=$( $DATE +%s )
-	
-	date_diff $FP_STARTEPOCH $FP_ENDEPOCH
-	
-	fp_print "$0 $VERSION ended at $FP_ENDTIME (Runtime:${FP_DDM}m${FP_DDS}s)"
+   if $TEST $SYSREMOUNT -eq 1; then
+      $MOUNT -o remount,ro $DEVICE /system > /dev/null 2>&1
+   fi
+   
+   if $TEST $SYSSDMOUNT -eq 1; then
+      $UMOUNT $SD_EXT_DIRECTORY > /dev/null 2>&1
+   fi
+   
+   if $TEST $SYSMOUNT -eq 1; then
+      $UMOUNT /system > /dev/null 2>&1
+   fi
+   
+   if $TEST $DATAMOUNT -eq 1; then
+      $UMOUNT /data > /dev/null 2>&1
+   fi
+   
+   FP_ENDTIME=$( $DATE +"%m-%d-%Y %H:%M:%S" )
+   FP_ENDEPOCH=$( $DATE +%s )
+   
+   date_diff $FP_STARTEPOCH $FP_ENDEPOCH
+   
+   fp_print "$0 $VERSION ended at $FP_ENDTIME (Runtime:${FP_DDM}m${FP_DDS}s)"
 }
 
 #MAIN SCRIPT
@@ -469,8 +477,8 @@
 fp_parseargs $@
 fp_start
 if $TEST "$ONLY_ONE" != "" -a "$ONLY_ONE" != "0" ; then
-	fp_single "$ONLY_ONE"
-else 
-	fp_all
+   fp_single "$ONLY_ONE"
+else
+   fp_all
 fi
 fp_end