diff options
Diffstat (limited to 'andbackup.sh')
-rwxr-xr-x | andbackup.sh | 114 |
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 ${@} |