diff options
author | Aaron Ball <nullspoon@iohq.net> | 2016-10-07 00:51:31 -0600 |
---|---|---|
committer | Aaron Ball <nullspoon@iohq.net> | 2016-10-07 00:51:31 -0600 |
commit | fd6b3fcf211fa79c5b0f413e57bd7544259d985e (patch) | |
tree | 797a778adb999f9685e26c310e0d52d03a6be945 /andbackup.sh | |
download | andbackup-fd6b3fcf211fa79c5b0f413e57bd7544259d985e.tar.gz andbackup-fd6b3fcf211fa79c5b0f413e57bd7544259d985e.tar.xz |
Initial commit
This currently performs single backups and restores, lists of backups
adn restores (stdin), and lists of backups and restores provided by an
inventory file.
This version has also been tested on system apps as well as user apps.
If an installer apk is available, that is backed up and is reinstalled
upon restore. If not, only the data is backed up (and subsequently
restored).
Note that this requires root.
Diffstat (limited to 'andbackup.sh')
-rwxr-xr-x | andbackup.sh | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/andbackup.sh b/andbackup.sh new file mode 100755 index 0000000..01ffedb --- /dev/null +++ b/andbackup.sh @@ -0,0 +1,201 @@ +#!/system/xbin/bash +# +# Andbackup performs Android backups and restores. +# Copyright (C) 2016 Aaron Ball <nullspoon@oper.io> +# +# 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 3 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, see <http://www.gnu.org/licenses/>. +# +set -u + +backups=/sdcard/andbackup + + +function backup_app { + local app=${1:-} + + # Make sure app is specified + if [[ -z ${app} ]]; then + echo "Please specify an app to backup." + return 1 + fi + + # Make sure app is installed + if [[ $(dumpsys package ${app} | wc -l) -eq 0 ]]; then + echo "Package ${app} appears to not be installed." + return 1 + fi + + echo "# Backing up ${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) + + # Create backup destination if not exist + [[ ! -d ${backups} ]] && mkdir -p ${backups} + [[ ! -d ${backups}/${app}/data ]] && mkdir -p ${backups}/${app}/data + + # Backup the apk file if it exists + if [[ -f ${code}/base.apk ]]; then + cp ${code}/base.apk ${backups}/${app}/base.apk + else + echo "${app} apk file could not be found. Skipping apk installer backup." + fi + + # Copy the user data + cp -rp ${data}/* ${backups}/${app}/data/ + # Delete cache directory if it exists + # This will sometimes significant amounts of space + if [[ -d "${backups}/${app}/data/cache" ]]; then + rm -rf "${backups}/${app}/data/cache" + fi + + # Compress the backup + echo "Compressing userdata for ${app}" + cd ${backups}/${app}/ + tar -cf data.tar data + bzip2 -f data.tar + rm -rf data +} + + +# function list_apps { +# cd ${userdata} +# for dir in *; do +# echo ${dir%-*} +# done +# } + + +function restore_app { + local app=${1:-} + + # Make sure app is specified + if [[ -z ${app} ]]; then + echo "Please specify an app to restore." + return 1 + fi + + # Check that backup exists to be restored + if [[ ! -d ${backups}/${app} ]]; then + echo "No backup for ${app} exists." + return 1 + fi + + echo "# Restoring ${app}" + + # Install app if it is not yet installed + if [[ ! -f "${backups}/${app}/base.apk" ]]; then + echo "Installer for ${app} not found. Only restoring data." + elif [[ $(dumpsys package ${app} | wc -l) -eq 0 ]]; then + echo "Installer detected but package ${app} is not installed. Installing" + pm install ${backups}/${app}/base.apk + fi + + # Stop the application if it is running + am force-stop ${app} + + # Get pertinent metadata + local owner=$(dumpsys package ${app} | grep userId | cut -d'=' -f2 | head -n1) + local code=$(dumpsys package ${app} | grep codePath | cut -d'=' -f2 | head -n1) + local data=$(dumpsys package ${app} | grep dataDir | cut -d'=' -f2 | head -n1) + + # Decompress backup + echo "Decompressing user data for ${app}." + cd ${backups}/${app}/ + bunzip2 -c data.tar.bz2 | tar -x + + # Copy the user data in + cp -rp ${backups}/${app}/data/* ${data}/ + # Fix data permissions + chown -R ${owner}:${owner} ${data} +} + + +function backup_apps { + local apps=${@} + [[ -z ${apps[@]:-} ]] && echo "At least one app is required." && return 1 + + for app in ${apps[@]}; do + backup_app ${app} + done +} + + +function restore_apps { + local apps=${@} + [[ -z ${apps[@]:-} ]] && echo "At least one app is required." && return 1 + + for app in ${apps[@]}; do + restore_app ${app} + done +} + +function list_backup_apps { + local list=${1:-} + [[ -z ${list} ]] && echo "A backup list is required." && return 1 + + for app in $(cat ${list}); do + backup_app ${app} + done +} + + +function list_restore_apps { + local list=${1} + [[ -z ${list} ]] && echo "A backup list is required." && return 1 + + for app in $(cat ${list}); do + restore_app ${app} + done +} + + +function main { + local cmd=${1:-} + shift + + # Ensure root is running this script + if [[ $(id -u) -gt 0 ]]; then + echo "Script must be run as root (uid 0)." + exit 1 + fi + + + if [[ ${cmd} == 'backup' ]]; then + backup_apps ${@} + elif [[ ${cmd} == 'listbackup' ]]; then + list_backup_apps ${@} + elif [[ ${cmd} == 'restore' ]]; then + restore_apps ${@} + elif [[ ${cmd} == 'listrestore' ]]; then + list_restore_apps ${@} + elif [[ ${cmd} == 'ls' || ${cmd} == 'list' ]]; then + list_apps + else + echo "Please specify a command" + echo -e "Available commands are...\n"\ + " backup\n"\ + " listbackup\n"\ + " restore\n"\ + " listrestore\n"\ + " list\n" + exit 1 + fi +} + +main ${@} |