summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Ball <nullspoon@oper.io>2017-10-14 17:02:29 -0600
committerAaron Ball <nullspoon@oper.io>2017-10-14 17:02:29 -0600
commit64b654a46aeb1aee4ee47d8c484a4346b9032e65 (patch)
tree069c07fbdc2dc33655d5858fcb836029fce619d1
parent1d2569958f93d6989c4940cab1bf5263c18a5963 (diff)
downloadandbackup-64b654a46aeb1aee4ee47d8c484a4346b9032e65.tar.gz
andbackup-64b654a46aeb1aee4ee47d8c484a4346b9032e65.tar.xz
backup_app:Add recovery mode support
Previously, this function was dependent on a running android system to get application metadata (eg: data path, code path, etc). Now we assume the defaults in global variables (can update them at a later date to be more intelligent should android change the standard...again). Now, the backup process uses POSIX shell compliant code to execute the backup process, without using android system resources. This enables the backup process to run while the system is in recover (eg: TWRP). NOTE: This is currently dependent on TWRP being the recovery of choice, as it checks for the presence of /sbin/twrp to determine if the system is currently in recovery. Support for other recoveries (are there any others?) can be added at a later date.
-rwxr-xr-xandbackup.sh114
1 files changed, 80 insertions, 34 deletions
diff --git a/andbackup.sh b/andbackup.sh
index 8df40a5..7f5c239 100755
--- a/andbackup.sh
+++ b/andbackup.sh
@@ -23,6 +23,10 @@ backups=/sdcard/andbackup
#backups=/storage/ext_sd/bk/andbackup/andbackupBK
flag_delimiter="-"
+export ANDROID_DATA='/data/data'
+export ANDROID_CODE='/data/app'
+export ANDROID_SYSTEM='/system'
+
usage() {
# NOTE: The maximum width of this text should be 65 chars. This
# will ensure it displays properly on most devices without
@@ -79,48 +83,50 @@ lfatal() {
backup_app() {
- local app=${1:-}
+ local app="${1}"
- # Make sure app is specified
- if [[ -z ${app} ]]; then
- lerror "Please specify an app to backup."
+ if [ -z "${app}" ]; then
+ lerror "Application name required."
return 1
fi
#If app has the flag_delimiter that means options are passed in
local preserveCache=false
- if [[ 0 = $(echo ${app} | grep -q [${flag_delimiter}]; echo $?) ]]; then
+ if [ 0 = $(echo ${app} | grep -q [${flag_delimiter}]; echo $?) ]; then
linfo "This app $app has passed in options"
- if [[ 0 = $(echo ${app} | grep -q "preserveCache"; echo $?) ]]; then
+ if [ 0 = $(echo ${app} | grep -q "preserveCache"; echo $?) ]; then
preserveCache=true
fi
#Need to get app back to std naming (without params)
app=`echo ${app} | grep -o ^.*- | sed s/-//g | cat -`
fi
-
+
# Make sure app is installed
- if [[ $(dumpsys package ${app} | wc -l) -eq 0 ]]; then
+ if [ ! -d "${ANDROID_DATA}/${app}" ]; then
lerror "Package ${app} appears to not be installed."
return 2
fi
linfo "Backing up ${app}"
+ local apk="$(find ${ANDROID_CODE}/${app}-*/base.apk | head -n1)"
+ local data="${ANDROID_DATA}/${app}"
- # Stop the application if it is running
- am force-stop ${app}
-
- # Get pertinent metadata
- local code=$(dumpsys package ${app} | grep codePath | cut -d'=' -f2 | head -n1)
- local data=$(dumpsys package ${app} | grep dataDir | cut -d'=' -f2 | head -n1)
- #linfo HERE is your data dir: $data
+ # No need to stop the application because we're in recovery mode
# Create backup destination if not exist
- [[ ! -d ${backups} ]] && mkdir -p ${backups}
- [[ ! -d ${backups}/${app}/data ]] && mkdir -p ${backups}/${app}/data
+ [ ! -d "${backups}" ] && mkdir -p "${backups}"
+ # Delete data stage directory if it exists so we can start new
+ [ -d "${backups}/${app}/data" ] && rm -rf "${backups}/${app}/data"
# Backup the apk file if it exists
- if [[ -f ${code}/base.apk ]]; then
- cp ${code}/base.apk ${backups}/${app}/base.apk
+ if [ ! -z "${apk}" ]; then
+ # Delete the old backup first
+ # There is a permissions issue querk when the backup was originall taken in
+ # recovery mode, but later is taken in android (Permission denied for no
+ # apparent reason)
+ [ -f "${backups}/${app}/base.apk" ] && rm -f "${backups}/${app}/base.apk"
+ # Copy the installer to the backup dir
+ cp -p "${apk}" "${backups}/${app}/base.apk"
else
linfo "${app} apk file could not be found. Skipping apk installer backup."
fi
@@ -129,16 +135,26 @@ backup_app() {
# backup. This covers a weird edge case where an application is installed but
# hasn't been launched (I think?). The data variable would be empty, causing
# this script to backup /*.
- if [ ! -d "${data:-}" ] || [ -z "${data:-}" ]; then
+ if [ -z "${data}" ] || [ ! -d "${data}" ]; then
lwarn "No data directory for application '${app}' found. Skipping backup."
return 2
fi
+ # Stop the application if it is running
+ # Don't try to stop it if the twrp binary is found. If we're in recovery
+ # mode, the application already isn't running.
+ if [ ! -f /sbin/twrp ]; then
+ linfo "Stopping application ${app}"
+ am force-stop "${app}"
+ else
+ linfo "Skipping application force stop while booted to recovery mode."
+ fi
+
# Copy the user data
- cp -rp ${data}/* ${backups}/${app}/data/
+ cp -rp "${data}" "${backups}/${app}/data"
# Delete cache directory if it exists
# This will sometimes free up significant amounts of space
- if [[ ! -d "${backups}/${app}/data/cache" ]]; then
+ if [ ! -d "${backups}/${app}/data/cache" ]; then
linfo "Cache doesn't exist for ${app}"
elif ! $preserveCache; then
linfo "Deleting cache for ${app}"
@@ -149,13 +165,13 @@ backup_app() {
# Compress the backup
linfo "Compressing userdata for ${app}"
- cd ${backups}/${app}/
+ cd "${backups}/${app}/"
tar -c data | gzip -c > data.tar.gz
rm -rf data
}
-function list_apps {
+list_apps() {
pm list package | cut -d ':' -f 2 | sort
}
@@ -164,11 +180,19 @@ restore_app() {
local app=${1:-}
# Make sure app is specified
- if [[ -z ${app} ]]; then
+ if [ -z "${app}" ]; then
lerror "Please specify an app to restore."
return 1
fi
+ # If twrp binary is found on the filesystem, do not attempt restore as
+ # restores cannot be done without a running system (the various android
+ # binaries don't work right).
+ if [ -f /sbin/twrp ]; then
+ printf "Cannot perform a %s while in recovery mode.\n" "${app}"
+ return 128
+ fi
+
# When restoring something with flags need to restore app alone
if [[ 0 = $(echo ${app} | grep -q [${flag_delimiter}]; echo $?) ]]; then
linfo "This app $app had passed in options"
@@ -221,37 +245,39 @@ restore_app() {
backup_apps() {
local apps=${@}
- [[ -z ${apps[@]:-} ]] && lerror "At least one app is required." && return 1
+ [ -z "${apps}" ] && lerror "At least one app is required." && return 1
- for app in ${apps[@]}; do
- backup_app ${app}
+ IFS=' '
+ for app in ${apps}; do
+ backup_app "${app}"
done
}
restore_apps() {
local apps=${@}
- [[ -z ${apps[@]:-} ]] && log error "At least one app is required." && return 1
+ [ -z "${apps}" ] && log error "At least one app is required.\n" && return 1
- for app in ${apps[@]}; do
- restore_app ${app}
+ IFS=' '
+ for app in ${apps}; do
+ restore_app "${app}"
done
}
list_backup_apps() {
local list=${1:-}
- [[ -z ${list} ]] && printf "A backup list is required." && return 1
+ [[ -z ${list} ]] && printf "A backup list is required.\n" && return 1
for app in $(cat ${list}); do
- backup_app ${app}
+ backup_app "${app}"
done
}
list_restore_apps() {
local list=${1}
- [[ -z ${list} ]] && printf "A backup list is required." && return 1
+ [[ -z ${list} ]] && printf "A backup list is required.\n" && return 1
for app in $(cat ${list}); do
restore_app ${app}
@@ -259,6 +285,25 @@ list_restore_apps() {
}
+verify_system() {
+ if [ ! -d "${ANDROID_DATA}" ]; then
+ printf "Data directory (%s) not found.\n" ${ANDROID_DATA} >&2
+ printf "Is it mounted?\n" >&2
+ return 1
+ fi
+ if [ ! -d "${ANDROID_CODE}" ]; then
+ printf "Application code directory (%s) not found.\n" ${ANDROID_CODE} >&2
+ printf "Is it mounted?\n" >&2
+ return 1
+ fi
+ if [ ! -d "${ANDROID_SYSTEM}/etc" ]; then
+ printf "System partition (%s) is not mounted.\n" ${ANDROID_SYSTEM} >&2
+ return 1
+ fi
+ return 0
+}
+
+
main() {
local cmd=${1:-}
shift
@@ -269,6 +314,7 @@ main() {
return 1
fi
+ verify_system || return 1
if [ "${cmd}" = 'backup' ]; then
backup_apps ${@}

Generated by cgit