#!/usr/bin/env bash set -e -u . /etc/crypted-backups user_mode="" source_mode="" verbose='' test_source="/tmp/test" test_destination="/home/dave/Downloads/test" function notification_source_to_destination () { local source_directory=$1 local destination_directory=$2 if [ $source_directory != "" -a $destination_directory != "" ];then echo "$source_directory -> $destination_directory" return 0 else echo "Source ($source_directory) or destination ($destination_directory) directory not given!" return 1 fi } function generate_timestamp () { local timestamp="$(date +"%Y%m%d-%H%M%S")-" echo ${timestamp} return 0 } # Adds trailing slash, if missing # Fails when path is not absolute, or not within user home, when not root function sanitize_pathname () { local path=$1 if [ ${#path} -ne 0 ]; then if [ ${path:0:1} = "/" -o ${path:0:2} = "~/" -a $(id -u) -ne 0 ]; then if [ ${path:${#path}-1} != "/" ]; then echo "$path/" return 0 else echo "$path" return 0 fi else echo "Directory must be absolute!" return 1 fi else echo "Directory can not be empty!" return 1 fi } function check_directory_exists () { local destination=$1 if [ ! -d $destination ]; then echo "Directory \"$destination\" does not exist yet. Creating..." mkdir -p $destination else return 0 fi } function check_directory_permission_root () { if [ -w $1 ]; then return 0 else echo "Directory not writable: $1." return 1 fi } function check_directory_writable_user () { if [ -w $1 ]; then return 0 else echo "Directory not writable: $1." return 1 fi } function check_directory_owner_user() { if [ ! -O $1 ]; then echo "Directory not owned by user $(whoami): $1" return 1 else return 0 fi } function check_user_directory () { local directory=$1 check_directory_exists $directory check_directory_writable_user $directory return 0 } function check_root_directory () { local directory=$1 check_directory_exists $directory check_directory_permission_root $directory return 0 } function get_parent_directory () { local directory=$1 local parent="" parent=$(dirname $directory) parent=$(sanitize_pathname $parent) echo "$parent" return 0 } function get_basename_directory () { local directory=$1 local base=$(basename $directory) echo "$base" return 0 } function compress_directory () { local source_directory=$1 local tmp_file=$2 echo "Compressing source directory ($source_directory) to temporary file ($tmp_file)." case $tar_suffix in ".tar.tbz") tar cfj "$tmp_file" $source_directory ;; ".tar.tgz") tar cfz "$tmp_file" $source_directory ;; ".tar.tlz") tar --lzma -cf "$tmp_file" $source_directory ;; ".tar.xz") tar cfJ "$tmp_file" $source_directory ;; *) echo "Using \"$tar_suffix\" as \$tar_suffix is not supported." return 1 ;; esac return 0 } function encrypt_tmp_file () { local tmp_file=$1 local destination_file=$2 echo "Encrypting $tmp_file to $destination_file." gpg -e \ -r "$gpg_public_key" \ -o "$destination_file" \ "$tmp_file" echo "Removing $tmp_file." rm -f "$tmp_file" return 0 } function backup_single_directory () { local source_directory=$1 local source_directory_basename=$(get_basename_directory $source_directory) local source_parent_directory=$(get_parent_directory $source_directory) local tmp_directory=$(sanitize_pathname $tmp) local destination_directory=$(sanitize_pathname $2) local timestamp=$(generate_timestamp) local tmp_file="$tmp_directory$timestamp$source_directory_basename$tar_suffix" local destination_file="$destination_directory$timestamp$source_directory_basename$tar_suffix$gpg_suffix" notification_source_to_destination "$source_parent_directory$source_directory_basename" $destination_file echo "Going to $source_directory_basename's parent directory: $source_parent_directory." cd $source_parent_directory check_directory_exists $source_directory "check_"$user_mode"_directory" $tmp_directory "check_"$user_mode"_directory" $destination_directory compress_directory $source_directory_basename $tmp_file encrypt_tmp_file $tmp_file $destination_file } function backup_multiple_directories () { local source_directory=$(sanitize_pathname $1) local destination_directory=$(sanitize_pathname $2) "check_"$user_mode"_directory" $destination_directory for sub_directory in $source_directory* do if [ -d $sub_directory ];then "check_"$user_mode"_directory" $sub_directory backup_single_directory $sub_directory $destination_directory fi done } function set_user_mode () { if [ $(id -u) -eq 0 ]; then user_mode="root" else user_mode="user" fi return 0 } function check_gpg_set () { if [ -z "$gpg_public_key" ];then echo "Error. gpg_public_key not set!" exit 1 fi } function print_help () { echo "help" exit 0 } #TODO: Add function to delete compressed data in working directory (also after fail) #TODO: Add function for database backups #TODO: Add function to cleanup backups #TODO: Add function to mirror backups #TODO: Add function to automatically add key to keyring, if not found #TODO: Create logic to distinguish between different backups #TODO: Add verbose flag check_gpg_set set_user_mode if [ ${#@} -gt 0 ]; then while getopts 'c:hr:s:v' flag; do case "${flag}" in c) echo "Cleanup" ;; h) print_help ;; r) echo "recall" ;; s) source_mode="${OPTARG}" ;; v) verbose='true' ;; *) echo "Error. Unrecognized option: ${flag}." exit 1 ;; esac done else print_help fi if [ -n "$source_mode" ];then case $source_mode in aura) ;; bitlbee) ;; etc) backup_single_directory $etc_source $etc_destination ;; git) ;; mail) ;; mailman) ;; mariadb) ;; logs) ;; websites) ;; firefox) ;; thunderbird) ;; weechat) ;; *) echo "Error. $source_mode is not a valid backup option." exit 1 esac fi