summaryrefslogtreecommitdiff
path: root/andbackup.sh
blob: d68fc2389d5979314dc10503b52c52dfd807af0d (plain)
    1 #!/system/xbin/bash
    2 #
    3 # Andbackup performs Android backups and restores.
    4 # Copyright (C) 2016  Aaron Ball <nullspoon@oper.io>
    5 #
    6 # This program is free software: you can redistribute it and/or modify
    7 # it under the terms of the GNU General Public License as published by
    8 # the Free Software Foundation, either version 3 of the License, or
    9 # (at your option) any later version.
   10 #
   11 # This program is distributed in the hope that it will be useful,
   12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 # GNU General Public License for more details.
   15 #
   16 # You should have received a copy of the GNU General Public License
   17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
   18 #
   19 set -u
   20 
   21 backups=/sdcard/andbackup
   22 
   23 
   24 function backup_app {
   25   local app=${1:-}
   26 
   27   # Make sure app is specified
   28   if [[ -z ${app} ]]; then
   29     echo "Please specify an app to backup."
   30     return 1
   31   fi
   32 
   33   # Make sure app is installed
   34   if [[ $(dumpsys package ${app} | wc -l) -eq 0 ]]; then
   35     echo "Package ${app} appears to not be installed."
   36     return 1
   37   fi
   38 
   39   echo "Backing up ${app}"
   40 
   41   # Stop the application if it is running
   42   am force-stop ${app}
   43 
   44   # Get pertinent metadata
   45   local code=$(dumpsys package ${app} | grep codePath | cut -d'=' -f2 | head -n1)
   46   local data=$(dumpsys package ${app} | grep dataDir  | cut -d'=' -f2 | head -n1)
   47 
   48   # Create backup destination if not exist
   49   [[ ! -d ${backups} ]] && mkdir -p ${backups}
   50   [[ ! -d ${backups}/${app}/data ]] && mkdir -p ${backups}/${app}/data
   51 
   52   # Backup the apk file if it exists
   53   if [[ -f ${code}/base.apk ]]; then
   54     cp ${code}/base.apk ${backups}/${app}/base.apk
   55   else
   56     echo "${app} apk file could not be found. Skipping apk installer backup."
   57   fi
   58 
   59   # Copy the user data
   60   cp -rp ${data}/* ${backups}/${app}/data/
   61   # Delete cache directory if it exists
   62   # This will sometimes significant amounts of space
   63   if [[ -d "${backups}/${app}/data/cache" ]]; then
   64     rm -rf "${backups}/${app}/data/cache"
   65   fi
   66 
   67   # Compress the backup
   68   echo "Compressing userdata for ${app}"
   69   cd ${backups}/${app}/
   70   tar -cf data.tar data
   71   bzip2 -f data.tar
   72   rm -rf data
   73 }
   74 
   75 
   76 # function list_apps {
   77 #   cd ${userdata}
   78 #   for dir in *; do
   79 #     echo ${dir%-*}
   80 #   done
   81 # }
   82 
   83 
   84 function restore_app {
   85   local app=${1:-}
   86 
   87   # Make sure app is specified
   88   if [[ -z ${app} ]]; then
   89     echo "Please specify an app to restore."
   90     return 1
   91   fi
   92 
   93   # Check that backup exists to be restored
   94   if [[ ! -d ${backups}/${app} ]]; then
   95     echo "No backup for ${app} exists."
   96     return 1
   97   fi
   98 
   99   echo "Restoring ${app}"
  100 
  101   # Install app if it is not yet installed
  102   if [[ ! -f "${backups}/${app}/base.apk" ]]; then
  103     echo "Installer for ${app} not found. Only restoring data."
  104   elif [[ $(dumpsys package ${app} | wc -l) -eq 0 ]]; then
  105     echo "Installer detected but package ${app} is not installed. Installing"
  106     pm install ${backups}/${app}/base.apk
  107   fi
  108 
  109   # Stop the application if it is running
  110   am force-stop ${app}
  111 
  112   # Get pertinent metadata
  113   local owner=$(dumpsys package ${app} | grep userId | cut -d'=' -f2 | head -n1)
  114   local code=$(dumpsys package ${app} | grep codePath | cut -d'=' -f2 | head -n1)
  115   local data=$(dumpsys package ${app} | grep dataDir  | cut -d'=' -f2 | head -n1)
  116 
  117   # Decompress backup
  118   echo "Decompressing user data for ${app}."
  119   cd ${backups}/${app}/
  120   bunzip2 -c data.tar.bz2 | tar -x
  121 
  122   # Copy the user data in
  123   cp -rp ${backups}/${app}/data/* ${data}/
  124   # Fix data permissions
  125   chown -R ${owner}:${owner} ${data}
  126 
  127   # Cleanup the extracted data so restores don't take too much space
  128   rm -rf ${backups}/${app}/data
  129 }
  130 
  131 
  132 function backup_apps {
  133   local apps=${@}
  134   [[ -z ${apps[@]:-} ]] && echo "At least one app is required." && return 1
  135 
  136   for app in ${apps[@]}; do
  137     backup_app ${app}
  138   done
  139 }
  140 
  141 
  142 function restore_apps {
  143   local apps=${@}
  144   [[ -z ${apps[@]:-} ]] && echo "At least one app is required." && return 1
  145 
  146   for app in ${apps[@]}; do
  147     restore_app ${app}
  148   done
  149 }
  150 
  151 
  152 function list_backup_apps {
  153   local list=${1:-}
  154   [[ -z ${list} ]] && echo "A backup list is required." && return 1
  155 
  156   for app in $(cat ${list}); do
  157     backup_app ${app}
  158   done
  159 }
  160 
  161 
  162 function list_restore_apps {
  163   local list=${1}
  164   [[ -z ${list} ]] && echo "A backup list is required." && return 1
  165 
  166   for app in $(cat ${list}); do
  167     restore_app ${app}
  168   done
  169 }
  170 
  171 
  172 function main {
  173   local cmd=${1:-}
  174   shift
  175 
  176   # Ensure root is running this script
  177   if [[ $(id -u) -gt 0 ]]; then
  178     echo "Script must be run as root (uid 0)."
  179     exit 1
  180   fi
  181 
  182 
  183   if [[ ${cmd} == 'backup' ]]; then
  184     backup_apps ${@}
  185   elif [[ ${cmd} == 'listbackup' ]]; then
  186     list_backup_apps ${@}
  187   elif [[ ${cmd} == 'restore' ]]; then
  188     restore_apps ${@}
  189   elif [[ ${cmd} == 'listrestore' ]]; then
  190     list_restore_apps ${@}
  191   elif [[ ${cmd} == 'ls' || ${cmd} == 'list' ]]; then
  192     list_apps
  193   else
  194     echo "Please specify a command"
  195     echo -e "Available commands are...\n"\
  196             " backup\n"\
  197             " listbackup\n"\
  198             " restore\n"\
  199             " listrestore\n"\
  200             " list\n"
  201     exit 1
  202   fi
  203 }
  204 
  205 main ${@}

Generated by cgit